From d495702f85e34075984a4c37655433cf6c00d1fd Mon Sep 17 00:00:00 2001 From: shinji-wombat Date: Fri, 6 Jan 2023 14:36:06 +0800 Subject: [PATCH 001/833] run yarn init-integration for wombat --- src/dex/wombat/config.ts | 15 ++ src/dex/wombat/types.ts | 22 ++ src/dex/wombat/wombat-e2e.test.ts | 161 ++++++++++++++ src/dex/wombat/wombat-events.test.ts | 105 +++++++++ src/dex/wombat/wombat-integration.test.ts | 250 ++++++++++++++++++++++ src/dex/wombat/wombat-pool.ts | 91 ++++++++ src/dex/wombat/wombat.ts | 178 +++++++++++++++ 7 files changed, 822 insertions(+) create mode 100644 src/dex/wombat/config.ts create mode 100644 src/dex/wombat/types.ts create mode 100644 src/dex/wombat/wombat-e2e.test.ts create mode 100644 src/dex/wombat/wombat-events.test.ts create mode 100644 src/dex/wombat/wombat-integration.test.ts create mode 100644 src/dex/wombat/wombat-pool.ts create mode 100644 src/dex/wombat/wombat.ts diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts new file mode 100644 index 000000000..43ca2de5e --- /dev/null +++ b/src/dex/wombat/config.ts @@ -0,0 +1,15 @@ +import { DexParams } from './types'; +import { DexConfigMap, AdapterMappings } from '../../types'; +import { Network, SwapSide } from '../../constants'; + +export const WombatConfig: DexConfigMap = { + Wombat: { + // TODO: complete me! + }, +}; + +export const Adapters: Record = { + // TODO: add adapters for each chain + // This is an example to copy + [Network.MAINNET]: { [SwapSide.SELL]: [{ name: '', index: 0 }] }, +}; diff --git a/src/dex/wombat/types.ts b/src/dex/wombat/types.ts new file mode 100644 index 000000000..c23319ee3 --- /dev/null +++ b/src/dex/wombat/types.ts @@ -0,0 +1,22 @@ +import { Address } from '../../types'; + +export type PoolState = { + // TODO: poolState is the state of event + // subscriber. This should be the minimum + // set of parameters required to compute + // pool prices. Complete me! +}; + +export type WombatData = { + // TODO: WombatData is the dex data that is + // returned by the API that can be used for + // tx building. The data structure should be minimal. + // Complete me! + exchange: Address; +}; + +export type DexParams = { + // TODO: DexParams is set of parameters the can + // be used to initiate a DEX fork. + // Complete me! +}; diff --git a/src/dex/wombat/wombat-e2e.test.ts b/src/dex/wombat/wombat-e2e.test.ts new file mode 100644 index 000000000..550cfd99b --- /dev/null +++ b/src/dex/wombat/wombat-e2e.test.ts @@ -0,0 +1,161 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { testE2E } from '../../../tests/utils-e2e'; +import { + Tokens, + Holders, + NativeTokenSymbols, +} from '../../../tests/constants-e2e'; +import { Network, ContractMethod, SwapSide } from '../../constants'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; + +/* + README + ====== + + This test script should add e2e tests for Wombat. The tests + should cover as many cases as possible. Most of the DEXes follow + the following test structure: + - DexName + - ForkName + Network + - ContractMethod + - ETH -> Token swap + - Token -> ETH swap + - Token -> Token swap + + The template already enumerates the basic structure which involves + testing simpleSwap, multiSwap, megaSwap contract methods for + ETH <> TOKEN and TOKEN <> TOKEN swaps. You should replace tokenA and + tokenB with any two highly liquid tokens on Wombat for the tests + to work. If the tokens that you would like to use are not defined in + Tokens or Holders map, you can update the './tests/constants-e2e' + + Other than the standard cases that are already added by the template + it is highly recommended to add test cases which could be specific + to testing Wombat (Eg. Tests based on poolType, special tokens, + etc). + + You can run this individual test script by running: + `npx jest src/dex//-e2e.test.ts` + + e2e tests use the Tenderly fork api. Please add the following to your + .env file: + TENDERLY_TOKEN=Find this under Account>Settings>Authorization. + TENDERLY_ACCOUNT_ID=Your Tenderly account name. + TENDERLY_PROJECT=Name of a Tenderly project you have created in your + dashboard. + + (This comment should be removed from the final implementation) +*/ + +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + // TODO: Add any direct swap contractMethod name if it exists + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + // TODO: If buy is not supported remove the buy contract methods + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }), + ); + }); +} + +describe('Wombat E2E', () => { + const dexKey = 'Wombat'; + + describe('Mainnet', () => { + const network = Network.MAINNET; + + // TODO: Modify the tokenASymbol, tokenBSymbol, tokenAAmount; + const tokenASymbol: string = 'tokenASymbol'; + const tokenBSymbol: string = 'tokenBSymbol'; + + const tokenAAmount: string = 'tokenAAmount'; + const tokenBAmount: string = 'tokenBAmount'; + const nativeTokenAmount = '1000000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + + // TODO: Add any additional test cases required to test Wombat + }); +}); diff --git a/src/dex/wombat/wombat-events.test.ts b/src/dex/wombat/wombat-events.test.ts new file mode 100644 index 000000000..1c4692079 --- /dev/null +++ b/src/dex/wombat/wombat-events.test.ts @@ -0,0 +1,105 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { WombatEventPool } from './wombat-pool'; +import { Network } from '../../constants'; +import { Address } from '../../types'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { testEventSubscriber } from '../../../tests/utils-events'; +import { PoolState } from './types'; + +/* + README + ====== + + This test script adds unit tests for Wombat event based + system. This is done by fetching the state on-chain before the + event block, manually pushing the block logs to the event-subscriber, + comparing the local state with on-chain state. + + Most of the logic for testing is abstracted by `testEventSubscriber`. + You need to do two things to make the tests work: + + 1. Fetch the block numbers where certain events were released. You + can modify the `./scripts/fetch-event-blocknumber.ts` to get the + block numbers for different events. Make sure to get sufficient + number of blockNumbers to cover all possible cases for the event + mutations. + + 2. Complete the implementation for fetchPoolState function. The + function should fetch the on-chain state of the event subscriber + using just the blocknumber. + + The template tests only include the test for a single event + subscriber. There can be cases where multiple event subscribers + exist for a single DEX. In such cases additional tests should be + added. + + You can run this individual test script by running: + `npx jest src/dex//-events.test.ts` + + (This comment should be removed from the final implementation) +*/ + +jest.setTimeout(50 * 1000); + +async function fetchPoolState( + wombatPools: WombatEventPool, + blockNumber: number, + poolAddress: string, +): Promise { + // TODO: complete me! + return {}; +} + +// eventName -> blockNumbers +type EventMappings = Record; + +describe('Wombat EventPool Mainnet', function () { + const dexKey = 'Wombat'; + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + const logger = dexHelper.getLogger(dexKey); + let wombatPool: WombatEventPool; + + // poolAddress -> EventMappings + const eventsToTest: Record = { + // TODO: complete me! + }; + + beforeEach(async () => { + wombatPool = new WombatEventPool( + dexKey, + network, + dexHelper, + logger, + /* TODO: Put here additional constructor arguments if needed */ + ); + }); + + Object.entries(eventsToTest).forEach( + ([poolAddress, events]: [string, EventMappings]) => { + describe(`Events for ${poolAddress}`, () => { + Object.entries(events).forEach( + ([eventName, blockNumbers]: [string, number[]]) => { + describe(`${eventName}`, () => { + blockNumbers.forEach((blockNumber: number) => { + it(`State after ${blockNumber}`, async function () { + await testEventSubscriber( + wombatPool, + wombatPool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolState(wombatPool, _blockNumber, poolAddress), + blockNumber, + `${dexKey}_${poolAddress}`, + dexHelper.provider, + ); + }); + }); + }); + }, + ); + }); + }, + ); +}); diff --git a/src/dex/wombat/wombat-integration.test.ts b/src/dex/wombat/wombat-integration.test.ts new file mode 100644 index 000000000..21e97cd80 --- /dev/null +++ b/src/dex/wombat/wombat-integration.test.ts @@ -0,0 +1,250 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { Interface, Result } from '@ethersproject/abi'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { Network, SwapSide } from '../../constants'; +import { BI_POWS } from '../../bigint-constants'; +import { Wombat } from './wombat'; +import { + checkPoolPrices, + checkPoolsLiquidity, + checkConstantPoolPrices, +} from '../../../tests/utils'; +import { Tokens } from '../../../tests/constants-e2e'; + +/* + README + ====== + + This test script adds tests for Wombat general integration + with the DEX interface. The test cases below are example tests. + It is recommended to add tests which cover Wombat specific + logic. + + You can run this individual test script by running: + `npx jest src/dex//-integration.test.ts` + + (This comment should be removed from the final implementation) +*/ + +function getReaderCalldata( + exchangeAddress: string, + readerIface: Interface, + amounts: bigint[], + funcName: string, + // TODO: Put here additional arguments you need +) { + return amounts.map(amount => ({ + target: exchangeAddress, + callData: readerIface.encodeFunctionData(funcName, [ + // TODO: Put here additional arguments to encode them + amount, + ]), + })); +} + +function decodeReaderResult( + results: Result, + readerIface: Interface, + funcName: string, +) { + // TODO: Adapt this function for your needs + return results.map(result => { + const parsed = readerIface.decodeFunctionResult(funcName, result); + return BigInt(parsed[0]._hex); + }); +} + +async function checkOnChainPricing( + wombat: Wombat, + funcName: string, + blockNumber: number, + prices: bigint[], + amounts: bigint[], +) { + const exchangeAddress = ''; // TODO: Put here the real exchange address + + // TODO: Replace dummy interface with the real one + // Normally you can get it from wombat.Iface or from eventPool. + // It depends on your implementation + const readerIface = new Interface(''); + + const readerCallData = getReaderCalldata( + exchangeAddress, + readerIface, + amounts.slice(1), + funcName, + ); + const readerResult = ( + await wombat.dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blockNumber) + ).returnData; + + const expectedPrices = [0n].concat( + decodeReaderResult(readerResult, readerIface, funcName), + ); + + expect(prices).toEqual(expectedPrices); +} + +async function testPricingOnNetwork( + wombat: Wombat, + network: Network, + dexKey: string, + blockNumber: number, + srcTokenSymbol: string, + destTokenSymbol: string, + side: SwapSide, + amounts: bigint[], + funcNameToCheck: string, +) { + const networkTokens = Tokens[network]; + + const pools = await wombat.getPoolIdentifiers( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + side, + blockNumber, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await wombat.getPricesVolume( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + amounts, + side, + blockNumber, + pools, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + if (wombat.hasConstantPriceLargeAmounts) { + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + } else { + checkPoolPrices(poolPrices!, amounts, side, dexKey); + } + + // Check if onchain pricing equals to calculated ones + await checkOnChainPricing( + wombat, + funcNameToCheck, + blockNumber, + poolPrices![0].prices, + amounts, + ); +} + +describe('Wombat', function () { + const dexKey = 'Wombat'; + let blockNumber: number; + let wombat: Wombat; + + describe('Mainnet', () => { + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + + // TODO: Put here token Symbol to check against + // Don't forget to update relevant tokens in constant-e2e.ts + const srcTokenSymbol = 'srcTokenSymbol'; + const destTokenSymbol = 'destTokenSymbol'; + + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals], + 2n * BI_POWS[tokens[destTokenSymbol].decimals], + 3n * BI_POWS[tokens[destTokenSymbol].decimals], + 4n * BI_POWS[tokens[destTokenSymbol].decimals], + 5n * BI_POWS[tokens[destTokenSymbol].decimals], + 6n * BI_POWS[tokens[destTokenSymbol].decimals], + 7n * BI_POWS[tokens[destTokenSymbol].decimals], + 8n * BI_POWS[tokens[destTokenSymbol].decimals], + 9n * BI_POWS[tokens[destTokenSymbol].decimals], + 10n * BI_POWS[tokens[destTokenSymbol].decimals], + ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + wombat = new Wombat(network, dexKey, dexHelper); + if (wombat.initializePricing) { + await wombat.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + wombat, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + '', // TODO: Put here proper function name to check pricing + ); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + wombat, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + '', // TODO: Put here proper function name to check pricing + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newWombat = new Wombat(network, dexKey, dexHelper); + if (newWombat.updatePoolState) { + await newWombat.updatePoolState(); + } + const poolLiquidity = await newWombat.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newWombat.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); + }); +}); diff --git a/src/dex/wombat/wombat-pool.ts b/src/dex/wombat/wombat-pool.ts new file mode 100644 index 000000000..00e9b519f --- /dev/null +++ b/src/dex/wombat/wombat-pool.ts @@ -0,0 +1,91 @@ +import { Interface } from '@ethersproject/abi'; +import { DeepReadonly } from 'ts-essentials'; +import { Log, Logger } from '../../types'; +import { catchParseLogError } from '../../utils'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { PoolState } from './types'; + +export class WombatEventPool extends StatefulEventSubscriber { + handlers: { + [event: string]: ( + event: any, + state: DeepReadonly, + log: Readonly, + ) => DeepReadonly | null; + } = {}; + + logDecoder: (log: Log) => any; + + addressesSubscribed: string[]; + + constructor( + parentName: string, + protected network: number, + protected dexHelper: IDexHelper, + logger: Logger, + protected wombatIface = new Interface( + '' /* TODO: Import and put here Wombat ABI */, + ), // TODO: add any additional params required for event subscriber + ) { + // TODO: fix arguments for super() + super(parentName, '', dexHelper, logger); + + // TODO: make logDecoder decode logs that + this.logDecoder = (log: Log) => this.wombatIface.parseLog(log); + this.addressesSubscribed = [ + /* subscribed addresses */ + ]; + + // Add handlers + this.handlers['myEvent'] = this.handleMyEvent.bind(this); + } + + /** + * The function is called every time any of the subscribed + * addresses release log. The function accepts the current + * state, updates the state according to the log, and returns + * the updated state. + * @param state - Current state of event subscriber + * @param log - Log released by one of the subscribed addresses + * @returns Updates state of the event subscriber after the log + */ + protected processLog( + state: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + try { + const event = this.logDecoder(log); + if (event.name in this.handlers) { + return this.handlers[event.name](event, state, log); + } + } catch (e) { + catchParseLogError(e, this.logger); + } + + return null; + } + + /** + * The function generates state using on-chain calls. This + * function is called to regenerate state if the event based + * system fails to fetch events and the local state is no + * more correct. + * @param blockNumber - Blocknumber for which the state should + * should be generated + * @returns state of the event subscriber at blocknumber + */ + async generateState(blockNumber: number): Promise> { + // TODO: complete me! + return {}; + } + + // Its just a dummy example + handleMyEvent( + event: any, + state: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + return null; + } +} diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts new file mode 100644 index 000000000..4d94d5475 --- /dev/null +++ b/src/dex/wombat/wombat.ts @@ -0,0 +1,178 @@ +import { AsyncOrSync } from 'ts-essentials'; +import { + Token, + Address, + ExchangePrices, + PoolPrices, + AdapterExchangeParam, + SimpleExchangeParam, + PoolLiquidity, + Logger, +} from '../../types'; +import { SwapSide, Network } from '../../constants'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { getDexKeysWithNetwork } from '../../utils'; +import { IDex } from '../../dex/idex'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { WombatData } from './types'; +import { SimpleExchange } from '../simple-exchange'; +import { WombatConfig, Adapters } from './config'; +import { WombatEventPool } from './wombat-pool'; + +export class Wombat extends SimpleExchange implements IDex { + protected eventPools: WombatEventPool; + + readonly hasConstantPriceLargeAmounts = false; + // TODO: set true here if protocols works only with wrapped asset + readonly needWrapNative = true; + + readonly isFeeOnTransferSupported = false; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(WombatConfig); + + logger: Logger; + + constructor( + readonly network: Network, + readonly dexKey: string, + readonly dexHelper: IDexHelper, + protected adapters = Adapters[network] || {}, // TODO: add any additional optional params to support other fork DEXes + ) { + super(dexHelper, dexKey); + this.logger = dexHelper.getLogger(dexKey); + this.eventPools = new WombatEventPool( + dexKey, + network, + dexHelper, + this.logger, + ); + } + + // Initialize pricing is called once in the start of + // pricing service. It is intended to setup the integration + // for pricing requests. It is optional for a DEX to + // implement this function + async initializePricing(blockNumber: number) { + // TODO: complete me! + } + + // Returns the list of contract adapters (name and index) + // for a buy/sell. Return null if there are no adapters. + getAdapters(side: SwapSide): { name: string; index: number }[] | null { + return this.adapters[side] ? this.adapters[side] : null; + } + + // Returns list of pool identifiers that can be used + // for a given swap. poolIdentifiers must be unique + // across DEXes. It is recommended to use + // ${dexKey}_${poolAddress} as a poolIdentifier + async getPoolIdentifiers( + srcToken: Token, + destToken: Token, + side: SwapSide, + blockNumber: number, + ): Promise { + // TODO: complete me! + return []; + } + + // Returns pool prices for amounts. + // If limitPools is defined only pools in limitPools + // should be used. If limitPools is undefined then + // any pools can be used. + async getPricesVolume( + srcToken: Token, + destToken: Token, + amounts: bigint[], + side: SwapSide, + blockNumber: number, + limitPools?: string[], + ): Promise> { + // TODO: complete me! + return null; + } + + // Returns estimated gas cost of calldata for this DEX in multiSwap + getCalldataGasCost(poolPrices: PoolPrices): number | number[] { + // TODO: update if there is any payload in getAdapterParam + return CALLDATA_GAS_COST.DEX_NO_PAYLOAD; + } + + // Encode params required by the exchange adapter + // Used for multiSwap, buy & megaSwap + // Hint: abiCoder.encodeParameter() could be useful + getAdapterParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: WombatData, + side: SwapSide, + ): AdapterExchangeParam { + // TODO: complete me! + const { exchange } = data; + + // Encode here the payload for adapter + const payload = ''; + + return { + targetExchange: exchange, + payload, + networkFee: '0', + }; + } + + // Encode call data used by simpleSwap like routers + // Used for simpleSwap & simpleBuy + // Hint: this.buildSimpleParamWithoutWETHConversion + // could be useful + async getSimpleParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: WombatData, + side: SwapSide, + ): Promise { + // TODO: complete me! + const { exchange } = data; + + // Encode here the transaction arguments + const swapData = ''; + + return this.buildSimpleParamWithoutWETHConversion( + srcToken, + srcAmount, + destToken, + destAmount, + swapData, + exchange, + ); + } + + // This is called once before getTopPoolsForToken is + // called for multiple tokens. This can be helpful to + // update common state required for calculating + // getTopPoolsForToken. It is optional for a DEX + // to implement this + async updatePoolState(): Promise { + // TODO: complete me! + } + + // Returns list of top pools based on liquidity. Max + // limit number pools should be returned. + async getTopPoolsForToken( + tokenAddress: Address, + limit: number, + ): Promise { + //TODO: complete me! + return []; + } + + // This is optional function in case if your implementation has acquired any resources + // you need to release for graceful shutdown. For example, it may be any interval timer + releaseResources(): AsyncOrSync { + // TODO: complete me! + } +} From b580aac7d3a393887956d6acdb7158d7c6c46c84 Mon Sep 17 00:00:00 2001 From: shinji-wombat Date: Mon, 9 Jan 2023 17:25:21 +0800 Subject: [PATCH 002/833] add wombat main pool config --- src/dex/wombat/config.ts | 10 +++++++++- src/dex/wombat/types.ts | 8 +++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts index 43ca2de5e..252c5de6c 100644 --- a/src/dex/wombat/config.ts +++ b/src/dex/wombat/config.ts @@ -4,7 +4,15 @@ import { Network, SwapSide } from '../../constants'; export const WombatConfig: DexConfigMap = { Wombat: { - // TODO: complete me! + [Network.BSC]: { + pools: [ + { + address: '0x312Bc7eAAF93f1C60Dc5AfC115FcCDE161055fb0', + name: 'Wombat Main Pool', + }, + /** @todo add Side and Dynamic pools */ + ], + }, }, }; diff --git a/src/dex/wombat/types.ts b/src/dex/wombat/types.ts index c23319ee3..0b76d37e4 100644 --- a/src/dex/wombat/types.ts +++ b/src/dex/wombat/types.ts @@ -16,7 +16,9 @@ export type WombatData = { }; export type DexParams = { - // TODO: DexParams is set of parameters the can - // be used to initiate a DEX fork. - // Complete me! + // DexParams is set of parameters that can be used to initiate a DEX fork. + pools: { + address: Address; + name: string; + }[]; }; From 55e99406905c2e7dbdfe482c7f9f4b62ff279a3e Mon Sep 17 00:00:00 2001 From: shinji-wombat Date: Mon, 9 Jan 2023 17:26:16 +0800 Subject: [PATCH 003/833] add wombat to dex index.ts --- src/dex/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dex/index.ts b/src/dex/index.ts index 91dbb0229..6761ca198 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -37,6 +37,7 @@ import { Excalibur } from './uniswap-v2/excalibur'; import { MakerPsm } from './maker-psm/maker-psm'; import { KyberDmm } from './kyberdmm/kyberdmm'; import { Platypus } from './platypus/platypus'; +import { Wombat } from './wombat/wombat'; import { GMX } from './gmx/gmx'; import { WooFi } from './woo-fi/woo-fi'; import { ParaSwapLimitOrders } from './paraswap-limit-orders/paraswap-limit-orders'; @@ -109,6 +110,7 @@ const Dexes = [ CurveV1Factory, SwaapV1, WstETH, + Wombat, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< From 520806e2b7056e3a91cc18ecf3a8c1ef09d698dd Mon Sep 17 00:00:00 2001 From: shinji-wombat Date: Thu, 12 Jan 2023 18:02:00 +0800 Subject: [PATCH 004/833] add wombat pool ABI --- src/abi/wombat/pool.json | 1264 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 1264 insertions(+) create mode 100644 src/abi/wombat/pool.json diff --git a/src/abi/wombat/pool.json b/src/abi/wombat/pool.json new file mode 100644 index 000000000..64eed2a67 --- /dev/null +++ b/src/abi/wombat/pool.json @@ -0,0 +1,1264 @@ +[ + { + "inputs": [], + "name": "CORE_UNDERFLOW", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_AMOUNT_TOO_LOW", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ASSET_ALREADY_EXIST", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ASSET_ALREADY_PAUSED", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ASSET_NOT_EXISTS", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ASSET_NOT_PAUSED", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_CASH_NOT_ENOUGH", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_EXPIRED", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_FORBIDDEN", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_INVALID_VALUE", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_SAME_ADDRESS", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ZERO_ADDRESS", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ZERO_AMOUNT", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ZERO_LIQUIDITY", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "AssetAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "AssetRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FillPool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "PausedAsset", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SetAmpFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "SetDev", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "lpDividendRatio", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "retentionRatio", + "type": "uint256" + } + ], + "name": "SetFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "SetFeeTo", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SetHaircutRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "SetMasterWombat", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SetMintFeeThreshold", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fromAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toAmount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "Swap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "TransferTipBucket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "UnpausedAsset", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "addAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "addressOfAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ampFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumLiquidity", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "shouldStake", + "type": "bool" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "dev", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "exchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "xr", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "fillPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getTokens", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalEquilCovRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "equilCovRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "invariantInUint", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "haircutRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ampFactor_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "haircutRate_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lpDividendRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterWombat", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "mintFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mintFeeThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "pauseAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "int256", + "name": "toAmount", + "type": "int256" + } + ], + "name": "quoteAmountIn", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "haircut", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "quotePotentialDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "int256", + "name": "fromAmount", + "type": "int256" + } + ], + "name": "quotePotentialSwap", + "outputs": [ + { + "internalType": "uint256", + "name": "potentialOutcome", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "haircut", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "name": "quotePotentialWithdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "name": "quotePotentialWithdrawFromOtherAsset", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrewAmount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "removeAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "retentionRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ampFactor_", + "type": "uint256" + } + ], + "name": "setAmpFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dev_", + "type": "address" + } + ], + "name": "setDev", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "lpDividendRatio_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "retentionRatio_", + "type": "uint256" + } + ], + "name": "setFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "feeTo_", + "type": "address" + } + ], + "name": "setFeeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "haircutRate_", + "type": "uint256" + } + ], + "name": "setHaircutRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "masterWombat_", + "type": "address" + } + ], + "name": "setMasterWombat", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "mintFeeThreshold_", + "type": "uint256" + } + ], + "name": "setMintFeeThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fromAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumToAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swap", + "outputs": [ + { + "internalType": "uint256", + "name": "actualToAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "haircut", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "tipBucketBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferTipBucket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unpauseAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "withdrawFromOtherAsset", + "outputs": [ + { + "internalType": "uint256", + "name": "toAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] From 538804fd7bcbcd536448c840bdf52d3416e3d95c Mon Sep 17 00:00:00 2001 From: shinji-wombat Date: Thu, 12 Jan 2023 21:56:40 +0800 Subject: [PATCH 005/833] add asset ABI --- src/abi/wombat/asset.json | 691 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 691 insertions(+) create mode 100644 src/abi/wombat/asset.json diff --git a/src/abi/wombat/asset.json b/src/abi/wombat/asset.json new file mode 100644 index 000000000..d68fe0b89 --- /dev/null +++ b/src/abi/wombat/asset.json @@ -0,0 +1,691 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "underlyingToken_", + "type": "address" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ASSET_OVERFLOW", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_FORBIDDEN", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "previousMaxSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMaxSupply", + "type": "uint256" + } + ], + "name": "SetMaxSupply", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousPoolAddr", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPoolAddr", + "type": "address" + } + ], + "name": "SetPool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "addCash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "addLiability", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "cash", + "outputs": [ + { + "internalType": "uint120", + "name": "", + "type": "uint120" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "liability", + "outputs": [ + { + "internalType": "uint120", + "name": "", + "type": "uint120" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "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": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "removeCash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "removeLiability", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxSupply_", + "type": "uint256" + } + ], + "name": "setMaxSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool_", + "type": "address" + } + ], + "name": "setPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "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": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferUnderlyingToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "underlyingToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "underlyingTokenBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "underlyingTokenDecimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + } +] From 07b60b2f14c80557207ea3f63a080811de4b4671 Mon Sep 17 00:00:00 2001 From: shinji-wombat Date: Thu, 12 Jan 2023 21:57:57 +0800 Subject: [PATCH 006/833] add config and types --- src/dex/wombat/config.ts | 12 +- src/dex/wombat/types.ts | 44 ++++++- src/dex/wombat/wombat.ts | 266 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 298 insertions(+), 24 deletions(-) diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts index 252c5de6c..3dc6f0d6b 100644 --- a/src/dex/wombat/config.ts +++ b/src/dex/wombat/config.ts @@ -17,7 +17,13 @@ export const WombatConfig: DexConfigMap = { }; export const Adapters: Record = { - // TODO: add adapters for each chain - // This is an example to copy - [Network.MAINNET]: { [SwapSide.SELL]: [{ name: '', index: 0 }] }, + [Network.BSC]: { + [SwapSide.SELL]: [ + { + name: 'BscAdapter01', + /** @todo check index number */ + index: 12, + }, + ], + }, }; diff --git a/src/dex/wombat/types.ts b/src/dex/wombat/types.ts index 0b76d37e4..cea087854 100644 --- a/src/dex/wombat/types.ts +++ b/src/dex/wombat/types.ts @@ -1,10 +1,50 @@ import { Address } from '../../types'; +import { ChainLinkState } from '../../lib/chainlink'; + +// State-related types export type PoolState = { - // TODO: poolState is the state of event + // poolState is the state of event // subscriber. This should be the minimum // set of parameters required to compute - // pool prices. Complete me! + // pool prices. + params: PoolParams; + chainlink: { [underlyingAddress: string]: ChainLinkState }; + underlyingAddresses: Address[]; + asset: { [underlyingAddress: string]: AssetState }; +}; + +export type AssetState = { + cash: bigint; + liability: bigint; +}; + +export type PoolParams = { + slippageParamK: bigint; + slippageParamN: bigint; + c1: bigint; + xThreshold: bigint; + haircutRate: bigint; + retentionRatio: bigint; + maxPriceDeviation: bigint; +}; + +// Wombat Config types + +export type WombatConfigInfo = { + poolAddresses: Address[]; + pools: { [poolAddress: string]: WombatPoolConfigInfo }; +}; + +export type WombatPoolConfigInfo = { + tokenAddresses: Address[]; + tokens: { + [tokenAddress: string]: { + tokenSymbol: string; + tokenDecimals: number; + assetAddress: Address; + }; + }; }; export type WombatData = { diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 4d94d5475..632d2bc82 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -1,4 +1,5 @@ import { AsyncOrSync } from 'ts-essentials'; +import { Interface } from '@ethersproject/abi'; import { Token, Address, @@ -8,19 +9,32 @@ import { SimpleExchangeParam, PoolLiquidity, Logger, + MultiCallInput, } from '../../types'; import { SwapSide, Network } from '../../constants'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { getDexKeysWithNetwork } from '../../utils'; import { IDex } from '../../dex/idex'; import { IDexHelper } from '../../dex-helper/idex-helper'; -import { WombatData } from './types'; +import { WombatData, DexParams, WombatConfigInfo } from './types'; import { SimpleExchange } from '../simple-exchange'; import { WombatConfig, Adapters } from './config'; import { WombatEventPool } from './wombat-pool'; +import PoolABI from '../../abi/wombat/pool.json'; +import AssetABI from '../../abi/wombat/asset.json'; +import ERC20ABI from '../../abi/erc20.json'; export class Wombat extends SimpleExchange implements IDex { - protected eventPools: WombatEventPool; + // contract interfaces + static readonly erc20Interface = new Interface(ERC20ABI); + static readonly poolInterface = new Interface(PoolABI); + static readonly assetInterface = new Interface(AssetABI); + + protected config: DexParams; + protected cfgInfo?: WombatConfigInfo; + protected poolLiquidityUSD?: { [poolAddress: string]: number }; + + protected eventPools?: { [poolAddress: string]: WombatEventPool }; readonly hasConstantPriceLargeAmounts = false; // TODO: set true here if protocols works only with wrapped asset @@ -41,12 +55,101 @@ export class Wombat extends SimpleExchange implements IDex { ) { super(dexHelper, dexKey); this.logger = dexHelper.getLogger(dexKey); - this.eventPools = new WombatEventPool( - dexKey, - network, - dexHelper, - this.logger, - ); + this.config = WombatConfig[dexKey][network]; + } + + async generateConfigInfo(blockNumber: number): Promise { + const cfgInfo: WombatConfigInfo = { + poolAddresses: [], + pools: {}, + }; + // Need to filter pools in case we are testing against an old block where the pool didn't exist! + for (const p of this.config.pools) { + // When there's no code, getCode should return '0x' but could return '0x0' instead + if ( + (await this.dexHelper.web3Provider.eth.getCode(p.address, blockNumber)) + .length > 3 // it's not '0x' or '0x0' + ) { + cfgInfo.poolAddresses.push(p.address.toLowerCase()); + } + } + // 1. Get tokens in each pool + let inputs: MultiCallInput[] = []; + for (const poolAddress of cfgInfo.poolAddresses) { + inputs.push({ + target: poolAddress, + callData: Wombat.poolInterface.encodeFunctionData('getTokens'), + }); + } + let returnData = ( + await this.dexHelper.multiContract.methods + .aggregate(inputs) + .call({}, blockNumber) + ).returnData; + + let i = 0; + for (const poolAddress of cfgInfo.poolAddresses) { + const tokenAddresses = Wombat.poolInterface + .decodeFunctionResult('getTokens', returnData[i++])[0] + .toLowerCase(); + cfgInfo.pools[poolAddress] = { + tokenAddresses, + tokens: {}, + }; + } + + // 2. For each pool, get tokens' symbol, decimals, asset (LP token) address + inputs = []; + for (const poolAddress of cfgInfo.poolAddresses) { + for (const tokenAddress of cfgInfo.pools[poolAddress].tokenAddresses) { + inputs.push({ + target: tokenAddress, + callData: Wombat.erc20Interface.encodeFunctionData('symbol'), + }); + inputs.push({ + target: tokenAddress, + callData: Wombat.erc20Interface.encodeFunctionData('decimals'), + }); + inputs.push({ + target: poolAddress, + callData: Wombat.poolInterface.encodeFunctionData('addressOfAsset', [ + tokenAddress, + ]), + }); + } + } + returnData = ( + await this.dexHelper.multiContract.methods + .aggregate(inputs) + .call({}, blockNumber) + ).returnData; + i = 0; + for (const poolAddress of cfgInfo.poolAddresses) { + for (const tokenAddress of cfgInfo.pools[poolAddress].tokenAddresses) { + const tokenSymbol = Wombat.erc20Interface.decodeFunctionResult( + 'symbol', + returnData[i++], + )[0]; + const tokenDecimals = Wombat.erc20Interface.decodeFunctionResult( + 'decimals', + returnData[i++], + )[0]; + const assetAddress = Wombat.poolInterface + .decodeFunctionResult('addressOfAsset', returnData[i++])[0] + .toLowerCase(); + cfgInfo.pools[poolAddress].tokens[tokenAddress] = { + tokenSymbol, + tokenDecimals, + assetAddress, + }; + } + } + return cfgInfo; + } + + async init(blockNumber: number) { + if (this.cfgInfo) return; + this.cfgInfo = await this.generateConfigInfo(blockNumber); } // Initialize pricing is called once in the start of @@ -54,7 +157,32 @@ export class Wombat extends SimpleExchange implements IDex { // for pricing requests. It is optional for a DEX to // implement this function async initializePricing(blockNumber: number) { - // TODO: complete me! + await this.init(blockNumber); + if (!this.cfgInfo) + throw new Error('initializePricing: cfgInfo still null after init'); + + const eventPools: { [poolAddress: string]: WombatEventPool } = {}; + for (const poolAddress of this.cfgInfo.poolAddresses) { + // const pool = new WombatEventPool( + // this.dexKey, + // this.network, + // this.config.pools.find( + // p => p.address.toLowerCase() === poolAddress, + // )!.name, + // poolAddress, + // this.cfgInfo.pools[poolAddress], + // this.dexHelper, + // ); + // const state = await pool.generateState(blockNumber); + // pool.setState(state, blockNumber); + // this.dexHelper.blockManager.subscribeToLogs( + // pool, + // pool.addressesSubscribed, + // blockNumber, + // ); + // eventPools[poolAddress] = pool; + } + this.eventPools = eventPools; } // Returns the list of contract adapters (name and index) @@ -73,8 +201,16 @@ export class Wombat extends SimpleExchange implements IDex { side: SwapSide, blockNumber: number, ): Promise { - // TODO: complete me! - return []; + /** @todo implement logic for BUY side */ + if (side === SwapSide.BUY) return []; + return this.findPools( + srcToken.address.toLowerCase(), + destToken.address.toLowerCase(), + ).map(p => this.getPoolIdentifier(p)); + } + + protected getPoolIdentifier(poolAddress: Address): string { + return `${this.dexKey}_${poolAddress}`; } // Returns pool prices for amounts. @@ -93,6 +229,20 @@ export class Wombat extends SimpleExchange implements IDex { return null; } + protected findPools( + srcTokenAddress: Address, + destTokenAddress: Address, + ): Address[] { + if (!this.cfgInfo) return []; + return Object.entries(this.cfgInfo.pools) + .filter( + ([poolAddress, poolConfig]) => + poolConfig.tokenAddresses.includes(srcTokenAddress) && + poolConfig.tokenAddresses.includes(destTokenAddress), + ) + .map(([poolAddress, poolConfig]) => poolAddress); + } + // Returns estimated gas cost of calldata for this DEX in multiSwap getCalldataGasCost(poolPrices: PoolPrices): number | number[] { // TODO: update if there is any payload in getAdapterParam @@ -114,7 +264,7 @@ export class Wombat extends SimpleExchange implements IDex { const { exchange } = data; // Encode here the payload for adapter - const payload = ''; + const payload = '0x'; return { targetExchange: exchange, @@ -135,11 +285,17 @@ export class Wombat extends SimpleExchange implements IDex { data: WombatData, side: SwapSide, ): Promise { - // TODO: complete me! const { exchange } = data; // Encode here the transaction arguments - const swapData = ''; + const swapData = Wombat.poolInterface.encodeFunctionData('swap', [ + srcToken, + destToken, + srcAmount, + 1 /** @todo assume slippage tolorence is 2% and set the minimum receive accordingly */, + this.augustusAddress, + this.getDeadline(), + ]); return this.buildSimpleParamWithoutWETHConversion( srcToken, @@ -154,10 +310,65 @@ export class Wombat extends SimpleExchange implements IDex { // This is called once before getTopPoolsForToken is // called for multiple tokens. This can be helpful to // update common state required for calculating - // getTopPoolsForToken. It is optional for a DEX - // to implement this + // getTopPoolsForToken. For example, poolLiquidityUSD. async updatePoolState(): Promise { - // TODO: complete me! + const blockNumber = await this.dexHelper.provider.getBlockNumber(); + await this.init(blockNumber); + if (!this.cfgInfo) + throw new Error('updatePoolState: Wombat cfgInfo still null after init'); + + // All tokens are USD stablecoins so to estimate liquidity can just add + // the cash balances of all the tokens + const poolLiquidityUSD: { [poolAddress: string]: number } = {}; + let inputs: MultiCallInput[] = []; + for (const poolAddress of this.cfgInfo.poolAddresses) { + for (const tokenAddress of this.cfgInfo.pools[poolAddress] + .tokenAddresses) { + inputs.push({ + target: + this.cfgInfo.pools[poolAddress].tokens[tokenAddress].assetAddress, + callData: Wombat.assetInterface.encodeFunctionData('cash'), + }); + } + } + const returnData = ( + await this.dexHelper.multiContract.methods + .aggregate(inputs) + .call({}, blockNumber) + ).returnData; + const usdPromises = []; + let i = 0; + for (const poolAddress of this.cfgInfo.poolAddresses) { + for (const tokenAddress of this.cfgInfo.pools[poolAddress] + .tokenAddresses) { + usdPromises.push( + this.dexHelper.getTokenUSDPrice( + { + address: tokenAddress, + decimals: + this.cfgInfo.pools[poolAddress].tokens[tokenAddress] + .tokenDecimals, + }, + /** @todo wombat asset addresses always have 18 d.p. need to convert this amount to underlying tokens native d.p. */ + BigInt( + Wombat.assetInterface + .decodeFunctionResult('cash', returnData[i++])[0] + .toString(), + ), + ), + ); + } + } + const usdValues = await Promise.all(usdPromises); + i = 0; + for (const poolAddress of this.cfgInfo.poolAddresses) { + poolLiquidityUSD[poolAddress] = 0; + for (const tokenAddress of this.cfgInfo.pools[poolAddress] + .tokenAddresses) { + poolLiquidityUSD[poolAddress] += usdValues[i++]; + } + } + this.poolLiquidityUSD = poolLiquidityUSD; } // Returns list of top pools based on liquidity. Max @@ -166,8 +377,25 @@ export class Wombat extends SimpleExchange implements IDex { tokenAddress: Address, limit: number, ): Promise { - //TODO: complete me! - return []; + if (!this.cfgInfo || !this.poolLiquidityUSD) await this.updatePoolState(); + tokenAddress = tokenAddress.toLowerCase(); + const pools = this.cfgInfo!.poolAddresses.filter( + poolAddress => !!this.cfgInfo!.pools[poolAddress].tokens[tokenAddress], + ); + // sort by liquidity + pools.sort((a, b) => this.poolLiquidityUSD![b] - this.poolLiquidityUSD![a]); + return pools.slice(0, limit).map(poolAddress => ({ + exchange: this.dexKey, + address: poolAddress, + // other tokens in the same pool + connectorTokens: this.cfgInfo!.pools[poolAddress].tokenAddresses.filter( + t => t !== tokenAddress, + ).map(t => ({ + decimals: this.cfgInfo!.pools[poolAddress].tokens[t].tokenDecimals, + address: t, + })), + liquidityUSD: this.poolLiquidityUSD![poolAddress], + })); } // This is optional function in case if your implementation has acquired any resources From 021f55057fac6985eb35efde6e323883a3521bae Mon Sep 17 00:00:00 2001 From: shinji-wombat Date: Fri, 13 Jan 2023 03:35:53 +0800 Subject: [PATCH 007/833] add utils function for calculating price --- src/dex/wombat/types.ts | 7 +-- src/dex/wombat/utils.ts | 97 +++++++++++++++++++++++++++++++ src/dex/wombat/wombat.ts | 122 +++++++++++++++++++++++++++++++-------- 3 files changed, 197 insertions(+), 29 deletions(-) create mode 100644 src/dex/wombat/utils.ts diff --git a/src/dex/wombat/types.ts b/src/dex/wombat/types.ts index cea087854..809550a10 100644 --- a/src/dex/wombat/types.ts +++ b/src/dex/wombat/types.ts @@ -20,13 +20,8 @@ export type AssetState = { }; export type PoolParams = { - slippageParamK: bigint; - slippageParamN: bigint; - c1: bigint; - xThreshold: bigint; + ampFactor: bigint; haircutRate: bigint; - retentionRatio: bigint; - maxPriceDeviation: bigint; }; // Wombat Config types diff --git a/src/dex/wombat/utils.ts b/src/dex/wombat/utils.ts new file mode 100644 index 000000000..0a7ffffe0 --- /dev/null +++ b/src/dex/wombat/utils.ts @@ -0,0 +1,97 @@ +import { BI_POWS } from '../../bigint-constants'; + +const WAD = BI_POWS[18]; + +function wmul(x: bigint, y: bigint): bigint { + return (x * y + WAD / 2n) / WAD; +} + +function wdiv(x: bigint, y: bigint): bigint { + return (x * WAD + y / 2n) / y; +} + +// Babylonian Method for solving sqrt +function sqrt(y: bigint): bigint { + let z = 0n; + if (y > 3) { + let z = y; + let x = y / 2n + 1n; + while (x < z) { + z = x; + x = (y / x + x) / 2n; + } + } else if (y != 0n) { + z = 1n; + } + return z; +} + +function solveQuad(b: bigint, c: bigint): bigint { + return (sqrt(b * b + c * 4n * WAD) - b) / 2n; +} + +function swapQuoteFunc( + assetX: bigint, + assetY: bigint, + liabilityX: bigint, + liabilityY: bigint, + dX: bigint, + a: bigint, +): bigint { + if (liabilityX == 0n || liabilityY == 0n) { + // in case div of 0, CORE_UNDERFLOW + return 0n; + } + // int256 D = Ax + Ay - A.wmul((Lx * Lx) / Ax + (Ly * Ly) / Ay); // flattened _invariantFunc + const d = + assetX + + assetY - + wmul( + a, + (liabilityX * liabilityX) / assetX + (liabilityY * liabilityY) / assetY, + ); + // int256 rx_ = (Ax + Dx).wdiv(Lx); + const rX = wdiv(assetX + dX, liabilityX); + // int256 b = (Lx * (rx_ - A.wdiv(rx_))) / Ly - D.wdiv(Ly); // flattened _coefficientFunc + const b = + (liabilityX * (rX - wdiv(a, rX))) / liabilityY - wdiv(d, liabilityY); + // int256 ry_ = _solveQuad(b, A); + const rY = solveQuad(b, a); + // int256 Dy = Ly.wmul(ry_) - Ay; + const dY = wmul(liabilityY, rY) - assetY; + // if (Dy < 0) { + // quote = uint256(-Dy); + // } else { + // quote = uint256(Dy); + // } + if (dY < 0n) { + return -dY; + } else { + return dY; + } +} + +export function quoteFrom( + assetX: bigint, + assetY: bigint, + liabilityX: bigint, + liabilityY: bigint, + fromAmount: bigint, + ampFactor: bigint, + haircutRate: bigint, +): bigint { + const idealToAmount = swapQuoteFunc( + assetX, + assetY, + liabilityX, + liabilityY, + fromAmount, + ampFactor, + ); + if (fromAmount > 0n && assetY < idealToAmount) { + return 0n; + } + const haircut = wmul(idealToAmount, haircutRate); + const actualToAmount = idealToAmount - haircut; + return actualToAmount; +} diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 632d2bc82..fde345f21 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -1,5 +1,7 @@ import { AsyncOrSync } from 'ts-essentials'; import { Interface } from '@ethersproject/abi'; +import { DeepReadonly } from 'ts-essentials'; + import { Token, Address, @@ -13,13 +15,14 @@ import { } from '../../types'; import { SwapSide, Network } from '../../constants'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { getDexKeysWithNetwork } from '../../utils'; +import { getDexKeysWithNetwork, getBigIntPow } from '../../utils'; import { IDex } from '../../dex/idex'; import { IDexHelper } from '../../dex-helper/idex-helper'; -import { WombatData, DexParams, WombatConfigInfo } from './types'; +import { WombatData, DexParams, WombatConfigInfo, PoolState } from './types'; import { SimpleExchange } from '../simple-exchange'; import { WombatConfig, Adapters } from './config'; import { WombatEventPool } from './wombat-pool'; +import { quoteFrom } from './utils'; import PoolABI from '../../abi/wombat/pool.json'; import AssetABI from '../../abi/wombat/asset.json'; import ERC20ABI from '../../abi/erc20.json'; @@ -37,7 +40,6 @@ export class Wombat extends SimpleExchange implements IDex { protected eventPools?: { [poolAddress: string]: WombatEventPool }; readonly hasConstantPriceLargeAmounts = false; - // TODO: set true here if protocols works only with wrapped asset readonly needWrapNative = true; readonly isFeeOnTransferSupported = false; @@ -163,24 +165,26 @@ export class Wombat extends SimpleExchange implements IDex { const eventPools: { [poolAddress: string]: WombatEventPool } = {}; for (const poolAddress of this.cfgInfo.poolAddresses) { - // const pool = new WombatEventPool( - // this.dexKey, - // this.network, - // this.config.pools.find( - // p => p.address.toLowerCase() === poolAddress, - // )!.name, - // poolAddress, - // this.cfgInfo.pools[poolAddress], - // this.dexHelper, - // ); - // const state = await pool.generateState(blockNumber); - // pool.setState(state, blockNumber); - // this.dexHelper.blockManager.subscribeToLogs( - // pool, - // pool.addressesSubscribed, - // blockNumber, - // ); - // eventPools[poolAddress] = pool; + const pool = new WombatEventPool( + this.dexKey, + '' /** @todo pool name */, + // this.config.pools.find( + // p => p.address.toLowerCase() === poolAddress, + // )!.name, + 3 /** @todo network number */, + this.dexHelper, + this.logger, + poolAddress, + this.cfgInfo.pools[poolAddress], + ); + const state = await pool.generateState(blockNumber); + pool.setState(state, blockNumber); + this.dexHelper.blockManager.subscribeToLogs( + pool, + pool.addressesSubscribed, + blockNumber, + ); + eventPools[poolAddress] = pool; } this.eventPools = eventPools; } @@ -225,8 +229,80 @@ export class Wombat extends SimpleExchange implements IDex { blockNumber: number, limitPools?: string[], ): Promise> { - // TODO: complete me! - return null; + /** @todo implement logic for BUY side */ + if (side === SwapSide.BUY) return null; + if (!this.eventPools) { + this.logger.error( + `Missing event pools for ${this.dexKey} in getPricesVolume`, + ); + return null; + } + const srcTokenAddress = srcToken.address.toLowerCase(); + const destTokenAddress = destToken.address.toLowerCase(); + if (srcTokenAddress === destTokenAddress) return null; + return await Promise.all( + this.findPools(srcTokenAddress, destTokenAddress) + .filter( + poolAddress => + !limitPools || + limitPools.includes(this.getPoolIdentifier(poolAddress)), + ) + .map(poolAddress => + (async () => { + let state = this.eventPools![poolAddress].getState(blockNumber); + if (!state) { + state = await this.eventPools![poolAddress].generateState( + blockNumber, + ); + this.eventPools![poolAddress].setState(state, blockNumber); + } + const [unit, ...prices] = this.computePrices( + srcTokenAddress, + this.cfgInfo!.pools[poolAddress].tokens[srcTokenAddress] + .tokenDecimals, + destTokenAddress, + this.cfgInfo!.pools[poolAddress].tokens[destTokenAddress] + .tokenDecimals, + [getBigIntPow(srcToken.decimals), ...amounts], + state, + ); + return { + prices, + unit, + data: { + exchange: poolAddress, + }, + poolAddresses: [poolAddress], + exchange: this.dexKey, + /** @todo specify gas cost */ + gasCost: 260 * 1000, + poolIdentifier: this.getPoolIdentifier(poolAddress), + }; + })(), + ), + ); + } + + // take PoolState to compute price + protected computePrices( + srcTokenAddress: Address, + srcTokenDecimals: number, + destTokenAddress: Address, + destTokenDecimals: number, + amounts: bigint[], + state: DeepReadonly, + ): bigint[] { + return amounts.map(fromAmount => { + return quoteFrom( + state.asset[srcTokenAddress].cash, + state.asset[srcTokenAddress].cash, + state.asset[destTokenAddress].liability, + state.asset[destTokenAddress].liability, + fromAmount, + state.params.ampFactor, + state.params.haircutRate, + ); + }); } protected findPools( From 8faabbdfed66bed113e6b2bdee47f7a6994e7c01 Mon Sep 17 00:00:00 2001 From: shinji-wombat Date: Fri, 13 Jan 2023 13:46:07 +0800 Subject: [PATCH 008/833] handle swap deposit and withdraw --- src/dex/wombat/types.ts | 2 - src/dex/wombat/wombat-pool.ts | 200 ++++++++++++++++++++++++++++++---- 2 files changed, 178 insertions(+), 24 deletions(-) diff --git a/src/dex/wombat/types.ts b/src/dex/wombat/types.ts index 809550a10..299dec08e 100644 --- a/src/dex/wombat/types.ts +++ b/src/dex/wombat/types.ts @@ -1,5 +1,4 @@ import { Address } from '../../types'; -import { ChainLinkState } from '../../lib/chainlink'; // State-related types @@ -9,7 +8,6 @@ export type PoolState = { // set of parameters required to compute // pool prices. params: PoolParams; - chainlink: { [underlyingAddress: string]: ChainLinkState }; underlyingAddresses: Address[]; asset: { [underlyingAddress: string]: AssetState }; }; diff --git a/src/dex/wombat/wombat-pool.ts b/src/dex/wombat/wombat-pool.ts index 00e9b519f..7fcf0e627 100644 --- a/src/dex/wombat/wombat-pool.ts +++ b/src/dex/wombat/wombat-pool.ts @@ -1,12 +1,23 @@ import { Interface } from '@ethersproject/abi'; import { DeepReadonly } from 'ts-essentials'; -import { Log, Logger } from '../../types'; +import { + Address, + Log, + Logger, + MultiCallInput, + MultiCallOutput, +} from '../../types'; import { catchParseLogError } from '../../utils'; import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; import { IDexHelper } from '../../dex-helper/idex-helper'; -import { PoolState } from './types'; +import { PoolState, WombatPoolConfigInfo } from './types'; +import PoolABI from '../../abi/wombat/pool.json'; +import AssetABI from '../../abi/wombat/asset.json'; export class WombatEventPool extends StatefulEventSubscriber { + static readonly poolInterface = new Interface(PoolABI); + static readonly assetInterface = new Interface(AssetABI); + handlers: { [event: string]: ( event: any, @@ -17,28 +28,45 @@ export class WombatEventPool extends StatefulEventSubscriber { logDecoder: (log: Log) => any; - addressesSubscribed: string[]; - + blankState: PoolState = { + asset: {}, + underlyingAddresses: [], + params: { + ampFactor: 0n, + haircutRate: 0n, + }, + }; constructor( - parentName: string, + dexKey: string, + name: string, protected network: number, protected dexHelper: IDexHelper, logger: Logger, - protected wombatIface = new Interface( - '' /* TODO: Import and put here Wombat ABI */, - ), // TODO: add any additional params required for event subscriber + protected poolAddress: Address, + protected poolCfg: WombatPoolConfigInfo, ) { - // TODO: fix arguments for super() - super(parentName, '', dexHelper, logger); + super( + `${dexKey} ${name}`, + `${dexKey}-${network} ${name}`, + dexHelper, + logger, + ); + + this.logDecoder = (log: Log) => WombatEventPool.poolInterface.parseLog(log); + + // users-actions handlers + this.handlers['Deposit'] = this.handleDeposit.bind(this); + this.handlers['Withdraw'] = this.handleWithdraw.bind(this); + this.handlers['Swap'] = this.handleSwap.bind(this); - // TODO: make logDecoder decode logs that - this.logDecoder = (log: Log) => this.wombatIface.parseLog(log); - this.addressesSubscribed = [ - /* subscribed addresses */ - ]; + // admin-actions handlers + /** @todo handle dynamically updating params */ + // this.handlers['SetAmpFactor'] = this.handleDeposit.bind(this); + // this.handlers['SetHaircutRate'] = this.handleDeposit.bind(this); - // Add handlers - this.handlers['myEvent'] = this.handleMyEvent.bind(this); + /** @todo handle dynamically adding/removing assets */ + // this.handlers['AssetAdded'] = this.handleAssetAdded.bind(this); + // this.handlers['AssetRemoved'] = this.handleAssetRemoved.bind(this); } /** @@ -76,16 +104,144 @@ export class WombatEventPool extends StatefulEventSubscriber { * @returns state of the event subscriber at blocknumber */ async generateState(blockNumber: number): Promise> { - // TODO: complete me! - return {}; + // const multiCallInputs = this.getGenerateStateMultiCallInputs(); + + // 1. Generate multiCallInputs + const multiCallInputs: MultiCallInput[] = []; + // 1 A. pool params + // ampFactor + multiCallInputs.push({ + target: this.poolAddress, + callData: WombatEventPool.poolInterface.encodeFunctionData('ampFactor'), + }); + // haircutRate + multiCallInputs.push({ + target: this.poolAddress, + callData: WombatEventPool.poolInterface.encodeFunctionData('haircutRate'), + }); + + // 1 B. asset state: cash and liability + for (const tokenInfo of Object.values(this.poolCfg.tokens)) { + multiCallInputs.push({ + target: tokenInfo.assetAddress, + callData: WombatEventPool.assetInterface.encodeFunctionData('cash'), + }); + multiCallInputs.push({ + target: tokenInfo.assetAddress, + callData: + WombatEventPool.assetInterface.encodeFunctionData('liability'), + }); + } + + // 2. Decode MultiCallOutput + let returnData: MultiCallOutput[] = []; + if (multiCallInputs.length) { + returnData = ( + await this.dexHelper.multiContract.methods + .aggregate(multiCallInputs) + .call({}, blockNumber) + ).returnData; + } + + let i = 0; + // 2 A. decode pool params + const ampFactor = WombatEventPool.poolInterface.decodeFunctionResult( + 'ampFactor', + returnData[i++], + )[0]; + const haircutRate = WombatEventPool.poolInterface.decodeFunctionResult( + 'haircutRate', + returnData[i++], + )[0]; + const poolState: PoolState = { + params: { + ampFactor, + haircutRate, + }, + underlyingAddresses: [], + asset: {}, + }; + // 2 B. decode asset state: cash and liability + for (const [tokenAddress, tokenInfo] of Object.entries( + this.poolCfg.tokens, + )) { + const cash = WombatEventPool.assetInterface.decodeFunctionResult( + 'cash', + returnData[i++], + )[0]; + const liability = WombatEventPool.assetInterface.decodeFunctionResult( + 'liability', + returnData[i++], + )[0]; + poolState.underlyingAddresses.push(tokenAddress); + poolState.asset[tokenAddress] = { + cash, + liability, + }; + } + return poolState; } - // Its just a dummy example - handleMyEvent( + handleDeposit( event: any, state: DeepReadonly, log: Readonly, ): DeepReadonly | null { - return null; + const amountAdded = BigInt(event.args.amount.toString()); + const tokenAddress = event.args.token.toString(); + + return { + ...state, + asset: { + ...state.asset, + [tokenAddress]: { + cash: state.asset[tokenAddress].cash + amountAdded, + liability: state.asset[tokenAddress].liability + amountAdded, + }, + }, + }; + } + handleWithdraw( + event: any, + state: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + const amountWithdrew = BigInt(event.args.amount.toString()); + const tokenAddress = event.args.token.toString(); + + return { + ...state, + asset: { + ...state.asset, + [tokenAddress]: { + cash: state.asset[tokenAddress].cash - amountWithdrew, + liability: state.asset[tokenAddress].liability - amountWithdrew, + }, + }, + }; + } + + handleSwap( + event: any, + state: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + const fromTokenAddress = event.args.fromToken.toString(); + const fromAmount = BigInt(event.args.fromAmount.toString()); + const toTokenAddress = event.args.toToken.toString(); + const toAmount = BigInt(event.args.toAmount.toString()); + + return { + ...state, + asset: { + ...state.asset, + [fromTokenAddress]: { + cash: state.asset[fromTokenAddress].cash + fromAmount, + }, + [toTokenAddress]: { + cash: state.asset[toTokenAddress].cash - toAmount, + }, + }, + }; } } From 2414aef5bc0ab7ed688b8ac7c2ac13d6cc47d116 Mon Sep 17 00:00:00 2001 From: shinji-wombat Date: Tue, 17 Jan 2023 08:29:22 +0800 Subject: [PATCH 009/833] update ABI --- src/abi/wombat/asset.json | 10 ------ src/abi/wombat/pool.json | 70 --------------------------------------- 2 files changed, 80 deletions(-) diff --git a/src/abi/wombat/asset.json b/src/abi/wombat/asset.json index d68fe0b89..9f551aa55 100644 --- a/src/abi/wombat/asset.json +++ b/src/abi/wombat/asset.json @@ -20,16 +20,6 @@ "stateMutability": "nonpayable", "type": "constructor" }, - { - "inputs": [], - "name": "ASSET_OVERFLOW", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_FORBIDDEN", - "type": "error" - }, { "anonymous": false, "inputs": [ diff --git a/src/abi/wombat/pool.json b/src/abi/wombat/pool.json index 64eed2a67..657c631ce 100644 --- a/src/abi/wombat/pool.json +++ b/src/abi/wombat/pool.json @@ -1,74 +1,4 @@ [ - { - "inputs": [], - "name": "CORE_UNDERFLOW", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_AMOUNT_TOO_LOW", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ASSET_ALREADY_EXIST", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ASSET_ALREADY_PAUSED", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ASSET_NOT_EXISTS", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ASSET_NOT_PAUSED", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_CASH_NOT_ENOUGH", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_EXPIRED", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_FORBIDDEN", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_INVALID_VALUE", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_SAME_ADDRESS", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ZERO_ADDRESS", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ZERO_AMOUNT", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ZERO_LIQUIDITY", - "type": "error" - }, { "anonymous": false, "inputs": [ From 73b207dbe3fc487d8257187f360f093b619d6b7e Mon Sep 17 00:00:00 2001 From: shinji-wombat Date: Tue, 17 Jan 2023 08:30:00 +0800 Subject: [PATCH 010/833] use lowercase for pool address --- src/dex/wombat/wombat-events.test.ts | 114 ++++++++++++++++----------- src/dex/wombat/wombat.ts | 6 +- 2 files changed, 71 insertions(+), 49 deletions(-) diff --git a/src/dex/wombat/wombat-events.test.ts b/src/dex/wombat/wombat-events.test.ts index 1c4692079..6655ee296 100644 --- a/src/dex/wombat/wombat-events.test.ts +++ b/src/dex/wombat/wombat-events.test.ts @@ -1,13 +1,19 @@ import dotenv from 'dotenv'; dotenv.config(); +import { DeepReadonly } from 'ts-essentials'; import { WombatEventPool } from './wombat-pool'; import { Network } from '../../constants'; import { Address } from '../../types'; import { DummyDexHelper } from '../../dex-helper/index'; -import { testEventSubscriber } from '../../../tests/utils-events'; -import { PoolState } from './types'; - +import { + testEventSubscriber, + getSavedConfig, + saveConfig, +} from '../../../tests/utils-events'; +import { PoolState, WombatConfigInfo } from './types'; +import { WombatConfig } from './config'; +import { Wombat } from './wombat'; /* README ====== @@ -41,65 +47,79 @@ import { PoolState } from './types'; (This comment should be removed from the final implementation) */ -jest.setTimeout(50 * 1000); +// npx jest src/dex/wombat/wombat-events.test.ts +jest.setTimeout(100 * 1000); async function fetchPoolState( - wombatPools: WombatEventPool, + wombatPool: WombatEventPool, blockNumber: number, - poolAddress: string, -): Promise { - // TODO: complete me! - return {}; +): Promise> { + return await wombatPool.generateState(blockNumber); } // eventName -> blockNumbers type EventMappings = Record; -describe('Wombat EventPool Mainnet', function () { +describe('Wombat EventPool BSC', function () { const dexKey = 'Wombat'; - const network = Network.MAINNET; + const network = Network.BSC; const dexHelper = new DummyDexHelper(network); const logger = dexHelper.getLogger(dexKey); let wombatPool: WombatEventPool; - + const mainPoolAddress = WombatConfig.Wombat[Network.BSC].pools[0].address; // poolAddress -> EventMappings const eventsToTest: Record = { - // TODO: complete me! + // Main pool + [mainPoolAddress]: { + Deposit: [22764190], + // Deposit: [24764190], + }, }; - beforeEach(async () => { - wombatPool = new WombatEventPool( - dexKey, - network, - dexHelper, - logger, - /* TODO: Put here additional constructor arguments if needed */ - ); - }); - - Object.entries(eventsToTest).forEach( - ([poolAddress, events]: [string, EventMappings]) => { - describe(`Events for ${poolAddress}`, () => { - Object.entries(events).forEach( - ([eventName, blockNumbers]: [string, number[]]) => { - describe(`${eventName}`, () => { - blockNumbers.forEach((blockNumber: number) => { - it(`State after ${blockNumber}`, async function () { - await testEventSubscriber( - wombatPool, - wombatPool.addressesSubscribed, - (_blockNumber: number) => - fetchPoolState(wombatPool, _blockNumber, poolAddress), - blockNumber, - `${dexKey}_${poolAddress}`, - dexHelper.provider, - ); - }); - }); + for (const [poolAddress, events] of Object.entries(eventsToTest)) { + describe(`Events for ${poolAddress}`, () => { + for (const [eventName, blockNumbers] of Object.entries(events)) { + describe(`${eventName}`, () => { + for (const blockNumber of blockNumbers) { + it(`State after ${blockNumber}`, async function () { + let cfgInfo = getSavedConfig( + blockNumber, + dexKey, + ); + + cfgInfo = undefined; + if (!cfgInfo) { + const dex = new Wombat(network, dexKey, dexHelper); + cfgInfo = await dex.generateConfigInfo(blockNumber); + saveConfig(blockNumber, dexKey, cfgInfo); + } + + wombatPool = new WombatEventPool( + dexKey, + 'Main Pool', + network, + dexHelper, + logger, + poolAddress.toLowerCase(), + cfgInfo.pools[poolAddress.toLowerCase()], + ); + + await testEventSubscriber( + wombatPool, + wombatPool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolState(wombatPool, _blockNumber), + blockNumber, + `${dexKey}_${poolAddress}`, + dexHelper.provider, + ); }); - }, - ); - }); - }, - ); + // }); + } + }); + } + // ); + }); + } + // ); }); diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index fde345f21..f05fed12b 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -93,7 +93,7 @@ export class Wombat extends SimpleExchange implements IDex { for (const poolAddress of cfgInfo.poolAddresses) { const tokenAddresses = Wombat.poolInterface .decodeFunctionResult('getTokens', returnData[i++])[0] - .toLowerCase(); + .map((s: string): string => s.toLowerCase()); cfgInfo.pools[poolAddress] = { tokenAddresses, tokens: {}, @@ -139,7 +139,9 @@ export class Wombat extends SimpleExchange implements IDex { const assetAddress = Wombat.poolInterface .decodeFunctionResult('addressOfAsset', returnData[i++])[0] .toLowerCase(); - cfgInfo.pools[poolAddress].tokens[tokenAddress] = { + cfgInfo.pools[poolAddress.toLowerCase()].tokens[ + tokenAddress.toLowerCase() + ] = { tokenSymbol, tokenDecimals, assetAddress, From 0d55b8110aa40e6be02f160d32cfeeaad8806900 Mon Sep 17 00:00:00 2001 From: ftm1337 <84405345+ftm1337@users.noreply.github.com> Date: Mon, 23 Jan 2023 11:15:09 -0500 Subject: [PATCH 011/833] add solidly fork: equalizer --- src/dex/solidly/forks-override/equalizer.ts | 58 +++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/dex/solidly/forks-override/equalizer.ts diff --git a/src/dex/solidly/forks-override/equalizer.ts b/src/dex/solidly/forks-override/equalizer.ts new file mode 100644 index 000000000..ee9531e64 --- /dev/null +++ b/src/dex/solidly/forks-override/equalizer.ts @@ -0,0 +1,58 @@ +import { Solidly } from '../solidly'; +import { SolidlyPair } from '../types'; +import { Network } from '../../../constants'; +import { IDexHelper } from '../../../dex-helper'; +import { Interface } from '@ethersproject/abi'; +import { getDexKeysWithNetwork } from '../../../utils'; +import { SolidlyConfig } from '../config'; +import _ from 'lodash'; + +const EqualizerFactoryABI = [ + { + inputs: [{ internalType: 'bool', name: '_stable', type: 'bool' }], + name: 'getFee', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, +]; + +const equalizerFactoryIface = new Interface(EqualizerFactoryABI); + +export class Equalizer extends Solidly { + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(_.pick(SolidlyConfig, ['Equalizer'])); + + constructor( + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + ) { + super( + network, + dexKey, + dexHelper, + true, // dynamic fees + ); + } + + protected getFeesMultiCallData(pair: SolidlyPair) { + const callEntry = { + target: this.factoryAddress, + callData: equalizerFactoryIface.encodeFunctionData('getFee', [ + pair.stable, + ]), + }; + const callDecoder = (values: any[]) => + parseInt( + equalizerFactoryIface + .decodeFunctionResult('getFee', values)[0] + .toString(), + ); + + return { + callEntry, + callDecoder, + }; + } +} From e8ef680257115ac5fa6c1aa3e5d9f8a0decc2cb7 Mon Sep 17 00:00:00 2001 From: ftm1337 <84405345+ftm1337@users.noreply.github.com> Date: Mon, 23 Jan 2023 11:33:36 -0500 Subject: [PATCH 012/833] Equalizer --- src/dex/solidly/config.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index acff06d0e..33d7f5ccc 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -72,6 +72,21 @@ export const SolidlyConfig: DexConfigMap = { feeCode: 0, // variable }, }, + Equalizer: { + [Network.FANTOM]: { + subgraphURL: '',//'https://api.thegraph.com/subgraphs/name/ftm1337/equalizer-subgraph-1',//inactive + factoryAddress: '0xc6366EFD0AF1d09171fe0EBF32c7943BB310832a', + router: '0x1A05EB736873485655F29a37DEf8a0AA87F5a447', + initCode: + '0x02ada2a0163cd4f7e0f0c9805f5230716a95b174140e4c84c14883de216cc6a3', + // updatable fees on the factory without event + //stableFee: 2, + //volatileFee: 20, + //feeCode: 2, + feeCode: 0, // variable + poolGasCost: 180 * 1000, + }, + }, }; export const Adapters: Record = { @@ -79,7 +94,7 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'PolygonAdapter02', index: 3 }], // dystopia }, [Network.FANTOM]: { - [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 10 }], // solidly + spiritSwapV2 + [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 10 }], // solidly + spiritSwapV2 + Equalizer }, [Network.OPTIMISM]: { [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 8 }], // velodrome From 099723d01164e6e524b93e62e9810f99155d73ac Mon Sep 17 00:00:00 2001 From: ftm1337 <84405345+ftm1337@users.noreply.github.com> Date: Mon, 23 Jan 2023 11:37:38 -0500 Subject: [PATCH 013/833] Add Equalizer --- src/dex/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dex/index.ts b/src/dex/index.ts index 30e32623b..944d0b21a 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -46,6 +46,7 @@ import { Velodrome } from './solidly/forks-override/velodrome'; import { SpiritSwapV2 } from './solidly/forks-override/spiritSwapV2'; import { Synthetix } from './synthetix/synthetix'; import { Cone } from './solidly/forks-override/cone'; +import { Equalizer } from './solidly/forks-override/equalizer'; import { QuickSwapV3 } from './quickswap-v3'; import { BalancerV1 } from './balancer-v1/balancer-v1'; import { balancerV1Merge } from './balancer-v1/optimizer'; @@ -105,6 +106,7 @@ const Dexes = [ SpiritSwapV2, Velodrome, Cone, + Equalizer, Synthetix, CurveV1Factory, SwaapV1, From 2d21c80bbcd79373019f23915159d3945c169aa6 Mon Sep 17 00:00:00 2001 From: ftm1337 <84405345+ftm1337@users.noreply.github.com> Date: Mon, 23 Jan 2023 11:46:29 -0500 Subject: [PATCH 014/833] Add Equalizer --- src/dex/solidly/solidly.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/solidly/solidly.ts b/src/dex/solidly/solidly.ts index 68475e380..2254b02c3 100644 --- a/src/dex/solidly/solidly.ts +++ b/src/dex/solidly/solidly.ts @@ -64,7 +64,7 @@ export class Solidly extends UniswapV2 { public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork( - _.omit(SolidlyConfig, ['Velodrome', 'SpiritSwapV2', 'Cone']), + _.omit(SolidlyConfig, ['Velodrome', 'SpiritSwapV2', 'Cone', 'Equalizer']), ); constructor( From 0c6fb5e856fa69a6bc51322587a6ec7f00f03fe1 Mon Sep 17 00:00:00 2001 From: Alexander Petrovich Date: Thu, 30 Mar 2023 13:45:51 +0400 Subject: [PATCH 015/833] add nomiswap-v2 dex --- src/abi/nomiswap-v2/nomiswap-v2-pool.json | 773 ++++++++++++++++++ src/dex/index.ts | 2 + src/dex/uniswap-v2/nomiswap-v2.ts | 61 ++ src/dex/uniswap-v2/uniswap-v2-e2e-bsc.test.ts | 146 ++++ 4 files changed, 982 insertions(+) create mode 100644 src/abi/nomiswap-v2/nomiswap-v2-pool.json create mode 100644 src/dex/uniswap-v2/nomiswap-v2.ts diff --git a/src/abi/nomiswap-v2/nomiswap-v2-pool.json b/src/abi/nomiswap-v2/nomiswap-v2-pool.json new file mode 100644 index 000000000..98740664d --- /dev/null +++ b/src/abi/nomiswap-v2/nomiswap-v2-pool.json @@ -0,0 +1,773 @@ +[ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "Burn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0In", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1In", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount0Out", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount1Out", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "Swap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint112", + "name": "reserve0", + "type": "uint112" + }, + { + "indexed": false, + "internalType": "uint112", + "name": "reserve1", + "type": "uint112" + } + ], + "name": "Sync", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MINIMUM_LIQUIDITY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "PERMIT_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "devFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "kLast", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "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": "permit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "price0CumulativeLast", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "price1CumulativeLast", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "swapFee", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "token0", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "token1", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getReserves", + "outputs": [ + { + "internalType": "uint112", + "name": "_reserve0", + "type": "uint112" + }, + { + "internalType": "uint112", + "name": "_reserve1", + "type": "uint112" + }, + { + "internalType": "uint32", + "name": "_blockTimestampLast", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_token0", + "type": "address" + }, + { + "internalType": "address", + "name": "_token1", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint32", + "name": "_swapFee", + "type": "uint32" + } + ], + "name": "setSwapFee", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_devFee", + "type": "uint256" + } + ], + "name": "setDevFee", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount0Out", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1Out", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "swap", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "skim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "sync", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/dex/index.ts b/src/dex/index.ts index bf5f53d52..aa03d24f5 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -62,6 +62,7 @@ import { MaverickV1 } from './maverick-v1/maverick-v1'; import { QuickSwapV3 } from './quickswap/quickswap-v3'; import { ZyberSwapV3 } from './quickswap/zyberswap-v3'; import { TraderJoeV2 } from './trader-joe-v2'; +import { NomiswapV2 } from './uniswap-v2/nomiswap-v2'; const LegacyDexes = [ CurveV2, @@ -121,6 +122,7 @@ const Dexes = [ Hashflow, MaverickV1, Camelot, + NomiswapV2, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< diff --git a/src/dex/uniswap-v2/nomiswap-v2.ts b/src/dex/uniswap-v2/nomiswap-v2.ts new file mode 100644 index 000000000..94ae0d7c0 --- /dev/null +++ b/src/dex/uniswap-v2/nomiswap-v2.ts @@ -0,0 +1,61 @@ +import { Network } from '../../constants'; +import { getDexKeysWithNetwork } from '../../utils'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { UniswapV2, UniswapV2Pair } from '../uniswap-v2/uniswap-v2'; +import { Interface } from '@ethersproject/abi'; +import NomiswapPoolABI from '../../abi/nomiswap-v2/nomiswap-v2-pool.json'; +import { DexParams } from './types'; +import { DexConfigMap } from '../../types'; + +export const NomiswapV2Config: DexConfigMap = { + NomiswapV2: { + [Network.BSC]: { + factoryAddress: '0xd6715A8be3944ec72738F0BFDC739d48C3c29349', + initCode: + '0x83eb759f5ea0525124f03d4ac741bb4af0bb1c703d5f694bd42a8bd72e495a01', + poolGasCost: 120 * 1000, + feeCode: 0, // this is ignored as Nomiswap uses dynamic fees + }, + }, +}; + +export class NomiswapV2 extends UniswapV2 { + nomiswapPool: Interface; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(NomiswapV2Config); + + constructor( + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + ) { + super( + network, + dexKey, + dexHelper, + true, + NomiswapV2Config[dexKey][network].factoryAddress, + NomiswapV2Config[dexKey][network].subgraphURL, + NomiswapV2Config[dexKey][network].initCode, + NomiswapV2Config[dexKey][network].feeCode, + NomiswapV2Config[dexKey][network].poolGasCost, + ); + this.nomiswapPool = new Interface(NomiswapPoolABI); + } + + protected getFeesMultiCallData(pair: UniswapV2Pair) { + const callEntry = { + target: pair.exchange!, + callData: this.nomiswapPool.encodeFunctionData('swapFee', []), + }; + const callDecoder = (values: any[]) => + parseInt( + this.nomiswapPool.decodeFunctionResult('swapFee', values)[0].toString(), + ) * 10; + return { + callEntry, + callDecoder, + }; + } +} diff --git a/src/dex/uniswap-v2/uniswap-v2-e2e-bsc.test.ts b/src/dex/uniswap-v2/uniswap-v2-e2e-bsc.test.ts index ff7a66013..24d23a214 100644 --- a/src/dex/uniswap-v2/uniswap-v2-e2e-bsc.test.ts +++ b/src/dex/uniswap-v2/uniswap-v2-e2e-bsc.test.ts @@ -1407,6 +1407,152 @@ describe('UniswapV2 E2E BSC', () => { }); }); + describe('NomiswapV2', () => { + const dexKey = 'NomiswapV2'; + + describe('Simpleswap', () => { + it('BNB -> TOKEN', async () => { + await testE2E( + tokens.BNB, + tokens.USDT, + holders.BNB, + '100000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + it('Token -> TOKEN', async () => { + await testE2E( + tokens.USDT, + tokens.USDC, + holders.USDT, + '1000000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + it('Token -> BNB', async () => { + await testE2E( + tokens.USDT, + tokens.BNB, + holders.USDT, + '1000000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + }); + + describe('BUY', () => { + it('BNB -> TOKEN', async () => { + await testE2E( + tokens.BNB, + tokens.USDT, + holders.BNB, + '100000000000000000000', + SwapSide.BUY, + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + it('Token -> TOKEN', async () => { + await testE2E( + tokens.USDT, + tokens.USDC, + holders.USDT, + '1000000000000000000000', + SwapSide.BUY, + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + it('Token -> BNB', async () => { + await testE2E( + tokens.BUSD, + tokens.BNB, + holders.BUSD, + '10000000000000000000', + SwapSide.BUY, + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + }); + + describe('Multiswap', () => { + it('BNB -> TOKEN', async () => { + await testE2E( + tokens.BNB, + tokens.USDT, + holders.BNB, + '100000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.multiSwap, + network, + provider, + ); + }); + it('Token -> TOKEN', async () => { + await testE2E( + tokens.USDT, + tokens.USDC, + holders.USDT, + '1000000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.multiSwap, + network, + provider, + ); + }); + it('Token -> BNB', async () => { + await testE2E( + tokens.USDT, + tokens.BNB, + holders.USDT, + '1000000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.multiSwap, + network, + provider, + ); + }); + }); + + describe('Megapath', () => { + it('Token -> TOKEN', async () => { + await testE2E( + tokens.USDT, + tokens.USDC, + holders.USDT, + '1000000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.megaSwap, + network, + provider, + ); + }); + }); + }); + describe(`Swapsicle`, () => { const dexKey = 'Swapsicle'; From bf99648ed047441d7da6a3e3ed487255b20e99e2 Mon Sep 17 00:00:00 2001 From: Alexander Petrovich Date: Fri, 21 Apr 2023 15:23:38 +0400 Subject: [PATCH 016/833] add nomiswap-v2 subgraph url --- src/dex/uniswap-v2/nomiswap-v2.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dex/uniswap-v2/nomiswap-v2.ts b/src/dex/uniswap-v2/nomiswap-v2.ts index 94ae0d7c0..116f08c96 100644 --- a/src/dex/uniswap-v2/nomiswap-v2.ts +++ b/src/dex/uniswap-v2/nomiswap-v2.ts @@ -14,7 +14,8 @@ export const NomiswapV2Config: DexConfigMap = { initCode: '0x83eb759f5ea0525124f03d4ac741bb4af0bb1c703d5f694bd42a8bd72e495a01', poolGasCost: 120 * 1000, - feeCode: 0, // this is ignored as Nomiswap uses dynamic fees + feeCode: 0, // this is ignored as Nomiswap uses dynamic fees, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/nominex/nomiswap-exchange-subgraph', }, }, }; From 1456ff0191b1d0250948efa9201df385c4327836 Mon Sep 17 00:00:00 2001 From: Pabheto Date: Tue, 9 May 2023 02:29:59 +0200 Subject: [PATCH 017/833] Integration of chronos.exchange --- src/dex/uniswap-v2/config.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/dex/uniswap-v2/config.ts b/src/dex/uniswap-v2/config.ts index f05e832f3..18c0218c1 100644 --- a/src/dex/uniswap-v2/config.ts +++ b/src/dex/uniswap-v2/config.ts @@ -686,4 +686,13 @@ export const UniswapV2Config: DexConfigMap = { feeCode: 30, }, }, + Chronos: { + [Network.ARBITRUM]: { + subgraphURL: 'https://api.thegraph.com/subgraphs/name/xliee/chronos', + factoryAddress: '0xce9240869391928253ed9cc9bcb8cb98cb5b0722', + initCode: + '0x5abbc2a893de2e0c13e13a387327e28bf31b9b2babc3c60dbe14ccb4c538a9cd', + feeCode: 30, + }, + }, }; From 5357141b5693ef6a7d340dd7184332e42ea76d11 Mon Sep 17 00:00:00 2001 From: Pabheto Date: Fri, 26 May 2023 01:52:24 +0200 Subject: [PATCH 018/833] Integrated Chronos Solidly Pools --- package.json | 1 + scripts/dex-integration.ts | 2 +- src/dex/uniswap-v2/config.ts | 9 - yarn.lock | 635 ++++++++++++++++++++++++++++++++++- 4 files changed, 636 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index d6141830a..82c2e1768 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "cross-fetch": "^3.1.5", "es6-promise": "^4.2.8", "ethers": "^5.6.5", + "jest-cli": "^29.5.0", "joi": "^17.7.0", "lens.ts": "^0.5.1", "lodash": "4.17.21", diff --git a/scripts/dex-integration.ts b/scripts/dex-integration.ts index e3487e690..2604166f3 100644 --- a/scripts/dex-integration.ts +++ b/scripts/dex-integration.ts @@ -116,7 +116,7 @@ function testIntegration(argv: IOptions) { process.env.NODE_ENV = 'test'; } - require('../node_modules/jest-cli/build/cli').run( + require('../node_modules/jest-cli/bin/jest.js').run( `src\/dex\/${dexNameParam}\/.+\.test\.ts`, ); } diff --git a/src/dex/uniswap-v2/config.ts b/src/dex/uniswap-v2/config.ts index 6bbcfb306..4c4399048 100644 --- a/src/dex/uniswap-v2/config.ts +++ b/src/dex/uniswap-v2/config.ts @@ -687,13 +687,4 @@ export const UniswapV2Config: DexConfigMap = { feeCode: 30, }, }, - Chronos: { - [Network.ARBITRUM]: { - subgraphURL: 'https://api.thegraph.com/subgraphs/name/xliee/chronos', - factoryAddress: '0xce9240869391928253ed9cc9bcb8cb98cb5b0722', - initCode: - '0x5abbc2a893de2e0c13e13a387327e28bf31b9b2babc3c60dbe14ccb4c538a9cd', - feeCode: 30, - }, - }, }; diff --git a/yarn.lock b/yarn.lock index 55c64de81..5f155d883 100644 --- a/yarn.lock +++ b/yarn.lock @@ -886,6 +886,18 @@ jest-util "^29.2.1" slash "^3.0.0" +"@jest/console@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.5.0.tgz#593a6c5c0d3f75689835f1b3b4688c4f8544cb57" + integrity sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ== + dependencies: + "@jest/types" "^29.5.0" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.5.0" + jest-util "^29.5.0" + slash "^3.0.0" + "@jest/core@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.2.1.tgz#30af794ebd73bfb87cd8ba36718738dfe38b772e" @@ -920,6 +932,40 @@ slash "^3.0.0" strip-ansi "^6.0.0" +"@jest/core@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.5.0.tgz#76674b96904484e8214614d17261cc491e5f1f03" + integrity sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ== + dependencies: + "@jest/console" "^29.5.0" + "@jest/reporters" "^29.5.0" + "@jest/test-result" "^29.5.0" + "@jest/transform" "^29.5.0" + "@jest/types" "^29.5.0" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.5.0" + jest-config "^29.5.0" + jest-haste-map "^29.5.0" + jest-message-util "^29.5.0" + jest-regex-util "^29.4.3" + jest-resolve "^29.5.0" + jest-resolve-dependencies "^29.5.0" + jest-runner "^29.5.0" + jest-runtime "^29.5.0" + jest-snapshot "^29.5.0" + jest-util "^29.5.0" + jest-validate "^29.5.0" + jest-watcher "^29.5.0" + micromatch "^4.0.4" + pretty-format "^29.5.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + "@jest/environment@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.2.1.tgz#acb1994fbd5ad02819a1a34a923c531e6923b665" @@ -930,6 +976,16 @@ "@types/node" "*" jest-mock "^29.2.1" +"@jest/environment@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.5.0.tgz#9152d56317c1fdb1af389c46640ba74ef0bb4c65" + integrity sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ== + dependencies: + "@jest/fake-timers" "^29.5.0" + "@jest/types" "^29.5.0" + "@types/node" "*" + jest-mock "^29.5.0" + "@jest/expect-utils@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.2.1.tgz#eae61c90f2066540f60d23b8f254f03b7869b22f" @@ -937,6 +993,13 @@ dependencies: jest-get-type "^29.2.0" +"@jest/expect-utils@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.5.0.tgz#f74fad6b6e20f924582dc8ecbf2cb800fe43a036" + integrity sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg== + dependencies: + jest-get-type "^29.4.3" + "@jest/expect@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.2.1.tgz#8d99be3886ebfcffd6cabb2b46602a301b976ffe" @@ -945,6 +1008,14 @@ expect "^29.2.1" jest-snapshot "^29.2.1" +"@jest/expect@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.5.0.tgz#80952f5316b23c483fbca4363ce822af79c38fba" + integrity sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g== + dependencies: + expect "^29.5.0" + jest-snapshot "^29.5.0" + "@jest/fake-timers@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.2.1.tgz#786d60e8cb60ca70c9f913cb49fcc77610c072bb" @@ -957,6 +1028,18 @@ jest-mock "^29.2.1" jest-util "^29.2.1" +"@jest/fake-timers@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.5.0.tgz#d4d09ec3286b3d90c60bdcd66ed28d35f1b4dc2c" + integrity sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg== + dependencies: + "@jest/types" "^29.5.0" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.5.0" + jest-mock "^29.5.0" + jest-util "^29.5.0" + "@jest/globals@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.2.1.tgz#6933beb8b4e43b990409a19c462fde7b71210e63" @@ -967,6 +1050,16 @@ "@jest/types" "^29.2.1" jest-mock "^29.2.1" +"@jest/globals@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.5.0.tgz#6166c0bfc374c58268677539d0c181f9c1833298" + integrity sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ== + dependencies: + "@jest/environment" "^29.5.0" + "@jest/expect" "^29.5.0" + "@jest/types" "^29.5.0" + jest-mock "^29.5.0" + "@jest/reporters@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.2.1.tgz#599e4376823751fdda50f2ca97243e013da10c4d" @@ -997,6 +1090,36 @@ strip-ansi "^6.0.0" v8-to-istanbul "^9.0.1" +"@jest/reporters@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.5.0.tgz#985dfd91290cd78ddae4914ba7921bcbabe8ac9b" + integrity sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.5.0" + "@jest/test-result" "^29.5.0" + "@jest/transform" "^29.5.0" + "@jest/types" "^29.5.0" + "@jridgewell/trace-mapping" "^0.3.15" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^5.1.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.5.0" + jest-util "^29.5.0" + jest-worker "^29.5.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + "@jest/schemas@^29.0.0": version "29.0.0" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a" @@ -1004,6 +1127,13 @@ dependencies: "@sinclair/typebox" "^0.24.1" +"@jest/schemas@^29.4.3": + version "29.4.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.3.tgz#39cf1b8469afc40b6f5a2baaa146e332c4151788" + integrity sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg== + dependencies: + "@sinclair/typebox" "^0.25.16" + "@jest/source-map@^29.2.0": version "29.2.0" resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.2.0.tgz#ab3420c46d42508dcc3dc1c6deee0b613c235744" @@ -1013,6 +1143,15 @@ callsites "^3.0.0" graceful-fs "^4.2.9" +"@jest/source-map@^29.4.3": + version "29.4.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.4.3.tgz#ff8d05cbfff875d4a791ab679b4333df47951d20" + integrity sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.15" + callsites "^3.0.0" + graceful-fs "^4.2.9" + "@jest/test-result@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.2.1.tgz#f42dbf7b9ae465d0a93eee6131473b8bb3bd2edb" @@ -1023,6 +1162,16 @@ "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" +"@jest/test-result@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.5.0.tgz#7c856a6ca84f45cc36926a4e9c6b57f1973f1408" + integrity sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ== + dependencies: + "@jest/console" "^29.5.0" + "@jest/types" "^29.5.0" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + "@jest/test-sequencer@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.2.1.tgz#cafd2c5f3528c70bd4cc243800459ac366e480cc" @@ -1033,6 +1182,16 @@ jest-haste-map "^29.2.1" slash "^3.0.0" +"@jest/test-sequencer@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz#34d7d82d3081abd523dbddc038a3ddcb9f6d3cc4" + integrity sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ== + dependencies: + "@jest/test-result" "^29.5.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.5.0" + slash "^3.0.0" + "@jest/transform@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.2.1.tgz#f3d8154edd19cdbcaf1d6646bd8f4ff7812318a2" @@ -1054,6 +1213,27 @@ slash "^3.0.0" write-file-atomic "^4.0.1" +"@jest/transform@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.5.0.tgz#cf9c872d0965f0cbd32f1458aa44a2b1988b00f9" + integrity sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.5.0" + "@jridgewell/trace-mapping" "^0.3.15" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.5.0" + jest-regex-util "^29.4.3" + jest-util "^29.5.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + "@jest/types@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" @@ -1077,6 +1257,18 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" +"@jest/types@^29.5.0": + version "29.5.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.5.0.tgz#f59ef9b031ced83047c67032700d8c807d6e1593" + integrity sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog== + dependencies: + "@jest/schemas" "^29.4.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" @@ -1516,6 +1708,11 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.47.tgz#530b67163714356f93e82bdb871e7db4b7bc564e" integrity sha512-J4Xw0xYK4h7eC34MNOPQi6IkNxGRck6n4VJpWDzXIFVTW8I/D43Gf+NfWz/v/7NHlzWOPd3+T4PJ4OqklQ2u7A== +"@sinclair/typebox@^0.25.16": + version "0.25.24" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718" + integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ== + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -1533,6 +1730,20 @@ dependencies: type-detect "4.0.8" +"@sinonjs/commons@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" + integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.2.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz#b3e322a34c5f26e3184e7f6115695f299c1b1194" + integrity sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@sinonjs/fake-timers@^9.1.2": version "9.1.2" resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz#4eaab737fab77332ab132d396a3c0d364bd0ea8c" @@ -2259,6 +2470,19 @@ babel-jest@^29.2.1: graceful-fs "^4.2.9" slash "^3.0.0" +babel-jest@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.5.0.tgz#3fe3ddb109198e78b1c88f9ebdecd5e4fc2f50a5" + integrity sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q== + dependencies: + "@jest/transform" "^29.5.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.5.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + babel-plugin-istanbul@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" @@ -2280,6 +2504,16 @@ babel-plugin-jest-hoist@^29.2.0: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" +babel-plugin-jest-hoist@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz#a97db437936f441ec196990c9738d4b88538618a" + integrity sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -2306,6 +2540,14 @@ babel-preset-jest@^29.2.0: babel-plugin-jest-hoist "^29.2.0" babel-preset-current-node-syntax "^1.0.0" +babel-preset-jest@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz#57bc8cc88097af7ff6a5ab59d1cd29d52a5916e2" + integrity sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg== + dependencies: + babel-plugin-jest-hoist "^29.5.0" + babel-preset-current-node-syntax "^1.0.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -2959,6 +3201,11 @@ convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -3224,6 +3471,11 @@ diff-sequences@^29.2.0: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.2.0.tgz#4c55b5b40706c7b5d2c5c75999a50c56d214e8f6" integrity sha512-413SY5JpYeSBZxmenGEmCVQ8mCgtFJF0w9PROdaS6z987XC2Pd2GOKqOITLtMftmyFZqgtCOb/QA7/Z3ZXfzIw== +diff-sequences@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2" + integrity sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA== + diff@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" @@ -3323,6 +3575,11 @@ emittery@^0.10.2: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933" integrity sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw== +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -3925,6 +4182,17 @@ expect@^29.2.1: jest-message-util "^29.2.1" jest-util "^29.2.1" +expect@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.5.0.tgz#68c0509156cb2a0adb8865d413b137eeaae682f7" + integrity sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg== + dependencies: + "@jest/expect-utils" "^29.5.0" + jest-get-type "^29.4.3" + jest-matcher-utils "^29.5.0" + jest-message-util "^29.5.0" + jest-util "^29.5.0" + express@^4.14.0, express@^4.18.2: version "4.18.2" resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" @@ -4995,6 +5263,14 @@ jest-changed-files@^29.2.0: execa "^5.0.0" p-limit "^3.1.0" +jest-changed-files@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.5.0.tgz#e88786dca8bf2aa899ec4af7644e16d9dcf9b23e" + integrity sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag== + dependencies: + execa "^5.0.0" + p-limit "^3.1.0" + jest-circus@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.2.1.tgz#1385353d9bca6acf58f916068bbeffcfc95bef02" @@ -5020,6 +5296,32 @@ jest-circus@^29.2.1: slash "^3.0.0" stack-utils "^2.0.3" +jest-circus@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.5.0.tgz#b5926989449e75bff0d59944bae083c9d7fb7317" + integrity sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA== + dependencies: + "@jest/environment" "^29.5.0" + "@jest/expect" "^29.5.0" + "@jest/test-result" "^29.5.0" + "@jest/types" "^29.5.0" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^0.7.0" + is-generator-fn "^2.0.0" + jest-each "^29.5.0" + jest-matcher-utils "^29.5.0" + jest-message-util "^29.5.0" + jest-runtime "^29.5.0" + jest-snapshot "^29.5.0" + jest-util "^29.5.0" + p-limit "^3.1.0" + pretty-format "^29.5.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + jest-cli@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.2.1.tgz#fbfa90b87b27a04e1041cc9d33ee80f32e2f2528" @@ -5038,6 +5340,24 @@ jest-cli@^29.2.1: prompts "^2.0.1" yargs "^17.3.1" +jest-cli@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.5.0.tgz#b34c20a6d35968f3ee47a7437ff8e53e086b4a67" + integrity sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw== + dependencies: + "@jest/core" "^29.5.0" + "@jest/test-result" "^29.5.0" + "@jest/types" "^29.5.0" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + import-local "^3.0.2" + jest-config "^29.5.0" + jest-util "^29.5.0" + jest-validate "^29.5.0" + prompts "^2.0.1" + yargs "^17.3.1" + jest-config@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.2.1.tgz#2182af014d6c73978208626335db5134803dd183" @@ -5066,6 +5386,34 @@ jest-config@^29.2.1: slash "^3.0.0" strip-json-comments "^3.1.1" +jest-config@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.5.0.tgz#3cc972faec8c8aaea9ae158c694541b79f3748da" + integrity sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.5.0" + "@jest/types" "^29.5.0" + babel-jest "^29.5.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.5.0" + jest-environment-node "^29.5.0" + jest-get-type "^29.4.3" + jest-regex-util "^29.4.3" + jest-resolve "^29.5.0" + jest-runner "^29.5.0" + jest-util "^29.5.0" + jest-validate "^29.5.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.5.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + jest-diff@^26.0.0: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" @@ -5086,6 +5434,16 @@ jest-diff@^29.2.1: jest-get-type "^29.2.0" pretty-format "^29.2.1" +jest-diff@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.5.0.tgz#e0d83a58eb5451dcc1fa61b1c3ee4e8f5a290d63" + integrity sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.4.3" + jest-get-type "^29.4.3" + pretty-format "^29.5.0" + jest-docblock@^29.2.0: version "29.2.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.2.0.tgz#307203e20b637d97cee04809efc1d43afc641e82" @@ -5093,6 +5451,13 @@ jest-docblock@^29.2.0: dependencies: detect-newline "^3.0.0" +jest-docblock@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.4.3.tgz#90505aa89514a1c7dceeac1123df79e414636ea8" + integrity sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg== + dependencies: + detect-newline "^3.0.0" + jest-each@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.2.1.tgz#6b0a88ee85c2ba27b571a6010c2e0c674f5c9b29" @@ -5104,6 +5469,17 @@ jest-each@^29.2.1: jest-util "^29.2.1" pretty-format "^29.2.1" +jest-each@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.5.0.tgz#fc6e7014f83eac68e22b7195598de8554c2e5c06" + integrity sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA== + dependencies: + "@jest/types" "^29.5.0" + chalk "^4.0.0" + jest-get-type "^29.4.3" + jest-util "^29.5.0" + pretty-format "^29.5.0" + jest-environment-node@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.2.1.tgz#f90311d0f0e8ef720349f83c97a076e403f90665" @@ -5116,6 +5492,18 @@ jest-environment-node@^29.2.1: jest-mock "^29.2.1" jest-util "^29.2.1" +jest-environment-node@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.5.0.tgz#f17219d0f0cc0e68e0727c58b792c040e332c967" + integrity sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw== + dependencies: + "@jest/environment" "^29.5.0" + "@jest/fake-timers" "^29.5.0" + "@jest/types" "^29.5.0" + "@types/node" "*" + jest-mock "^29.5.0" + jest-util "^29.5.0" + jest-get-type@^26.3.0: version "26.3.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" @@ -5126,6 +5514,11 @@ jest-get-type@^29.2.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.2.0.tgz#726646f927ef61d583a3b3adb1ab13f3a5036408" integrity sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA== +jest-get-type@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.4.3.tgz#1ab7a5207c995161100b5187159ca82dd48b3dd5" + integrity sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg== + jest-haste-map@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.2.1.tgz#f803fec57f8075e6c55fb5cd551f99a72471c699" @@ -5145,6 +5538,25 @@ jest-haste-map@^29.2.1: optionalDependencies: fsevents "^2.3.2" +jest-haste-map@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.5.0.tgz#69bd67dc9012d6e2723f20a945099e972b2e94de" + integrity sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA== + dependencies: + "@jest/types" "^29.5.0" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.4.3" + jest-util "^29.5.0" + jest-worker "^29.5.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + jest-leak-detector@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.2.1.tgz#ec551686b7d512ec875616c2c3534298b1ffe2fc" @@ -5153,6 +5565,14 @@ jest-leak-detector@^29.2.1: jest-get-type "^29.2.0" pretty-format "^29.2.1" +jest-leak-detector@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz#cf4bdea9615c72bac4a3a7ba7e7930f9c0610c8c" + integrity sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow== + dependencies: + jest-get-type "^29.4.3" + pretty-format "^29.5.0" + jest-matcher-utils@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.2.1.tgz#2bf876c5f891b33786aadf5d65d5da5970744122" @@ -5163,6 +5583,16 @@ jest-matcher-utils@^29.2.1: jest-get-type "^29.2.0" pretty-format "^29.2.1" +jest-matcher-utils@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz#d957af7f8c0692c5453666705621ad4abc2c59c5" + integrity sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw== + dependencies: + chalk "^4.0.0" + jest-diff "^29.5.0" + jest-get-type "^29.4.3" + pretty-format "^29.5.0" + jest-message-util@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.2.1.tgz#3a51357fbbe0cc34236f17a90d772746cf8d9193" @@ -5178,6 +5608,21 @@ jest-message-util@^29.2.1: slash "^3.0.0" stack-utils "^2.0.3" +jest-message-util@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.5.0.tgz#1f776cac3aca332ab8dd2e3b41625435085c900e" + integrity sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.5.0" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.5.0" + slash "^3.0.0" + stack-utils "^2.0.3" + jest-mock@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.2.1.tgz#a0d361cffcb28184fa9c5443adbf591fa5759775" @@ -5187,6 +5632,15 @@ jest-mock@^29.2.1: "@types/node" "*" jest-util "^29.2.1" +jest-mock@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.5.0.tgz#26e2172bcc71d8b0195081ff1f146ac7e1518aed" + integrity sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw== + dependencies: + "@jest/types" "^29.5.0" + "@types/node" "*" + jest-util "^29.5.0" + jest-pnp-resolver@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" @@ -5197,6 +5651,11 @@ jest-regex-util@^29.2.0: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.2.0.tgz#82ef3b587e8c303357728d0322d48bbfd2971f7b" integrity sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA== +jest-regex-util@^29.4.3: + version "29.4.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.4.3.tgz#a42616141e0cae052cfa32c169945d00c0aa0bb8" + integrity sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg== + jest-resolve-dependencies@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.2.1.tgz#8d717dd41dc615fef1d412d395ea3deccfb1b9fa" @@ -5205,6 +5664,14 @@ jest-resolve-dependencies@^29.2.1: jest-regex-util "^29.2.0" jest-snapshot "^29.2.1" +jest-resolve-dependencies@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz#f0ea29955996f49788bf70996052aa98e7befee4" + integrity sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg== + dependencies: + jest-regex-util "^29.4.3" + jest-snapshot "^29.5.0" + jest-resolve@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.2.1.tgz#a4d2f76db88aeb6ec5f5453c9a40b52483d17799" @@ -5220,6 +5687,21 @@ jest-resolve@^29.2.1: resolve.exports "^1.1.0" slash "^3.0.0" +jest-resolve@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.5.0.tgz#b053cc95ad1d5f6327f0ac8aae9f98795475ecdc" + integrity sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.5.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.5.0" + jest-validate "^29.5.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + jest-runner@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.2.1.tgz#885afe64661cb2f51f84c1b97afb713d1093c124" @@ -5247,6 +5729,33 @@ jest-runner@^29.2.1: p-limit "^3.1.0" source-map-support "0.5.13" +jest-runner@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.5.0.tgz#6a57c282eb0ef749778d444c1d758c6a7693b6f8" + integrity sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ== + dependencies: + "@jest/console" "^29.5.0" + "@jest/environment" "^29.5.0" + "@jest/test-result" "^29.5.0" + "@jest/transform" "^29.5.0" + "@jest/types" "^29.5.0" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.4.3" + jest-environment-node "^29.5.0" + jest-haste-map "^29.5.0" + jest-leak-detector "^29.5.0" + jest-message-util "^29.5.0" + jest-resolve "^29.5.0" + jest-runtime "^29.5.0" + jest-util "^29.5.0" + jest-watcher "^29.5.0" + jest-worker "^29.5.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + jest-runtime@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.2.1.tgz#62e3a23c33710ae4d9c3304dda851a5fb225b574" @@ -5275,6 +5784,34 @@ jest-runtime@^29.2.1: slash "^3.0.0" strip-bom "^4.0.0" +jest-runtime@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.5.0.tgz#c83f943ee0c1da7eb91fa181b0811ebd59b03420" + integrity sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw== + dependencies: + "@jest/environment" "^29.5.0" + "@jest/fake-timers" "^29.5.0" + "@jest/globals" "^29.5.0" + "@jest/source-map" "^29.4.3" + "@jest/test-result" "^29.5.0" + "@jest/transform" "^29.5.0" + "@jest/types" "^29.5.0" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.5.0" + jest-message-util "^29.5.0" + jest-mock "^29.5.0" + jest-regex-util "^29.4.3" + jest-resolve "^29.5.0" + jest-snapshot "^29.5.0" + jest-util "^29.5.0" + slash "^3.0.0" + strip-bom "^4.0.0" + jest-snapshot@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.2.1.tgz#f3843b3099c8fec7e6218dea18cc506f10ea5d30" @@ -5305,6 +5842,35 @@ jest-snapshot@^29.2.1: pretty-format "^29.2.1" semver "^7.3.5" +jest-snapshot@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.5.0.tgz#c9c1ce0331e5b63cd444e2f95a55a73b84b1e8ce" + integrity sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.5.0" + "@jest/transform" "^29.5.0" + "@jest/types" "^29.5.0" + "@types/babel__traverse" "^7.0.6" + "@types/prettier" "^2.1.5" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.5.0" + graceful-fs "^4.2.9" + jest-diff "^29.5.0" + jest-get-type "^29.4.3" + jest-matcher-utils "^29.5.0" + jest-message-util "^29.5.0" + jest-util "^29.5.0" + natural-compare "^1.4.0" + pretty-format "^29.5.0" + semver "^7.3.5" + jest-util@^29.0.0, jest-util@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.2.1.tgz#f26872ba0dc8cbefaba32c34f98935f6cf5fc747" @@ -5317,6 +5883,18 @@ jest-util@^29.0.0, jest-util@^29.2.1: graceful-fs "^4.2.9" picomatch "^2.2.3" +jest-util@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.5.0.tgz#24a4d3d92fc39ce90425311b23c27a6e0ef16b8f" + integrity sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ== + dependencies: + "@jest/types" "^29.5.0" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + jest-validate@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.2.1.tgz#db814ce12c4c7e4746044922762e56eb177d066c" @@ -5329,6 +5907,18 @@ jest-validate@^29.2.1: leven "^3.1.0" pretty-format "^29.2.1" +jest-validate@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.5.0.tgz#8e5a8f36178d40e47138dc00866a5f3bd9916ffc" + integrity sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ== + dependencies: + "@jest/types" "^29.5.0" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.4.3" + leven "^3.1.0" + pretty-format "^29.5.0" + jest-watcher@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.2.1.tgz#1cb91f8aa9e77b1332af139944ad65e51430d7c3" @@ -5343,6 +5933,20 @@ jest-watcher@^29.2.1: jest-util "^29.2.1" string-length "^4.0.1" +jest-watcher@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.5.0.tgz#cf7f0f949828ba65ddbbb45c743a382a4d911363" + integrity sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA== + dependencies: + "@jest/test-result" "^29.5.0" + "@jest/types" "^29.5.0" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.5.0" + string-length "^4.0.1" + jest-worker@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.2.1.tgz#8ba68255438252e1674f990f0180c54dfa26a3b1" @@ -5353,6 +5957,16 @@ jest-worker@^29.2.1: merge-stream "^2.0.0" supports-color "^8.0.0" +jest-worker@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.5.0.tgz#bdaefb06811bd3384d93f009755014d8acb4615d" + integrity sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA== + dependencies: + "@types/node" "*" + jest-util "^29.5.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + jest@^29.0.3: version "29.2.1" resolved "https://registry.yarnpkg.com/jest/-/jest-29.2.1.tgz#352ec0b81a0e436691d546d984cd7d8f72ffd26a" @@ -6464,6 +7078,15 @@ pretty-format@^29.2.1: ansi-styles "^5.0.0" react-is "^18.0.0" +pretty-format@^29.5.0: + version "29.5.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.5.0.tgz#283134e74f70e2e3e7229336de0e4fce94ccde5a" + integrity sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw== + dependencies: + "@jest/schemas" "^29.4.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + pretty-quick@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-3.1.3.tgz#15281108c0ddf446675157ca40240099157b638e" @@ -6537,6 +7160,11 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +pure-rand@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.2.tgz#a9c2ddcae9b68d736a8163036f088a2781c8b306" + integrity sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ== + qs@6.11.0, qs@^6.7.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" @@ -6701,6 +7329,11 @@ resolve.exports@^1.1.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== +resolve.exports@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + resolve@1.17.0: version "1.17.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" @@ -7975,7 +8608,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write-file-atomic@^4.0.1: +write-file-atomic@^4.0.1, write-file-atomic@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== From 437bdab58e9cb9cced7ce7a51bfb4b6314997f6f Mon Sep 17 00:00:00 2001 From: tbotteam <112426427+tbotteam@users.noreply.github.com> Date: Mon, 29 May 2023 19:21:12 +0200 Subject: [PATCH 019/833] usdfi dex --- src/dex/index.ts | 2 + src/dex/solidly/config.ts | 17 ++- src/dex/solidly/forks-override/usdfi.ts | 12 ++ src/dex/solidly/solidly-e2e.test.ts | 191 ++++++++++++++++++++++++ src/dex/solidly/solidly.ts | 1 + 5 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 src/dex/solidly/forks-override/usdfi.ts diff --git a/src/dex/index.ts b/src/dex/index.ts index e0bd081c9..ab2191144 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -47,6 +47,7 @@ import { SpiritSwapV2 } from './solidly/forks-override/spiritSwapV2'; import { Synthetix } from './synthetix/synthetix'; import { Cone } from './solidly/forks-override/cone'; import { SoliSnek } from './solidly/forks-override/solisnek'; +import { Usdfi } from './solidly/forks-override/usdfi'; import { BalancerV1 } from './balancer-v1/balancer-v1'; import { balancerV1Merge } from './balancer-v1/optimizer'; import { CurveV1 } from './curve-v1/curve-v1'; @@ -122,6 +123,7 @@ const Dexes = [ Velodrome, Cone, SoliSnek, + Usdfi, Synthetix, CurveV1Factory, SwaapV1, diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index f251f0ac2..69b657dd5 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -101,6 +101,21 @@ export const SolidlyConfig: DexConfigMap = { feeCode: 2, }, }, + Usdfi: { + [Network.BSC]: { + subgraphURL: + 'https://thegraph.com/hosted-service/subgraph/tbotteam/usdfi-dexv2', + factoryAddress: '0xB3863573d9f25e6a84895d4685a408db7a488416', + router: '0x226E6a0114729ad4db1c80C55900729D352E2132', + initCode: + '0x1d770cc32abcf060a45b0de3f0afbd8594effe9f6d836f93d19c05d76b4b4dfa ', + // Variable fees. Defaults: + // Stable: 10000 (0,01%) ('1' in uniswap) + // Volatile: 2000 (0,05%) ('5' in uniswap) + poolGasCost: 180 * 1000, + feeCode: 0, // variable + }, + }, }; export const Adapters: Record = { @@ -114,7 +129,7 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 8 }], // velodrome }, [Network.BSC]: { - [SwapSide.SELL]: [{ name: 'BscAdapter02', index: 1 }], // cone + [SwapSide.SELL]: [{ name: 'BscAdapter02', index: 1 }], // cone & usdfi }, [Network.MAINNET]: { [SwapSide.SELL]: [{ name: 'Adapter04', index: 1 }], // solidly diff --git a/src/dex/solidly/forks-override/usdfi.ts b/src/dex/solidly/forks-override/usdfi.ts new file mode 100644 index 000000000..8ab8e0c6d --- /dev/null +++ b/src/dex/solidly/forks-override/usdfi.ts @@ -0,0 +1,12 @@ +import { Solidly } from '../solidly'; +import { SolidlyPair } from '../types'; +import { Network } from '../../../constants'; +import { getDexKeysWithNetwork } from '../../../utils'; +import { SolidlyConfig } from '../config'; +import _ from 'lodash'; + +export class Usdfi extends Solidly { + feeFactor = 1e4; + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(_.pick(SolidlyConfig, ['Usdfi'])); +} diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index 0e5d26589..2c60244d6 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -890,6 +890,197 @@ describe('Solidly E2E', () => { }); }); }); + + describe('Usdfi', () => { + const dexKey = 'Usdfi'; + const usdAmount = '1000000'; + + describe('Usdfi UniswapV2 Pools', () => { + const bnbAmount = '1000000000000000000'; + + describe('simpleSwap', () => { + it('BNB -> TOKEN', async () => { + await testE2E( + tokens.BNB, + tokens.BUSD, + holders.BNB, + bnbAmount, + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('Token -> BNB', async () => { + await testE2E( + tokens.USDT, + tokens.BNB, + holders.USDT, + usdAmount, + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('Token -> Token', async () => { + await testE2E( + tokens.WBNB, + tokens.CONE, + holders.WBNB, + bnbAmount, + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + }); + + describe('multiSwap', () => { + it('BNB -> TOKEN', async () => { + await testE2E( + tokens.BNB, + tokens.BUSD, + holders.BNB, + bnbAmount, + SwapSide.SELL, + dexKey, + ContractMethod.multiSwap, + network, + provider, + ); + }); + + it('Token -> BNB', async () => { + await testE2E( + tokens.USDT, + tokens.BNB, + holders.USDT, + usdAmount, + SwapSide.SELL, + dexKey, + ContractMethod.multiSwap, + network, + provider, + ); + }); + + it('Token -> Token', async () => { + await testE2E( + tokens.WBNB, + tokens.CONE, + holders.WBNB, + bnbAmount, + SwapSide.SELL, + dexKey, + ContractMethod.multiSwap, + network, + provider, + ); + }); + }); + + describe('megaSwap', () => { + it('BNB -> TOKEN', async () => { + await testE2E( + tokens.USDT, + tokens.BNB, + holders.USDT, + usdAmount, + SwapSide.SELL, + dexKey, + ContractMethod.megaSwap, + network, + provider, + ); + }); + + it('Token -> BNB', async () => { + await testE2E( + tokens.USDT, + tokens.BNB, + holders.USDT, + usdAmount, + SwapSide.SELL, + dexKey, + ContractMethod.megaSwap, + network, + provider, + ); + }); + + it('Token -> Token', async () => { + await testE2E( + tokens.WBNB, + tokens.CONE, + holders.WBNB, + bnbAmount, + SwapSide.SELL, + dexKey, + ContractMethod.megaSwap, + network, + provider, + ); + }); + }); + }); + + describe('Usdfi Stable Pools', () => { + describe('simpleSwap', () => { + it('Token -> Token', async () => { + await testE2E( + tokens.USDC, + tokens.USDT, + holders.USDC, + usdAmount, + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + }); + + describe('multiSwap', () => { + it('Token -> Token', async () => { + await testE2E( + tokens.USDC, + tokens.USDT, + holders.USDC, + usdAmount, + SwapSide.SELL, + dexKey, + ContractMethod.multiSwap, + network, + provider, + ); + }); + }); + + describe('megaSwap', () => { + it('Token -> Token', async () => { + await testE2E( + tokens.USDC, + tokens.USDT, + holders.USDC, + usdAmount, + SwapSide.SELL, + dexKey, + ContractMethod.megaSwap, + network, + provider, + ); + }); + }); + }); + }); }); describe('Avalanche', () => { diff --git a/src/dex/solidly/solidly.ts b/src/dex/solidly/solidly.ts index 781644b93..6514c7dc3 100644 --- a/src/dex/solidly/solidly.ts +++ b/src/dex/solidly/solidly.ts @@ -70,6 +70,7 @@ export class Solidly extends UniswapV2 { 'Cone', 'SolidlyV2', 'SoliSnek', + 'Usdfi', ]), ); From 35811d35c855302cbc21783b1c91e3aec92cf92d Mon Sep 17 00:00:00 2001 From: 0xshad0w Date: Thu, 22 Jun 2023 03:06:43 +0100 Subject: [PATCH 020/833] 1 - add solidly/ramses V1 --- src/dex/solidly/config.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index f8e364db3..6e71d0301 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -125,6 +125,18 @@ export const SolidlyConfig: DexConfigMap = { feeCode: 0, }, }, + Ramses: { + [Network.ARBITRUM]: { + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/ramsesexchange/api-subgraph', + factoryAddress: '0xAAA20D08e59F6561f242b08513D36266C5A29415', + router: '0xAAA87963EFeB6f7E0a2711F397663105Acb1805e', + initCode: + '0x1565b129f2d1790f12d45301b9b084335626f0c92410bc43130763b69971135d', + poolGasCost: 180 * 1000, + feeCode: 0, + }, + }, }; export const Adapters: Record = { @@ -147,6 +159,6 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 3 }], // solisnek }, [Network.ARBITRUM]: { - [SwapSide.SELL]: [{ name: 'ArbitrumAdapter02', index: 1 }], // chronos + [SwapSide.SELL]: [{ name: 'ArbitrumAdapter02', index: 1 }], // chronos, ramses }, }; From 0e9aac2e44b83e41e72b84ab1115dcd239e82861 Mon Sep 17 00:00:00 2001 From: 0xshad0w Date: Thu, 22 Jun 2023 03:08:11 +0100 Subject: [PATCH 021/833] 1 - add solidly/ramses V1 --- src/dex/index.ts | 2 + src/dex/solidly/forks-override/ramses.ts | 10 ++ src/dex/solidly/solidly-e2e.test.ts | 90 ++++++++++++- src/dex/solidly/solidly-integration.test.ts | 135 ++++++++++++++++++++ 4 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 src/dex/solidly/forks-override/ramses.ts diff --git a/src/dex/index.ts b/src/dex/index.ts index d06e99259..adfc76e98 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -42,6 +42,7 @@ import { WooFiV2 } from './woo-fi-v2/woo-fi-v2'; import { ParaSwapLimitOrders } from './paraswap-limit-orders/paraswap-limit-orders'; import { AugustusRFQOrder } from './augustus-rfq'; import { Solidly } from './solidly/solidly'; +import { Ramses } from './solidly/forks-override/ramses'; import { Thena } from './solidly/forks-override/thena'; import { Chronos } from './solidly/forks-override/chronos'; import { Velodrome } from './solidly/forks-override/velodrome'; @@ -124,6 +125,7 @@ const Dexes = [ Solidly, SolidlyEthereum, SpiritSwapV2, + Ramses, Thena, Chronos, Velodrome, diff --git a/src/dex/solidly/forks-override/ramses.ts b/src/dex/solidly/forks-override/ramses.ts new file mode 100644 index 000000000..46452acc7 --- /dev/null +++ b/src/dex/solidly/forks-override/ramses.ts @@ -0,0 +1,10 @@ +import { Velodrome } from './velodrome'; +import { Network } from '../../../constants'; +import { getDexKeysWithNetwork } from '../../../utils'; +import { SolidlyConfig } from '../config'; +import _ from 'lodash'; + +export class Ramses extends Velodrome { + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(_.pick(SolidlyConfig, ['Ramses'])); +} \ No newline at end of file diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index 338f3e1d3..7dd530380 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -1179,5 +1179,93 @@ describe('Solidly E2E', () => { }), ); }); + describe('Ramses', () => { + const dexKey = 'Ramses'; + + describe('simpleSwap', () => { + it('NATIVE -> TOKEN', async () => { + await testE2E( + tokens.ETH, + tokens.USDC, + holders.ETH, + '3000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + it('TOKEN -> NATIVE', async () => { + await testE2E( + tokens.USDC, + tokens.ETH, + holders.USDC, + '9900000000', + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + it('TOKEN -> TOKEN', async () => { + await testE2E( + tokens.WETH, + tokens.USDC, + holders.WETH, + '3000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + + network, + provider, + ); + }); + }); + describe('multiSwap', () => { + it('NATIVE -> TOKEN', async () => { + await testE2E( + tokens.ETH, + tokens.USDC, + holders.ETH, + '3000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.multiSwap, + + network, + provider, + ); + }); + it('TOKEN -> NATIVE', async () => { + await testE2E( + tokens.USDC, + tokens.ETH, + holders.USDC, + '9900000000', + SwapSide.SELL, + dexKey, + ContractMethod.multiSwap, + network, + provider, + ); + }); + it('TOKEN -> TOKEN', async () => { + await testE2E( + tokens.WETH, + tokens.USDC, + holders.WETH, + '3000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.multiSwap, + network, + provider, + ); + }); + }); + }); }); -}); +}); \ No newline at end of file diff --git a/src/dex/solidly/solidly-integration.test.ts b/src/dex/solidly/solidly-integration.test.ts index 06bc8243a..695f83e2e 100644 --- a/src/dex/solidly/solidly-integration.test.ts +++ b/src/dex/solidly/solidly-integration.test.ts @@ -12,6 +12,7 @@ import solidlyPairABI from '../../abi/solidly/SolidlyPair.json'; import { SpiritSwapV2 } from './forks-override/spiritSwapV2'; import { Cone } from './forks-override/cone'; import { Chronos } from './forks-override/chronos'; +import { Ramses } from './forks-override/ramses'; const amounts18 = [0n, BI_POWS[18], 2000000000000000000n]; const amounts6 = [0n, BI_POWS[6], 2000000n]; @@ -768,5 +769,139 @@ describe('Solidly integration tests', () => { }); }); }); + + describe('Ramses', function () { + const dexKey = 'Ramses'; + const ramses = new Ramses(network, dexKey, dexHelper); + + describe('UniswapV2 like pool', function () { + const TokenASymbol = 'USDC'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'WETH'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts18; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await ramses.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await ramses.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + + for (const i in poolPrices || []) { + await checkOnChainPricing( + ramses, + 'getAmountOut', + blocknumber, + poolPrices![i].prices, + poolPrices![i].poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + + it('getTopPoolsForToken', async function () { + const poolLiquidity = await ramses.getTopPoolsForToken( + tokenA.address, + 10, + ); + console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, tokenA.address, dexKey); + }); + }); + + describe('Curve like stable pool', function () { + const TokenASymbol = 'USDT'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'USDC'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts6; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await ramses.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await ramses.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + for (const i in poolPrices || []) { + await checkOnChainPricing( + ramses, + 'getAmountOut', + blocknumber, + poolPrices![i].prices, + poolPrices![i].poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + + it('getTopPoolsForToken', async function () { + const poolLiquidity = await ramses.getTopPoolsForToken( + tokenA.address, + 10, + ); + console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, tokenA.address, dexKey); + }); + }); + }); }); }); From ebe18789c1ee6339c7aa03d6b08d23d427ad4fac Mon Sep 17 00:00:00 2001 From: 0xshad0w Date: Fri, 23 Jun 2023 12:03:34 +0100 Subject: [PATCH 022/833] 1 - create dex/ramses-v2 --- src/dex/ramses-v2/config.ts | 31 + src/dex/ramses-v2/constants.ts | 41 ++ src/dex/ramses-v2/contract-math/BitMath.ts | 90 +++ .../ramses-v2/contract-math/FixedPoint128.ts | 3 + .../ramses-v2/contract-math/FixedPoint96.ts | 4 + src/dex/ramses-v2/contract-math/FullMath.ts | 30 + .../ramses-v2/contract-math/LiquidityMath.ts | 17 + src/dex/ramses-v2/contract-math/Oracle.ts | 226 ++++++ .../ramses-v2/contract-math/SqrtPriceMath.ts | 226 ++++++ src/dex/ramses-v2/contract-math/SwapMath.ts | 139 ++++ src/dex/ramses-v2/contract-math/Tick.ts | 82 +++ src/dex/ramses-v2/contract-math/TickBitMap.ts | 128 ++++ src/dex/ramses-v2/contract-math/TickMath.ts | 211 ++++++ src/dex/ramses-v2/contract-math/UnsafeMath.ts | 5 + .../contract-math/uniswap-v3-math.ts | 671 ++++++++++++++++++ src/dex/ramses-v2/contract-math/utils.ts | 11 + src/dex/ramses-v2/ramses-v2-e2e.test.ts | 67 ++ src/dex/ramses-v2/ramses-v2-events.test.ts | 106 +++ .../ramses-v2/ramses-v2-integration.test.ts | 251 +++++++ src/dex/ramses-v2/ramses-v2-pool.ts | 91 +++ src/dex/ramses-v2/ramses-v2.ts | 178 +++++ src/dex/ramses-v2/types.ts | 22 + 22 files changed, 2630 insertions(+) create mode 100644 src/dex/ramses-v2/config.ts create mode 100644 src/dex/ramses-v2/constants.ts create mode 100644 src/dex/ramses-v2/contract-math/BitMath.ts create mode 100644 src/dex/ramses-v2/contract-math/FixedPoint128.ts create mode 100644 src/dex/ramses-v2/contract-math/FixedPoint96.ts create mode 100644 src/dex/ramses-v2/contract-math/FullMath.ts create mode 100644 src/dex/ramses-v2/contract-math/LiquidityMath.ts create mode 100644 src/dex/ramses-v2/contract-math/Oracle.ts create mode 100644 src/dex/ramses-v2/contract-math/SqrtPriceMath.ts create mode 100644 src/dex/ramses-v2/contract-math/SwapMath.ts create mode 100644 src/dex/ramses-v2/contract-math/Tick.ts create mode 100644 src/dex/ramses-v2/contract-math/TickBitMap.ts create mode 100644 src/dex/ramses-v2/contract-math/TickMath.ts create mode 100644 src/dex/ramses-v2/contract-math/UnsafeMath.ts create mode 100644 src/dex/ramses-v2/contract-math/uniswap-v3-math.ts create mode 100644 src/dex/ramses-v2/contract-math/utils.ts create mode 100644 src/dex/ramses-v2/ramses-v2-e2e.test.ts create mode 100644 src/dex/ramses-v2/ramses-v2-events.test.ts create mode 100644 src/dex/ramses-v2/ramses-v2-integration.test.ts create mode 100644 src/dex/ramses-v2/ramses-v2-pool.ts create mode 100644 src/dex/ramses-v2/ramses-v2.ts create mode 100644 src/dex/ramses-v2/types.ts diff --git a/src/dex/ramses-v2/config.ts b/src/dex/ramses-v2/config.ts new file mode 100644 index 000000000..4433aac63 --- /dev/null +++ b/src/dex/ramses-v2/config.ts @@ -0,0 +1,31 @@ +import { DexParams } from './types'; +import { DexConfigMap, AdapterMappings } from '../../types'; +import { Network, SwapSide } from '../../constants'; + +const RAMSES_SUPPORTED_FEES = [10000n, 2500n, 500n, 100n]; + +export const RamsesV2Config: DexConfigMap = { + RamsesV2: { + [Network.ARBITRUM]: { + factory: '0xAA2cd7477c451E703f3B9Ba5663334914763edF8', + deployer: '0xb3e423ab9cE6C03D98326A3A2a0D7D96b0829f22', + quoter: '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', + router: '0xAA23611badAFB62D37E7295A682D21960ac85A90', + supportedFees: RAMSES_SUPPORTED_FEES, + stateMulticall: '0x80898f80cFA3Fa3AbF410d90e69aDc432AE5D4c2', + uniswapMulticall: '0xac1cE734566f390A94b00eb9bf561c2625BF44ea', + chunksCount: 10, + initHash: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/ramsesexchange/concentrated-liquidity-graph', + }, + }, +}; + +export const Adapters: Record = { + [Network.ARBITRUM]: { + [SwapSide.SELL]: [{ name: 'ArbitrumAdapter01', index: 3 }], + [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 2 }], + }, +}; diff --git a/src/dex/ramses-v2/constants.ts b/src/dex/ramses-v2/constants.ts new file mode 100644 index 000000000..e6f5f8510 --- /dev/null +++ b/src/dex/ramses-v2/constants.ts @@ -0,0 +1,41 @@ +export const UNISWAPV3_TICK_GAS_COST = 24_000; // Ceiled +export const UNISWAPV3_TICK_BASE_OVERHEAD = 75_000; +export const UNISWAPV3_POOL_SEARCH_OVERHEAD = 10_000; + +// This is used for price calculation. If out of scope, return 0n +export const TICK_BITMAP_TO_USE = 4n; + +// This is used to check if the state is still valid. +export const TICK_BITMAP_BUFFER = 8n; + +export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 128; + +export const UNISWAPV3_SUBGRAPH_URL = + 'https://api.thegraph.com/subgraphs/name/ramsesexchange/concentrated-liquidity-graph'; + +export const UNISWAPV3_EFFICIENCY_FACTOR = 3; + +export const ZERO_TICK_INFO = { + liquidityGross: 0n, + liquidityNet: 0n, + tickCumulativeOutside: 0n, + secondsPerLiquidityOutsideX128: 0n, + secondsOutside: 0n, + initialized: false, +}; + +export const ZERO_ORACLE_OBSERVATION = { + blockTimestamp: 0n, + tickCumulative: 0n, + secondsPerLiquidityCumulativeX128: 0n, + initialized: false, +}; + +export const OUT_OF_RANGE_ERROR_POSTFIX = `INVALID_TICK_BIT_MAP_RANGES`; + +export const DEFAULT_POOL_INIT_CODE_HASH = `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`; + +export enum DirectMethods { + directSell = 'directUniV3Swap', + directBuy = 'directUniV3Buy', +} diff --git a/src/dex/ramses-v2/contract-math/BitMath.ts b/src/dex/ramses-v2/contract-math/BitMath.ts new file mode 100644 index 000000000..d7a2e6d9a --- /dev/null +++ b/src/dex/ramses-v2/contract-math/BitMath.ts @@ -0,0 +1,90 @@ +import { + BI_MAX_UINT128, + BI_MAX_UINT16, + BI_MAX_UINT32, + BI_MAX_UINT64, + BI_MAX_UINT8, +} from '../../../bigint-constants'; +import { _require } from '../../../utils'; + +export class BitMath { + static mostSignificantBit(x: bigint): bigint { + _require(x > 0, '', { x }, 'x > 0'); + let r = 0n; + + if (x >= 0x100000000000000000000000000000000n) { + x >>= 128n; + r += 128n; + } + if (x >= 0x10000000000000000n) { + x >>= 64n; + r += 64n; + } + if (x >= 0x100000000n) { + x >>= 32n; + r += 32n; + } + if (x >= 0x10000n) { + x >>= 16n; + r += 16n; + } + if (x >= 0x100n) { + x >>= 8n; + r += 8n; + } + if (x >= 0x10n) { + x >>= 4n; + r += 4n; + } + if (x >= 0x4n) { + x >>= 2n; + r += 2n; + } + if (x >= 0x2n) r += 1n; + + return r; + } + + static leastSignificantBit(x: bigint): bigint { + _require(x > 0, '', { x }, 'x > 0'); + + let r = 255n; + if ((x & BI_MAX_UINT128) > 0n) { + r -= 128n; + } else { + x >>= 128n; + } + if ((x & BI_MAX_UINT64) > 0n) { + r -= 64n; + } else { + x >>= 64n; + } + if ((x & BI_MAX_UINT32) > 0n) { + r -= 32n; + } else { + x >>= 32n; + } + if ((x & BI_MAX_UINT16) > 0n) { + r -= 16n; + } else { + x >>= 16n; + } + if ((x & BI_MAX_UINT8) > 0n) { + r -= 8n; + } else { + x >>= 8n; + } + if ((x & 0xfn) > 0n) { + r -= 4n; + } else { + x >>= 4n; + } + if ((x & 0x3n) > 0n) { + r -= 2n; + } else { + x >>= 2n; + } + if ((x & 0x1n) > 0n) r -= 1n; + return r; + } +} diff --git a/src/dex/ramses-v2/contract-math/FixedPoint128.ts b/src/dex/ramses-v2/contract-math/FixedPoint128.ts new file mode 100644 index 000000000..2058307bd --- /dev/null +++ b/src/dex/ramses-v2/contract-math/FixedPoint128.ts @@ -0,0 +1,3 @@ +export class FixedPoint128 { + static readonly Q128 = 0x100000000000000000000000000000000n; +} diff --git a/src/dex/ramses-v2/contract-math/FixedPoint96.ts b/src/dex/ramses-v2/contract-math/FixedPoint96.ts new file mode 100644 index 000000000..1a551dcb9 --- /dev/null +++ b/src/dex/ramses-v2/contract-math/FixedPoint96.ts @@ -0,0 +1,4 @@ +export class FixedPoint96 { + static readonly RESOLUTION = 96n; + static readonly Q96 = 0x1000000000000000000000000n; +} diff --git a/src/dex/ramses-v2/contract-math/FullMath.ts b/src/dex/ramses-v2/contract-math/FullMath.ts new file mode 100644 index 000000000..7c6a3bdc3 --- /dev/null +++ b/src/dex/ramses-v2/contract-math/FullMath.ts @@ -0,0 +1,30 @@ +import { BI_MAX_UINT256 } from '../../../bigint-constants'; +import { _require } from '../../../utils'; + +export class FullMath { + static mulDiv(a: bigint, b: bigint, denominator: bigint) { + const result = (a * b) / denominator; + + _require( + result <= BI_MAX_UINT256, + '', + { result, BI_MAX_UINT: BI_MAX_UINT256 }, + 'result <= BI_MAX_UINT', + ); + + return result; + } + + static mulDivRoundingUp(a: bigint, b: bigint, denominator: bigint) { + const result = (a * b + denominator - 1n) / denominator; + + _require( + result <= BI_MAX_UINT256, + '', + { result, BI_MAX_UINT: BI_MAX_UINT256 }, + 'result <= BI_MAX_UINT', + ); + + return result; + } +} diff --git a/src/dex/ramses-v2/contract-math/LiquidityMath.ts b/src/dex/ramses-v2/contract-math/LiquidityMath.ts new file mode 100644 index 000000000..a495e55cc --- /dev/null +++ b/src/dex/ramses-v2/contract-math/LiquidityMath.ts @@ -0,0 +1,17 @@ +import { _require } from '../../../utils'; + +export class LiquidityMath { + static addDelta(x: bigint, y: bigint): bigint { + let z; + if (y < 0) { + const _y = BigInt.asUintN(128, -y); + z = x - _y; + _require(z < x, 'LS', { z, x, y, _y }, 'z < x'); + } else { + const _y = BigInt.asUintN(128, y); + z = x + _y; + _require(z >= x, 'LA', { z, x, y, _y }, 'z >= x'); + } + return z; + } +} diff --git a/src/dex/ramses-v2/contract-math/Oracle.ts b/src/dex/ramses-v2/contract-math/Oracle.ts new file mode 100644 index 000000000..059e84e28 --- /dev/null +++ b/src/dex/ramses-v2/contract-math/Oracle.ts @@ -0,0 +1,226 @@ +import { + OracleObservation, + OracleObservationCandidates, + PoolState, +} from '../../uniswap-v3/types'; +import { _require } from '../../../utils'; +import { DeepReadonly } from 'ts-essentials'; +import { ZERO_ORACLE_OBSERVATION } from '../constants'; + +function replaceUndefinedObservationWithZero(state: PoolState, index: number) { + if (state.observations[index] === undefined) { + state.observations[index] = { ...ZERO_ORACLE_OBSERVATION }; + } +} + +export class Oracle { + static transform( + state: DeepReadonly, + last: OracleObservation, + blockTimestamp: bigint, + tick: bigint, + liquidity: bigint, + ): OracleObservation { + const delta = blockTimestamp - last.blockTimestamp; + return { + blockTimestamp: state.blockTimestamp, + tickCumulative: last.tickCumulative + BigInt.asIntN(56, tick) * delta, + secondsPerLiquidityCumulativeX128: + last.secondsPerLiquidityCumulativeX128 + + (BigInt.asUintN(160, delta) << 128n) / + (liquidity > 0n ? liquidity : 1n), + initialized: true, + }; + } + + static write( + state: PoolState, + index: number, + blockTimestamp: bigint, + tick: bigint, + liquidity: bigint, + cardinality: number, + cardinalityNext: number, + ): [number, number] { + const last = state.observations[index]; + + if (last.blockTimestamp == state.blockTimestamp) + return [index, cardinality]; + + let indexUpdated = 0; + let cardinalityUpdated = 0; + + if (cardinalityNext > cardinality && index == cardinality - 1) { + cardinalityUpdated = cardinalityNext; + } else { + cardinalityUpdated = cardinality; + } + + indexUpdated = (index + 1) % cardinalityUpdated; + + state.observations[indexUpdated] = Oracle.transform( + state, + last, + blockTimestamp, + tick, + liquidity, + ); + if (indexUpdated !== index) { + delete state.observations[index]; + } + return [indexUpdated, cardinalityUpdated]; + } + + static lte(time: bigint, a: bigint, b: bigint): boolean { + if (a <= time && b <= time) return a <= b; + + const aAdjusted = a > time ? a : a + 2n ** 32n; + const bAdjusted = b > time ? b : b + 2n ** 32n; + return aAdjusted <= bAdjusted; + } + + static binarySearch( + state: DeepReadonly, + time: bigint, + target: bigint, + index: number, + cardinality: number, + ): OracleObservationCandidates { + let l = (index + 1) % cardinality; + let r = l + cardinality - 1; + let i; + + let beforeOrAt; + let atOrAfter; + while (true) { + i = (l + r) / 2; + + beforeOrAt = state.observations[i % cardinality]; + + // we've landed on an uninitialized tick, keep searching higher (more recently) + if (!beforeOrAt.initialized) { + l = i + 1; + continue; + } + + atOrAfter = state.observations[(i + 1) % cardinality]; + + const targetAtOrAfter = Oracle.lte( + time, + beforeOrAt.blockTimestamp, + target, + ); + + // check if we've found the answer! + if (targetAtOrAfter && Oracle.lte(time, target, atOrAfter.blockTimestamp)) + break; + + if (!targetAtOrAfter) r = i - 1; + else l = i + 1; + } + return { beforeOrAt, atOrAfter }; + } + + static getSurroundingObservations( + state: DeepReadonly, + time: bigint, + target: bigint, + tick: bigint, + index: number, + liquidity: bigint, + cardinality: number, + ): OracleObservationCandidates { + let beforeOrAt = state.observations[index]; + + if (Oracle.lte(time, beforeOrAt.blockTimestamp, target)) { + if (beforeOrAt.blockTimestamp === target) { + return { beforeOrAt, atOrAfter: beforeOrAt }; + } else { + return { + beforeOrAt, + atOrAfter: Oracle.transform( + state, + beforeOrAt, + target, + tick, + liquidity, + ), + }; + } + } + + beforeOrAt = state.observations[(index + 1) % cardinality]; + if (!beforeOrAt.initialized) beforeOrAt = state.observations[0]; + + _require( + Oracle.lte(time, beforeOrAt.blockTimestamp, target), + 'OLD', + { time, beforeOrAtBlockTimestamp: beforeOrAt.blockTimestamp, target }, + 'Oracle.lte(time, beforeOrAt.blockTimestamp, target)', + ); + + return Oracle.binarySearch(state, time, target, index, cardinality); + } + + static observeSingle( + state: DeepReadonly, + time: bigint, + secondsAgo: bigint, + tick: bigint, + index: number, + liquidity: bigint, + cardinality: number, + ): [bigint, bigint] { + if (secondsAgo == 0n) { + let last = state.observations[index]; + if (last.blockTimestamp != time) + last = Oracle.transform(state, last, time, tick, liquidity); + return [last.tickCumulative, last.secondsPerLiquidityCumulativeX128]; + } + + const target = time - secondsAgo; + + const { beforeOrAt, atOrAfter } = Oracle.getSurroundingObservations( + state, + time, + target, + tick, + index, + liquidity, + cardinality, + ); + + if (target === beforeOrAt.blockTimestamp) { + return [ + beforeOrAt.tickCumulative, + beforeOrAt.secondsPerLiquidityCumulativeX128, + ]; + } else if (target === atOrAfter.blockTimestamp) { + return [ + atOrAfter.tickCumulative, + atOrAfter.secondsPerLiquidityCumulativeX128, + ]; + } else { + const observationTimeDelta = + atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp; + const targetDelta = target - beforeOrAt.blockTimestamp; + return [ + beforeOrAt.tickCumulative + + ((atOrAfter.tickCumulative - beforeOrAt.tickCumulative) / + observationTimeDelta) * + targetDelta, + beforeOrAt.secondsPerLiquidityCumulativeX128 + + BigInt.asUintN( + 160, + (BigInt.asUintN( + 256, + atOrAfter.secondsPerLiquidityCumulativeX128 - + beforeOrAt.secondsPerLiquidityCumulativeX128, + ) * + targetDelta) / + observationTimeDelta, + ), + ]; + } + } +} diff --git a/src/dex/ramses-v2/contract-math/SqrtPriceMath.ts b/src/dex/ramses-v2/contract-math/SqrtPriceMath.ts new file mode 100644 index 000000000..31b801d73 --- /dev/null +++ b/src/dex/ramses-v2/contract-math/SqrtPriceMath.ts @@ -0,0 +1,226 @@ +import { BI_MAX_UINT160 } from '../../../bigint-constants'; +import { FixedPoint96 } from './FixedPoint96'; +import { FullMath } from './FullMath'; +import { UnsafeMath } from './UnsafeMath'; +import { _require } from '../../../utils'; + +export class SqrtPriceMath { + static getNextSqrtPriceFromAmount0RoundingUp( + sqrtPX96: bigint, + liquidity: bigint, + amount: bigint, + add: boolean, + ): bigint { + if (amount === 0n) return sqrtPX96; + const numerator1 = + BigInt.asUintN(256, liquidity) << FixedPoint96.RESOLUTION; + + const product = amount * sqrtPX96; + if (add) { + if (product / amount === sqrtPX96) { + const denominator = numerator1 + product; + if (denominator >= numerator1) { + return BigInt.asUintN( + 160, + FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator), + ); + } + } + return BigInt.asUintN( + 160, + UnsafeMath.divRoundingUp(numerator1, numerator1 / sqrtPX96 + amount), + ); + } else { + _require( + product / amount === sqrtPX96 && numerator1 > product, + '', + { product, amount, sqrtPX96, numerator1 }, + 'product / amount === sqrtPX96 && numerator1 > product', + ); + const denominator = numerator1 - product; + return BigInt.asUintN( + 160, + FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator), + ); + } + } + + static getNextSqrtPriceFromAmount1RoundingDown( + sqrtPX96: bigint, + liquidity: bigint, + amount: bigint, + add: boolean, + ): bigint { + if (add) { + const quotient = + amount <= BI_MAX_UINT160 + ? (amount << FixedPoint96.RESOLUTION) / liquidity + : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity); + return BigInt.asUintN(160, BigInt.asUintN(256, sqrtPX96) + quotient); + } else { + const quotient = + amount <= BI_MAX_UINT160 + ? UnsafeMath.divRoundingUp( + amount << FixedPoint96.RESOLUTION, + liquidity, + ) + : FullMath.mulDivRoundingUp(amount, FixedPoint96.Q96, liquidity); + + _require( + sqrtPX96 > quotient, + '', + { sqrtPX96, quotient }, + 'sqrtPX96 > quotient', + ); + return BigInt.asUintN(160, sqrtPX96 - quotient); + } + } + + static getNextSqrtPriceFromInput( + sqrtPX96: bigint, + liquidity: bigint, + amountIn: bigint, + zeroForOne: boolean, + ): bigint { + _require(sqrtPX96 > 0n, '', { sqrtPX96 }, 'sqrtPX96 > 0n'); + _require(liquidity > 0n, '', { liquidity }, 'liquidity > 0n'); + + return zeroForOne + ? SqrtPriceMath.getNextSqrtPriceFromAmount0RoundingUp( + sqrtPX96, + liquidity, + amountIn, + true, + ) + : SqrtPriceMath.getNextSqrtPriceFromAmount1RoundingDown( + sqrtPX96, + liquidity, + amountIn, + true, + ); + } + + static getNextSqrtPriceFromOutput( + sqrtPX96: bigint, + liquidity: bigint, + amountOut: bigint, + zeroForOne: boolean, + ): bigint { + _require(sqrtPX96 > 0n, '', { sqrtPX96 }, 'sqrtPX96 > 0n'); + _require(liquidity > 0n, '', { liquidity }, 'liquidity > 0n'); + + return zeroForOne + ? SqrtPriceMath.getNextSqrtPriceFromAmount1RoundingDown( + sqrtPX96, + liquidity, + amountOut, + false, + ) + : SqrtPriceMath.getNextSqrtPriceFromAmount0RoundingUp( + sqrtPX96, + liquidity, + amountOut, + false, + ); + } + + static getAmount0Delta( + sqrtRatioAX96: bigint, + sqrtRatioBX96: bigint, + liquidity: bigint, + roundUp: boolean, + ) { + if (sqrtRatioAX96 > sqrtRatioBX96) { + [sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]; + } + + const numerator1 = + BigInt.asUintN(256, liquidity) << FixedPoint96.RESOLUTION; + const numerator2 = sqrtRatioBX96 - sqrtRatioAX96; + + _require(sqrtRatioAX96 > 0, '', { sqrtRatioAX96 }, 'sqrtRatioAX96 > 0'); + + return roundUp + ? UnsafeMath.divRoundingUp( + FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96), + sqrtRatioAX96, + ) + : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96; + } + + static getAmount1Delta( + sqrtRatioAX96: bigint, + sqrtRatioBX96: bigint, + liquidity: bigint, + roundUp: boolean, + ) { + if (sqrtRatioAX96 > sqrtRatioBX96) + [sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]; + + return roundUp + ? FullMath.mulDivRoundingUp( + liquidity, + sqrtRatioBX96 - sqrtRatioAX96, + FixedPoint96.Q96, + ) + : FullMath.mulDiv( + liquidity, + sqrtRatioBX96 - sqrtRatioAX96, + FixedPoint96.Q96, + ); + } + + // Overloaded with different argument numbers + static _getAmount0DeltaO( + sqrtRatioAX96: bigint, + sqrtRatioBX96: bigint, + liquidity: bigint, + ) { + return liquidity < 0 + ? -BigInt.asIntN( + 256, + SqrtPriceMath.getAmount0Delta( + sqrtRatioAX96, + sqrtRatioBX96, + BigInt.asUintN(128, -liquidity), + false, + ), + ) + : BigInt.asIntN( + 256, + SqrtPriceMath.getAmount0Delta( + sqrtRatioAX96, + sqrtRatioBX96, + BigInt.asUintN(128, liquidity), + true, + ), + ); + } + + // Overloaded with different argument numbers + static _getAmount1DeltaO( + sqrtRatioAX96: bigint, + sqrtRatioBX96: bigint, + liquidity: bigint, + ) { + return liquidity < 0 + ? -BigInt.asIntN( + 256, + SqrtPriceMath.getAmount1Delta( + sqrtRatioAX96, + sqrtRatioBX96, + BigInt.asUintN(128, -liquidity), + false, + ), + ) + : BigInt.asIntN( + 256, + SqrtPriceMath.getAmount1Delta( + sqrtRatioAX96, + sqrtRatioBX96, + BigInt.asUintN(128, liquidity), + true, + ), + ); + } +} diff --git a/src/dex/ramses-v2/contract-math/SwapMath.ts b/src/dex/ramses-v2/contract-math/SwapMath.ts new file mode 100644 index 000000000..3f19cf8cb --- /dev/null +++ b/src/dex/ramses-v2/contract-math/SwapMath.ts @@ -0,0 +1,139 @@ +import { BI_POWS } from '../../../bigint-constants'; +import { FullMath } from './FullMath'; +import { SqrtPriceMath } from './SqrtPriceMath'; + +export class SwapMath { + static computeSwapStep( + sqrtRatioCurrentX96: bigint, + sqrtRatioTargetX96: bigint, + liquidity: bigint, + amountRemaining: bigint, + feePips: bigint, + ): { + sqrtRatioNextX96: bigint; + amountIn: bigint; + amountOut: bigint; + feeAmount: bigint; + } { + const zeroForOne = sqrtRatioCurrentX96 >= sqrtRatioTargetX96; + const exactIn = amountRemaining >= 0n; + + let sqrtRatioNextX96 = 0n; + let amountIn = 0n; + let amountOut = 0n; + let feeAmount = 0n; + + if (exactIn) { + const amountRemainingLessFee = FullMath.mulDiv( + BigInt.asUintN(256, amountRemaining), + BI_POWS[6] - feePips, + BI_POWS[6], + ); + amountIn = zeroForOne + ? SqrtPriceMath.getAmount0Delta( + sqrtRatioTargetX96, + sqrtRatioCurrentX96, + liquidity, + true, + ) + : SqrtPriceMath.getAmount1Delta( + sqrtRatioCurrentX96, + sqrtRatioTargetX96, + liquidity, + true, + ); + if (amountRemainingLessFee >= amountIn) + sqrtRatioNextX96 = sqrtRatioTargetX96; + else + sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromInput( + sqrtRatioCurrentX96, + liquidity, + amountRemainingLessFee, + zeroForOne, + ); + } else { + amountOut = zeroForOne + ? SqrtPriceMath.getAmount1Delta( + sqrtRatioTargetX96, + sqrtRatioCurrentX96, + liquidity, + false, + ) + : SqrtPriceMath.getAmount0Delta( + sqrtRatioCurrentX96, + sqrtRatioTargetX96, + liquidity, + false, + ); + if (BigInt.asUintN(256, -amountRemaining) >= amountOut) + sqrtRatioNextX96 = sqrtRatioTargetX96; + else + sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromOutput( + sqrtRatioCurrentX96, + liquidity, + BigInt.asUintN(256, -amountRemaining), + zeroForOne, + ); + } + + const max = sqrtRatioTargetX96 == sqrtRatioNextX96; + + if (zeroForOne) { + amountIn = + max && exactIn + ? amountIn + : SqrtPriceMath.getAmount0Delta( + sqrtRatioNextX96, + sqrtRatioCurrentX96, + liquidity, + true, + ); + amountOut = + max && !exactIn + ? amountOut + : SqrtPriceMath.getAmount1Delta( + sqrtRatioNextX96, + sqrtRatioCurrentX96, + liquidity, + false, + ); + } else { + amountIn = + max && exactIn + ? amountIn + : SqrtPriceMath.getAmount1Delta( + sqrtRatioCurrentX96, + sqrtRatioNextX96, + liquidity, + true, + ); + amountOut = + max && !exactIn + ? amountOut + : SqrtPriceMath.getAmount0Delta( + sqrtRatioCurrentX96, + sqrtRatioNextX96, + liquidity, + false, + ); + } + + // cap the output amount to not exceed the remaining output amount + if (!exactIn && amountOut > BigInt.asUintN(256, -amountRemaining)) { + amountOut = BigInt.asUintN(256, -amountRemaining); + } + + if (exactIn && sqrtRatioNextX96 != sqrtRatioTargetX96) { + // we didn't reach the target, so take the remainder of the maximum input as fee + feeAmount = BigInt.asUintN(256, amountRemaining) - amountIn; + } else { + feeAmount = FullMath.mulDivRoundingUp( + amountIn, + feePips, + BI_POWS[6] - feePips, + ); + } + + return { sqrtRatioNextX96, amountIn, amountOut, feeAmount }; + } +} diff --git a/src/dex/ramses-v2/contract-math/Tick.ts b/src/dex/ramses-v2/contract-math/Tick.ts new file mode 100644 index 000000000..43090a37c --- /dev/null +++ b/src/dex/ramses-v2/contract-math/Tick.ts @@ -0,0 +1,82 @@ +import { PoolState, TickInfo } from '../types'; +import { LiquidityMath } from './LiquidityMath'; +import { _require } from '../../../utils'; +import { NumberAsString } from '@paraswap/core'; +import { ZERO_TICK_INFO } from '../constants'; + +export class Tick { + static update( + state: PoolState, + tick: bigint, + tickCurrent: bigint, + liquidityDelta: bigint, + secondsPerLiquidityCumulativeX128: bigint, + tickCumulative: bigint, + time: bigint, + upper: boolean, + maxLiquidity: bigint, + ): boolean { + let info = state.ticks[Number(tick)]; + + if (info === undefined) { + info = { ...ZERO_TICK_INFO }; + state.ticks[Number(tick)] = info; + } + + const liquidityGrossBefore = info.liquidityGross; + const liquidityGrossAfter = LiquidityMath.addDelta( + liquidityGrossBefore, + liquidityDelta, + ); + + _require( + liquidityGrossAfter <= maxLiquidity, + 'LO', + { liquidityGrossAfter, maxLiquidity }, + 'liquidityGrossAfter <= maxLiquidity', + ); + + const flipped = (liquidityGrossAfter == 0n) != (liquidityGrossBefore == 0n); + + if (liquidityGrossBefore == 0n) { + if (tick <= tickCurrent) { + info.secondsPerLiquidityOutsideX128 = secondsPerLiquidityCumulativeX128; + info.tickCumulativeOutside = tickCumulative; + info.secondsOutside = time; + } + info.initialized = true; + } + + info.liquidityGross = liquidityGrossAfter; + + info.liquidityNet = upper + ? BigInt.asIntN( + 128, + BigInt.asIntN(256, info.liquidityNet) - liquidityDelta, + ) + : BigInt.asIntN( + 128, + BigInt.asIntN(256, info.liquidityNet) + liquidityDelta, + ); + return flipped; + } + + static clear(state: PoolState, tick: bigint) { + delete state.ticks[Number(tick)]; + } + + static cross( + ticks: Record, + tick: bigint, + secondsPerLiquidityCumulativeX128: bigint, + tickCumulative: bigint, + time: bigint, + ): bigint { + const info = ticks[Number(tick)]; + info.secondsPerLiquidityOutsideX128 = + secondsPerLiquidityCumulativeX128 - info.secondsPerLiquidityOutsideX128; + info.tickCumulativeOutside = tickCumulative - info.tickCumulativeOutside; + info.secondsOutside = time - info.secondsOutside; + return info.liquidityNet; + } +} diff --git a/src/dex/ramses-v2/contract-math/TickBitMap.ts b/src/dex/ramses-v2/contract-math/TickBitMap.ts new file mode 100644 index 000000000..4e8648872 --- /dev/null +++ b/src/dex/ramses-v2/contract-math/TickBitMap.ts @@ -0,0 +1,128 @@ +import { BI_MAX_UINT8 } from '../../../bigint-constants'; +import { PoolState } from '../../uniswap-v3/types'; +import { BitMath } from './BitMath'; +import { _require } from '../../../utils'; +import { DeepReadonly } from 'ts-essentials'; +import { + OUT_OF_RANGE_ERROR_POSTFIX, + TICK_BITMAP_BUFFER, + TICK_BITMAP_TO_USE, +} from '../constants'; + +function isWordPosOut( + wordPos: bigint, + startTickBitmap: bigint, + // For pricing we use wider range to check price impact. If function called from event + // it must always be within buffer + isPriceQuery: boolean, +) { + let lowerTickBitmapLimit; + let upperTickBitmapLimit; + + if (isPriceQuery) { + lowerTickBitmapLimit = + startTickBitmap - (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE); + upperTickBitmapLimit = + startTickBitmap + (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE); + } else { + lowerTickBitmapLimit = startTickBitmap - TICK_BITMAP_BUFFER; + upperTickBitmapLimit = startTickBitmap + TICK_BITMAP_BUFFER; + } + + _require( + wordPos >= lowerTickBitmapLimit && wordPos <= upperTickBitmapLimit, + `wordPos is out of safe state tickBitmap request range: ${OUT_OF_RANGE_ERROR_POSTFIX}`, + { wordPos }, + `wordPos >= LOWER_TICK_REQUEST_LIMIT && wordPos <= UPPER_TICK_REQUEST_LIMIT`, + ); +} + +export class TickBitMap { + static position(tick: bigint): [bigint, bigint] { + return [BigInt.asIntN(16, tick >> 8n), BigInt.asUintN(8, tick % 256n)]; + } + + static flipTick(state: PoolState, tick: bigint, tickSpacing: bigint) { + _require( + tick % tickSpacing === 0n, + '', + { tick, tickSpacing }, + 'tick % tickSpacing == 0n,', + ); + const [wordPos, bitPos] = TickBitMap.position(tick / tickSpacing); + const mask = 1n << bitPos; + + // flipTick is used only in _updatePosition which is always state changing event + // Therefore it is never used in price query + isWordPosOut(wordPos, state.startTickBitmap, false); + + const stringWordPos = wordPos.toString(); + if (state.tickBitmap[stringWordPos] === undefined) { + state.tickBitmap[stringWordPos] = 0n; + } + + state.tickBitmap[stringWordPos] ^= mask; + } + + static nextInitializedTickWithinOneWord( + state: DeepReadonly, + tick: bigint, + tickSpacing: bigint, + lte: boolean, + isPriceQuery: boolean, + ): [bigint, boolean] { + let compressed = tick / tickSpacing; + if (tick < 0n && tick % tickSpacing != 0n) compressed--; + + let next = 0n; + let initialized = false; + + if (lte) { + const [wordPos, bitPos] = TickBitMap.position(compressed); + const mask = (1n << bitPos) - 1n + (1n << bitPos); + + isWordPosOut(wordPos, state.startTickBitmap, isPriceQuery); + let tickBitmapValue = state.tickBitmap[wordPos.toString()]; + tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; + + const masked = tickBitmapValue & mask; + + initialized = masked != 0n; + next = initialized + ? (compressed - + BigInt.asIntN(24, bitPos - BitMath.mostSignificantBit(masked))) * + tickSpacing + : (compressed - BigInt.asIntN(24, bitPos)) * tickSpacing; + } else { + // start from the word of the next tick, since the current tick state doesn't matter + const [wordPos, bitPos] = TickBitMap.position(compressed + 1n); + const mask = ~((1n << bitPos) - 1n); + + isWordPosOut(wordPos, state.startTickBitmap, isPriceQuery); + let tickBitmapValue = state.tickBitmap[wordPos.toString()]; + tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; + + const masked = tickBitmapValue & mask; + + initialized = masked != 0n; + next = initialized + ? (compressed + + 1n + + BigInt.asIntN(24, BitMath.leastSignificantBit(masked) - bitPos)) * + tickSpacing + : (compressed + 1n + BigInt.asIntN(24, BI_MAX_UINT8 - bitPos)) * + tickSpacing; + } + + return [next, initialized]; + } + + static _putZeroIfUndefined( + state: PoolState, + tickBitmapValue: bigint | undefined, + wordPos: bigint, + isPriceQuery: boolean = false, + ): bigint { + return tickBitmapValue === undefined ? 0n : tickBitmapValue; + } +} diff --git a/src/dex/ramses-v2/contract-math/TickMath.ts b/src/dex/ramses-v2/contract-math/TickMath.ts new file mode 100644 index 000000000..5515ce15c --- /dev/null +++ b/src/dex/ramses-v2/contract-math/TickMath.ts @@ -0,0 +1,211 @@ +import { gt } from 'lodash'; +import { BI_MAX_UINT256 } from '../../../bigint-constants'; +import { _gt } from './utils'; +import { _require } from '../../../utils'; + +export class TickMath { + static readonly MIN_TICK = -887272n; + static readonly MAX_TICK = -TickMath.MIN_TICK; + static readonly MIN_SQRT_RATIO = 4295128739n; + static readonly MAX_SQRT_RATIO = + 1461446703485210103287273052203988822378723970342n; + + static getSqrtRatioAtTick(tick: bigint): bigint { + const absTick = + tick < 0n + ? BigInt.asUintN(256, -BigInt.asIntN(256, tick)) + : BigInt.asUintN(256, BigInt.asIntN(256, tick)); + _require( + absTick <= BigInt.asUintN(256, TickMath.MAX_TICK), + 'T', + { absTick }, + 'absTick <= BigInt.asUintN(256, TickMath.MAX_TICK)', + ); + + let ratio = + (absTick & 0x1n) !== 0n + ? 0xfffcb933bd6fad37aa2d162d1a594001n + : 0x100000000000000000000000000000000n; + if ((absTick & 0x2n) !== 0n) + ratio = (ratio * 0xfff97272373d413259a46990580e213an) >> 128n; + if ((absTick & 0x4n) !== 0n) + ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdccn) >> 128n; + if ((absTick & 0x8n) !== 0n) + ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0n) >> 128n; + if ((absTick & 0x10n) !== 0n) + ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644n) >> 128n; + if ((absTick & 0x20n) !== 0n) + ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0n) >> 128n; + if ((absTick & 0x40n) !== 0n) + ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861n) >> 128n; + if ((absTick & 0x80n) !== 0n) + ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053n) >> 128n; + if ((absTick & 0x100n) !== 0n) + ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4n) >> 128n; + if ((absTick & 0x200n) !== 0n) + ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54n) >> 128n; + if ((absTick & 0x400n) !== 0n) + ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3n) >> 128n; + if ((absTick & 0x800n) !== 0n) + ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9n) >> 128n; + if ((absTick & 0x1000n) !== 0n) + ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825n) >> 128n; + if ((absTick & 0x2000n) !== 0n) + ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5n) >> 128n; + if ((absTick & 0x4000n) !== 0n) + ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7n) >> 128n; + if ((absTick & 0x8000n) !== 0n) + ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6n) >> 128n; + if ((absTick & 0x10000n) !== 0n) + ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9n) >> 128n; + if ((absTick & 0x20000n) !== 0n) + ratio = (ratio * 0x5d6af8dedb81196699c329225ee604n) >> 128n; + if ((absTick & 0x40000n) !== 0n) + ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98n) >> 128n; + if ((absTick & 0x80000n) !== 0n) + ratio = (ratio * 0x48a170391f7dc42444e8fa2n) >> 128n; + + if (tick > 0) ratio = BI_MAX_UINT256 / ratio; + return BigInt.asUintN( + 160, + (ratio >> 32n) + (ratio % (1n << 32n) == 0n ? 0n : 1n), + ); + } + + static getTickAtSqrtRatio(sqrtPriceX96: bigint): bigint { + _require( + sqrtPriceX96 >= TickMath.MIN_SQRT_RATIO && + sqrtPriceX96 < TickMath.MAX_SQRT_RATIO, + 'R', + { sqrtPriceX96 }, + 'sqrtPriceX96 >= TickMath.MIN_SQRT_RATIO && sqrtPriceX96 < TickMath.MAX_SQRT_RATIO', + ); + + let ratio = BigInt.asUintN(256, sqrtPriceX96) << 32n; + + let r = ratio; + let msb = 0n; + + let f = _gt(r, 0xffffffffffffffffffffffffffffffffn) << 7n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xffffffffffffffffn) << 6n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xffffffffn) << 5n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xffffn) << 4n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xffn) << 3n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xfn) << 2n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0x3n) << 1n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0x1n); + msb = msb | f; + + if (msb >= 128n) r = ratio >> (msb - 127n); + else r = ratio << (127n - msb); + + let log_2 = (BigInt.asIntN(256, msb) - 128n) << 64n; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 63n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 62n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 61n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 60n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 59n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 58n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 57n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 56n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 55n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 54n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 53n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 52n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 51n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 50n); + + const log_sqrt10001 = log_2 * 255738958999603826347141n; // 128.128 number + + const tickLow = BigInt.asIntN( + 24, + (log_sqrt10001 - 3402992956809132418596140100660247210n) >> 128n, + ); + const tickHi = BigInt.asIntN( + 24, + (log_sqrt10001 + 291339464771989622907027621153398088495n) >> 128n, + ); + + return tickLow === tickHi + ? tickLow + : TickMath.getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 + ? tickHi + : tickLow; + } +} diff --git a/src/dex/ramses-v2/contract-math/UnsafeMath.ts b/src/dex/ramses-v2/contract-math/UnsafeMath.ts new file mode 100644 index 000000000..aebd7c579 --- /dev/null +++ b/src/dex/ramses-v2/contract-math/UnsafeMath.ts @@ -0,0 +1,5 @@ +export class UnsafeMath { + static divRoundingUp(x: bigint, y: bigint) { + return (x + y - 1n) / y; + } +} diff --git a/src/dex/ramses-v2/contract-math/uniswap-v3-math.ts b/src/dex/ramses-v2/contract-math/uniswap-v3-math.ts new file mode 100644 index 000000000..3cf27092a --- /dev/null +++ b/src/dex/ramses-v2/contract-math/uniswap-v3-math.ts @@ -0,0 +1,671 @@ +import _ from 'lodash'; +import { + OutputResult, + PoolState, + Slot0, + TickInfo, +} from '../../uniswap-v3/types'; +import { LiquidityMath } from './LiquidityMath'; +import { Oracle } from './Oracle'; +import { SqrtPriceMath } from './SqrtPriceMath'; +import { SwapMath } from './SwapMath'; +import { Tick } from './Tick'; +import { TickBitMap } from './TickBitMap'; +import { TickMath } from './TickMath'; +import { _require } from '../../../utils'; +import { DeepReadonly } from 'ts-essentials'; +import { NumberAsString, SwapSide } from '@paraswap/core'; +import { BI_MAX_INT } from '../../../bigint-constants'; +import { + MAX_PRICING_COMPUTATION_STEPS_ALLOWED, + OUT_OF_RANGE_ERROR_POSTFIX, +} from '../constants'; + +type ModifyPositionParams = { + tickLower: bigint; + tickUpper: bigint; + liquidityDelta: bigint; +}; + +type PriceComputationState = { + amountSpecifiedRemaining: bigint; + amountCalculated: bigint; + sqrtPriceX96: bigint; + tick: bigint; + protocolFee: bigint; + liquidity: bigint; + isFirstCycleState: boolean; +}; + +type PriceComputationCache = { + liquidityStart: bigint; + blockTimestamp: bigint; + feeProtocol: bigint; + secondsPerLiquidityCumulativeX128: bigint; + tickCumulative: bigint; + computedLatestObservation: boolean; + tickCount: number; +}; + +function _updatePriceComputationObjects< + T extends PriceComputationState | PriceComputationCache, +>(toUpdate: T, updateBy: T) { + for (const k of Object.keys(updateBy) as (keyof T)[]) { + toUpdate[k] = updateBy[k]; + } +} + +function _priceComputationCycles( + poolState: DeepReadonly, + ticksCopy: Record, + slot0Start: Slot0, + state: PriceComputationState, + cache: PriceComputationCache, + sqrtPriceLimitX96: bigint, + zeroForOne: boolean, + exactInput: boolean, +): [ + // result + PriceComputationState, + // Latest calculated full cycle state we can use for bigger amounts + { + latestFullCycleState: PriceComputationState; + latestFullCycleCache: PriceComputationCache; + }, +] { + const latestFullCycleState: PriceComputationState = { ...state }; + + if (cache.tickCount == 0) { + cache.tickCount = 1; + } + const latestFullCycleCache: PriceComputationCache = { ...cache }; + + // We save tick before any change. Later we use this to restore + // state before last step + let lastTicksCopy: { index: number; tick: TickInfo } | undefined; + + let i = 0; + for ( + ; + state.amountSpecifiedRemaining !== 0n && + state.sqrtPriceX96 !== sqrtPriceLimitX96; + ++i + ) { + if ( + latestFullCycleCache.tickCount + i > + MAX_PRICING_COMPUTATION_STEPS_ALLOWED + ) { + state.amountSpecifiedRemaining = 0n; + state.amountCalculated = 0n; + break; + } + + const step = { + sqrtPriceStartX96: 0n, + tickNext: 0n, + initialized: false, + sqrtPriceNextX96: 0n, + amountIn: 0n, + amountOut: 0n, + feeAmount: 0n, + }; + + step.sqrtPriceStartX96 = state.sqrtPriceX96; + + try { + [step.tickNext, step.initialized] = + TickBitMap.nextInitializedTickWithinOneWord( + poolState, + state.tick, + poolState.tickSpacing, + zeroForOne, + true, + ); + } catch (e) { + if ( + e instanceof Error && + e.message.endsWith(OUT_OF_RANGE_ERROR_POSTFIX) + ) { + state.amountSpecifiedRemaining = 0n; + state.amountCalculated = 0n; + break; + } + throw e; + } + + if (step.tickNext < TickMath.MIN_TICK) { + step.tickNext = TickMath.MIN_TICK; + } else if (step.tickNext > TickMath.MAX_TICK) { + step.tickNext = TickMath.MAX_TICK; + } + + step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext); + + const swapStepResult = SwapMath.computeSwapStep( + state.sqrtPriceX96, + ( + zeroForOne + ? step.sqrtPriceNextX96 < sqrtPriceLimitX96 + : step.sqrtPriceNextX96 > sqrtPriceLimitX96 + ) + ? sqrtPriceLimitX96 + : step.sqrtPriceNextX96, + state.liquidity, + state.amountSpecifiedRemaining, + poolState.fee, + ); + + state.sqrtPriceX96 = swapStepResult.sqrtRatioNextX96; + step.amountIn = swapStepResult.amountIn; + step.amountOut = swapStepResult.amountOut; + step.feeAmount = swapStepResult.feeAmount; + + if (exactInput) { + state.amountSpecifiedRemaining -= step.amountIn + step.feeAmount; + state.amountCalculated = state.amountCalculated - step.amountOut; + } else { + state.amountSpecifiedRemaining += step.amountOut; + state.amountCalculated = + state.amountCalculated + step.amountIn + step.feeAmount; + } + + if (cache.feeProtocol > 0n) { + const delta = step.feeAmount / cache.feeProtocol; + step.feeAmount -= delta; + state.protocolFee += delta; + } + + if (state.sqrtPriceX96 === step.sqrtPriceNextX96) { + if (step.initialized) { + if (!cache.computedLatestObservation) { + [cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128] = + Oracle.observeSingle( + poolState, + cache.blockTimestamp, + 0n, + slot0Start.tick, + slot0Start.observationIndex, + cache.liquidityStart, + slot0Start.observationCardinality, + ); + cache.computedLatestObservation = true; + } + + if (state.amountSpecifiedRemaining === 0n) { + const castTickNext = Number(step.tickNext); + lastTicksCopy = { + index: castTickNext, + tick: { ...ticksCopy[castTickNext] }, + }; + } + + let liquidityNet = Tick.cross( + ticksCopy, + step.tickNext, + cache.secondsPerLiquidityCumulativeX128, + cache.tickCumulative, + cache.blockTimestamp, + ); + if (zeroForOne) liquidityNet = -liquidityNet; + + state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet); + } + + state.tick = zeroForOne ? step.tickNext - 1n : step.tickNext; + } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) { + state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96); + } + + if (state.amountSpecifiedRemaining !== 0n) { + _updatePriceComputationObjects(latestFullCycleState, state); + _updatePriceComputationObjects(latestFullCycleCache, cache); + // If it last cycle, check if ticks were changed and then restore previous state + // for next calculations + } else if (lastTicksCopy !== undefined) { + ticksCopy[lastTicksCopy.index] = lastTicksCopy.tick; + } + } + + if (i > 1) { + latestFullCycleCache.tickCount += i - 1; + } + + if (state.amountSpecifiedRemaining !== 0n) { + state.amountSpecifiedRemaining = 0n; + state.amountCalculated = 0n; + } + + return [state, { latestFullCycleState, latestFullCycleCache }]; +} + +class UniswapV3Math { + queryOutputs( + poolState: DeepReadonly, + // Amounts must increase + amounts: bigint[], + zeroForOne: boolean, + side: SwapSide, + ): OutputResult { + const slot0Start = poolState.slot0; + + const isSell = side === SwapSide.SELL; + + // While calculating, ticks are changing, so to not change the actual state, + // we use copy + const ticksCopy = _.cloneDeep(poolState.ticks); + + const sqrtPriceLimitX96 = zeroForOne + ? TickMath.MIN_SQRT_RATIO + 1n + : TickMath.MAX_SQRT_RATIO - 1n; + + const cache: PriceComputationCache = { + liquidityStart: poolState.liquidity, + blockTimestamp: this._blockTimestamp(poolState), + feeProtocol: zeroForOne + ? slot0Start.feeProtocol % 16n + : slot0Start.feeProtocol >> 4n, + secondsPerLiquidityCumulativeX128: 0n, + tickCumulative: 0n, + computedLatestObservation: false, + tickCount: 0, + }; + + const state: PriceComputationState = { + // Will be overwritten later + amountSpecifiedRemaining: 0n, + amountCalculated: 0n, + sqrtPriceX96: slot0Start.sqrtPriceX96, + tick: slot0Start.tick, + protocolFee: 0n, + liquidity: cache.liquidityStart, + isFirstCycleState: true, + }; + + let isOutOfRange = false; + let previousAmount = 0n; + + const outputs = new Array(amounts.length); + const tickCounts = new Array(amounts.length); + for (const [i, amount] of amounts.entries()) { + if (amount === 0n) { + outputs[i] = 0n; + tickCounts[i] = 0; + continue; + } + + const amountSpecified = isSell + ? BigInt.asIntN(256, amount) + : -BigInt.asIntN(256, amount); + + if (state.isFirstCycleState) { + // Set first non zero amount + state.amountSpecifiedRemaining = amountSpecified; + state.isFirstCycleState = false; + } else { + state.amountSpecifiedRemaining = + amountSpecified - (previousAmount - state.amountSpecifiedRemaining); + } + + const exactInput = amountSpecified > 0n; + + _require( + zeroForOne + ? sqrtPriceLimitX96 < slot0Start.sqrtPriceX96 && + sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO + : sqrtPriceLimitX96 > slot0Start.sqrtPriceX96 && + sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO, + 'SPL', + { zeroForOne, sqrtPriceLimitX96, slot0Start }, + 'zeroForOne ? sqrtPriceLimitX96 < slot0Start.sqrtPriceX96 && sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO : sqrtPriceLimitX96 > slot0Start.sqrtPriceX96 && sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO', + ); + + if (!isOutOfRange) { + const [finalState, { latestFullCycleState, latestFullCycleCache }] = + _priceComputationCycles( + poolState, + ticksCopy, + slot0Start, + state, + cache, + sqrtPriceLimitX96, + zeroForOne, + exactInput, + ); + if ( + finalState.amountSpecifiedRemaining === 0n && + finalState.amountCalculated === 0n + ) { + isOutOfRange = true; + outputs[i] = 0n; + tickCounts[i] = 0; + continue; + } + + // We use it on next step to correct state.amountSpecifiedRemaining + previousAmount = amountSpecified; + + // First extract calculated values + const [amount0, amount1] = + zeroForOne === exactInput + ? [ + amountSpecified - finalState.amountSpecifiedRemaining, + finalState.amountCalculated, + ] + : [ + finalState.amountCalculated, + amountSpecified - finalState.amountSpecifiedRemaining, + ]; + + // Update for next amount + _updatePriceComputationObjects(state, latestFullCycleState); + _updatePriceComputationObjects(cache, latestFullCycleCache); + + if (isSell) { + outputs[i] = BigInt.asUintN(256, -(zeroForOne ? amount1 : amount0)); + tickCounts[i] = latestFullCycleCache.tickCount; + continue; + } else { + outputs[i] = zeroForOne + ? BigInt.asUintN(256, amount0) + : BigInt.asUintN(256, amount1); + tickCounts[i] = latestFullCycleCache.tickCount; + continue; + } + } else { + outputs[i] = 0n; + tickCounts[i] = 0; + } + } + + return { + outputs, + tickCounts, + }; + } + + swapFromEvent( + poolState: PoolState, + newSqrtPriceX96: bigint, + newTick: bigint, + newLiquidity: bigint, + zeroForOne: boolean, + ): void { + const slot0Start = poolState.slot0; + + const cache = { + liquidityStart: poolState.liquidity, + blockTimestamp: this._blockTimestamp(poolState), + feeProtocol: 0n, + secondsPerLiquidityCumulativeX128: 0n, + tickCumulative: 0n, + computedLatestObservation: false, + }; + + const state = { + // Because I don't have the exact amount user used, set this number to MAX_NUMBER to proceed + // with calculations. I think it is not a problem since in loop I don't rely on this value + amountSpecifiedRemaining: BI_MAX_INT, + amountCalculated: 0n, + sqrtPriceX96: slot0Start.sqrtPriceX96, + tick: slot0Start.tick, + protocolFee: 0n, + liquidity: cache.liquidityStart, + }; + + // Because I didn't have all variables, adapted loop stop with state.tick !== newTick + // condition. This cycle need only to calculate Tick.cross() function values + // It means that we are interested in cycling only if state.tick !== newTick + // When they become equivalent, we proceed with state updating part as normal + // And if assumptions regarding this cycle are correct, we don't need to process + // the last cycle when state.tick === newTick + while (state.tick !== newTick && state.sqrtPriceX96 !== newSqrtPriceX96) { + const step = { + sqrtPriceStartX96: 0n, + tickNext: 0n, + initialized: false, + sqrtPriceNextX96: 0n, + amountIn: 0n, + amountOut: 0n, + feeAmount: 0n, + }; + + step.sqrtPriceStartX96 = state.sqrtPriceX96; + + [step.tickNext, step.initialized] = + TickBitMap.nextInitializedTickWithinOneWord( + poolState, + state.tick, + poolState.tickSpacing, + zeroForOne, + false, + ); + + if (step.tickNext < TickMath.MIN_TICK) { + step.tickNext = TickMath.MIN_TICK; + } else if (step.tickNext > TickMath.MAX_TICK) { + step.tickNext = TickMath.MAX_TICK; + } + + step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext); + + const swapStepResult = SwapMath.computeSwapStep( + state.sqrtPriceX96, + ( + zeroForOne + ? step.sqrtPriceNextX96 < newSqrtPriceX96 + : step.sqrtPriceNextX96 > newSqrtPriceX96 + ) + ? newSqrtPriceX96 + : step.sqrtPriceNextX96, + state.liquidity, + state.amountSpecifiedRemaining, + poolState.fee, + ); + + state.sqrtPriceX96 = swapStepResult.sqrtRatioNextX96; + + if (state.sqrtPriceX96 == step.sqrtPriceNextX96) { + if (step.initialized) { + if (!cache.computedLatestObservation) { + [cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128] = + Oracle.observeSingle( + poolState, + cache.blockTimestamp, + 0n, + slot0Start.tick, + slot0Start.observationIndex, + cache.liquidityStart, + slot0Start.observationCardinality, + ); + cache.computedLatestObservation = true; + } + + let liquidityNet = Tick.cross( + poolState.ticks, + step.tickNext, + cache.secondsPerLiquidityCumulativeX128, + cache.tickCumulative, + cache.blockTimestamp, + ); + + if (zeroForOne) liquidityNet = -liquidityNet; + + state.liquidity = LiquidityMath.addDelta( + state.liquidity, + liquidityNet, + ); + } + + state.tick = zeroForOne ? step.tickNext - 1n : step.tickNext; + } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) { + state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96); + } + } + + if (slot0Start.tick !== newTick) { + const [observationIndex, observationCardinality] = Oracle.write( + poolState, + slot0Start.observationIndex, + this._blockTimestamp(poolState), + slot0Start.tick, + poolState.liquidity, + slot0Start.observationCardinality, + slot0Start.observationCardinalityNext, + ); + + [ + poolState.slot0.sqrtPriceX96, + poolState.slot0.tick, + poolState.slot0.observationIndex, + poolState.slot0.observationCardinality, + ] = [newSqrtPriceX96, newTick, observationIndex, observationCardinality]; + } else { + poolState.slot0.sqrtPriceX96 = newSqrtPriceX96; + } + + if (poolState.liquidity !== newLiquidity) + poolState.liquidity = newLiquidity; + } + + _modifyPosition( + state: PoolState, + params: ModifyPositionParams, + ): [bigint, bigint] { + const _slot0 = state.slot0; + + this._updatePosition( + state, + params.tickLower, + params.tickUpper, + params.liquidityDelta, + _slot0.tick, + ); + + let amount0 = 0n; + let amount1 = 0n; + if (params.liquidityDelta !== 0n) { + if (_slot0.tick < params.tickLower) { + amount0 = SqrtPriceMath._getAmount0DeltaO( + TickMath.getSqrtRatioAtTick(params.tickLower), + TickMath.getSqrtRatioAtTick(params.tickUpper), + params.liquidityDelta, + ); + } else if (_slot0.tick < params.tickUpper) { + const liquidityBefore = state.liquidity; + + [state.slot0.observationIndex, state.slot0.observationCardinality] = + Oracle.write( + state, + _slot0.observationIndex, + this._blockTimestamp(state), + _slot0.tick, + liquidityBefore, + _slot0.observationCardinality, + _slot0.observationCardinalityNext, + ); + + amount0 = SqrtPriceMath._getAmount0DeltaO( + _slot0.sqrtPriceX96, + TickMath.getSqrtRatioAtTick(params.tickUpper), + params.liquidityDelta, + ); + amount1 = SqrtPriceMath._getAmount1DeltaO( + TickMath.getSqrtRatioAtTick(params.tickLower), + _slot0.sqrtPriceX96, + params.liquidityDelta, + ); + + state.liquidity = LiquidityMath.addDelta( + liquidityBefore, + params.liquidityDelta, + ); + } else { + amount1 = SqrtPriceMath._getAmount1DeltaO( + TickMath.getSqrtRatioAtTick(params.tickLower), + TickMath.getSqrtRatioAtTick(params.tickUpper), + params.liquidityDelta, + ); + } + } + return [amount0, amount1]; + } + + private _isTickToProcess(state: PoolState, tick: bigint): boolean { + return tick >= state.lowestKnownTick && tick <= state.highestKnownTick; + } + + private _updatePosition( + state: PoolState, + tickLower: bigint, + tickUpper: bigint, + liquidityDelta: bigint, + tick: bigint, + ): void { + // if we need to update the ticks, do it + let flippedLower = false; + let flippedUpper = false; + if (liquidityDelta !== 0n) { + const time = this._blockTimestamp(state); + const [tickCumulative, secondsPerLiquidityCumulativeX128] = + Oracle.observeSingle( + state, + time, + 0n, + state.slot0.tick, + state.slot0.observationIndex, + state.liquidity, + state.slot0.observationCardinality, + ); + + if (this._isTickToProcess(state, tickLower)) { + flippedLower = Tick.update( + state, + tickLower, + tick, + liquidityDelta, + secondsPerLiquidityCumulativeX128, + tickCumulative, + time, + false, + state.maxLiquidityPerTick, + ); + } + if (this._isTickToProcess(state, tickUpper)) { + flippedUpper = Tick.update( + state, + tickUpper, + tick, + liquidityDelta, + secondsPerLiquidityCumulativeX128, + tickCumulative, + time, + true, + state.maxLiquidityPerTick, + ); + } + + if (flippedLower) { + TickBitMap.flipTick(state, tickLower, state.tickSpacing); + } + if (flippedUpper) { + TickBitMap.flipTick(state, tickUpper, state.tickSpacing); + } + } + + // clear any tick data that is no longer needed + if (liquidityDelta < 0n) { + if (flippedLower) { + Tick.clear(state, tickLower); + } + if (flippedUpper) { + Tick.clear(state, tickUpper); + } + } + } + + private _blockTimestamp(state: DeepReadonly) { + return BigInt.asUintN(32, state.blockTimestamp); + } +} + +export const uniswapV3Math = new UniswapV3Math(); diff --git a/src/dex/ramses-v2/contract-math/utils.ts b/src/dex/ramses-v2/contract-math/utils.ts new file mode 100644 index 000000000..0f4caff99 --- /dev/null +++ b/src/dex/ramses-v2/contract-math/utils.ts @@ -0,0 +1,11 @@ +export function _mulmod(x: bigint, y: bigint, m: bigint): bigint { + return m === 0n ? 0n : (x * y) % m; +} + +export function _lt(x: bigint, y: bigint) { + return x < y ? 1n : 0n; +} + +export function _gt(x: bigint, y: bigint) { + return x > y ? 1n : 0n; +} diff --git a/src/dex/ramses-v2/ramses-v2-e2e.test.ts b/src/dex/ramses-v2/ramses-v2-e2e.test.ts new file mode 100644 index 000000000..8088a7897 --- /dev/null +++ b/src/dex/ramses-v2/ramses-v2-e2e.test.ts @@ -0,0 +1,67 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { testE2E } from '../../../tests/utils-e2e'; +import { + Tokens, + Holders, + NativeTokenSymbols, +} from '../../../tests/constants-e2e'; +import { Network, ContractMethod, SwapSide } from '../../constants'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; + +describe('RamsesV2 E2E', () => { + const dexKey = 'RamsesV2'; + + describe('UniswapV3 MAINNET', () => { + const network = Network.ARBITRUM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + it('BUY DAI -> USDC', async () => { + await testE2E( + tokens['DAI'], + tokens['USDC'], + holders['DAI'], + '100000000000', + SwapSide.BUY, + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + it('SELL WETH -> SHIBA', async () => { + await testE2E( + tokens['WETH'], + tokens['SHIBA'], + holders['WETH'], + '1000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('directSwap SELL WETH -> USDC', async () => { + await testE2E( + tokens['WETH'], + tokens['USDC'], + holders['WETH'], + '1000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.directUniV3Swap, + network, + provider, + ); + }); + }); +}); diff --git a/src/dex/ramses-v2/ramses-v2-events.test.ts b/src/dex/ramses-v2/ramses-v2-events.test.ts new file mode 100644 index 000000000..ef49cebc1 --- /dev/null +++ b/src/dex/ramses-v2/ramses-v2-events.test.ts @@ -0,0 +1,106 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { RamsesV2EventPool } from './ramses-v2-pool'; +import { Network } from '../../constants'; +import { Address } from '../../types'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { testEventSubscriber } from '../../../tests/utils-events'; +import { PoolState } from './types'; + +/* + README + ====== + + This test script adds unit tests for RamsesV2 event based + system. This is done by fetching the state on-chain before the + event block, manually pushing the block logs to the event-subscriber, + comparing the local state with on-chain state. + + Most of the logic for testing is abstracted by `testEventSubscriber`. + You need to do two things to make the tests work: + + 1. Fetch the block numbers where certain events were released. You + can modify the `./scripts/fetch-event-blocknumber.ts` to get the + block numbers for different events. Make sure to get sufficient + number of blockNumbers to cover all possible cases for the event + mutations. + + 2. Complete the implementation for fetchPoolState function. The + function should fetch the on-chain state of the event subscriber + using just the blocknumber. + + The template tests only include the test for a single event + subscriber. There can be cases where multiple event subscribers + exist for a single DEX. In such cases additional tests should be + added. + + You can run this individual test script by running: + `npx jest src/dex//-events.test.ts` + + (This comment should be removed from the final implementation) +*/ + +jest.setTimeout(50 * 1000); + +async function fetchPoolState( + ramsesV2Pools: RamsesV2EventPool, + blockNumber: number, + poolAddress: string, +): Promise { + // TODO: complete me! + return {}; +} + +// eventName -> blockNumbers +type EventMappings = Record; + +describe('RamsesV2 EventPool Mainnet', function () { + const dexKey = 'RamsesV2'; + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + const logger = dexHelper.getLogger(dexKey); + let ramsesV2Pool: RamsesV2EventPool; + + // poolAddress -> EventMappings + const eventsToTest: Record = { + // TODO: complete me! + }; + + beforeEach(async () => { + ramsesV2Pool = new RamsesV2EventPool( + dexKey, + network, + dexHelper, + logger, + /* TODO: Put here additional constructor arguments if needed */ + ); + }); + + Object.entries(eventsToTest).forEach( + ([poolAddress, events]: [string, EventMappings]) => { + describe(`Events for ${poolAddress}`, () => { + Object.entries(events).forEach( + ([eventName, blockNumbers]: [string, number[]]) => { + describe(`${eventName}`, () => { + blockNumbers.forEach((blockNumber: number) => { + it(`State after ${blockNumber}`, async function () { + await testEventSubscriber( + ramsesV2Pool, + ramsesV2Pool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolState(ramsesV2Pool, _blockNumber, poolAddress), + blockNumber, + `${dexKey}_${poolAddress}`, + dexHelper.provider, + ); + }); + }); + }); + }, + ); + }); + }, + ); +}); diff --git a/src/dex/ramses-v2/ramses-v2-integration.test.ts b/src/dex/ramses-v2/ramses-v2-integration.test.ts new file mode 100644 index 000000000..debf0fd9b --- /dev/null +++ b/src/dex/ramses-v2/ramses-v2-integration.test.ts @@ -0,0 +1,251 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { Interface, Result } from '@ethersproject/abi'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { Network, SwapSide } from '../../constants'; +import { BI_POWS } from '../../bigint-constants'; +import { RamsesV2 } from './ramses-v2'; +import { + checkPoolPrices, + checkPoolsLiquidity, + checkConstantPoolPrices, +} from '../../../tests/utils'; +import { Tokens } from '../../../tests/constants-e2e'; + +/* + README + ====== + + This test script adds tests for RamsesV2 general integration + with the DEX interface. The test cases below are example tests. + It is recommended to add tests which cover RamsesV2 specific + logic. + + You can run this individual test script by running: + `npx jest src/dex//-integration.test.ts` + + (This comment should be removed from the final implementation) +*/ + +function getReaderCalldata( + exchangeAddress: string, + readerIface: Interface, + amounts: bigint[], + funcName: string, + // TODO: Put here additional arguments you need +) { + return amounts.map(amount => ({ + target: exchangeAddress, + callData: readerIface.encodeFunctionData(funcName, [ + // TODO: Put here additional arguments to encode them + amount, + ]), + })); +} + +function decodeReaderResult( + results: Result, + readerIface: Interface, + funcName: string, +) { + // TODO: Adapt this function for your needs + return results.map(result => { + const parsed = readerIface.decodeFunctionResult(funcName, result); + return BigInt(parsed[0]._hex); + }); +} + +async function checkOnChainPricing( + ramsesV2: RamsesV2, + funcName: string, + blockNumber: number, + prices: bigint[], + amounts: bigint[], +) { + const exchangeAddress = ''; // TODO: Put here the real exchange address + + // TODO: Replace dummy interface with the real one + // Normally you can get it from ramsesV2.Iface or from eventPool. + // It depends on your implementation + const readerIface = new Interface(''); + + const readerCallData = getReaderCalldata( + exchangeAddress, + readerIface, + amounts.slice(1), + funcName, + ); + const readerResult = ( + await ramsesV2.dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blockNumber) + ).returnData; + + const expectedPrices = [0n].concat( + decodeReaderResult(readerResult, readerIface, funcName), + ); + + expect(prices).toEqual(expectedPrices); +} + +async function testPricingOnNetwork( + ramsesV2: RamsesV2, + network: Network, + dexKey: string, + blockNumber: number, + srcTokenSymbol: string, + destTokenSymbol: string, + side: SwapSide, + amounts: bigint[], + funcNameToCheck: string, +) { + const networkTokens = Tokens[network]; + + const pools = await ramsesV2.getPoolIdentifiers( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + side, + blockNumber, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await ramsesV2.getPricesVolume( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + amounts, + side, + blockNumber, + pools, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + if (ramsesV2.hasConstantPriceLargeAmounts) { + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + } else { + checkPoolPrices(poolPrices!, amounts, side, dexKey); + } + + // Check if onchain pricing equals to calculated ones + await checkOnChainPricing( + ramsesV2, + funcNameToCheck, + blockNumber, + poolPrices![0].prices, + amounts, + ); +} + +describe('RamsesV2', function () { + const dexKey = 'RamsesV2'; + let blockNumber: number; + let ramsesV2: RamsesV2; + + describe('Mainnet', () => { + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + + // TODO: Put here token Symbol to check against + // Don't forget to update relevant tokens in constant-e2e.ts + const srcTokenSymbol = 'srcTokenSymbol'; + const destTokenSymbol = 'destTokenSymbol'; + + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals], + 2n * BI_POWS[tokens[destTokenSymbol].decimals], + 3n * BI_POWS[tokens[destTokenSymbol].decimals], + 4n * BI_POWS[tokens[destTokenSymbol].decimals], + 5n * BI_POWS[tokens[destTokenSymbol].decimals], + 6n * BI_POWS[tokens[destTokenSymbol].decimals], + 7n * BI_POWS[tokens[destTokenSymbol].decimals], + 8n * BI_POWS[tokens[destTokenSymbol].decimals], + 9n * BI_POWS[tokens[destTokenSymbol].decimals], + 10n * BI_POWS[tokens[destTokenSymbol].decimals], + ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + ramsesV2 = new RamsesV2(network, dexKey, dexHelper); + if (ramsesV2.initializePricing) { + await ramsesV2.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + ramsesV2, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + '', // TODO: Put here proper function name to check pricing + ); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + ramsesV2, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + '', // TODO: Put here proper function name to check pricing + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newRamsesV2 = new RamsesV2(network, dexKey, dexHelper); + if (newRamsesV2.updatePoolState) { + await newRamsesV2.updatePoolState(); + } + const poolLiquidity = await newRamsesV2.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newRamsesV2.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); + }); +}); diff --git a/src/dex/ramses-v2/ramses-v2-pool.ts b/src/dex/ramses-v2/ramses-v2-pool.ts new file mode 100644 index 000000000..413e21742 --- /dev/null +++ b/src/dex/ramses-v2/ramses-v2-pool.ts @@ -0,0 +1,91 @@ +import { Interface } from '@ethersproject/abi'; +import { DeepReadonly } from 'ts-essentials'; +import { Log, Logger } from '../../types'; +import { catchParseLogError } from '../../utils'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { PoolState } from './types'; + +export class RamsesV2EventPool extends StatefulEventSubscriber { + handlers: { + [event: string]: ( + event: any, + state: DeepReadonly, + log: Readonly, + ) => DeepReadonly | null; + } = {}; + + logDecoder: (log: Log) => any; + + addressesSubscribed: string[]; + + constructor( + readonly parentName: string, + protected network: number, + protected dexHelper: IDexHelper, + logger: Logger, + protected ramsesV2Iface = new Interface( + '' /* TODO: Import and put here RamsesV2 ABI */, + ), // TODO: add any additional params required for event subscriber + ) { + // TODO: Add pool name + super(parentName, 'POOL_NAME', dexHelper, logger); + + // TODO: make logDecoder decode logs that + this.logDecoder = (log: Log) => this.ramsesV2Iface.parseLog(log); + this.addressesSubscribed = [ + /* subscribed addresses */ + ]; + + // Add handlers + this.handlers['myEvent'] = this.handleMyEvent.bind(this); + } + + /** + * The function is called every time any of the subscribed + * addresses release log. The function accepts the current + * state, updates the state according to the log, and returns + * the updated state. + * @param state - Current state of event subscriber + * @param log - Log released by one of the subscribed addresses + * @returns Updates state of the event subscriber after the log + */ + protected processLog( + state: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + try { + const event = this.logDecoder(log); + if (event.name in this.handlers) { + return this.handlers[event.name](event, state, log); + } + } catch (e) { + catchParseLogError(e, this.logger); + } + + return null; + } + + /** + * The function generates state using on-chain calls. This + * function is called to regenerate state if the event based + * system fails to fetch events and the local state is no + * more correct. + * @param blockNumber - Blocknumber for which the state should + * should be generated + * @returns state of the event subscriber at blocknumber + */ + async generateState(blockNumber: number): Promise> { + // TODO: complete me! + return {}; + } + + // Its just a dummy example + handleMyEvent( + event: any, + state: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + return null; + } +} diff --git a/src/dex/ramses-v2/ramses-v2.ts b/src/dex/ramses-v2/ramses-v2.ts new file mode 100644 index 000000000..7f72e7cfb --- /dev/null +++ b/src/dex/ramses-v2/ramses-v2.ts @@ -0,0 +1,178 @@ +import { AsyncOrSync } from 'ts-essentials'; +import { + Token, + Address, + ExchangePrices, + PoolPrices, + AdapterExchangeParam, + SimpleExchangeParam, + PoolLiquidity, + Logger, +} from '../../types'; +import { SwapSide, Network } from '../../constants'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { getDexKeysWithNetwork } from '../../utils'; +import { IDex } from '../../dex/idex'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { RamsesV2Data } from './types'; +import { SimpleExchange } from '../simple-exchange'; +import { RamsesV2Config, Adapters } from './config'; +import { RamsesV2EventPool } from './ramses-v2-pool'; + +export class RamsesV2 extends SimpleExchange implements IDex { + protected eventPools: RamsesV2EventPool; + + readonly hasConstantPriceLargeAmounts = false; + // TODO: set true here if protocols works only with wrapped asset + readonly needWrapNative = true; + + readonly isFeeOnTransferSupported = false; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(RamsesV2Config); + + logger: Logger; + + constructor( + readonly network: Network, + readonly dexKey: string, + readonly dexHelper: IDexHelper, + protected adapters = Adapters[network] || {}, // TODO: add any additional optional params to support other fork DEXes + ) { + super(dexHelper, dexKey); + this.logger = dexHelper.getLogger(dexKey); + this.eventPools = new RamsesV2EventPool( + dexKey, + network, + dexHelper, + this.logger, + ); + } + + // Initialize pricing is called once in the start of + // pricing service. It is intended to setup the integration + // for pricing requests. It is optional for a DEX to + // implement this function + async initializePricing(blockNumber: number) { + // TODO: complete me! + } + + // Returns the list of contract adapters (name and index) + // for a buy/sell. Return null if there are no adapters. + getAdapters(side: SwapSide): { name: string; index: number }[] | null { + return this.adapters[side] ? this.adapters[side] : null; + } + + // Returns list of pool identifiers that can be used + // for a given swap. poolIdentifiers must be unique + // across DEXes. It is recommended to use + // ${dexKey}_${poolAddress} as a poolIdentifier + async getPoolIdentifiers( + srcToken: Token, + destToken: Token, + side: SwapSide, + blockNumber: number, + ): Promise { + // TODO: complete me! + return []; + } + + // Returns pool prices for amounts. + // If limitPools is defined only pools in limitPools + // should be used. If limitPools is undefined then + // any pools can be used. + async getPricesVolume( + srcToken: Token, + destToken: Token, + amounts: bigint[], + side: SwapSide, + blockNumber: number, + limitPools?: string[], + ): Promise> { + // TODO: complete me! + return null; + } + + // Returns estimated gas cost of calldata for this DEX in multiSwap + getCalldataGasCost(poolPrices: PoolPrices): number | number[] { + // TODO: update if there is any payload in getAdapterParam + return CALLDATA_GAS_COST.DEX_NO_PAYLOAD; + } + + // Encode params required by the exchange adapter + // Used for multiSwap, buy & megaSwap + // Hint: abiCoder.encodeParameter() could be useful + getAdapterParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: RamsesV2Data, + side: SwapSide, + ): AdapterExchangeParam { + // TODO: complete me! + const { exchange } = data; + + // Encode here the payload for adapter + const payload = ''; + + return { + targetExchange: exchange, + payload, + networkFee: '0', + }; + } + + // Encode call data used by simpleSwap like routers + // Used for simpleSwap & simpleBuy + // Hint: this.buildSimpleParamWithoutWETHConversion + // could be useful + async getSimpleParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: RamsesV2Data, + side: SwapSide, + ): Promise { + // TODO: complete me! + const { exchange } = data; + + // Encode here the transaction arguments + const swapData = ''; + + return this.buildSimpleParamWithoutWETHConversion( + srcToken, + srcAmount, + destToken, + destAmount, + swapData, + exchange, + ); + } + + // This is called once before getTopPoolsForToken is + // called for multiple tokens. This can be helpful to + // update common state required for calculating + // getTopPoolsForToken. It is optional for a DEX + // to implement this + async updatePoolState(): Promise { + // TODO: complete me! + } + + // Returns list of top pools based on liquidity. Max + // limit number pools should be returned. + async getTopPoolsForToken( + tokenAddress: Address, + limit: number, + ): Promise { + //TODO: complete me! + return []; + } + + // This is optional function in case if your implementation has acquired any resources + // you need to release for graceful shutdown. For example, it may be any interval timer + releaseResources(): AsyncOrSync { + // TODO: complete me! + } +} diff --git a/src/dex/ramses-v2/types.ts b/src/dex/ramses-v2/types.ts new file mode 100644 index 000000000..8cfcd3d32 --- /dev/null +++ b/src/dex/ramses-v2/types.ts @@ -0,0 +1,22 @@ +import { Address } from '../../types'; + +export type PoolState = { + // TODO: poolState is the state of event + // subscriber. This should be the minimum + // set of parameters required to compute + // pool prices. Complete me! +}; + +export type RamsesV2Data = { + // TODO: RamsesV2Data is the dex data that is + // returned by the API that can be used for + // tx building. The data structure should be minimal. + // Complete me! + exchange: Address; +}; + +export type DexParams = { + // TODO: DexParams is set of parameters the can + // be used to initiate a DEX fork. + // Complete me! +}; From fef448d7d0e02394cd3b24caee3ba3e20618e96c Mon Sep 17 00:00:00 2001 From: 0xshad0w Date: Fri, 23 Jun 2023 12:04:59 +0100 Subject: [PATCH 023/833] 1 - create dex/ramses-v2 --- src/dex/ramses-v2/contract-math/Tick.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/ramses-v2/contract-math/Tick.ts b/src/dex/ramses-v2/contract-math/Tick.ts index 43090a37c..d5621c7fa 100644 --- a/src/dex/ramses-v2/contract-math/Tick.ts +++ b/src/dex/ramses-v2/contract-math/Tick.ts @@ -1,4 +1,4 @@ -import { PoolState, TickInfo } from '../types'; +import { PoolState, TickInfo } from '../../uniswap-v3/types'; import { LiquidityMath } from './LiquidityMath'; import { _require } from '../../../utils'; import { NumberAsString } from '@paraswap/core'; From bb54ed96bf77d1c637ed1028c2b2b0ea1a1b3edc Mon Sep 17 00:00:00 2001 From: 0xshad0w Date: Fri, 23 Jun 2023 13:21:12 +0100 Subject: [PATCH 024/833] 2 - updates --- src/dex/ramses-v2/contract-math/Oracle.ts | 2 +- src/dex/ramses-v2/contract-math/Tick.ts | 2 +- src/dex/ramses-v2/contract-math/TickBitMap.ts | 2 +- .../contract-math/uniswap-v3-math.ts | 7 +- src/dex/ramses-v2/ramses-v2-pool.ts | 565 ++++++++- src/dex/ramses-v2/ramses-v2.ts | 1118 +++++++++++++++-- src/dex/ramses-v2/types.ts | 179 ++- 7 files changed, 1719 insertions(+), 156 deletions(-) diff --git a/src/dex/ramses-v2/contract-math/Oracle.ts b/src/dex/ramses-v2/contract-math/Oracle.ts index 059e84e28..19b1918d1 100644 --- a/src/dex/ramses-v2/contract-math/Oracle.ts +++ b/src/dex/ramses-v2/contract-math/Oracle.ts @@ -2,7 +2,7 @@ import { OracleObservation, OracleObservationCandidates, PoolState, -} from '../../uniswap-v3/types'; +} from '../types'; import { _require } from '../../../utils'; import { DeepReadonly } from 'ts-essentials'; import { ZERO_ORACLE_OBSERVATION } from '../constants'; diff --git a/src/dex/ramses-v2/contract-math/Tick.ts b/src/dex/ramses-v2/contract-math/Tick.ts index d5621c7fa..43090a37c 100644 --- a/src/dex/ramses-v2/contract-math/Tick.ts +++ b/src/dex/ramses-v2/contract-math/Tick.ts @@ -1,4 +1,4 @@ -import { PoolState, TickInfo } from '../../uniswap-v3/types'; +import { PoolState, TickInfo } from '../types'; import { LiquidityMath } from './LiquidityMath'; import { _require } from '../../../utils'; import { NumberAsString } from '@paraswap/core'; diff --git a/src/dex/ramses-v2/contract-math/TickBitMap.ts b/src/dex/ramses-v2/contract-math/TickBitMap.ts index 4e8648872..2d50a779c 100644 --- a/src/dex/ramses-v2/contract-math/TickBitMap.ts +++ b/src/dex/ramses-v2/contract-math/TickBitMap.ts @@ -1,5 +1,5 @@ import { BI_MAX_UINT8 } from '../../../bigint-constants'; -import { PoolState } from '../../uniswap-v3/types'; +import { PoolState } from '../types'; import { BitMath } from './BitMath'; import { _require } from '../../../utils'; import { DeepReadonly } from 'ts-essentials'; diff --git a/src/dex/ramses-v2/contract-math/uniswap-v3-math.ts b/src/dex/ramses-v2/contract-math/uniswap-v3-math.ts index 3cf27092a..ab3a1f301 100644 --- a/src/dex/ramses-v2/contract-math/uniswap-v3-math.ts +++ b/src/dex/ramses-v2/contract-math/uniswap-v3-math.ts @@ -1,10 +1,5 @@ import _ from 'lodash'; -import { - OutputResult, - PoolState, - Slot0, - TickInfo, -} from '../../uniswap-v3/types'; +import { OutputResult, PoolState, Slot0, TickInfo } from '../types'; import { LiquidityMath } from './LiquidityMath'; import { Oracle } from './Oracle'; import { SqrtPriceMath } from './SqrtPriceMath'; diff --git a/src/dex/ramses-v2/ramses-v2-pool.ts b/src/dex/ramses-v2/ramses-v2-pool.ts index 413e21742..b68af23a3 100644 --- a/src/dex/ramses-v2/ramses-v2-pool.ts +++ b/src/dex/ramses-v2/ramses-v2-pool.ts @@ -1,91 +1,546 @@ +import _ from 'lodash'; +import { Contract } from 'web3-eth-contract'; import { Interface } from '@ethersproject/abi'; -import { DeepReadonly } from 'ts-essentials'; -import { Log, Logger } from '../../types'; -import { catchParseLogError } from '../../utils'; -import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { ethers } from 'ethers'; +import { assert, DeepReadonly } from 'ts-essentials'; +import { Log, Logger, BlockHeader, Address } from '../../types'; +import { + InitializeStateOptions, + StatefulEventSubscriber, +} from '../../stateful-event-subscriber'; import { IDexHelper } from '../../dex-helper/idex-helper'; -import { PoolState } from './types'; +import { + PoolState, + DecodedStateMultiCallResultWithRelativeBitmaps, + TickInfo, + TickBitMapMappingsWithBigNumber, + TickInfoMappingsWithBigNumber, +} from './types'; +import UniswapV3PoolABI from '../../abi/uniswap-v3/UniswapV3Pool.abi.json'; +import { bigIntify, catchParseLogError, isSampled } from '../../utils'; +import { uniswapV3Math } from './contract-math/uniswap-v3-math'; +import { MultiCallParams } from '../../lib/multi-wrapper'; +import { NumberAsString } from '@paraswap/core'; +import { + DEFAULT_POOL_INIT_CODE_HASH, + OUT_OF_RANGE_ERROR_POSTFIX, + TICK_BITMAP_BUFFER, + TICK_BITMAP_TO_USE, +} from './constants'; +import { TickBitMap } from './contract-math/TickBitMap'; +import { uint256ToBigInt } from '../../lib/decoders'; +import { decodeStateMultiCallResultWithRelativeBitmaps } from './utils'; export class RamsesV2EventPool extends StatefulEventSubscriber { handlers: { [event: string]: ( event: any, - state: DeepReadonly, - log: Readonly, - ) => DeepReadonly | null; + pool: PoolState, + log: Log, + blockHeader: Readonly, + ) => PoolState; } = {}; logDecoder: (log: Log) => any; - addressesSubscribed: string[]; + readonly token0: Address; + + readonly token1: Address; + + private _poolAddress?: Address; + + private _stateRequestCallData?: MultiCallParams< + bigint | DecodedStateMultiCallResultWithRelativeBitmaps + >[]; + + public readonly poolIface = new Interface(UniswapV3PoolABI); + + public readonly feeCodeAsString; constructor( - readonly parentName: string, - protected network: number, - protected dexHelper: IDexHelper, + readonly dexHelper: IDexHelper, + parentName: string, + readonly stateMultiContract: Contract, + readonly erc20Interface: Interface, + protected readonly factoryAddress: Address, + public readonly feeCode: bigint, + token0: Address, + token1: Address, logger: Logger, - protected ramsesV2Iface = new Interface( - '' /* TODO: Import and put here RamsesV2 ABI */, - ), // TODO: add any additional params required for event subscriber + mapKey: string = '', + readonly poolInitCodeHash: string, ) { - // TODO: Add pool name - super(parentName, 'POOL_NAME', dexHelper, logger); - - // TODO: make logDecoder decode logs that - this.logDecoder = (log: Log) => this.ramsesV2Iface.parseLog(log); - this.addressesSubscribed = [ - /* subscribed addresses */ - ]; + super( + parentName, + `${token0}_${token1}_${feeCode}`, + dexHelper, + logger, + true, + mapKey, + ); + this.feeCodeAsString = feeCode.toString(); + this.token0 = token0.toLowerCase(); + this.token1 = token1.toLowerCase(); + this.logDecoder = (log: Log) => this.poolIface.parseLog(log); + this.addressesSubscribed = new Array
(1); // Add handlers - this.handlers['myEvent'] = this.handleMyEvent.bind(this); - } - - /** - * The function is called every time any of the subscribed - * addresses release log. The function accepts the current - * state, updates the state according to the log, and returns - * the updated state. - * @param state - Current state of event subscriber - * @param log - Log released by one of the subscribed addresses - * @returns Updates state of the event subscriber after the log - */ + this.handlers['Swap'] = this.handleSwapEvent.bind(this); + this.handlers['Burn'] = this.handleBurnEvent.bind(this); + this.handlers['Mint'] = this.handleMintEvent.bind(this); + this.handlers['SetFeeProtocol'] = this.handleSetFeeProtocolEvent.bind(this); + this.handlers['IncreaseObservationCardinalityNext'] = + this.handleIncreaseObservationCardinalityNextEvent.bind(this); + + // Wen need them to keep balance of the pool up to date + this.handlers['Collect'] = this.handleCollectEvent.bind(this); + // Almost the same as Collect, but for pool owners + this.handlers['CollectProtocol'] = this.handleCollectEvent.bind(this); + this.handlers['Flash'] = this.handleFlashEvent.bind(this); + } + + get poolAddress() { + if (this._poolAddress === undefined) { + this._poolAddress = this._computePoolAddress( + this.token0, + this.token1, + this.feeCode, + ); + } + return this._poolAddress; + } + + set poolAddress(address: Address) { + this._poolAddress = address.toLowerCase(); + } + + async initialize( + blockNumber: number, + options?: InitializeStateOptions, + ) { + await super.initialize(blockNumber, options); + } + + protected async processBlockLogs( + state: DeepReadonly, + logs: Readonly[], + blockHeader: Readonly, + ): Promise | null> { + const newState = await super.processBlockLogs(state, logs, blockHeader); + if (newState && !newState.isValid) { + return await this.generateState(blockHeader.number); + } + return newState; + } + protected processLog( state: DeepReadonly, log: Readonly, + blockHeader: Readonly, ): DeepReadonly | null { try { const event = this.logDecoder(log); + + const uniswapV3EventLoggingSampleRate = + this.dexHelper.config.data.uniswapV3EventLoggingSampleRate; + if ( + !this.dexHelper.config.isSlave && + uniswapV3EventLoggingSampleRate && + isSampled(uniswapV3EventLoggingSampleRate) + ) { + this.logger.info( + `event=${event.name} - block=${ + blockHeader.number + }. Log sampled at rate ${uniswapV3EventLoggingSampleRate * 100}%`, + ); + } + if (event.name in this.handlers) { - return this.handlers[event.name](event, state, log); + // Because we have observations in array which is mutable by nature, there is a + // ts compile error: https://stackoverflow.com/questions/53412934/disable-allowing-assigning-readonly-types-to-non-readonly-types + // And there is no good workaround, so turn off the type checker for this line + const _state = _.cloneDeep(state) as PoolState; + try { + return this.handlers[event.name](event, _state, log, blockHeader); + } catch (e) { + if ( + e instanceof Error && + e.message.endsWith(OUT_OF_RANGE_ERROR_POSTFIX) + ) { + this.logger.warn( + `${this.parentName}: Pool ${this.poolAddress} on ${ + this.dexHelper.config.data.network + } is out of TickBitmap requested range. Re-query the state. ${JSON.stringify( + event, + )}`, + e, + ); + } else { + this.logger.error( + `${this.parentName}: Pool ${this.poolAddress}, ` + + `network=${this.dexHelper.config.data.network}: Unexpected ` + + `error while handling event on blockNumber=${blockHeader.number}, ` + + `blockHash=${blockHeader.hash} and parentHash=${ + blockHeader.parentHash + } for UniswapV3, ${JSON.stringify(event)}`, + e, + ); + } + _state.isValid = false; + return _state; + } } } catch (e) { catchParseLogError(e, this.logger); } + return null; // ignore unrecognized event + } + + private _getStateRequestCallData() { + if (!this._stateRequestCallData) { + const callData: MultiCallParams< + bigint | DecodedStateMultiCallResultWithRelativeBitmaps + >[] = [ + { + target: this.token0, + callData: this.erc20Interface.encodeFunctionData('balanceOf', [ + this.poolAddress, + ]), + decodeFunction: uint256ToBigInt, + }, + { + target: this.token1, + callData: this.erc20Interface.encodeFunctionData('balanceOf', [ + this.poolAddress, + ]), + decodeFunction: uint256ToBigInt, + }, + { + target: this.stateMultiContract.options.address, + callData: this.stateMultiContract.methods + .getFullStateWithRelativeBitmaps( + this.factoryAddress, + this.token0, + this.token1, + this.feeCode, + this.getBitmapRangeToRequest(), + this.getBitmapRangeToRequest(), + ) + .encodeABI(), + decodeFunction: decodeStateMultiCallResultWithRelativeBitmaps, + }, + ]; + this._stateRequestCallData = callData; + } + return this._stateRequestCallData; + } - return null; + getBitmapRangeToRequest() { + return TICK_BITMAP_TO_USE + TICK_BITMAP_BUFFER; } - /** - * The function generates state using on-chain calls. This - * function is called to regenerate state if the event based - * system fails to fetch events and the local state is no - * more correct. - * @param blockNumber - Blocknumber for which the state should - * should be generated - * @returns state of the event subscriber at blocknumber - */ - async generateState(blockNumber: number): Promise> { - // TODO: complete me! - return {}; + async generateState(blockNumber: number): Promise> { + const callData = this._getStateRequestCallData(); + + const [resBalance0, resBalance1, resState] = + await this.dexHelper.multiWrapper.tryAggregate< + bigint | DecodedStateMultiCallResultWithRelativeBitmaps + >( + false, + callData, + blockNumber, + this.dexHelper.multiWrapper.defaultBatchSize, + false, + ); + + // Quite ugly solution, but this is the one that fits to current flow. + // I think UniswapV3 callbacks subscriptions are complexified for no reason. + // Need to be revisited later + assert(resState.success, 'Pool does not exist'); + + const [balance0, balance1, _state] = [ + resBalance0.returnData, + resBalance1.returnData, + resState.returnData, + ] as [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmaps]; + + const tickBitmap = {}; + const ticks = {}; + + this._reduceTickBitmap(tickBitmap, _state.tickBitmap); + this._reduceTicks(ticks, _state.ticks); + + const observations = { + [_state.slot0.observationIndex]: { + blockTimestamp: bigIntify(_state.observation.blockTimestamp), + tickCumulative: bigIntify(_state.observation.tickCumulative), + secondsPerLiquidityCumulativeX128: bigIntify( + _state.observation.secondsPerLiquidityCumulativeX128, + ), + initialized: _state.observation.initialized, + }, + }; + + const currentTick = bigIntify(_state.slot0.tick); + const tickSpacing = bigIntify(_state.tickSpacing); + + const startTickBitmap = TickBitMap.position(currentTick / tickSpacing)[0]; + const requestedRange = this.getBitmapRangeToRequest(); + + return { + pool: _state.pool, + blockTimestamp: bigIntify(_state.blockTimestamp), + slot0: { + sqrtPriceX96: bigIntify(_state.slot0.sqrtPriceX96), + tick: currentTick, + observationIndex: +_state.slot0.observationIndex, + observationCardinality: +_state.slot0.observationCardinality, + observationCardinalityNext: +_state.slot0.observationCardinalityNext, + feeProtocol: bigIntify(_state.slot0.feeProtocol), + }, + liquidity: bigIntify(_state.liquidity), + fee: this.feeCode, + tickSpacing, + maxLiquidityPerTick: bigIntify(_state.maxLiquidityPerTick), + tickBitmap, + ticks, + observations, + isValid: true, + startTickBitmap, + lowestKnownTick: + (BigInt.asIntN(24, startTickBitmap - requestedRange) << 8n) * + tickSpacing, + highestKnownTick: + ((BigInt.asIntN(24, startTickBitmap + requestedRange) << 8n) + + BigInt.asIntN(24, 255n)) * + tickSpacing, + balance0, + balance1, + }; } - // Its just a dummy example - handleMyEvent( + handleSwapEvent( event: any, - state: DeepReadonly, - log: Readonly, - ): DeepReadonly | null { - return null; + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const newSqrtPriceX96 = bigIntify(event.args.sqrtPriceX96); + const amount0 = bigIntify(event.args.amount0); + const amount1 = bigIntify(event.args.amount1); + const newTick = bigIntify(event.args.tick); + const newLiquidity = bigIntify(event.args.liquidity); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + if (amount0 <= 0n && amount1 <= 0n) { + this.logger.error( + `${this.parentName}: amount0 <= 0n && amount1 <= 0n for ` + + `${this.poolAddress} and ${blockHeader.number}. Check why it happened`, + ); + pool.isValid = false; + return pool; + } else { + const zeroForOne = amount0 > 0n; + + uniswapV3Math.swapFromEvent( + pool, + newSqrtPriceX96, + newTick, + newLiquidity, + zeroForOne, + ); + + if (zeroForOne) { + if (amount1 < 0n) { + pool.balance1 -= BigInt.asUintN(256, -amount1); + } else { + this.logger.error( + `In swapEvent for pool ${pool.pool} received incorrect values ${zeroForOne} and ${amount1}`, + ); + pool.isValid = false; + } + // This is not correct fully, because pool may get more tokens then it needs, but + // it is not accounted in internal state, it should be good enough + pool.balance0 += BigInt.asUintN(256, amount0); + } else { + if (amount0 < 0n) { + pool.balance0 -= BigInt.asUintN(256, -amount0); + } else { + this.logger.error( + `In swapEvent for pool ${pool.pool} received incorrect values ${zeroForOne} and ${amount0}`, + ); + pool.isValid = false; + } + pool.balance1 += BigInt.asUintN(256, amount1); + } + + return pool; + } + } + + handleBurnEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const amount = bigIntify(event.args.amount); + const tickLower = bigIntify(event.args.tickLower); + const tickUpper = bigIntify(event.args.tickUpper); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + uniswapV3Math._modifyPosition(pool, { + tickLower, + tickUpper, + liquidityDelta: -BigInt.asIntN(128, BigInt.asIntN(256, amount)), + }); + + // From this transaction I conclude that there is no balance change from + // Burn event: https://dashboard.tenderly.co/tx/mainnet/0xfccf5341147ac3ad0e66452273d12dfc3219e81f8fb369a6cdecfb24b9b9d078/logs + // And it aligns with UniswapV3 doc: + // https://github.com/Uniswap/v3-core/blob/05c10bf6d547d6121622ac51c457f93775e1df09/contracts/interfaces/pool/IUniswapV3PoolActions.sol#L59 + // It just updates positions and tokensOwed which may be requested calling collect + // So, we don't need to update pool.balances0 and pool.balances1 here + + return pool; + } + + handleMintEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const amount = bigIntify(event.args.amount); + const tickLower = bigIntify(event.args.tickLower); + const tickUpper = bigIntify(event.args.tickUpper); + const amount0 = bigIntify(event.args.amount0); + const amount1 = bigIntify(event.args.amount1); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + uniswapV3Math._modifyPosition(pool, { + tickLower, + tickUpper, + liquidityDelta: amount, + }); + + pool.balance0 += amount0; + pool.balance1 += amount1; + + return pool; + } + + handleSetFeeProtocolEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const feeProtocol0 = bigIntify(event.args.feeProtocol0New); + const feeProtocol1 = bigIntify(event.args.feeProtocol1New); + pool.slot0.feeProtocol = feeProtocol0 + (feeProtocol1 << 4n); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + return pool; + } + + handleCollectEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const amount0 = bigIntify(event.args.amount0); + const amount1 = bigIntify(event.args.amount1); + pool.balance0 -= amount0; + pool.balance1 -= amount1; + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + return pool; + } + + handleFlashEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const paid0 = bigIntify(event.args.paid0); + const paid1 = bigIntify(event.args.paid1); + pool.balance0 += paid0; + pool.balance1 += paid1; + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + return pool; + } + + handleIncreaseObservationCardinalityNextEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + pool.slot0.observationCardinalityNext = parseInt( + event.args.observationCardinalityNextNew, + 10, + ); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + return pool; + } + + private _reduceTickBitmap( + tickBitmap: Record, + tickBitmapToReduce: TickBitMapMappingsWithBigNumber[], + ) { + return tickBitmapToReduce.reduce>( + (acc, curr) => { + const { index, value } = curr; + acc[index] = bigIntify(value); + return acc; + }, + tickBitmap, + ); + } + + private _reduceTicks( + ticks: Record, + ticksToReduce: TickInfoMappingsWithBigNumber[], + ) { + return ticksToReduce.reduce>((acc, curr) => { + const { index, value } = curr; + acc[index] = { + liquidityGross: bigIntify(value.liquidityGross), + liquidityNet: bigIntify(value.liquidityNet), + tickCumulativeOutside: bigIntify(value.tickCumulativeOutside), + secondsPerLiquidityOutsideX128: bigIntify( + value.secondsPerLiquidityOutsideX128, + ), + secondsOutside: bigIntify(value.secondsOutside), + initialized: value.initialized, + }; + return acc; + }, ticks); + } + + private _computePoolAddress( + token0: Address, + token1: Address, + fee: bigint, + ): Address { + // https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/PoolAddress.sol + if (token0 > token1) [token0, token1] = [token1, token0]; + + const encodedKey = ethers.utils.keccak256( + ethers.utils.defaultAbiCoder.encode( + ['address', 'address', 'uint24'], + [token0, token1, BigInt.asUintN(24, fee)], + ), + ); + + return ethers.utils.getCreate2Address( + this.factoryAddress, + encodedKey, + this.poolInitCodeHash, + ); } } diff --git a/src/dex/ramses-v2/ramses-v2.ts b/src/dex/ramses-v2/ramses-v2.ts index 7f72e7cfb..6a62dade8 100644 --- a/src/dex/ramses-v2/ramses-v2.ts +++ b/src/dex/ramses-v2/ramses-v2.ts @@ -1,86 +1,467 @@ -import { AsyncOrSync } from 'ts-essentials'; +import { defaultAbiCoder, Interface } from '@ethersproject/abi'; +import _ from 'lodash'; +import { pack } from '@ethersproject/solidity'; import { Token, Address, ExchangePrices, - PoolPrices, AdapterExchangeParam, SimpleExchangeParam, PoolLiquidity, Logger, + NumberAsString, + PoolPrices, + TxInfo, + PreprocessTransactionOptions, + ExchangeTxInfo, } from '../../types'; -import { SwapSide, Network } from '../../constants'; +import { SwapSide, Network, CACHE_PREFIX } from '../../constants'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { getDexKeysWithNetwork } from '../../utils'; +import { + getBigIntPow, + getDexKeysWithNetwork, + interpolate, + isTruthy, + uuidToBytes16, +} from '../../utils'; import { IDex } from '../../dex/idex'; import { IDexHelper } from '../../dex-helper/idex-helper'; -import { RamsesV2Data } from './types'; -import { SimpleExchange } from '../simple-exchange'; +import { + DexParams, + OutputResult, + PoolState, + RamsesV2Data, + RamsesV2Functions, + RamsesV2Param, + RamsesV2SimpleSwapParams, +} from './types'; +import { + getLocalDeadlineAsFriendlyPlaceholder, + SimpleExchange, +} from '../simple-exchange'; import { RamsesV2Config, Adapters } from './config'; import { RamsesV2EventPool } from './ramses-v2-pool'; +import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; +import UniswapV3QuoterABI from '../../abi/uniswap-v3/UniswapV3Quoter.abi.json'; +import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; +import DirectSwapABI from '../../abi/DirectSwap.json'; +import UniswapV3StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; +import { + DirectMethods, + UNISWAPV3_EFFICIENCY_FACTOR, + UNISWAPV3_POOL_SEARCH_OVERHEAD, + UNISWAPV3_TICK_BASE_OVERHEAD, + UNISWAPV3_TICK_GAS_COST, +} from './constants'; +import { assert, DeepReadonly } from 'ts-essentials'; +import { uniswapV3Math } from './contract-math/uniswap-v3-math'; +import { Contract } from 'web3-eth-contract'; +import { AbiItem } from 'web3-utils'; +import { BalanceRequest, getBalances } from '../../lib/tokens/balancer-fetcher'; +import { + AssetType, + DEFAULT_ID_ERC20, + DEFAULT_ID_ERC20_AS_STRING, +} from '../../lib/tokens/types'; +import { OptimalSwapExchange } from '@paraswap/core'; + +type PoolPairsInfo = { + token0: Address; + token1: Address; + fee: string; +}; + +const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 60 * 60 * 24 * 1000; // 24 hours +const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 30 * 60 * 1000; // Once in 30 minutes +const UNISWAPV3_QUOTE_GASLIMIT = 200_000; -export class RamsesV2 extends SimpleExchange implements IDex { - protected eventPools: RamsesV2EventPool; +export class RamsesV2 + extends SimpleExchange + implements IDex +{ + readonly isFeeOnTransferSupported: boolean = false; + readonly eventPools: Record = {}; readonly hasConstantPriceLargeAmounts = false; - // TODO: set true here if protocols works only with wrapped asset readonly needWrapNative = true; - readonly isFeeOnTransferSupported = false; + readonly directSwapIface = new Interface(DirectSwapABI); + + intervalTask?: NodeJS.Timeout; public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(RamsesV2Config); + getDexKeysWithNetwork(_.pick(RamsesV2Config, ['RamsesV2'])); logger: Logger; + private uniswapMulti: Contract; + private stateMultiContract: Contract; + + private notExistingPoolSetKey: string; + constructor( - readonly network: Network, - readonly dexKey: string, - readonly dexHelper: IDexHelper, - protected adapters = Adapters[network] || {}, // TODO: add any additional optional params to support other fork DEXes + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + protected adapters = Adapters[network] || {}, + readonly routerIface = new Interface(UniswapV3RouterABI), + readonly quoterIface = new Interface(UniswapV3QuoterABI), + protected config = RamsesV2Config[dexKey][network], ) { super(dexHelper, dexKey); - this.logger = dexHelper.getLogger(dexKey); - this.eventPools = new RamsesV2EventPool( - dexKey, - network, - dexHelper, - this.logger, + this.logger = dexHelper.getLogger(dexKey + '-' + network); + this.uniswapMulti = new this.dexHelper.web3Provider.eth.Contract( + UniswapV3MultiABI as AbiItem[], + this.config.uniswapMulticall, + ); + this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( + UniswapV3StateMulticallABI as AbiItem[], + this.config.stateMulticall, ); + + // To receive revert reasons + this.dexHelper.web3Provider.eth.handleRevert = false; + + // Normalize once all config addresses and use across all scenarios + this.config = this._toLowerForAllConfigAddresses(); + + this.notExistingPoolSetKey = + `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); } - // Initialize pricing is called once in the start of - // pricing service. It is intended to setup the integration - // for pricing requests. It is optional for a DEX to - // implement this function - async initializePricing(blockNumber: number) { - // TODO: complete me! + get supportedFees() { + return this.config.supportedFees; } - // Returns the list of contract adapters (name and index) - // for a buy/sell. Return null if there are no adapters. getAdapters(side: SwapSide): { name: string; index: number }[] | null { return this.adapters[side] ? this.adapters[side] : null; } - // Returns list of pool identifiers that can be used - // for a given swap. poolIdentifiers must be unique - // across DEXes. It is recommended to use - // ${dexKey}_${poolAddress} as a poolIdentifier + getPoolIdentifier(srcAddress: Address, destAddress: Address, fee: bigint) { + const tokenAddresses = this._sortTokens(srcAddress, destAddress).join('_'); + return `${this.dexKey}_${tokenAddresses}_${fee}`; + } + + async initializePricing(blockNumber: number) { + if (!this.dexHelper.config.isSlave) { + const cleanExpiredNotExistingPoolsKeys = async () => { + const maxTimestamp = + Date.now() - UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS; + await this.dexHelper.cache.zremrangebyscore( + this.notExistingPoolSetKey, + 0, + maxTimestamp, + ); + }; + + this.intervalTask = setInterval( + cleanExpiredNotExistingPoolsKeys.bind(this), + UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS, + ); + } + } + + async getPool( + srcAddress: Address, + destAddress: Address, + fee: bigint, + blockNumber: number, + ): Promise { + let pool = + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)]; + + if (pool === undefined) { + const [token0, token1] = this._sortTokens(srcAddress, destAddress); + + const key = `${token0}_${token1}_${fee}`.toLowerCase(); + + const notExistingPoolScore = await this.dexHelper.cache.zscore( + this.notExistingPoolSetKey, + key, + ); + + const poolDoesNotExist = notExistingPoolScore !== null; + + if (poolDoesNotExist) { + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = + null; + return null; + } + + await this.dexHelper.cache.hset( + this.dexmapKey, + key, + JSON.stringify({ + token0, + token1, + fee: fee.toString(), + }), + ); + + this.logger.trace(`starting to listen to new pool: ${key}`); + pool = new RamsesV2EventPool( + this.dexHelper, + this.dexKey, + this.stateMultiContract, + this.erc20Interface, + this.config.factory, + fee, + token0, + token1, + this.logger, + this.cacheStateKey, + this.config.initHash, + ); + + try { + await pool.initialize(blockNumber, { + initCallback: (state: DeepReadonly) => { + //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber + pool!.addressesSubscribed[0] = state.pool; + pool!.poolAddress = state.pool; + }, + }); + } catch (e) { + if (e instanceof Error && e.message.endsWith('Pool does not exist')) { + // no need to await we want the set to have the pool key but it's not blocking + this.dexHelper.cache.zadd( + this.notExistingPoolSetKey, + [Date.now(), key], + 'NX', + ); + + // Pool does not exist for this feeCode, so we can set it to null + // to prevent more requests for this pool + pool = null; + this.logger.trace( + `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, + e, + ); + } else { + // Unexpected Error. Break execution. Do not save the pool in this.eventPools + this.logger.error( + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool`, + e, + ); + throw new Error('Cannot generate pool state'); + } + } + + if (pool !== null) { + const allEventPools = Object.values(this.eventPools); + this.logger.info( + `starting to listen to new non-null pool: ${key}. Already following ${allEventPools + // Not that I like this reduce, but since it is done only on initialization, expect this to be ok + .reduce( + (acc, curr) => (curr !== null ? ++acc : acc), + 0, + )} non-null pools or ${allEventPools.length} total pools`, + ); + } + + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = + pool; + } + return pool; + } + + async addMasterPool(poolKey: string, blockNumber: number): Promise { + const _pairs = await this.dexHelper.cache.hget(this.dexmapKey, poolKey); + if (!_pairs) { + this.logger.warn( + `did not find poolConfig in for key ${this.dexmapKey} ${poolKey}`, + ); + return false; + } + + const poolInfo: PoolPairsInfo = JSON.parse(_pairs); + + const pool = await this.getPool( + poolInfo.token0, + poolInfo.token1, + BigInt(poolInfo.fee), + blockNumber, + ); + + if (!pool) { + return false; + } + + return true; + } + async getPoolIdentifiers( srcToken: Token, destToken: Token, side: SwapSide, blockNumber: number, ): Promise { - // TODO: complete me! - return []; + const _srcToken = this.dexHelper.config.wrapETH(srcToken); + const _destToken = this.dexHelper.config.wrapETH(destToken); + + const [_srcAddress, _destAddress] = this._getLoweredAddresses( + _srcToken, + _destToken, + ); + + if (_srcAddress === _destAddress) return []; + + const pools = ( + await Promise.all( + this.supportedFees.map(async fee => + this.getPool(_srcAddress, _destAddress, fee, blockNumber), + ), + ) + ).filter(pool => pool); + + if (pools.length === 0) return []; + + return pools.map(pool => + this.getPoolIdentifier(_srcAddress, _destAddress, pool!.feeCode), + ); + } + + async getPricingFromRpc( + from: Token, + to: Token, + amounts: bigint[], + side: SwapSide, + pools: RamsesV2EventPool[], + ): Promise | null> { + if (pools.length === 0) { + return null; + } + this.logger.warn(`fallback to rpc for ${pools.length} pool(s)`); + + const requests = pools.map( + pool => ({ + owner: pool.poolAddress, + asset: side == SwapSide.SELL ? from.address : to.address, + assetType: AssetType.ERC20, + ids: [ + { + id: DEFAULT_ID_ERC20, + spenders: [], + }, + ], + }), + [], + ); + + const balances = await getBalances(this.dexHelper.multiWrapper, requests); + + pools = pools.filter((pool, index) => { + const balance = balances[index].amounts[DEFAULT_ID_ERC20_AS_STRING]; + if (balance >= amounts[amounts.length - 1]) { + return true; + } + this.logger.warn( + `[${this.network}][${pool.parentName}] have no balance ${pool.poolAddress} ${from.address} ${to.address}. (Balance: ${balance})`, + ); + return false; + }); + + pools.forEach(pool => { + this.logger.warn( + `[${this.network}][${pool.parentName}] fallback to rpc for ${pool.name}`, + ); + }); + + const unitVolume = getBigIntPow( + (side === SwapSide.SELL ? from : to).decimals, + ); + + const chunks = amounts.length - 1; + + const _width = Math.floor(chunks / this.config.chunksCount); + + const _amounts = [unitVolume].concat( + Array.from(Array(this.config.chunksCount).keys()).map( + i => amounts[(i + 1) * _width], + ), + ); + + const calldata = pools.map(pool => + _amounts.map(_amount => ({ + target: this.config.quoter, + gasLimit: UNISWAPV3_QUOTE_GASLIMIT, + callData: + side === SwapSide.SELL + ? this.quoterIface.encodeFunctionData('quoteExactInputSingle', [ + [ + from.address, + to.address, + _amount.toString(), + pool.feeCodeAsString, + 0, //sqrtPriceLimitX96 + ], + ]) + : this.quoterIface.encodeFunctionData('quoteExactOutputSingle', [ + [ + from.address, + to.address, + _amount.toString(), + pool.feeCodeAsString, + 0, //sqrtPriceLimitX96 + ], + ]), + })), + ); + + const data = await this.uniswapMulti.methods + .multicall(calldata.flat()) + .call(); + + const decode = (j: number): bigint => { + if (!data.returnData[j].success) { + return 0n; + } + const decoded = defaultAbiCoder.decode( + ['uint256'], + data.returnData[j].returnData, + ); + return BigInt(decoded[0].toString()); + }; + + let i = 0; + const result = pools.map(pool => { + const _rates = _amounts.map(() => decode(i++)); + const unit: bigint = _rates[0]; + + const prices = interpolate( + _amounts.slice(1), + _rates.slice(1), + amounts, + side, + ); + + return { + prices, + unit, + data: { + path: [ + { + tokenIn: from.address, + tokenOut: to.address, + fee: pool.feeCodeAsString, + }, + ], + exchange: pool.poolAddress, + }, + poolIdentifier: this.getPoolIdentifier( + pool.token0, + pool.token1, + pool.feeCode, + ), + exchange: this.dexKey, + gasCost: prices.map(p => (p === 0n ? 0 : UNISWAPV3_QUOTE_GASLIMIT)), + poolAddresses: [pool.poolAddress], + }; + }); + + return result; } - // Returns pool prices for amounts. - // If limitPools is defined only pools in limitPools - // should be used. If limitPools is undefined then - // any pools can be used. async getPricesVolume( srcToken: Token, destToken: Token, @@ -89,19 +470,209 @@ export class RamsesV2 extends SimpleExchange implements IDex { blockNumber: number, limitPools?: string[], ): Promise> { - // TODO: complete me! - return null; - } + try { + const _srcToken = this.dexHelper.config.wrapETH(srcToken); + const _destToken = this.dexHelper.config.wrapETH(destToken); - // Returns estimated gas cost of calldata for this DEX in multiSwap - getCalldataGasCost(poolPrices: PoolPrices): number | number[] { - // TODO: update if there is any payload in getAdapterParam - return CALLDATA_GAS_COST.DEX_NO_PAYLOAD; + const [_srcAddress, _destAddress] = this._getLoweredAddresses( + _srcToken, + _destToken, + ); + + if (_srcAddress === _destAddress) return null; + + let selectedPools: RamsesV2EventPool[] = []; + + if (!limitPools) { + selectedPools = ( + await Promise.all( + this.supportedFees.map(async fee => { + const locallyFoundPool = + this.eventPools[ + this.getPoolIdentifier(_srcAddress, _destAddress, fee) + ]; + if (locallyFoundPool) return locallyFoundPool; + + const newlyFetchedPool = await this.getPool( + _srcAddress, + _destAddress, + fee, + blockNumber, + ); + return newlyFetchedPool; + }), + ) + ).filter(isTruthy); + } else { + const pairIdentifierWithoutFee = this.getPoolIdentifier( + _srcAddress, + _destAddress, + 0n, + // Trim from 0 fee postfix, so it become comparable + ).slice(0, -1); + + const poolIdentifiers = limitPools.filter(identifier => + identifier.startsWith(pairIdentifierWithoutFee), + ); + + selectedPools = ( + await Promise.all( + poolIdentifiers.map(async identifier => { + let locallyFoundPool = this.eventPools[identifier]; + if (locallyFoundPool) return locallyFoundPool; + + const [, srcAddress, destAddress, fee] = identifier.split('_'); + const newlyFetchedPool = await this.getPool( + srcAddress, + destAddress, + BigInt(fee), + blockNumber, + ); + return newlyFetchedPool; + }), + ) + ).filter(isTruthy); + } + + if (selectedPools.length === 0) return null; + + const poolsToUse = selectedPools.reduce( + (acc, pool) => { + let state = pool.getState(blockNumber); + if (state === null) { + this.logger.trace( + `${this.dexKey}: State === null. Fallback to rpc ${pool.name}`, + ); + acc.poolWithoutState.push(pool); + } else { + acc.poolWithState.push(pool); + } + return acc; + }, + { + poolWithState: [] as RamsesV2EventPool[], + poolWithoutState: [] as RamsesV2EventPool[], + }, + ); + + const rpcResultsPromise = this.getPricingFromRpc( + _srcToken, + _destToken, + amounts, + side, + poolsToUse.poolWithoutState, + ); + + const states = poolsToUse.poolWithState.map( + p => p.getState(blockNumber)!, + ); + + const unitAmount = getBigIntPow( + side == SwapSide.SELL ? _srcToken.decimals : _destToken.decimals, + ); + + const _amounts = [...amounts.slice(1)]; + + const [token0] = this._sortTokens(_srcAddress, _destAddress); + + const zeroForOne = token0 === _srcAddress ? true : false; + + const result = await Promise.all( + poolsToUse.poolWithState.map(async (pool, i) => { + const state = states[i]; + + if (state.liquidity <= 0n) { + this.logger.trace(`pool have 0 liquidity`); + return null; + } + + const balanceDestToken = + _destAddress === pool.token0 ? state.balance0 : state.balance1; + + const unitResult = this._getOutputs( + state, + [unitAmount], + zeroForOne, + side, + balanceDestToken, + ); + const pricesResult = this._getOutputs( + state, + _amounts, + zeroForOne, + side, + balanceDestToken, + ); + + if (!unitResult || !pricesResult) { + this.logger.debug('Prices or unit is not calculated'); + return null; + } + + const prices = [0n, ...pricesResult.outputs]; + const gasCost = [ + 0, + ...pricesResult.outputs.map((p, index) => { + if (p == 0n) { + return 0; + } else { + return ( + UNISWAPV3_POOL_SEARCH_OVERHEAD + + UNISWAPV3_TICK_BASE_OVERHEAD + + pricesResult.tickCounts[index] * UNISWAPV3_TICK_GAS_COST + ); + } + }), + ]; + return { + unit: unitResult.outputs[0], + prices, + data: { + path: [ + { + tokenIn: _srcAddress, + tokenOut: _destAddress, + fee: pool.feeCode.toString(), + }, + ], + }, + poolIdentifier: this.getPoolIdentifier( + pool.token0, + pool.token1, + pool.feeCode, + ), + exchange: this.dexKey, + gasCost: gasCost, + poolAddresses: [pool.poolAddress], + }; + }), + ); + const rpcResults = await rpcResultsPromise; + + const notNullResult = result.filter( + res => res !== null, + ) as ExchangePrices; + + if (rpcResults) { + rpcResults.forEach(r => { + if (r) { + notNullResult.push(r); + } + }); + } + + return notNullResult; + } catch (e) { + this.logger.error( + `Error_getPricesVolume ${srcToken.symbol || srcToken.address}, ${ + destToken.symbol || destToken.address + }, ${side}:`, + e, + ); + return null; + } } - // Encode params required by the exchange adapter - // Used for multiSwap, buy & megaSwap - // Hint: abiCoder.encodeParameter() could be useful getAdapterParam( srcToken: string, destToken: string, @@ -110,23 +681,178 @@ export class RamsesV2 extends SimpleExchange implements IDex { data: RamsesV2Data, side: SwapSide, ): AdapterExchangeParam { - // TODO: complete me! - const { exchange } = data; + const { path: rawPath } = data; + const path = this._encodePath(rawPath, side); - // Encode here the payload for adapter - const payload = ''; + const payload = this.abiCoder.encodeParameter( + { + ParentStruct: { + path: 'bytes', + deadline: 'uint256', + }, + }, + { + path, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), // FIXME: more gas efficient to pass block.timestamp in adapter + }, + ); return { - targetExchange: exchange, + targetExchange: this.config.router, payload, networkFee: '0', }; } - // Encode call data used by simpleSwap like routers - // Used for simpleSwap & simpleBuy - // Hint: this.buildSimpleParamWithoutWETHConversion - // could be useful + getCalldataGasCost(poolPrices: PoolPrices): number | number[] { + const gasCost = + CALLDATA_GAS_COST.DEX_OVERHEAD + + CALLDATA_GAS_COST.LENGTH_SMALL + + // ParentStruct header + CALLDATA_GAS_COST.OFFSET_SMALL + + // ParentStruct -> path header + CALLDATA_GAS_COST.OFFSET_SMALL + + // ParentStruct -> deadline + CALLDATA_GAS_COST.TIMESTAMP + + // ParentStruct -> path (20+3+20 = 43 = 32+11 bytes) + CALLDATA_GAS_COST.LENGTH_SMALL + + CALLDATA_GAS_COST.FULL_WORD + + CALLDATA_GAS_COST.wordNonZeroBytes(11); + const arr = new Array(poolPrices.prices.length); + poolPrices.prices.forEach((p, index) => { + if (p == 0n) { + arr[index] = 0; + } else { + arr[index] = gasCost; + } + }); + return arr; + } + + getTokenFromAddress(address: Address): Token { + // In this Dex decimals are not used + return { address, decimals: 0 }; + } + + async preProcessTransaction( + optimalSwapExchange: OptimalSwapExchange, + srcToken: Token, + _0: Token, + _1: SwapSide, + options: PreprocessTransactionOptions, + ): Promise<[OptimalSwapExchange, ExchangeTxInfo]> { + if (!options.isDirectMethod) { + return [ + optimalSwapExchange, + { + deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), + }, + ]; + } + + assert( + optimalSwapExchange.data !== undefined, + `preProcessTransaction: data field is missing`, + ); + + let isApproved: boolean | undefined; + + try { + this.erc20Contract.options.address = + this.dexHelper.config.wrapETH(srcToken).address; + const allowance = await this.erc20Contract.methods + .allowance(this.augustusAddress, this.config.router) + .call(undefined, 'latest'); + isApproved = + BigInt(allowance.toString()) >= BigInt(optimalSwapExchange.srcAmount); + } catch (e) { + this.logger.error( + `preProcessTransaction failed to retrieve allowance info: `, + e, + ); + } + + return [ + { + ...optimalSwapExchange, + data: { + ...optimalSwapExchange.data, + isApproved, + }, + }, + { + deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), + }, + ]; + } + + getDirectParam( + srcToken: Address, + destToken: Address, + srcAmount: NumberAsString, + destAmount: NumberAsString, + expectedAmount: NumberAsString, + data: RamsesV2Data, + side: SwapSide, + permit: string, + uuid: string, + feePercent: NumberAsString, + deadline: NumberAsString, + partner: string, + beneficiary: string, + contractMethod?: string, + ): TxInfo { + if ( + contractMethod !== DirectMethods.directSell && + contractMethod !== DirectMethods.directBuy + ) { + throw new Error(`Invalid contract method ${contractMethod}`); + } + + let isApproved: boolean = !!data.isApproved; + if (data.isApproved === undefined) { + this.logger.warn(`isApproved is undefined, defaulting to false`); + } + + const path = this._encodePath(data.path, side); + + const swapParams: RamsesV2Param = [ + srcToken, + destToken, + this.config.router, + srcAmount, + destAmount, + expectedAmount, + feePercent, + deadline, + partner, + isApproved, + beneficiary, + path, + permit, + uuidToBytes16(uuid), + ]; + + const encoder = (...params: RamsesV2Param) => { + return this.directSwapIface.encodeFunctionData( + side === SwapSide.SELL + ? DirectMethods.directSell + : DirectMethods.directBuy, + [params], + ); + }; + + return { + params: swapParams, + encoder, + networkFee: '0', + }; + } + + static getDirectFunctionName(): string[] { + return [DirectMethods.directSell, DirectMethods.directBuy]; + } + async getSimpleParam( srcToken: string, destToken: string, @@ -135,11 +861,31 @@ export class RamsesV2 extends SimpleExchange implements IDex { data: RamsesV2Data, side: SwapSide, ): Promise { - // TODO: complete me! - const { exchange } = data; + const swapFunction = + side === SwapSide.SELL + ? RamsesV2Functions.exactInput + : RamsesV2Functions.exactOutput; - // Encode here the transaction arguments - const swapData = ''; + const path = this._encodePath(data.path, side); + const swapFunctionParams: RamsesV2SimpleSwapParams = + side === SwapSide.SELL + ? { + recipient: this.augustusAddress, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), + amountIn: srcAmount, + amountOutMinimum: destAmount, + path, + } + : { + recipient: this.augustusAddress, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), + amountOut: destAmount, + amountInMaximum: srcAmount, + path, + }; + const swapData = this.routerIface.encodeFunctionData(swapFunction, [ + swapFunctionParams, + ]); return this.buildSimpleParamWithoutWETHConversion( srcToken, @@ -147,32 +893,244 @@ export class RamsesV2 extends SimpleExchange implements IDex { destToken, destAmount, swapData, - exchange, + this.config.router, ); } - // This is called once before getTopPoolsForToken is - // called for multiple tokens. This can be helpful to - // update common state required for calculating - // getTopPoolsForToken. It is optional for a DEX - // to implement this - async updatePoolState(): Promise { - // TODO: complete me! - } - - // Returns list of top pools based on liquidity. Max - // limit number pools should be returned. async getTopPoolsForToken( tokenAddress: Address, limit: number, ): Promise { - //TODO: complete me! - return []; + const _tokenAddress = tokenAddress.toLowerCase(); + + const res = await this._querySubgraph( + `query ($token: Bytes!, $count: Int) { + pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + }`, + { + token: _tokenAddress, + count: limit, + }, + ); + + if (!(res && res.pools0 && res.pools1)) { + this.logger.error( + `Error_${this.dexKey}_Subgraph: couldn't fetch the pools from the subgraph`, + ); + return []; + } + + const pools0 = _.map(res.pools0, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token1.id.toLowerCase(), + decimals: parseInt(pool.token1.decimals), + }, + ], + liquidityUSD: + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + })); + + const pools1 = _.map(res.pools1, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token0.id.toLowerCase(), + decimals: parseInt(pool.token0.decimals), + }, + ], + liquidityUSD: + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + })); + + const pools = _.slice( + _.sortBy(_.concat(pools0, pools1), [pool => -1 * pool.liquidityUSD]), + 0, + limit, + ); + return pools; + } + + private async _getPoolsFromIdentifiers( + poolIdentifiers: string[], + blockNumber: number, + ): Promise { + const pools = await Promise.all( + poolIdentifiers.map(async identifier => { + const [, srcAddress, destAddress, fee] = identifier.split('_'); + return this.getPool(srcAddress, destAddress, BigInt(fee), blockNumber); + }), + ); + return pools.filter(pool => pool) as RamsesV2EventPool[]; + } + + private _getLoweredAddresses(srcToken: Token, destToken: Token) { + return [srcToken.address.toLowerCase(), destToken.address.toLowerCase()]; + } + + private _sortTokens(srcAddress: Address, destAddress: Address) { + return [srcAddress, destAddress].sort((a, b) => (a < b ? -1 : 1)); + } + + private _toLowerForAllConfigAddresses() { + // If new config property will be added, the TS will throw compile error + const newConfig: DexParams = { + router: this.config.router.toLowerCase(), + quoter: this.config.quoter.toLowerCase(), + factory: this.config.factory.toLowerCase(), + supportedFees: this.config.supportedFees, + stateMulticall: this.config.stateMulticall.toLowerCase(), + chunksCount: this.config.chunksCount, + uniswapMulticall: this.config.uniswapMulticall, + deployer: this.config.deployer?.toLowerCase(), + initHash: this.config.initHash, + subgraphURL: this.config.subgraphURL, + }; + return newConfig; + } + + private _getOutputs( + state: DeepReadonly, + amounts: bigint[], + zeroForOne: boolean, + side: SwapSide, + destTokenBalance: bigint, + ): OutputResult | null { + try { + const outputsResult = uniswapV3Math.queryOutputs( + state, + amounts, + zeroForOne, + side, + ); + + if (side === SwapSide.SELL) { + if (outputsResult.outputs[0] > destTokenBalance) { + return null; + } + + for (let i = 0; i < outputsResult.outputs.length; i++) { + if (outputsResult.outputs[i] > destTokenBalance) { + outputsResult.outputs[i] = 0n; + outputsResult.tickCounts[i] = 0; + } + } + } else { + if (amounts[0] > destTokenBalance) { + return null; + } + + // This may be improved by first checking outputs and requesting outputs + // only for amounts that makes more sense, but I don't think this is really + // important now + for (let i = 0; i < amounts.length; i++) { + if (amounts[i] > destTokenBalance) { + outputsResult.outputs[i] = 0n; + outputsResult.tickCounts[i] = 0; + } + } + } + + return outputsResult; + } catch (e) { + this.logger.debug( + `${this.dexKey}: received error in _getOutputs while calculating outputs`, + e, + ); + return null; + } + } + + private async _querySubgraph( + query: string, + variables: Object, + timeout = 30000, + ) { + try { + const res = await this.dexHelper.httpRequest.post( + this.config.subgraphURL, + { query, variables }, + undefined, + { timeout: timeout }, + ); + return res.data; + } catch (e) { + this.logger.error(`${this.dexKey}: can not query subgraph: `, e); + return {}; + } + } + + private _encodePath( + path: { + tokenIn: Address; + tokenOut: Address; + fee: NumberAsString; + }[], + side: SwapSide, + ): string { + if (path.length === 0) { + this.logger.error( + `${this.dexKey}: Received invalid path=${path} for side=${side} to encode`, + ); + return '0x'; + } + + const { _path, types } = path.reduce( + ( + { _path, types }: { _path: string[]; types: string[] }, + curr, + index, + ): { _path: string[]; types: string[] } => { + if (index === 0) { + return { + types: ['address', 'uint24', 'address'], + _path: [curr.tokenIn, curr.fee, curr.tokenOut], + }; + } else { + return { + types: [...types, 'uint24', 'address'], + _path: [..._path, curr.fee, curr.tokenOut], + }; + } + }, + { _path: [], types: [] }, + ); + + return side === SwapSide.BUY + ? pack(types.reverse(), _path.reverse()) + : pack(types, _path); } - // This is optional function in case if your implementation has acquired any resources - // you need to release for graceful shutdown. For example, it may be any interval timer - releaseResources(): AsyncOrSync { - // TODO: complete me! + releaseResources() { + if (this.intervalTask !== undefined) { + clearInterval(this.intervalTask); + this.intervalTask = undefined; + } } } diff --git a/src/dex/ramses-v2/types.ts b/src/dex/ramses-v2/types.ts index 8cfcd3d32..c2db00297 100644 --- a/src/dex/ramses-v2/types.ts +++ b/src/dex/ramses-v2/types.ts @@ -1,22 +1,177 @@ +import { BigNumber } from 'ethers'; +import { NumberAsString } from '../../types'; import { Address } from '../../types'; +export type OracleObservation = { + blockTimestamp: bigint; + tickCumulative: bigint; + secondsPerLiquidityCumulativeX128: bigint; + initialized: boolean; +}; + +export type OracleObservationCandidates = { + beforeOrAt: OracleObservation; + atOrAfter: OracleObservation; +}; + +export type TickInfo = { + liquidityGross: bigint; + liquidityNet: bigint; + tickCumulativeOutside: bigint; + secondsPerLiquidityOutsideX128: bigint; + secondsOutside: bigint; + initialized: boolean; +}; + +export type Slot0 = { + sqrtPriceX96: bigint; + tick: bigint; + observationIndex: number; + observationCardinality: number; + observationCardinalityNext: number; + feeProtocol: bigint; +}; + export type PoolState = { - // TODO: poolState is the state of event - // subscriber. This should be the minimum - // set of parameters required to compute - // pool prices. Complete me! + pool: string; + blockTimestamp: bigint; + tickSpacing: bigint; + fee: bigint; + slot0: Slot0; + liquidity: bigint; + maxLiquidityPerTick: bigint; + tickBitmap: Record; + ticks: Record; + observations: Record; + isValid: boolean; + startTickBitmap: bigint; + lowestKnownTick: bigint; + highestKnownTick: bigint; + balance0: bigint; + balance1: bigint; }; export type RamsesV2Data = { - // TODO: RamsesV2Data is the dex data that is - // returned by the API that can be used for - // tx building. The data structure should be minimal. - // Complete me! - exchange: Address; + path: { + tokenIn: Address; + tokenOut: Address; + fee: NumberAsString; + }[]; + isApproved?: boolean; }; export type DexParams = { - // TODO: DexParams is set of parameters the can - // be used to initiate a DEX fork. - // Complete me! + router: Address; + quoter: Address; + factory: Address; + stateMulticall: Address; + uniswapMulticall: Address; + supportedFees: bigint[]; + chunksCount: number; + deployer?: Address; + subgraphURL: string; + initHash: string; +}; + +export type RamsesV2SimpleSwapSellParam = { + path: string; + recipient: Address; + deadline: string; + amountIn: NumberAsString; + amountOutMinimum: NumberAsString; +}; + +export type RamsesV2SimpleSwapBuyParam = { + path: string; + recipient: Address; + deadline: string; + amountOut: NumberAsString; + amountInMaximum: NumberAsString; +}; + +export type RamsesV2SimpleSwapParams = + | RamsesV2SimpleSwapSellParam + | RamsesV2SimpleSwapBuyParam; + +export type RamsesV2Param = [ + fromToken: Address, + toToken: Address, + exchange: Address, + fromAmount: NumberAsString, + toAmount: NumberAsString, + expectedAmount: NumberAsString, + feePercent: NumberAsString, + deadline: NumberAsString, + partner: Address, + isApproved: boolean, + beneficiary: Address, + path: string, + permit: string, + uuid: string, +]; + +export enum RamsesV2Functions { + exactInput = 'exactInput', + exactOutput = 'exactOutput', +} + +export type TickInfoMappings = { + index: number; + value: TickInfo; +}; + +export type TickBitMapMappings = { + index: number; + value: bigint; +}; + +export type OutputResult = { + outputs: bigint[]; + tickCounts: number[]; +}; + +// Just rewrote every type with BigNumber basically + +export type TickBitMapMappingsWithBigNumber = { + index: number; + value: BigNumber; +}; + +export type TickInfoWithBigNumber = { + initialized: boolean; + liquidityGross: BigNumber; + liquidityNet: BigNumber; + secondsOutside: number; + secondsPerLiquidityOutsideX128: BigNumber; + tickCumulativeOutside: BigNumber; +}; + +export type TickInfoMappingsWithBigNumber = { + index: number; + value: TickInfoWithBigNumber; +}; + +export type DecodedStateMultiCallResultWithRelativeBitmaps = { + pool: Address; + blockTimestamp: BigNumber; + slot0: { + feeProtocol: number; + observationCardinality: number; + observationCardinalityNext: number; + observationIndex: number; + sqrtPriceX96: BigNumber; + tick: number; + unlocked: boolean; + }; + liquidity: BigNumber; + tickSpacing: number; + maxLiquidityPerTick: BigNumber; + observation: { + blockTimestamp: number; + initialized: boolean; + secondsPerLiquidityCumulativeX128: BigNumber; + tickCumulative: BigNumber; + }; + tickBitmap: TickBitMapMappingsWithBigNumber[]; + ticks: TickInfoMappingsWithBigNumber[]; }; From af14a983511e27f66f1f9ab2881dc30a764d41d2 Mon Sep 17 00:00:00 2001 From: 0xshad0w Date: Fri, 23 Jun 2023 13:21:58 +0100 Subject: [PATCH 025/833] 2 - updates --- src/dex/ramses-v2/utils.ts | 83 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/dex/ramses-v2/utils.ts diff --git a/src/dex/ramses-v2/utils.ts b/src/dex/ramses-v2/utils.ts new file mode 100644 index 000000000..afd953e07 --- /dev/null +++ b/src/dex/ramses-v2/utils.ts @@ -0,0 +1,83 @@ +import { BytesLike, ethers } from 'ethers'; +import { assert } from 'ts-essentials'; +import { extractSuccessAndValue } from '../../lib/decoders'; +import { MultiResult } from '../../lib/multi-wrapper'; +import { DexConfigMap } from '../../types'; +import { + DexParams, + DecodedStateMultiCallResultWithRelativeBitmaps, +} from './types'; + +export function getUniswapV3DexKey(UniswapV3Config: DexConfigMap) { + const UniswapV3Keys = Object.keys(UniswapV3Config); + if (UniswapV3Keys.length !== 1) { + throw new Error( + `UniswapV3 key in UniswapV3Config is not unique. Update relevant places (optimizer) or fix config issue. Received: ${JSON.stringify( + UniswapV3Config, + (_0, value) => (typeof value === 'bigint' ? value.toString() : value), + )}`, + ); + } + + return UniswapV3Keys[0].toLowerCase(); +} + +export function decodeStateMultiCallResultWithRelativeBitmaps( + result: MultiResult | BytesLike, +): DecodedStateMultiCallResultWithRelativeBitmaps { + const [isSuccess, toDecode] = extractSuccessAndValue(result); + + assert( + isSuccess && toDecode !== '0x', + `decodeStateMultiCallResultWithRelativeBitmaps failed to get decodable result: ${result}`, + ); + + const decoded = ethers.utils.defaultAbiCoder.decode( + [ + // I don't want to pass here any interface, so I just use it in ethers format + ` + tuple( + address pool, + uint256 blockTimestamp, + tuple( + uint160 sqrtPriceX96, + int24 tick, + uint16 observationIndex, + uint16 observationCardinality, + uint16 observationCardinalityNext, + uint8 feeProtocol, + bool unlocked, + ) slot0, + uint128 liquidity, + int24 tickSpacing, + uint128 maxLiquidityPerTick, + tuple( + uint32 blockTimestamp, + int56 tickCumulative, + uint160 secondsPerLiquidityCumulativeX128, + bool initialized, + ) observation, + tuple( + int16 index, + uint256 value, + )[] tickBitmap, + tuple( + int24 index, + tuple( + uint128 liquidityGross, + int128 liquidityNet, + int56 tickCumulativeOutside, + uint160 secondsPerLiquidityOutsideX128, + uint32 secondsOutside, + bool initialized, + ) value, + )[] ticks + ) + `, + ], + toDecode, + )[0]; + // This conversion is not precise, because when we decode, we have more values + // But I typed only the ones that are used later + return decoded as DecodedStateMultiCallResultWithRelativeBitmaps; +} From 144f5d9962dd6eb0fbfd814fb3679f59a826204b Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xmasayoshi@protonmail.com> Date: Fri, 26 May 2023 20:26:33 +0700 Subject: [PATCH 026/833] sushiswap-v3 integration --- package.json | 1 + src/abi/sushiswap-v3/QuoterV2.json | 267 + src/abi/sushiswap-v3/RouterProcessor3.json | 289 + src/dex/index.ts | 2 + src/dex/sushiswap-v3/config.ts | 119 + src/dex/sushiswap-v3/constants.ts | 25 + src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts | 154 + .../sushiswap-v3/sushiswap-v3-events.test.ts | 119 + .../sushiswap-v3-integration.test.ts | 378 ++ src/dex/sushiswap-v3/sushiswap-v3-pool.ts | 1 + src/dex/sushiswap-v3/sushiswap-v3.ts | 1017 +++ src/dex/sushiswap-v3/token.ts | 25 + src/dex/sushiswap-v3/types.ts | 17 + yarn.lock | 5808 ++++++++++++++++- 14 files changed, 8075 insertions(+), 147 deletions(-) create mode 100644 src/abi/sushiswap-v3/QuoterV2.json create mode 100644 src/abi/sushiswap-v3/RouterProcessor3.json create mode 100644 src/dex/sushiswap-v3/config.ts create mode 100644 src/dex/sushiswap-v3/constants.ts create mode 100644 src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts create mode 100644 src/dex/sushiswap-v3/sushiswap-v3-events.test.ts create mode 100644 src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts create mode 100644 src/dex/sushiswap-v3/sushiswap-v3-pool.ts create mode 100644 src/dex/sushiswap-v3/sushiswap-v3.ts create mode 100644 src/dex/sushiswap-v3/token.ts create mode 100644 src/dex/sushiswap-v3/types.ts diff --git a/package.json b/package.json index a63ebc2f4..f9837fbfa 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "@hashflow/sdk": "1.2.4", "@hashflow/taker-js": "0.0.2", "@paraswap/core": "1.1.0", + "@sushiswap/router": "^0.0.12", "async": "^3.2.4", "axios": "0.26.0", "bignumber.js": "9.1.0", diff --git a/src/abi/sushiswap-v3/QuoterV2.json b/src/abi/sushiswap-v3/QuoterV2.json new file mode 100644 index 000000000..ce1374e69 --- /dev/null +++ b/src/abi/sushiswap-v3/QuoterV2.json @@ -0,0 +1,267 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_WETH9", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "WETH9", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "path", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + } + ], + "name": "quoteExactInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint160[]", + "name": "sqrtPriceX96AfterList", + "type": "uint160[]" + }, + { + "internalType": "uint32[]", + "name": "initializedTicksCrossedList", + "type": "uint32[]" + }, + { + "internalType": "uint256", + "name": "gasEstimate", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "uint160", + "name": "sqrtPriceLimitX96", + "type": "uint160" + } + ], + "internalType": "struct IQuoterV2.QuoteExactInputSingleParams", + "name": "params", + "type": "tuple" + } + ], + "name": "quoteExactInputSingle", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint160", + "name": "sqrtPriceX96After", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "initializedTicksCrossed", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasEstimate", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "path", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "quoteExactOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint160[]", + "name": "sqrtPriceX96AfterList", + "type": "uint160[]" + }, + { + "internalType": "uint32[]", + "name": "initializedTicksCrossedList", + "type": "uint32[]" + }, + { + "internalType": "uint256", + "name": "gasEstimate", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "uint160", + "name": "sqrtPriceLimitX96", + "type": "uint160" + } + ], + "internalType": "struct IQuoterV2.QuoteExactOutputSingleParams", + "name": "params", + "type": "tuple" + } + ], + "name": "quoteExactOutputSingle", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint160", + "name": "sqrtPriceX96After", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "initializedTicksCrossed", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasEstimate", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "path", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/abi/sushiswap-v3/RouterProcessor3.json b/src/abi/sushiswap-v3/RouterProcessor3.json new file mode 100644 index 000000000..d8959084f --- /dev/null +++ b/src/abi/sushiswap-v3/RouterProcessor3.json @@ -0,0 +1,289 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/src/dex/index.ts b/src/dex/index.ts index d06e99259..e4ff2887e 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -70,6 +70,7 @@ import { SwaapV2 } from './swaap-v2/swaap-v2'; import { SpiritSwapV3 } from './quickswap/spiritswap-v3'; import { TraderJoeV21 } from './trader-joe-v2.1'; import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3'; +import { SushiswapV3 } from './sushiswap-v3/sushiswap-v3'; const LegacyDexes = [ CurveV2, @@ -105,6 +106,7 @@ const Dexes = [ UniswapV2, UniswapV3, PancakeswapV3, + SushiswapV3, BiSwap, MDEX, Dfyn, diff --git a/src/dex/sushiswap-v3/config.ts b/src/dex/sushiswap-v3/config.ts new file mode 100644 index 000000000..4ee0b9f03 --- /dev/null +++ b/src/dex/sushiswap-v3/config.ts @@ -0,0 +1,119 @@ +import { DexParams } from './types'; +import { DexConfigMap, AdapterMappings } from '../../types'; +import { Network, SwapSide } from '../../constants'; + +const SUPPORTED_FEES = [10000n, 3000n, 500n, 100n]; + +export const SushiswapV3Config: DexConfigMap = { + SushiswapV3: { + [Network.MAINNET]: { + factory: '0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F', + quoter: '0x64e8802FE490fa7cc61d3463958199161Bb608A7', + router: '0x827179dD56d07A7eeA32e3873493835da2866976', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-ethereum', + }, + [Network.POLYGON]: { + factory: '0x917933899c6a5f8e37f31e19f92cdbff7e8ff0e2', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-polygon', + }, + [Network.BSC]: { + factory: '0x126555dd55a39328F69400d6aE4F782Bd4C34ABb', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x400d75dAb26bBc18D163AEA3e83D9Ea68F6c1804', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x593F39A4Ba26A9c8ed2128ac95D109E8e403C485', + uniswapMulticall: '0x963Df249eD09c358A4819E39d9Cd5736c3087184', + chunksCount: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-bsc', + }, + [Network.AVALANCHE]: { + factory: '0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x717b7948AA264DeCf4D780aa6914482e5F46Da3e', + supportedFees: SUPPORTED_FEES, + stateMulticall: '', + uniswapMulticall: '0x8C0F842791F03C095b6c633759224FcC9ACe68ea', + chunksCount: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-avalanche', + }, + [Network.FANTOM]: { + factory: '0x7770978eED668a3ba661d51a773d3a992Fc9DDCB', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x2214A42d8e2A1d20635c2cb0664422c528B6A432', + supportedFees: SUPPORTED_FEES, + stateMulticall: '', + uniswapMulticall: '0xB1395e098c0a847CC719Bcf1Fc8114421a9F8232', + chunksCount: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-fantom', + }, + [Network.ARBITRUM]: { + factory: '0x1af415a1eba07a4986a52b6f2e7de7003d82231e', + quoter: '0x0524E833cCD057e4d7A296e3aaAb9f7675964Ce1', + router: '0xfc506AaA1340b4dedFfd88bE278bEe058952D674', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-arbitrum', + }, + [Network.OPTIMISM]: { + factory: '0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x4C5D5234f232BD2D76B96aA33F5AE4FCF0E4BFAb', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x4FF0dEC5f9a763Aa1E5C2a962aa6f4eDFeE4f9eA', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-optimism', + }, + }, +}; + +export const Adapters: Record = { + [Network.MAINNET]: { + [SwapSide.SELL]: [{ name: 'Adapter01', index: 6 }], + [SwapSide.BUY]: [{ name: 'BuyAdapter', index: 2 }], + }, + [Network.BSC]: { + [SwapSide.SELL]: [{ name: 'BscAdapter02', index: 4 }], + [SwapSide.BUY]: [{ name: 'BscBuyAdapter', index: 5 }], + }, + [Network.POLYGON]: { + [SwapSide.SELL]: [{ name: 'PolygonAdapter01', index: 13 }], + [SwapSide.BUY]: [{ name: 'PolygonBuyAdapter', index: 2 }], + }, + [Network.ARBITRUM]: { + [SwapSide.SELL]: [{ name: 'ArbitrumAdapter01', index: 3 }], + [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 2 }], + }, + [Network.OPTIMISM]: { + [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 3 }], + [SwapSide.BUY]: [{ name: 'OptimismBuyAdapter', index: 2 }], + }, + [Network.FANTOM]: { + [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 11 }], + [SwapSide.BUY]: [{ name: 'FantomBuyAdapter', index: 3 }], + }, +}; diff --git a/src/dex/sushiswap-v3/constants.ts b/src/dex/sushiswap-v3/constants.ts new file mode 100644 index 000000000..a722e8088 --- /dev/null +++ b/src/dex/sushiswap-v3/constants.ts @@ -0,0 +1,25 @@ +import { Chain } from 'viem'; +import { + arbitrum, + avalanche, + bsc, + fantom, + mainnet, + optimism, + polygon, +} from '@sushiswap/viem-config'; +import { Network } from '../../constants'; + +export * from '../uniswap-v3/constants'; + +export const ViemChain: Record = { + [Network.ARBITRUM]: arbitrum, + [Network.AVALANCHE]: avalanche, + [Network.BSC]: bsc, + [Network.FANTOM]: fantom, + [Network.MAINNET]: mainnet, + [Network.OPTIMISM]: optimism, + [Network.POLYGON]: polygon, + [Network.RINKEBY]: undefined, + [Network.ROPSTEN]: undefined, +}; diff --git a/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts b/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts new file mode 100644 index 000000000..2c7c52b85 --- /dev/null +++ b/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts @@ -0,0 +1,154 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { testE2E } from '../../../tests/utils-e2e'; +import { + Tokens, + Holders, + NativeTokenSymbols, +} from '../../../tests/constants-e2e'; +import { Network, ContractMethod, SwapSide } from '../../constants'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; + +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, + slippage?: number | undefined, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + 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, + 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, + network, + provider, + undefined, + undefined, + undefined, + slippage, + ); + }); + }); + }); + }), + ); + }); +} + +describe('SushiswapV3 E2E', () => { + const dexKey = 'SushiswapV3'; + + describe('MAINNET', () => { + const network = Network.MAINNET; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'WETH'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '110000000000000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + 500, // 5% + ); + }); + + describe('ARBITRUM', () => { + const network = Network.ARBITRUM; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'WETH'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '110000000000000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + 500, // 5% + ); + }); +}); diff --git a/src/dex/sushiswap-v3/sushiswap-v3-events.test.ts b/src/dex/sushiswap-v3/sushiswap-v3-events.test.ts new file mode 100644 index 000000000..687386915 --- /dev/null +++ b/src/dex/sushiswap-v3/sushiswap-v3-events.test.ts @@ -0,0 +1,119 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { SushiswapV3EventPool } from './sushiswap-v3-pool'; +import { Network } from '../../constants'; +import { Address } from '../../types'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { testEventSubscriber } from '../../../tests/utils-events'; +import { PoolState } from './types'; +import ERC20ABI from '../../abi/erc20.json'; +import StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; +import { AbiItem } from 'web3-utils'; +import { Interface } from 'ethers/lib/utils'; + +jest.setTimeout(50 * 1000); + +async function fetchPoolState( + sushiswapV3Pool: SushiswapV3EventPool, + blockNumber: number, + poolAddress: string, +): Promise { + const message = `UniswapV3: ${poolAddress} blockNumber ${blockNumber}`; + console.log(`Fetching state ${message}`); + // Be careful to not request state prior to contract deployment + // Otherwise need to use manual state sourcing from multicall + // We had that mechanism, but removed it with this commit + // You can restore it, but better just to find block after state multicall + // deployment + const state = sushiswapV3Pool.generateState(blockNumber); + console.log(`Done ${message}`); + return state; +} + +// eventName -> blockNumbers +type EventMappings = Record; + +describe('SushiswapV3 EventPool Mainnet', function () { + const dexKey = 'SushiswapV3'; + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + const logger = dexHelper.getLogger(dexKey); + let sushiswapV3Pool: SushiswapV3EventPool; + + const factory = '0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F'; + const poolFeeCode = 500n; + const token0 = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'; + const token1 = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'; + const stateMulticall = '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63'; + const initCodeHash = + '0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54'; + + // poolAddress -> EventMappings + const eventsToTest: Record = { + ['0x35644fb61afbc458bf92b15add6abc1996be5014']: { + // topic0 - 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67 + ['Swap']: [ + 17293592, 17293446, 17293111, 17289023, 17280383, 17280375, 17279057, + ], + // // topic0 - 0x0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c + ['Burn']: [17259974], + // // topic0 - 0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde + ['Mint']: [17215311], + // // topic0 - 0x973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b133 + ['SetFeeProtocol']: [16988973], + // // topic0 - 0x70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0 + ['Collect']: [17259974], + }, + }; + + beforeEach(async () => { + sushiswapV3Pool = new SushiswapV3EventPool( + dexHelper, + dexKey, + new dexHelper.web3Provider.eth.Contract( + StateMulticallABI as AbiItem[], + stateMulticall, + ), + new Interface(ERC20ABI), + factory, + poolFeeCode, + token0, + token1, + logger, + undefined, + initCodeHash, + ); + }); + + Object.entries(eventsToTest).forEach( + ([poolAddress, events]: [string, EventMappings]) => { + describe(`Events for ${poolAddress}`, () => { + Object.entries(events).forEach( + ([eventName, blockNumbers]: [string, number[]]) => { + describe(`${eventName}`, () => { + blockNumbers.forEach((blockNumber: number) => { + it(`State after ${blockNumber}`, async function () { + await testEventSubscriber( + sushiswapV3Pool, + [poolAddress], + (_blockNumber: number) => + fetchPoolState( + sushiswapV3Pool, + _blockNumber, + poolAddress, + ), + blockNumber, + `${dexKey}_${poolAddress}`, + dexHelper.provider, + ); + }); + }); + }); + }, + ); + }); + }, + ); +}); diff --git a/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts b/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts new file mode 100644 index 000000000..7be6e3cf0 --- /dev/null +++ b/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts @@ -0,0 +1,378 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { Interface, Result } from '@ethersproject/abi'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { Network, SwapSide } from '../../constants'; +import { BI_POWS } from '../../bigint-constants'; +import { SushiswapV3 } from './sushiswap-v3'; +import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; +import { Tokens } from '../../../tests/constants-e2e'; +import { Address } from '../../types'; +import { + QuoteExactInputSingleParams, + QuoteExactOutputSingleParams, +} from './types'; + +function getQuoterV2Params( + funcName: string, + tokenIn: Address, + tokenOut: Address, + amount: bigint, + fee: bigint, +): QuoteExactInputSingleParams | QuoteExactOutputSingleParams { + return funcName === 'quoteExactInputSingle' + ? { tokenIn, tokenOut, fee, sqrtPriceLimitX96: 0n, amountIn: amount } + : { tokenIn, tokenOut, fee, sqrtPriceLimitX96: 0n, amount }; +} + +function getReaderCalldata( + exchangeAddress: string, + readerIface: Interface, + amounts: bigint[], + funcName: string, + tokenIn: Address, + tokenOut: Address, + fee: bigint, +) { + return amounts.map(amount => ({ + target: exchangeAddress, + callData: readerIface.encodeFunctionData(funcName, [ + getQuoterV2Params(funcName, tokenIn, tokenOut, amount, fee), + ]), + })); +} + +function decodeReaderResult( + results: Result, + readerIface: Interface, + funcName: string, +) { + return results.map(result => { + const parsed = readerIface.decodeFunctionResult(funcName, result); + return BigInt(parsed[0]._hex); + }); +} + +async function checkOnChainPricing( + sushiswapV3: SushiswapV3, + funcName: string, + blockNumber: number, + prices: bigint[], + tokenIn: Address, + tokenOut: Address, + fee: bigint, + amounts: bigint[], +) { + const quoterAddress = sushiswapV3.config.quoter; + const readerIface = sushiswapV3.quoterIface; + + const sum = prices.reduce((acc, curr) => (acc += curr), 0n); + + if (sum === 0n) { + console.log( + `Prices were not calculated for tokenIn=${tokenIn}, tokenOut=${tokenOut}, fee=${fee.toString()}. Most likely price impact is too big for requested amount`, + ); + return false; + } + + const readerCallData = getReaderCalldata( + quoterAddress, + readerIface, + amounts.slice(1), + funcName, + tokenIn, + tokenOut, + fee, + ); + + let readerResult; + try { + readerResult = ( + await sushiswapV3.dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blockNumber) + ).returnData; + } catch (e) { + console.log( + `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, + e, + ); + return false; + } + + const expectedPrices = [0n].concat( + decodeReaderResult(readerResult, readerIface, funcName), + ); + + let firstZeroIndex = prices.slice(1).indexOf(0n); + + // we skipped first, so add +1 on result + firstZeroIndex = firstZeroIndex === -1 ? prices.length : firstZeroIndex; + + // Compare only the ones for which we were able to calculate prices + expect(prices.slice(0, firstZeroIndex)).toEqual( + expectedPrices.slice(0, firstZeroIndex), + ); + return true; +} + +async function testPricingOnNetwork( + sushiswapV3: SushiswapV3, + network: Network, + dexKey: string, + blockNumber: number, + srcTokenSymbol: string, + destTokenSymbol: string, + side: SwapSide, + amounts: bigint[], +) { + const networkTokens = Tokens[network]; + + const pools = await sushiswapV3.getPoolIdentifiers( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + side, + blockNumber, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await sushiswapV3.getPricesVolume( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + amounts, + side, + blockNumber, + pools, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices( + poolPrices!.filter(poolPrice => + poolPrice.prices.slice(1).every(price => price > 0), + ), + amounts, + side, + dexKey, + ); + + // Check if onchain pricing equals to calculated ones + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = sushiswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + sushiswapV3, + side === SwapSide.SELL + ? 'quoteExactInputSingle' + : 'quoteExactOutputSingle', + blockNumber, + price.prices, + networkTokens[srcTokenSymbol].address, + networkTokens[destTokenSymbol].address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); +} + +describe('SushiswapV3', function () { + const dexKey = 'SushiswapV3'; + let blockNumber: number; + let sushiswapV3: SushiswapV3; + + describe('Mainnet', () => { + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + + const srcTokenSymbol = 'USDC'; + const destTokenSymbol = 'WETH'; + + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 2n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 3n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 4n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 5n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 6n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 7n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 8n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 9n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 10n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + sushiswapV3 = new SushiswapV3(network, dexKey, dexHelper); + if (sushiswapV3.initializePricing) { + await sushiswapV3.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + sushiswapV3, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + ); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + sushiswapV3, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newSushiswapV3 = new SushiswapV3(network, dexKey, dexHelper); + const poolLiquidity = await newSushiswapV3.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newSushiswapV3.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); + }); + + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + + const srcTokenSymbol = 'USDC'; + const destTokenSymbol = 'WETH'; + + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 2n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 3n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 4n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 5n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 6n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 7n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 8n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 9n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + 10n * BI_POWS[tokens[destTokenSymbol].decimals - 2], + ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + sushiswapV3 = new SushiswapV3(network, dexKey, dexHelper); + if (sushiswapV3.initializePricing) { + await sushiswapV3.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + sushiswapV3, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + ); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + sushiswapV3, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newSushiswapV3 = new SushiswapV3(network, dexKey, dexHelper); + const poolLiquidity = await newSushiswapV3.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newSushiswapV3.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); + }); +}); diff --git a/src/dex/sushiswap-v3/sushiswap-v3-pool.ts b/src/dex/sushiswap-v3/sushiswap-v3-pool.ts new file mode 100644 index 000000000..d3e853d6e --- /dev/null +++ b/src/dex/sushiswap-v3/sushiswap-v3-pool.ts @@ -0,0 +1 @@ +export { UniswapV3EventPool as SushiswapV3EventPool } from '../uniswap-v3/uniswap-v3-pool'; diff --git a/src/dex/sushiswap-v3/sushiswap-v3.ts b/src/dex/sushiswap-v3/sushiswap-v3.ts new file mode 100644 index 000000000..19ef285d4 --- /dev/null +++ b/src/dex/sushiswap-v3/sushiswap-v3.ts @@ -0,0 +1,1017 @@ +import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; +import { + Token, + Address, + ExchangePrices, + PoolPrices, + AdapterExchangeParam, + SimpleExchangeParam, + PoolLiquidity, + Logger, + NumberAsString, +} from '../../types'; +import { SwapSide, Network, CACHE_PREFIX } from '../../constants'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { + getBigIntPow, + getDexKeysWithNetwork, + interpolate, + isTruthy, +} from '../../utils'; +import { IDex } from '../../dex/idex'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { + DexParams, + OutputResult, + PoolState, + QuoteExactInputSingleParams, + QuoteExactOutputSingleParams, + UniswapV3Data as SushiswapV3Data, +} from './types'; +import { + SimpleExchange, + getLocalDeadlineAsFriendlyPlaceholder, +} from '../simple-exchange'; +import { SushiswapV3Config, Adapters } from './config'; +import { SushiswapV3EventPool } from './sushiswap-v3-pool'; +import { Interface, defaultAbiCoder } from 'ethers/lib/utils'; +import { AbiItem } from 'web3-utils'; +import { Contract } from 'web3-eth-contract'; +import { pack } from '@ethersproject/solidity'; +import { + UNISWAPV3_EFFICIENCY_FACTOR, + UNISWAPV3_POOL_SEARCH_OVERHEAD, + UNISWAPV3_TICK_BASE_OVERHEAD, + UNISWAPV3_TICK_GAS_COST, + ViemChain, +} from './constants'; +import { uniswapV3Math } from '../uniswap-v3/contract-math/uniswap-v3-math'; +import { BalanceRequest, getBalances } from '../../lib/tokens/balancer-fetcher'; +import { + AssetType, + DEFAULT_ID_ERC20, + DEFAULT_ID_ERC20_AS_STRING, +} from '../../lib/tokens/types'; +import { DataFetcher, LiquidityProviders, Router } from '@sushiswap/router'; +import { ChainId } from '@sushiswap/chain'; +import { createPublicClient, http } from 'viem'; + +import SushiswapV3RouterABI from '../../abi/sushiswap-v3/RouterProcessor3.json'; +import SushiswapV3QuoterV2ABI from '../../abi/sushiswap-v3/QuoterV2.json'; +import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; +import UniswapV3StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; +import { generateConfig } from '../../config'; +import { BigNumber } from 'ethers'; +import { getToken } from './token'; +import _ from 'lodash'; +import { UniswapV3Config } from '../uniswap-v3/config'; + +const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 60 * 60 * 24 * 1000; // 24 hours +const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 30 * 60 * 1000; // Once in 30 minutes +const UNISWAPV3_QUOTE_GASLIMIT = 200_000; + +export class SushiswapV3 + extends SimpleExchange + implements IDex +{ + readonly eventPools: Record = {}; + + readonly hasConstantPriceLargeAmounts = false; + readonly needWrapNative = true; + + intervalTask?: NodeJS.Timeout; + + readonly isFeeOnTransferSupported = false; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(SushiswapV3Config); + + logger: Logger; + + private uniswapMulti: Contract; + private stateMultiContract: Contract; + + private notExistingPoolSetKey: string; + + constructor( + readonly network: Network, + readonly dexKey: string, + readonly dexHelper: IDexHelper, + protected adapters = Adapters[network] || {}, + readonly routerIface = new Interface(SushiswapV3RouterABI), + readonly quoterIface = new Interface(SushiswapV3QuoterV2ABI), + readonly config = SushiswapV3Config[dexKey][network], + ) { + super(dexHelper, dexKey); + this.logger = dexHelper.getLogger(dexKey + '-' + network); + + this.uniswapMulti = new this.dexHelper.web3Provider.eth.Contract( + UniswapV3MultiABI as AbiItem[], + this.config.uniswapMulticall, + ); + this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( + UniswapV3StateMulticallABI as AbiItem[], + this.config.stateMulticall, + ); + + // To receive revert reasons + this.dexHelper.web3Provider.eth.handleRevert = false; + + // Normalise once all config addresses and use across all scenarios + this.config = this._toLowerForAllConfigAddresses(); + + this.notExistingPoolSetKey = + `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); + } + + // Initialize pricing is called once in the start of + // pricing service. It is intended to setup the integration + // for pricing requests. It is optional for a DEX to + // implement this function + async initializePricing(blockNumber: number) { + if (!this.dexHelper.config.isSlave) { + const cleanExpiredNotExistingPoolsKeys = async () => { + const maxTimestamp = + Date.now() - UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS; + await this.dexHelper.cache.zremrangebyscore( + this.notExistingPoolSetKey, + 0, + maxTimestamp, + ); + }; + + this.intervalTask = setInterval( + cleanExpiredNotExistingPoolsKeys.bind(this), + UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS, + ); + } + } + + get supportedFees() { + return this.config.supportedFees; + } + + // Returns the list of contract adapters (name and index) + // for a buy/sell. Return null if there are no adapters. + getAdapters(side: SwapSide): { name: string; index: number }[] | null { + return this.adapters[side] ? this.adapters[side] : null; + } + + getPoolIdentifier(srcAddress: Address, destAddress: Address, fee: bigint) { + const tokenAddresses = this._sortTokens(srcAddress, destAddress).join('_'); + return `${this.dexKey}_${tokenAddresses}_${fee}`; + } + + // Returns pool prices for amounts. + // If limitPools is defined only pools in limitPools + // should be used. If limitPools is undefined then + // any pools can be used. + async getPricesVolume( + srcToken: Token, + destToken: Token, + amounts: bigint[], + side: SwapSide, + blockNumber: number, + limitPools?: string[], + ): Promise> { + try { + const _srcToken = this.dexHelper.config.wrapETH(srcToken); + const _destToken = this.dexHelper.config.wrapETH(destToken); + + const [_srcAddress, _destAddress] = this._getLoweredAddresses( + _srcToken, + _destToken, + ); + + if (_srcAddress === _destAddress) return null; + + let selectedPools: SushiswapV3EventPool[] = []; + + if (!limitPools) { + selectedPools = ( + await Promise.all( + this.supportedFees.map(async fee => { + const locallyFoundPool = + this.eventPools[ + this.getPoolIdentifier(_srcAddress, _destAddress, fee) + ]; + if (locallyFoundPool) return locallyFoundPool; + + const newlyFetchedPool = await this.getPool( + _srcAddress, + _destAddress, + fee, + blockNumber, + ); + return newlyFetchedPool; + }), + ) + ).filter(isTruthy); + } else { + const pairIdentifierWithoutFee = this.getPoolIdentifier( + _srcAddress, + _destAddress, + 0n, + // Trim from 0 fee postfix, so it become comparable + ).slice(0, -1); + + const poolIdentifiers = limitPools.filter(identifier => + identifier.startsWith(pairIdentifierWithoutFee), + ); + + selectedPools = ( + await Promise.all( + poolIdentifiers.map(async identifier => { + let locallyFoundPool = this.eventPools[identifier]; + if (locallyFoundPool) return locallyFoundPool; + + const [, srcAddress, destAddress, fee] = identifier.split('_'); + const newlyFetchedPool = await this.getPool( + srcAddress, + destAddress, + BigInt(fee), + blockNumber, + ); + return newlyFetchedPool; + }), + ) + ).filter(isTruthy); + } + + if (selectedPools.length === 0) return null; + + const poolsToUse = selectedPools.reduce( + (acc, pool) => { + let state = pool.getState(blockNumber); + if (state === null) { + this.logger.trace( + `${this.dexKey}: State === null. Fallback to rpc ${pool.name}`, + ); + acc.poolWithoutState.push(pool); + } else { + acc.poolWithState.push(pool); + } + return acc; + }, + { + poolWithState: [] as SushiswapV3EventPool[], + poolWithoutState: [] as SushiswapV3EventPool[], + }, + ); + + const rpcResultsPromise = this.getPricingFromRpc( + _srcToken, + _destToken, + amounts, + side, + poolsToUse.poolWithoutState, + ); + + const states = poolsToUse.poolWithState.map( + p => p.getState(blockNumber)!, + ); + + const unitAmount = getBigIntPow( + side == SwapSide.SELL ? _srcToken.decimals : _destToken.decimals, + ); + + const _amounts = [...amounts.slice(1)]; + + const [token0] = this._sortTokens(_srcAddress, _destAddress); + + const zeroForOne = token0 === _srcAddress ? true : false; + + const result = await Promise.all( + poolsToUse.poolWithState.map(async (pool, i) => { + const state = states[i]; + + if (state.liquidity <= 0n) { + this.logger.trace(`pool have 0 liquidity`); + return null; + } + + const balanceDestToken = + _destAddress === pool.token0 ? state.balance0 : state.balance1; + + const unitResult = this._getOutputs( + state, + [unitAmount], + zeroForOne, + side, + balanceDestToken, + ); + const pricesResult = this._getOutputs( + state, + _amounts, + zeroForOne, + side, + balanceDestToken, + ); + + if (!unitResult || !pricesResult) { + this.logger.debug('Prices or unit is not calculated'); + return null; + } + + const prices = [0n, ...pricesResult.outputs]; + const gasCost = [ + 0, + ...pricesResult.outputs.map((p, index) => { + if (p == 0n) { + return 0; + } else { + return ( + UNISWAPV3_POOL_SEARCH_OVERHEAD + + UNISWAPV3_TICK_BASE_OVERHEAD + + pricesResult.tickCounts[index] * UNISWAPV3_TICK_GAS_COST + ); + } + }), + ]; + return { + unit: unitResult.outputs[0], + prices, + data: { + path: [ + { + tokenIn: _srcAddress, + tokenOut: _destAddress, + fee: pool.feeCode.toString(), + }, + ], + }, + poolIdentifier: this.getPoolIdentifier( + pool.token0, + pool.token1, + pool.feeCode, + ), + exchange: this.dexKey, + gasCost: gasCost, + poolAddresses: [pool.poolAddress], + }; + }), + ); + const rpcResults = await rpcResultsPromise; + + const notNullResult = result.filter( + res => res !== null, + ) as ExchangePrices; + + if (rpcResults) { + rpcResults.forEach(r => { + if (r) { + notNullResult.push(r); + } + }); + } + + return notNullResult; + } catch (e) { + this.logger.error( + `Error_getPricesVolume ${srcToken.symbol || srcToken.address}, ${ + destToken.symbol || destToken.address + }, ${side}:`, + e, + ); + return null; + } + } + + private getQuoterV2CallData( + funcName: string, + tokenIn: Address, + tokenOut: Address, + amount: bigint, + fee: bigint, + ): QuoteExactInputSingleParams | QuoteExactOutputSingleParams { + return funcName === 'quoteExactInputSingle' + ? { tokenIn, tokenOut, fee, sqrtPriceLimitX96: 0n, amountIn: amount } + : { tokenIn, tokenOut, fee, sqrtPriceLimitX96: 0n, amount }; + } + + async getPricingFromRpc( + from: Token, + to: Token, + amounts: bigint[], + side: SwapSide, + pools: SushiswapV3EventPool[], + ): Promise | null> { + if (pools.length === 0) { + return null; + } + this.logger.warn(`fallback to rpc for ${pools.length} pool(s)`); + + const requests = pools.map( + pool => ({ + owner: pool.poolAddress, + asset: side == SwapSide.SELL ? from.address : to.address, + assetType: AssetType.ERC20, + ids: [ + { + id: DEFAULT_ID_ERC20, + spenders: [], + }, + ], + }), + [], + ); + + const balances = await getBalances(this.dexHelper.multiWrapper, requests); + + pools = pools.filter((pool, index) => { + const balance = balances[index].amounts[DEFAULT_ID_ERC20_AS_STRING]; + if (balance >= amounts[amounts.length - 1]) { + return true; + } + this.logger.warn( + `[${this.network}][${pool.parentName}] have no balance ${pool.poolAddress} ${from.address} ${to.address}. (Balance: ${balance})`, + ); + return false; + }); + + pools.forEach(pool => { + this.logger.warn( + `[${this.network}][${pool.parentName}] fallback to rpc for ${pool.name}`, + ); + }); + + const unitVolume = getBigIntPow( + (side === SwapSide.SELL ? from : to).decimals, + ); + + const chunks = amounts.length - 1; + + const _width = Math.floor(chunks / this.config.chunksCount); + + const _amounts = [unitVolume].concat( + Array.from(Array(this.config.chunksCount).keys()).map( + i => amounts[(i + 1) * _width], + ), + ); + + const funcName = + side === SwapSide.SELL + ? 'quoteExactInputSingle' + : 'quoteExactOutputSingle'; + + const calldata = pools.map(pool => + _amounts.map(_amount => ({ + target: this.config.quoter, + gasLimit: UNISWAPV3_QUOTE_GASLIMIT, + callData: this.quoterIface.encodeFunctionData(funcName, [ + this.getQuoterV2CallData( + funcName, + from.address, + to.address, + _amount, + pool.feeCode, + ), + ]), + })), + ); + + const data = await new this.dexHelper.web3Provider.eth.Contract( + UniswapV3MultiABI as AbiItem[], + this.config.uniswapMulticall, + ).methods + .multicall(calldata.flat()) + .call(); + + const decode = (j: number): bigint => { + if (!data.returnData[j].success) { + return 0n; + } + const decoded = defaultAbiCoder.decode( + ['uint256'], + data.returnData[j].returnData, + ); + return BigInt(decoded[0].toString()); + }; + + let i = 0; + const result = pools.map(pool => { + const _rates = _amounts.map(() => decode(i++)); + const unit: bigint = _rates[0]; + + const prices = interpolate( + _amounts.slice(1), + _rates.slice(1), + amounts, + side, + ); + + return { + prices, + unit, + data: { + path: [ + { + tokenIn: from.address, + tokenOut: to.address, + fee: pool.feeCodeAsString, + }, + ], + }, + poolIdentifier: this.getPoolIdentifier( + pool.token0, + pool.token1, + pool.feeCode, + ), + exchange: this.dexKey, + gasCost: prices.map(p => (p === 0n ? 0 : UNISWAPV3_QUOTE_GASLIMIT)), + poolAddresses: [pool.poolAddress], + }; + }); + + return result; + } + + // Returns estimated gas cost of calldata for this DEX in multiSwap + getCalldataGasCost( + poolPrices: PoolPrices, + ): number | number[] { + const gasCost = + CALLDATA_GAS_COST.DEX_OVERHEAD + + CALLDATA_GAS_COST.LENGTH_SMALL + + // ParentStruct header + CALLDATA_GAS_COST.OFFSET_SMALL + + // ParentStruct -> path header + CALLDATA_GAS_COST.OFFSET_SMALL + + // ParentStruct -> deadline + CALLDATA_GAS_COST.TIMESTAMP + + // ParentStruct -> path (20+3+20 = 43 = 32+11 bytes) + CALLDATA_GAS_COST.LENGTH_SMALL + + CALLDATA_GAS_COST.FULL_WORD + + CALLDATA_GAS_COST.wordNonZeroBytes(11); + const arr = new Array(poolPrices.prices.length); + poolPrices.prices.forEach((p, index) => { + if (p == 0n) { + arr[index] = 0; + } else { + arr[index] = gasCost; + } + }); + return arr; + } + + // Encode params required by the exchange adapter + // Used for multiSwap, buy & megaSwap + getAdapterParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: SushiswapV3Data, + side: SwapSide, + ): AdapterExchangeParam { + const { path: rawPath } = data; + const path = this._encodePath(rawPath, side); + + const payload = this.abiCoder.encodeParameter( + { + ParentStruct: { + path: 'bytes', + deadline: 'uint256', + }, + }, + { + path, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), // FIXME: more gas efficient to pass block.timestamp in adapter + }, + ); + + return { + targetExchange: UniswapV3Config['UniswapV3'][this.network].router, + payload, + networkFee: '0', + }; + } + + // Encode call data used by simpleSwap like routers + // Used for simpleSwap & simpleBuy + async getSimpleParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: SushiswapV3Data, + ): Promise { + const web3Client = createPublicClient({ + chain: ViemChain[this.network], + transport: http(generateConfig(this.network).privateHttpProvider), + }); + + const dataFetcher = new DataFetcher( + web3Client.chain.id as ChainId, + web3Client, + ); + + dataFetcher.startDataFetching([LiquidityProviders.SushiSwapV3]); + + const fromToken = await getToken({ web3Client, address: srcToken }); + + const toToken = await getToken({ web3Client, address: destToken }); + + await dataFetcher.fetchPoolsForToken(fromToken, toToken); + + const pcMap = dataFetcher.getCurrentPoolCodeMap(fromToken, toToken); + + const route = Router.findBestRoute( + pcMap, + this.network as unknown as ChainId, + fromToken, + BigNumber.from(srcAmount), + toToken, + 50e9, + [LiquidityProviders.SushiSwapV3], + ); + + const rpParams = Router.routeProcessor2Params( + pcMap, + route, + fromToken, + toToken, + this.augustusAddress, + this.config.router, + ); + + const swapData = this.routerIface.encodeFunctionData('processRoute', [ + rpParams.tokenIn, + rpParams.amountIn, + rpParams.tokenOut, + rpParams.amountOutMin, + rpParams.to, + rpParams.routeCode, + ]); + + dataFetcher.stopDataFetching(); + + return this.buildSimpleParamWithoutWETHConversion( + srcToken, + srcAmount, + destToken, + destAmount, + swapData, + this.config.router, + ); + } + + async getTopPoolsForToken( + tokenAddress: Address, + limit: number, + ): Promise { + const _tokenAddress = tokenAddress.toLowerCase(); + + const res = await this._querySubgraph( + `query ($token: Bytes!, $count: Int) { + pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + }`, + { + token: _tokenAddress, + count: limit, + }, + ); + + if (!(res && res.pools0 && res.pools1)) { + this.logger.error( + `Error_${this.dexKey}_Subgraph: couldn't fetch the pools from the subgraph`, + ); + return []; + } + + const pools0 = _.map(res.pools0, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token1.id.toLowerCase(), + decimals: parseInt(pool.token1.decimals), + }, + ], + liquidityUSD: + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + })); + + const pools1 = _.map(res.pools1, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token0.id.toLowerCase(), + decimals: parseInt(pool.token0.decimals), + }, + ], + liquidityUSD: + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + })); + + const pools = _.slice( + _.sortBy(_.concat(pools0, pools1), [pool => -1 * pool.liquidityUSD]), + 0, + limit, + ); + return pools; + } + + private _encodePath( + path: { + tokenIn: Address; + tokenOut: Address; + fee: NumberAsString; + }[], + side: SwapSide, + ): string { + if (path.length === 0) { + this.logger.error( + `${this.dexKey}: Received invalid path=${path} for side=${side} to encode`, + ); + return '0x'; + } + + const { _path, types } = path.reduce( + ( + { _path, types }: { _path: string[]; types: string[] }, + curr, + index, + ): { _path: string[]; types: string[] } => { + if (index === 0) { + return { + types: ['address', 'uint24', 'address'], + _path: [curr.tokenIn, curr.fee, curr.tokenOut], + }; + } else { + return { + types: [...types, 'uint24', 'address'], + _path: [..._path, curr.fee, curr.tokenOut], + }; + } + }, + { _path: [], types: [] }, + ); + + return side === SwapSide.BUY + ? pack(types.reverse(), _path.reverse()) + : pack(types, _path); + } + + async getPoolIdentifiers( + srcToken: Token, + destToken: Token, + side: SwapSide, + blockNumber: number, + ): Promise { + const _srcToken = this.dexHelper.config.wrapETH(srcToken); + const _destToken = this.dexHelper.config.wrapETH(destToken); + + const [_srcAddress, _destAddress] = this._getLoweredAddresses( + _srcToken, + _destToken, + ); + + if (_srcAddress === _destAddress) return []; + + const pools = ( + await Promise.all( + this.supportedFees.map(async fee => + this.getPool(_srcAddress, _destAddress, fee, blockNumber), + ), + ) + ).filter(pool => pool); + + if (pools.length === 0) return []; + + return pools.map(pool => + this.getPoolIdentifier(_srcAddress, _destAddress, pool!.feeCode), + ); + } + + async getPool( + srcAddress: Address, + destAddress: Address, + fee: bigint, + blockNumber: number, + ): Promise { + let pool = + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)]; + + if (pool === undefined) { + const [token0, token1] = this._sortTokens(srcAddress, destAddress); + + const key = `${token0}_${token1}_${fee}`.toLowerCase(); + + const notExistingPoolScore = await this.dexHelper.cache.zscore( + this.notExistingPoolSetKey, + key, + ); + + const poolDoesNotExist = notExistingPoolScore !== null; + + if (poolDoesNotExist) { + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = + null; + return null; + } + + await this.dexHelper.cache.hset( + this.dexmapKey, + key, + JSON.stringify({ + token0, + token1, + fee: fee.toString(), + }), + ); + + this.logger.trace(`starting to listen to new pool: ${key}`); + pool = new SushiswapV3EventPool( + this.dexHelper, + this.dexKey, + this.stateMultiContract, + this.erc20Interface, + this.config.factory, + fee, + token0, + token1, + this.logger, + this.cacheStateKey, + this.config.initHash, + ); + + try { + await pool.initialize(blockNumber, { + initCallback: (state: DeepReadonly) => { + //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber + pool!.addressesSubscribed[0] = state.pool; + pool!.poolAddress = state.pool; + }, + }); + } catch (e) { + if (e instanceof Error && e.message.endsWith('Pool does not exist')) { + // no need to await we want the set to have the pool key but it's not blocking + this.dexHelper.cache.zadd( + this.notExistingPoolSetKey, + [Date.now(), key], + 'NX', + ); + + // Pool does not exist for this feeCode, so we can set it to null + // to prevent more requests for this pool + pool = null; + this.logger.trace( + `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, + e, + ); + } else { + // Unexpected Error. Break execution. Do not save the pool in this.eventPools + this.logger.error( + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool`, + e, + ); + throw new Error('Cannot generate pool state'); + } + } + + if (pool !== null) { + const allEventPools = Object.values(this.eventPools); + this.logger.info( + `starting to listen to new non-null pool: ${key}. Already following ${allEventPools + // Not that I like this reduce, but since it is done only on initialization, expect this to be ok + .reduce( + (acc, curr) => (curr !== null ? ++acc : acc), + 0, + )} non-null pools or ${allEventPools.length} total pools`, + ); + } + + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = + pool; + } + return pool; + } + + private _getLoweredAddresses(srcToken: Token, destToken: Token) { + return [srcToken.address.toLowerCase(), destToken.address.toLowerCase()]; + } + + private _sortTokens(srcAddress: Address, destAddress: Address) { + return [srcAddress, destAddress].sort((a, b) => (a < b ? -1 : 1)); + } + + private _toLowerForAllConfigAddresses() { + // If new config property will be added, the TS will throw compile error + const newConfig: DexParams = { + router: this.config.router.toLowerCase(), + quoter: this.config.quoter.toLowerCase(), + factory: this.config.factory.toLowerCase(), + supportedFees: this.config.supportedFees, + stateMulticall: this.config.stateMulticall.toLowerCase(), + chunksCount: this.config.chunksCount, + uniswapMulticall: this.config.uniswapMulticall, + deployer: this.config.deployer?.toLowerCase(), + initHash: this.config.initHash, + subgraphURL: this.config.subgraphURL, + }; + return newConfig; + } + + private async _querySubgraph( + query: string, + variables: Object, + timeout = 30000, + ) { + try { + const res = await this.dexHelper.httpRequest.post( + this.config.subgraphURL, + { query, variables }, + undefined, + { timeout: timeout }, + ); + return res.data; + } catch (e) { + this.logger.error(`${this.dexKey}: can not query subgraph: `, e); + return {}; + } + } + + private _getOutputs( + state: DeepReadonly, + amounts: bigint[], + zeroForOne: boolean, + side: SwapSide, + destTokenBalance: bigint, + ): OutputResult | null { + try { + const outputsResult = uniswapV3Math.queryOutputs( + state, + amounts, + zeroForOne, + side, + ); + + if (side === SwapSide.SELL) { + if (outputsResult.outputs[0] > destTokenBalance) { + return null; + } + + for (let i = 0; i < outputsResult.outputs.length; i++) { + if (outputsResult.outputs[i] > destTokenBalance) { + outputsResult.outputs[i] = 0n; + outputsResult.tickCounts[i] = 0; + } + } + } else { + if (amounts[0] > destTokenBalance) { + return null; + } + + // This may be improved by first checking outputs and requesting outputs + // only for amounts that makes more sense, but I don't think this is really + // important now + for (let i = 0; i < amounts.length; i++) { + if (amounts[i] > destTokenBalance) { + outputsResult.outputs[i] = 0n; + outputsResult.tickCounts[i] = 0; + } + } + } + + return outputsResult; + } catch (e) { + this.logger.debug( + `${this.dexKey}: received error in _getOutputs while calculating outputs`, + e, + ); + return null; + } + } + + releaseResources(): AsyncOrSync { + if (this.intervalTask !== undefined) { + clearInterval(this.intervalTask); + this.intervalTask = undefined; + } + } +} diff --git a/src/dex/sushiswap-v3/token.ts b/src/dex/sushiswap-v3/token.ts new file mode 100644 index 000000000..2e22b7176 --- /dev/null +++ b/src/dex/sushiswap-v3/token.ts @@ -0,0 +1,25 @@ +import { PublicClient, Address, Transport, Chain } from 'viem'; +import { Token } from '@sushiswap/currency'; + +import ERC20Abi from '../../abi/erc20.json'; + +export async function getToken({ + web3Client, + address, +}: { + web3Client: PublicClient; + address: string; +}) { + const decimals: number = (await web3Client.readContract({ + address: address as Address, + abi: ERC20Abi, + functionName: 'decimals', + args: [], + })) as unknown as number; + + return new Token({ + address, + chainId: web3Client.chain.id, + decimals, + }); +} diff --git a/src/dex/sushiswap-v3/types.ts b/src/dex/sushiswap-v3/types.ts new file mode 100644 index 000000000..e61e91b34 --- /dev/null +++ b/src/dex/sushiswap-v3/types.ts @@ -0,0 +1,17 @@ +export * from '../uniswap-v3/types'; + +export type QuoteExactInputSingleParams = { + tokenIn: string; + tokenOut: string; + amountIn: bigint; + fee: bigint; + sqrtPriceLimitX96: bigint; +}; + +export type QuoteExactOutputSingleParams = { + tokenIn: string; + tokenOut: string; + amount: bigint; + fee: bigint; + sqrtPriceLimitX96: bigint; +}; diff --git a/yarn.lock b/yarn.lock index eb77e24a1..ae78a3df3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -41,6 +41,11 @@ js-sha3 "^0.7.0" lodash "^4.17.11" +"@adraffy/ens-normalize@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.9.0.tgz#223572538f6bea336750039bb43a4016dcc8182d" + integrity sha512-iowxq3U30sghZotgl4s/oJRci6WPBfNO5YYgk2cIOMCHr3LeGPcsZjCEr+33Q4N+oV3OABDAtA+pyvWjbvBifQ== + "@ampproject/remapping@^2.1.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" @@ -331,11 +336,57 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@balena/dockerignore@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" + integrity sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q== + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@chainsafe/as-sha256@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz#3639df0e1435cab03f4d9870cc3ac079e57a6fc9" + integrity sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg== + +"@chainsafe/persistent-merkle-tree@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz#4c9ee80cc57cd3be7208d98c40014ad38f36f7ff" + integrity sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + +"@chainsafe/persistent-merkle-tree@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz#2b4a62c9489a5739dedd197250d8d2f5427e9f63" + integrity sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + +"@chainsafe/ssz@^0.10.0": + version "0.10.2" + resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.10.2.tgz#c782929e1bb25fec66ba72e75934b31fd087579e" + integrity sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + "@chainsafe/persistent-merkle-tree" "^0.5.0" + +"@chainsafe/ssz@^0.9.2": + version "0.9.4" + resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.9.4.tgz#696a8db46d6975b600f8309ad3a12f7c0e310497" + integrity sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + "@chainsafe/persistent-merkle-tree" "^0.4.2" + case "^1.6.3" + +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -343,6 +394,22 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@ensdomains/ens@^0.4.4": + version "0.4.5" + resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" + integrity sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw== + dependencies: + bluebird "^3.5.2" + eth-ens-namehash "^2.0.8" + solc "^0.4.20" + testrpc "0.0.1" + web3-utils "^1.0.0-beta.31" + +"@ensdomains/resolver@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" + integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== + "@eslint/eslintrc@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.0.tgz#8ec64e0df3e7a1971ee1ff5158da87389f167a63" @@ -412,6 +479,59 @@ merkletreejs "^0.2.27" rlp "^2.2.7" +"@ethereum-waffle/chai@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.4.tgz#16c4cc877df31b035d6d92486dfdf983df9138ff" + integrity sha512-/K8czydBtXXkcM9X6q29EqEkc5dN3oYenyH2a9hF7rGAApAJUpH8QBtojxOY/xQ2up5W332jqgxwp0yPiYug1g== + dependencies: + "@ethereum-waffle/provider" "^3.4.4" + ethers "^5.5.2" + +"@ethereum-waffle/compiler@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.4.tgz#d568ee0f6029e68b5c645506079fbf67d0dfcf19" + integrity sha512-RUK3axJ8IkD5xpWjWoJgyHclOeEzDLQFga6gKpeGxiS/zBu+HB0W2FvsrrLalTFIaPw/CGYACRBSIxqiCqwqTQ== + dependencies: + "@resolver-engine/imports" "^0.3.3" + "@resolver-engine/imports-fs" "^0.3.3" + "@typechain/ethers-v5" "^2.0.0" + "@types/mkdirp" "^0.5.2" + "@types/node-fetch" "^2.5.5" + ethers "^5.0.1" + mkdirp "^0.5.1" + node-fetch "^2.6.1" + solc "^0.6.3" + ts-generator "^0.1.1" + typechain "^3.0.0" + +"@ethereum-waffle/ens@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.4.4.tgz#db97ea2c9decbb70b9205d53de2ccbd6f3182ba1" + integrity sha512-0m4NdwWxliy3heBYva1Wr4WbJKLnwXizmy5FfSSr5PMbjI7SIGCdCB59U7/ZzY773/hY3bLnzLwvG5mggVjJWg== + dependencies: + "@ensdomains/ens" "^0.4.4" + "@ensdomains/resolver" "^0.2.4" + ethers "^5.5.2" + +"@ethereum-waffle/mock-contract@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.4.4.tgz#fc6ffa18813546f4950a69f5892d4dd54b2c685a" + integrity sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA== + dependencies: + "@ethersproject/abi" "^5.5.0" + ethers "^5.5.2" + +"@ethereum-waffle/provider@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.4.tgz#398fc1f7eb91cc2df7d011272eacba8af0c7fffb" + integrity sha512-GK8oKJAM8+PKy2nK08yDgl4A80mFuI8zBkE0C9GqTRYQqvuxIyXoLmJ5NZU9lIwyWVv5/KsoA11BgAv2jXE82g== + dependencies: + "@ethereum-waffle/ens" "^3.4.4" + ethers "^5.5.2" + ganache-core "^2.13.2" + patch-package "^6.2.2" + postinstall-postinstall "^2.1.0" + "@ethereumjs/common@^2.3.0", "@ethereumjs/common@^2.4.0", "@ethereumjs/common@^2.6.4": version "2.6.5" resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30" @@ -428,6 +548,21 @@ "@ethereumjs/common" "^2.6.4" ethereumjs-util "^7.1.5" +"@ethersproject/abi@5.0.0-beta.153": + version "5.0.0-beta.153" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" + integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg== + dependencies: + "@ethersproject/address" ">=5.0.0-beta.128" + "@ethersproject/bignumber" ">=5.0.0-beta.130" + "@ethersproject/bytes" ">=5.0.0-beta.129" + "@ethersproject/constants" ">=5.0.0-beta.128" + "@ethersproject/hash" ">=5.0.0-beta.128" + "@ethersproject/keccak256" ">=5.0.0-beta.127" + "@ethersproject/logger" ">=5.0.0-beta.129" + "@ethersproject/properties" ">=5.0.0-beta.131" + "@ethersproject/strings" ">=5.0.0-beta.130" + "@ethersproject/abi@5.0.7": version "5.0.7" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" @@ -443,7 +578,7 @@ "@ethersproject/properties" "^5.0.3" "@ethersproject/strings" "^5.0.4" -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== @@ -482,7 +617,7 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/address@5.7.0", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.7.0": +"@ethersproject/address@5.7.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== @@ -508,7 +643,7 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.7.0": +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== @@ -517,14 +652,14 @@ "@ethersproject/logger" "^5.7.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.7.0": +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.7.0": +"@ethersproject/constants@5.7.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== @@ -547,7 +682,7 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/transactions" "^5.7.0" -"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.7.0": +"@ethersproject/hash@5.7.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== @@ -599,7 +734,7 @@ aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.7.0": +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== @@ -607,7 +742,7 @@ "@ethersproject/bytes" "^5.7.0" js-sha3 "0.8.0" -"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.7.0": +"@ethersproject/logger@5.7.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== @@ -627,14 +762,14 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/sha2" "^5.7.0" -"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.7.0": +"@ethersproject/properties@5.7.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.0": +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.0", "@ethersproject/providers@^5.7.1", "@ethersproject/providers@^5.7.2": version "5.7.2" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== @@ -697,7 +832,7 @@ elliptic "6.5.4" hash.js "1.1.7" -"@ethersproject/solidity@5.7.0": +"@ethersproject/solidity@5.7.0", "@ethersproject/solidity@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== @@ -709,7 +844,7 @@ "@ethersproject/sha2" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.7.0": +"@ethersproject/strings@5.7.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== @@ -733,7 +868,7 @@ "@ethersproject/rlp" "^5.7.0" "@ethersproject/signing-key" "^5.7.0" -"@ethersproject/units@5.7.0": +"@ethersproject/units@5.7.0", "@ethersproject/units@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== @@ -742,7 +877,7 @@ "@ethersproject/constants" "^5.7.0" "@ethersproject/logger" "^5.7.0" -"@ethersproject/wallet@5.7.0": +"@ethersproject/wallet@5.7.0", "@ethersproject/wallet@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== @@ -1125,6 +1260,22 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" +"@matterlabs/hardhat-zksync-deploy@0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-deploy/-/hardhat-zksync-deploy-0.6.2.tgz#077beeaadc28af5afc469c0a94f394bbc9d96ad4" + integrity sha512-TRGbYXqFdLspaGRjNRWFcej0i8+OgYodDPFVRMg/3KJvC0QLViEEcBZ2cpBqC/R5fydsIql5KXe8ZVMz22AeqA== + dependencies: + chalk "4.1.2" + +"@matterlabs/hardhat-zksync-solc@0.3.14": + version "0.3.14" + resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-solc/-/hardhat-zksync-solc-0.3.14.tgz#0a32f01b4cd8631ecd8dfe0547e3ac49ab8290d5" + integrity sha512-iKuQ+vvnpv3K2lkFO41xpJcNWH0KHJ/5JbOboTlPZATVR7F3GJeHfJL+GG4wkxKXnxZczpxyQqC4rAfMKvRaDg== + dependencies: + "@nomiclabs/hardhat-docker" "^2.0.0" + chalk "4.1.2" + dockerode "^3.3.4" + "@metamask/eth-sig-util@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" @@ -1136,16 +1287,33 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" +"@noble/curves@1.0.0", "@noble/curves@~1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.0.0.tgz#e40be8c7daf088aaf291887cbc73f43464a92932" + integrity sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw== + dependencies: + "@noble/hashes" "1.3.0" + "@noble/hashes@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== +"@noble/hashes@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" + integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== + "@noble/hashes@~1.1.1": version "1.1.5" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.5.tgz#1a0377f3b9020efe2fae03290bd2a12140c95c11" integrity sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ== +"@noble/hashes@~1.3.0": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" + integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== + "@noble/secp256k1@1.6.3", "@noble/secp256k1@~1.6.0": version "1.6.3" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.6.3.tgz#7eed12d9f4404b416999d0c87686836c4c5c9b94" @@ -1172,6 +1340,19 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@nomicfoundation/ethereumjs-block@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.1.tgz#6f89664f55febbd723195b6d0974773d29ee133d" + integrity sha512-u1Yioemi6Ckj3xspygu/SfFvm8vZEO8/Yx5a1QLzi6nVU0jz3Pg2OmHKJ5w+D9Ogk1vhwRiqEBAqcb0GVhCyHw== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + ethereum-cryptography "0.1.3" + ethers "^5.7.1" + "@nomicfoundation/ethereumjs-block@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.0.0.tgz#fdd5c045e7baa5169abeed0e1202bf94e4481c49" @@ -1184,6 +1365,25 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" ethereum-cryptography "0.1.3" +"@nomicfoundation/ethereumjs-blockchain@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.1.tgz#80e0bd3535bfeb9baa29836b6f25123dab06a726" + integrity sha512-NhzndlGg829XXbqJEYrF1VeZhAwSPgsK/OB7TVrdzft3y918hW5KNd7gIZ85sn6peDZOdjBsAXIpXZ38oBYE5A== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-ethash" "3.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + abstract-level "^1.0.3" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + level "^8.0.0" + lru-cache "^5.1.1" + memory-level "^1.0.0" + "@nomicfoundation/ethereumjs-blockchain@^6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.0.0.tgz#1a8c243a46d4d3691631f139bfb3a4a157187b0c" @@ -1202,6 +1402,14 @@ lru-cache "^5.1.1" memory-level "^1.0.0" +"@nomicfoundation/ethereumjs-common@4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.1.tgz#4702d82df35b07b5407583b54a45bf728e46a2f0" + integrity sha512-OBErlkfp54GpeiE06brBW/TTbtbuBJV5YI5Nz/aB2evTDo+KawyEzPjBlSr84z/8MFfj8wS2wxzQX1o32cev5g== + dependencies: + "@nomicfoundation/ethereumjs-util" "9.0.1" + crc-32 "^1.2.0" + "@nomicfoundation/ethereumjs-common@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.0.0.tgz#f6bcc7753994555e49ab3aa517fc8bcf89c280b9" @@ -1210,6 +1418,18 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" crc-32 "^1.2.0" +"@nomicfoundation/ethereumjs-ethash@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.1.tgz#65ca494d53e71e8415c9a49ef48bc921c538fc41" + integrity sha512-KDjGIB5igzWOp8Ik5I6QiRH5DH+XgILlplsHR7TEuWANZA759G6krQ6o8bvj+tRUz08YygMQu/sGd9mJ1DYT8w== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + abstract-level "^1.0.3" + bigint-crypto-utils "^3.0.23" + ethereum-cryptography "0.1.3" + "@nomicfoundation/ethereumjs-ethash@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.0.tgz#11539c32fe0990e1122ff987d1b84cfa34774e81" @@ -1222,6 +1442,20 @@ bigint-crypto-utils "^3.0.23" ethereum-cryptography "0.1.3" +"@nomicfoundation/ethereumjs-evm@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.1.tgz#f35681e203363f69ce2b3d3bf9f44d4e883ca1f1" + integrity sha512-oL8vJcnk0Bx/onl+TgQOQ1t/534GKFaEG17fZmwtPFeH8S5soiBYPCLUrvANOl4sCp9elYxIMzIiTtMtNNN8EQ== + dependencies: + "@ethersproject/providers" "^5.7.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + "@nomicfoundation/ethereumjs-evm@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.0.0.tgz#99cd173c03b59107c156a69c5e215409098a370b" @@ -1236,11 +1470,28 @@ mcl-wasm "^0.7.1" rustbn.js "~0.2.0" +"@nomicfoundation/ethereumjs-rlp@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.1.tgz#0b30c1cf77d125d390408e391c4bb5291ef43c28" + integrity sha512-xtxrMGa8kP4zF5ApBQBtjlSbN5E2HI8m8FYgVSYAnO6ssUoY5pVPGy2H8+xdf/bmMa22Ce8nWMH3aEW8CcqMeQ== + "@nomicfoundation/ethereumjs-rlp@^4.0.0", "@nomicfoundation/ethereumjs-rlp@^4.0.0-beta.2": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.0.tgz#d9a9c5f0f10310c8849b6525101de455a53e771d" integrity sha512-GaSOGk5QbUk4eBP5qFbpXoZoZUj/NrW7MRa0tKY4Ew4c2HAS0GXArEMAamtFrkazp0BO4K5p2ZCG3b2FmbShmw== +"@nomicfoundation/ethereumjs-statemanager@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.1.tgz#8824a97938db4471911e2d2f140f79195def5935" + integrity sha512-B5ApMOnlruVOR7gisBaYwFX+L/AP7i/2oAahatssjPIBVDF6wTX1K7Qpa39E/nzsH8iYuL3krkYeUFIdO3EMUQ== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + ethers "^5.7.1" + js-sdsl "^4.1.4" + "@nomicfoundation/ethereumjs-statemanager@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.0.tgz#14a9d4e1c828230368f7ab520c144c34d8721e4b" @@ -1254,6 +1505,17 @@ ethereum-cryptography "0.1.3" functional-red-black-tree "^1.0.1" +"@nomicfoundation/ethereumjs-trie@6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.1.tgz#662c55f6b50659fd4b22ea9f806a7401cafb7717" + integrity sha512-A64It/IMpDVODzCgxDgAAla8jNjNtsoQZIzZUfIV5AY6Coi4nvn7+VReBn5itlxMiL2yaTlQr9TRWp3CSI6VoA== + dependencies: + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + "@types/readable-stream" "^2.3.13" + ethereum-cryptography "0.1.3" + readable-stream "^3.6.0" + "@nomicfoundation/ethereumjs-trie@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.0.tgz#dcfbe3be53a94bc061c9767a396c16702bc2f5b7" @@ -1264,6 +1526,18 @@ ethereum-cryptography "0.1.3" readable-stream "^3.6.0" +"@nomicfoundation/ethereumjs-tx@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.1.tgz#7629dc2036b4a33c34e9f0a592b43227ef4f0c7d" + integrity sha512-0HwxUF2u2hrsIM1fsasjXvlbDOq1ZHFV2dd1yGq8CA+MEYhaxZr8OTScpVkkxqMwBcc5y83FyPl0J9MZn3kY0w== + dependencies: + "@chainsafe/ssz" "^0.9.2" + "@ethersproject/providers" "^5.7.2" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + ethereum-cryptography "0.1.3" + "@nomicfoundation/ethereumjs-tx@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.0.0.tgz#59dc7452b0862b30342966f7052ab9a1f7802f52" @@ -1274,6 +1548,15 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" ethereum-cryptography "0.1.3" +"@nomicfoundation/ethereumjs-util@9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.1.tgz#530cda8bae33f8b5020a8f199ed1d0a2ce48ec89" + integrity sha512-TwbhOWQ8QoSCFhV/DDfSmyfFIHjPjFBj957219+V3jTZYZ2rf9PmDtNOeZWAE3p3vlp8xb02XGpd0v6nTUPbsA== + dependencies: + "@chainsafe/ssz" "^0.10.0" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + ethereum-cryptography "0.1.3" + "@nomicfoundation/ethereumjs-util@^8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.0.tgz#deb2b15d2c308a731e82977aefc4e61ca0ece6c5" @@ -1282,6 +1565,25 @@ "@nomicfoundation/ethereumjs-rlp" "^4.0.0-beta.2" ethereum-cryptography "0.1.3" +"@nomicfoundation/ethereumjs-vm@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.1.tgz#7d035e0993bcad10716c8b36e61dfb87fa3ca05f" + integrity sha512-rArhyn0jPsS/D+ApFsz3yVJMQ29+pVzNZ0VJgkzAZ+7FqXSRtThl1C1prhmlVr3YNUlfpZ69Ak+RUT4g7VoOuQ== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-blockchain" "7.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-evm" "2.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-statemanager" "2.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + "@nomicfoundation/ethereumjs-vm@^6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.0.0.tgz#2bb50d332bf41790b01a3767ffec3987585d1de6" @@ -1370,6 +1672,56 @@ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.0" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.0" +"@nomiclabs/hardhat-docker@^2.0.0": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-docker/-/hardhat-docker-2.0.2.tgz#ae964be17951275a55859ff7358e9e7c77448846" + integrity sha512-XgGEpRT3wlA1VslyB57zyAHV+oll8KnV1TjwnxxC1tpAL04/lbdwpdO5KxInVN8irMSepqFpsiSkqlcnvbE7Ng== + dependencies: + dockerode "^2.5.8" + fs-extra "^7.0.1" + node-fetch "^2.6.0" + +"@nomiclabs/hardhat-ethers@^2.1.1": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz#b41053e360c31a32c2640c9a45ee981a7e603fe0" + integrity sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg== + +"@nomiclabs/hardhat-ethers@npm:hardhat-deploy-ethers@0.3.0-beta.13", hardhat-deploy-ethers@0.3.0-beta.13: + version "0.3.0-beta.13" + resolved "https://registry.yarnpkg.com/hardhat-deploy-ethers/-/hardhat-deploy-ethers-0.3.0-beta.13.tgz#b96086ff768ddf69928984d5eb0a8d78cfca9366" + integrity sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw== + +"@nomiclabs/hardhat-etherscan@3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.3.tgz#c9dbaa4174edfa075a464a0e9142bc8710a2c4e2" + integrity sha512-UeNO97j0lwOHqX7mrH6SfQQBdXq1Ng6eFr7uJKuQOrq2UVTWGD70lE5QO4fAFVPz9ao+xlNpMyIqSR7+OaDR+Q== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@ethersproject/address" "^5.0.2" + cbor "^8.1.0" + chalk "^2.4.2" + debug "^4.1.1" + fs-extra "^7.0.1" + lodash "^4.17.11" + semver "^6.3.0" + table "^6.8.0" + undici "^5.4.0" + +"@nomiclabs/hardhat-solhint@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-solhint/-/hardhat-solhint-2.0.1.tgz#62896569d10c95a17cefab0229701cfffd19246f" + integrity sha512-SrTLufY21t78KLpJL5fS6gHIsCwVv0yWsHp1aQOPL1qwRWpe0Mnh5wb2YzBHd3Dbr/KzUYys+j2ui0PsSVU9pg== + dependencies: + solhint "^2.0.0" + +"@nomiclabs/hardhat-waffle@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.3.tgz#9c538a09c5ed89f68f5fd2dc3f78f16ed1d6e0b1" + integrity sha512-049PHSnI1CZq6+XTbrMbMv5NaL7cednTfPenx02k3cEh8wBMLa6ys++dBETJa6JjfwgA9nBhhHQ173LJv6k2Pg== + dependencies: + "@types/sinon-chai" "^3.2.3" + "@types/web3" "1.0.19" + "@openzeppelin/contracts-upgradeable@4.7.3": version "4.7.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.7.3.tgz#f1d606e2827d409053f3e908ba4eb8adb1dd6995" @@ -1380,6 +1732,16 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.1.tgz#363f7dd08f25f8f77e16d374350c3d6b43340a7a" integrity sha512-1wTv+20lNiC0R07jyIAbHU7TNHKRwGiTGRfiNnA8jOWjKT98g5OgLpYWOi40Vgpk8SPLA9EvfJAbAeIyVn+7Bw== +"@openzeppelin/contracts@3.4.1-solc-0.7-2": + version "3.4.1-solc-0.7-2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.1-solc-0.7-2.tgz#371c67ebffe50f551c3146a9eec5fe6ffe862e92" + integrity sha512-tAG9LWg8+M2CMu7hIsqHPaTyG4uDzjr6mhvH96LvOpLZZj6tgzTluBt+LsCf1/QaYrlis6pITvpIaIhE+iZB+Q== + +"@openzeppelin/contracts@3.4.2-solc-0.7": + version "3.4.2-solc-0.7" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.2-solc-0.7.tgz#38f4dbab672631034076ccdf2f3201fab1726635" + integrity sha512-W6QmqgkADuFcTLzHL8vVoNBtkwjvQRpYIAom7KiUNoLKghyx3FgH0GBjt8NRvigV1ZmMOBllvE1By1C+bi8WpA== + "@openzeppelin/contracts@4.7.3": version "4.7.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.3.tgz#939534757a81f8d69cc854c7692805684ff3111e" @@ -1404,6 +1766,48 @@ bignumber.js "^9.0.2" ts-essentials "^9.1.2" +"@rari-capital/solmate@6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@rari-capital/solmate/-/solmate-6.2.0.tgz#4f70dc236606c27ec2cb1b4261dd830235d01fe4" + integrity sha512-g94F+Ra9ixyJyNgvnOIufNjUz488uEG0nxIEEtJ7+g+tA1XGUupRB2kB5b+VO7WYO26RNOVD2fW6xE4e14iWpg== + +"@resolver-engine/core@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" + integrity sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ== + dependencies: + debug "^3.1.0" + is-url "^1.2.4" + request "^2.85.0" + +"@resolver-engine/fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.3.3.tgz#fbf83fa0c4f60154a82c817d2fe3f3b0c049a973" + integrity sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports-fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz#4085db4b8d3c03feb7a425fbfcf5325c0d1e6c1b" + integrity sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA== + dependencies: + "@resolver-engine/fs" "^0.3.3" + "@resolver-engine/imports" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.3.3.tgz#badfb513bb3ff3c1ee9fd56073e3144245588bcc" + integrity sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + hosted-git-info "^2.6.0" + path-browserify "^1.0.0" + url "^0.11.0" + "@scure/base@~1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" @@ -1418,6 +1822,15 @@ "@noble/secp256k1" "~1.6.0" "@scure/base" "~1.1.0" +"@scure/bip32@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.0.tgz#6c8d980ef3f290987736acd0ee2e0f0d50068d87" + integrity sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q== + dependencies: + "@noble/curves" "~1.0.0" + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + "@scure/bip39@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.0.tgz#92f11d095bae025f166bef3defcc5bf4945d419a" @@ -1426,6 +1839,14 @@ "@noble/hashes" "~1.1.1" "@scure/base" "~1.1.0" +"@scure/bip39@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.0.tgz#a207e2ef96de354de7d0002292ba1503538fc77b" + integrity sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + "@sentry/core@5.30.0": version "5.30.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" @@ -1540,6 +1961,191 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@sushiswap/abi@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@sushiswap/abi/-/abi-0.0.1.tgz#2bb8ab632e4a95ec2152603c489f88fcc8ffdf7d" + integrity sha512-J4zWyfZdFiDIBa28MV/yYmr9nmWDqX8CXVfUoLfg48RVUyqPsu57dKtEKiBqAO/xpl7d9ZciNcya0d09NXvm8w== + +"@sushiswap/amm@0.1.12": + version "0.1.12" + resolved "https://registry.yarnpkg.com/@sushiswap/amm/-/amm-0.1.12.tgz#e4ddd4e8dfc6eccb3b6dbd203557333db1d3d655" + integrity sha512-SvgRfKZnNxSUwocuUbQFfHi2VYysrgPVxGnDC7iOTVU+4mS27XcNUmWXeJ/qciQe/f6x7z/GNbbeXjM2ZdehVg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@sushiswap/chain" "0.1.2" + "@sushiswap/currency" "0.1.1" + "@sushiswap/math" "0.1.0" + "@sushiswap/tines" "1.0.8" + "@sushiswap/trident-core" "1.0.7" + "@sushiswap/types" "0.0.2" + "@sushiswap/v2-sdk" "0.0.8" + tiny-invariant "1.3.1" + tiny-warning "1.0.3" + zod "3.21.4" + +"@sushiswap/bentobox@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@sushiswap/bentobox/-/bentobox-1.0.1.tgz#a3fb265d66b28e4ddba290182ccf2f3e565a7da7" + integrity sha512-Wg3QVWie0YIVHch0oE0y6Dy+qpX/e5fsiF0MSaXgYNhTki1Uc5IPTcJ2wCISbkMjDpEP+HiLWivftNdc7gc+aw== + +"@sushiswap/chain@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@sushiswap/chain/-/chain-0.1.2.tgz#dc164887ace62edd781a8d9afac1054cbdefd582" + integrity sha512-A0S5fYxYxUZu3UQj3AwekCRgjDQ8hzLRjc1p9XwV9i+0r9ZxAdXafWFrpQufDoXS0lfKd/4XiFh50LsbhvWA8A== + +"@sushiswap/currency@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@sushiswap/currency/-/currency-0.1.1.tgz#627b20155fbf40d76f4a930251c4bf088e3d93b3" + integrity sha512-AjzrYYUvpYabel13CmGBpDk+NHNkBIExTcLyZl1QBtDKkhWl/1239NU8WgEF04Pxx0UD1wK/FTCput2n5yK50Q== + dependencies: + "@ethersproject/address" "5.7.0" + "@ethersproject/units" "^5.7.0" + "@sushiswap/chain" "0.1.2" + "@sushiswap/math" "0.1.0" + lodash.flatmap "4.5.0" + tiny-invariant "1.3.1" + zod "3.21.4" + +"@sushiswap/hardhat-config@0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@sushiswap/hardhat-config/-/hardhat-config-0.1.3.tgz#33e7a457be3094716be7cffc3e5a37f8280f200b" + integrity sha512-lc+tPdmin2j3C/KtquoqsUZdQCIh7ibWThqfx0BMqixFwyBR3REp48JzN6hWmODKwQE8PKnYmldZ1GmZczKOMw== + dependencies: + "@matterlabs/hardhat-zksync-deploy" "0.6.2" + "@matterlabs/hardhat-zksync-solc" "0.3.14" + "@nomiclabs/hardhat-ethers" "npm:hardhat-deploy-ethers@0.3.0-beta.13" + "@nomiclabs/hardhat-etherscan" "3.1.3" + "@nomiclabs/hardhat-solhint" "2.0.1" + "@nomiclabs/hardhat-waffle" "2.0.3" + "@sushiswap/types" "0.0.2" + "@tenderly/hardhat-tenderly" "1.3.2" + "@typechain/ethers-v5" "10.1.1" + "@typechain/hardhat" "6.1.4" + dotenv "16.0.3" + ethereum-waffle "3.4.4" + hardhat-deploy "0.11.22" + hardhat-deploy-ethers "0.3.0-beta.13" + typechain "8.1.1" + +"@sushiswap/math@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@sushiswap/math/-/math-0.1.0.tgz#e4821e81997a8acfcc11fdd55eccdd160cb308fe" + integrity sha512-bchOAQo7vWPHufXJQuk7+sWGxjhlbdlaI+kin3m3cLkUzKPPHqZxMwND4G9IpXsqEbko/DFrQL/M6a25gs7InA== + dependencies: + big.js "^6.1.1" + decimal.js-light "^2.5.1" + jsbi "^4.1.0" + tiny-invariant "^1.2.0" + toformat "^2.0.0" + +"@sushiswap/router-config@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sushiswap/router-config/-/router-config-2.0.0.tgz#5052f57472f1c9e72153995927ee4c72089c3b79" + integrity sha512-cVN20sur3EbC4GTxywuCVPovhXcuBh7hUMSFyhYhOQxhQGbvlPYot/+PX77UpYviTsJOTdo+ov2LyMT5AGdTHA== + +"@sushiswap/router@^0.0.12": + version "0.0.12" + resolved "https://registry.yarnpkg.com/@sushiswap/router/-/router-0.0.12.tgz#89d65dc04bfb971c5c9a987078cf8ee4ec92165c" + integrity sha512-53cPuNmZPDnt7u9l7q9CpoiJQHnOdtPMjnq1EsHKDh7Meb1pFav9zYrAFgCbn/5Np9Qs83/xxn77JtlGSh0ypw== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@sushiswap/abi" "0.0.1" + "@sushiswap/amm" "0.1.12" + "@sushiswap/bentobox" "1.0.1" + "@sushiswap/chain" "0.1.2" + "@sushiswap/currency" "0.1.1" + "@sushiswap/math" "0.1.0" + "@sushiswap/router-config" "2.0.0" + "@sushiswap/tines" "1.0.8" + "@sushiswap/trident-core" "1.0.7" + "@sushiswap/v2-sdk" "0.0.8" + "@sushiswap/v3-sdk" "1.0.9" + "@sushiswap/viem-config" "1.0.2" + date-fns "2.29.3" + ethers "5.7.2" + lodash.flatmap "^4.5.0" + node-fetch "2.6.6" + tiny-invariant "1.3.1" + tiny-warning "1.0.3" + viem "1.0.2" + zod "3.21.4" + +"@sushiswap/tines@1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@sushiswap/tines/-/tines-1.0.8.tgz#11e7a0ed3bffe7fb0dea4141811b44294f09f95a" + integrity sha512-se9CnYcjnsuDqf7pbEXfo7FYaLgjSrBjaEc/TvEd0r8bO/goQSHUwNqklA+i9DpzYSki72GT2G5+4r6OxnActA== + dependencies: + "@ethersproject/bignumber" "5.7.0" + "@sushiswap/currency" "0.1.1" + +"@sushiswap/trident-core@1.0.7": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@sushiswap/trident-core/-/trident-core-1.0.7.tgz#20c7691374332a0601e13fe1045189ae063d49b9" + integrity sha512-u2Z22726Y2hC8sx0jDj/lGMf2egFZ/uTctGUWrlUDb3KyT/LtxFVQOSYgaFw6GnRhunSfE0oOpHlYJNHEVYBpA== + dependencies: + "@openzeppelin/contracts" "4.7.3" + "@rari-capital/solmate" "6.2.0" + "@sushiswap/bentobox" "1.0.1" + "@sushiswap/currency" "0.1.1" + "@sushiswap/hardhat-config" "0.1.3" + "@sushiswap/types" "0.0.2" + +"@sushiswap/types@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@sushiswap/types/-/types-0.0.2.tgz#9088674d01afede9c3738f6a62a908976f8bc639" + integrity sha512-Aa4MnBFq/SK/F4zZlRXNpLcqza2RsE0mLxxv4+8an1Dtr7l26lyWd+3PbVrtv1bA7OVmBXoqJhTrQKA8w3zEPA== + +"@sushiswap/v2-sdk@0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@sushiswap/v2-sdk/-/v2-sdk-0.0.8.tgz#14c0460c8f3164314cd9d9b574815e1d365e7c06" + integrity sha512-o1h7uDkUOauNiVh2DUFZEfp5ASqt7muOs25VQxRV966YHYwDPs9SZEI9fVXn6a04jTWWOVbPP8BnDLYH+MRh8Q== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@sushiswap/chain" "0.1.2" + "@sushiswap/currency" "0.1.1" + "@sushiswap/math" "0.1.0" + tiny-invariant "1.3.1" + tiny-warning "1.0.3" + zod "3.21.4" + +"@sushiswap/v3-sdk@1.0.9": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@sushiswap/v3-sdk/-/v3-sdk-1.0.9.tgz#79d280a00b100886d8dee52dcfd0b9c2a115b32c" + integrity sha512-Lb5aJTy4atLUd8vtCQH3ZgAxFFefeZ26JqEeYlCrH2ayh73bs2CPET7E3ZKvKEOD1g2l67bvHfWesbueCyurVg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@sushiswap/amm" "0.1.12" + "@sushiswap/chain" "0.1.2" + "@sushiswap/currency" "0.1.1" + "@sushiswap/math" "0.1.0" + "@sushiswap/tines" "1.0.8" + "@uniswap/swap-router-contracts" "1.3.0" + "@uniswap/v3-core" "1.0.1" + "@uniswap/v3-periphery" "1.4.3" + "@uniswap/v3-staker" "1.0.2" + tiny-invariant "1.3.1" + tiny-warning "1.0.3" + zod "3.21.4" + +"@sushiswap/viem-config@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@sushiswap/viem-config/-/viem-config-1.0.2.tgz#82112a2cdddc63fa902f6d568d899423402200b8" + integrity sha512-IpZ/vmgs67LeR4eqrfIF/Og/taFGD9NW3E12kzS2sFyJJ0uZQP/hpqLNtNmXTPg9oV6/JCtnTGL+6Ic0EUd+gA== + dependencies: + "@sushiswap/chain" "0.1.2" + "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -1554,6 +2160,21 @@ dependencies: defer-to-connect "^2.0.0" +"@tenderly/hardhat-tenderly@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@tenderly/hardhat-tenderly/-/hardhat-tenderly-1.3.2.tgz#9ee69ba1fb8650d18160c637e8e487d938f6dcea" + integrity sha512-0kE0gv8RIu0N5JXKCCfYcydsMgGgj8z3qCvbeD/ynBKwOBvbFB+NZFRyTHNopbeaUKO7Q3bGFau8vS1B0EWS0g== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@nomiclabs/hardhat-ethers" "^2.1.1" + axios "^0.27.2" + ethers "^5.7.0" + fs-extra "^10.1.0" + hardhat "^2.10.2" + hardhat-deploy "^0.11.14" + js-yaml "^4.1.0" + tenderly "^0.0.3" + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -1574,6 +2195,28 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== +"@typechain/ethers-v5@10.1.1": + version "10.1.1" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-10.1.1.tgz#fdb527d8854129cea5f139d76c6c6e1c9bb040ec" + integrity sha512-o6nffJBxwmeX1ZiZpdnP/tqGd/7M7iYvQC88ZXaFFoyAGh7eYncynzVjOJV0XmaKzAc6puqyqZrnva+gJbk4sw== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + +"@typechain/ethers-v5@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" + integrity sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw== + dependencies: + ethers "^5.0.2" + +"@typechain/hardhat@6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-6.1.4.tgz#da930bf17bdae5e0996b86d37992c6c58b8a49c8" + integrity sha512-S8k5d1Rjc+plwKpkorlifmh72M7Ki0XNUOVVLtdbcA/vLaEkuqZSJFdddpBgS5QxiJP+6CbRa/yO6EVTE2+fMQ== + dependencies: + fs-extra "^9.1.0" + "@types/async-eventemitter@^0.2.1": version "0.2.1" resolved "https://registry.yarnpkg.com/@types/async-eventemitter/-/async-eventemitter-0.2.1.tgz#f8e6280e87e8c60b2b938624b0a3530fb3e24712" @@ -1624,6 +2267,13 @@ dependencies: "@babel/types" "^7.3.0" +"@types/bn.js@*", "@types/bn.js@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== + dependencies: + "@types/node" "*" + "@types/bn.js@^4.11.0", "@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": version "4.11.6" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" @@ -1631,13 +2281,6 @@ dependencies: "@types/node" "*" -"@types/bn.js@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" - integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== - dependencies: - "@types/node" "*" - "@types/body-parser@*": version "1.19.2" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" @@ -1656,6 +2299,11 @@ "@types/node" "*" "@types/responselike" "*" +"@types/chai@*": + version "4.3.5" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b" + integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== + "@types/connect@*": version "3.4.35" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" @@ -1758,6 +2406,21 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== +"@types/mkdirp@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" + integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== + dependencies: + "@types/node" "*" + +"@types/node-fetch@^2.5.5": + version "2.6.4" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" + integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*": version "18.11.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.3.tgz#78a6d7ec962b596fc2d2ec102c4dd3ef073fea6a" @@ -1780,6 +2443,11 @@ dependencies: "@types/node" "*" +"@types/prettier@^2.1.1": + version "2.7.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" + integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== + "@types/prettier@^2.1.5": version "2.7.1" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e" @@ -1790,7 +2458,7 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== -"@types/qs@*": +"@types/qs@*", "@types/qs@^6.9.7": version "6.9.7" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== @@ -1809,6 +2477,21 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/readable-stream@^2.3.13": + version "2.3.15" + resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.15.tgz#3d79c9ceb1b6a57d5f6e6976f489b9b5384321ae" + integrity sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ== + dependencies: + "@types/node" "*" + safe-buffer "~5.1.1" + +"@types/resolve@^0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" + integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== + dependencies: + "@types/node" "*" + "@types/responselike@*", "@types/responselike@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" @@ -1841,16 +2524,49 @@ "@types/mime" "*" "@types/node" "*" +"@types/sinon-chai@^3.2.3": + version "3.2.9" + resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.9.tgz#71feb938574bbadcb176c68e5ff1a6014c5e69d4" + integrity sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ== + dependencies: + "@types/chai" "*" + "@types/sinon" "*" + +"@types/sinon@*": + version "10.0.15" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.15.tgz#513fded9c3cf85e589bbfefbf02b2a0541186b48" + integrity sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ== + dependencies: + "@types/sinonjs__fake-timers" "*" + +"@types/sinonjs__fake-timers@*": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz#bf2e02a3dbd4aecaf95942ecd99b7402e03fad5e" + integrity sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA== + "@types/stack-utils@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== +"@types/underscore@*": + version "1.11.5" + resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.5.tgz#963de9bc8c8908d9ba1777d3978c63484fbb9fe1" + integrity sha512-b8e//LrIlhoXaaBcMC0J/s2/lIF9y5VJYKqbW4nA+tW/nqqDk1Dacd1ULLT7zgGsKs7PGbSnqCPzqEniZ0RxYg== + "@types/uuid@^9.0.1": version "9.0.2" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.2.tgz#ede1d1b1e451548d44919dc226253e32a6952c4b" integrity sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ== +"@types/web3@1.0.19": + version "1.0.19" + resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.0.19.tgz#46b85d91d398ded9ab7c85a5dd57cb33ac558924" + integrity sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A== + dependencies: + "@types/bn.js" "*" + "@types/underscore" "*" + "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" @@ -1953,31 +2669,146 @@ "@typescript-eslint/types" "5.47.0" eslint-visitor-keys "^3.3.0" -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== +"@uniswap/lib@^4.0.1-alpha": + version "4.0.1-alpha" + resolved "https://registry.yarnpkg.com/@uniswap/lib/-/lib-4.0.1-alpha.tgz#2881008e55f075344675b3bca93f020b028fbd02" + integrity sha512-f6UIliwBbRsgVLxIaBANF6w09tYqc6Y/qXdsrbEmXHyFA7ILiKrIwRFXe1yOg8M3cksgVsO9N7yuL2DdCGQKBA== + +"@uniswap/swap-router-contracts@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@uniswap/swap-router-contracts/-/swap-router-contracts-1.3.0.tgz#8d555ca6d74b888d6e02a26ebb806ce315605f1f" + integrity sha512-iKvCuRkHXEe0EMjOf8HFUISTIhlxI57kKFllf3C3PUIE0HmwxrayyoflwAz5u/TRsFGYqJ9IjX2UgzLCsrNa5A== dependencies: - event-target-shim "^5.0.0" + "@openzeppelin/contracts" "3.4.2-solc-0.7" + "@uniswap/v2-core" "1.0.1" + "@uniswap/v3-core" "1.0.0" + "@uniswap/v3-periphery" "1.4.1" + dotenv "^14.2.0" + hardhat-watcher "^2.1.1" -abortcontroller-polyfill@^1.1.9: - version "1.7.5" - resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" - integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== +"@uniswap/v2-core@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@uniswap/v2-core/-/v2-core-1.0.1.tgz#af8f508bf183204779938969e2e54043e147d425" + integrity sha512-MtybtkUPSyysqLY2U210NBDeCHX+ltHt3oADGdjqoThZaFRDKwM6k1Nb3F0A3hk5hwuQvytFWhrWHOEq6nVJ8Q== -abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" - integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== +"@uniswap/v3-core@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.0.tgz#6c24adacc4c25dceee0ba3ca142b35adbd7e359d" + integrity sha512-kSC4djMGKMHj7sLMYVnn61k9nu+lHjMIxgg9CDQT+s2QYLoA56GbSK9Oxr+qJXzzygbkrmuY6cwgP6cW2JXPFA== + +"@uniswap/v3-core@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.1.tgz#b6d2bdc6ba3c3fbd610bdc502395d86cd35264a0" + integrity sha512-7pVk4hEm00j9tc71Y9+ssYpO6ytkeI0y7WE9P6UcmNzhxPePwyAxImuhVsTqWK9YFvzgtvzJHi64pBl4jUzKMQ== + +"@uniswap/v3-periphery@1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.4.1.tgz#b90f08b7386163c0abfd7258831caef6339c7862" + integrity sha512-Ab0ZCKOQrQMKIcpBTezTsEhWfQjItd0TtkCG8mPhoQu+wC67nPaf4hYUhM6wGHeFUmDiYY5MpEQuokB0ENvoTg== dependencies: - buffer "^6.0.3" - catering "^2.1.0" + "@openzeppelin/contracts" "3.4.2-solc-0.7" + "@uniswap/lib" "^4.0.1-alpha" + "@uniswap/v2-core" "1.0.1" + "@uniswap/v3-core" "1.0.0" + base64-sol "1.0.1" + hardhat-watcher "^2.1.1" + +"@uniswap/v3-periphery@1.4.3", "@uniswap/v3-periphery@^1.0.1": + version "1.4.3" + resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.4.3.tgz#a6da4632dbd46b139cc13a410e4ec09ad22bd19f" + integrity sha512-80c+wtVzl5JJT8UQskxVYYG3oZb4pkhY0zDe0ab/RX4+8f9+W5d8wI4BT0wLB0wFQTSnbW+QdBSpkHA/vRyGBA== + dependencies: + "@openzeppelin/contracts" "3.4.2-solc-0.7" + "@uniswap/lib" "^4.0.1-alpha" + "@uniswap/v2-core" "1.0.1" + "@uniswap/v3-core" "1.0.0" + base64-sol "1.0.1" + +"@uniswap/v3-staker@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@uniswap/v3-staker/-/v3-staker-1.0.2.tgz#febad4905903032bb114ab58138c2d5200c87a3c" + integrity sha512-+swIh/yhY9GQGyQxT4Gz54aXYLK+uc3qsmIvaAX+FjvhcL9TGOvS9tXbQsCZM4AJW63vj6TLsmHIjGMIePL1BQ== + dependencies: + "@openzeppelin/contracts" "3.4.1-solc-0.7-2" + "@uniswap/v3-core" "1.0.0" + "@uniswap/v3-periphery" "^1.0.1" + +"@wagmi/chains@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-1.1.0.tgz#d351b3dc6f472b167f180721f46f6098b6c1585b" + integrity sha512-pWZlxBk0Ql8E7DV8DwqlbBpOyUdaG9UDlQPBxJNALuEK1I0tbQ3AVvSDnlsEIt06UPmPo5o27gzs3hwPQ/A+UA== + +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + +JSONStream@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" + integrity sha512-mn0KSip7N4e0UDPZHnqDsHECo5uGQrixQKnAskOM1BIB8hd7QKbd6il8IPRPudPHOeHiECoCFqhyMaRO9+nWyA== + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +abitype@0.8.7: + version "0.8.7" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.8.7.tgz#e4b3f051febd08111f486c0cc6a98fa72d033622" + integrity sha512-wQ7hV8Yg/yKmGyFpqrNZufCxbszDe5es4AZGYPBitocfSqXtjrTG9JMWFcc4N30ukl2ve48aBTwt7NJxVQdU3w== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +abortcontroller-polyfill@^1.1.9: + version "1.7.5" + resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" + integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== + +abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" + integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== + dependencies: + buffer "^6.0.3" + catering "^2.1.0" is-buffer "^2.0.5" level-supports "^4.0.0" level-transcoder "^1.0.1" module-error "^1.0.1" queue-microtask "^1.2.3" +abstract-leveldown@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" + integrity sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^2.4.1, abstract-leveldown@~2.7.1: + version "2.7.2" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" + integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz#f7128e1f86ccabf7d2893077ce5d06d798e386c6" + integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@~2.6.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" + integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== + dependencies: + xtend "~4.0.0" + accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -1986,7 +2817,7 @@ accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-jsx@^5.3.2: +acorn-jsx@^5.0.0, acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== @@ -1996,6 +2827,11 @@ acorn-walk@^8.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== +acorn@^6.0.7: + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== + acorn@^8.4.1: version "8.8.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" @@ -2016,6 +2852,11 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== +aes-js@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" + integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -2031,7 +2872,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.6.1, ajv@^6.9.1: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2041,6 +2882,16 @@ ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.0.1: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -2051,6 +2902,11 @@ ansi-colors@^4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -2058,12 +2914,32 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: dependencies: type-fest "^0.21.3" +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== + +ansi-regex@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + ansi-regex@^5.0.0, ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^3.2.1: +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -2082,6 +2958,11 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== +antlr4@4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.7.1.tgz#69984014f096e9e775f53dd9744bf994d8959773" + integrity sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ== + anymatch@^3.0.3: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" @@ -2115,6 +2996,53 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== + +array-back@^1.0.3, array-back@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" + integrity sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw== + dependencies: + typical "^2.6.0" + +array-back@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" + integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== + dependencies: + typical "^2.6.1" + +array-back@^3.0.1, array-back@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + +array-back@^4.0.1, array-back@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== + +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + array-differ@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" @@ -2141,6 +3069,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== + array.prototype.flat@^1.2.5: version "1.3.1" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" @@ -2151,6 +3084,17 @@ array.prototype.flat@^1.2.5: es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" +array.prototype.reduce@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" + integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + arrify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" @@ -2166,7 +3110,7 @@ asn1.js@^5.2.0: minimalistic-assert "^1.0.0" safer-buffer "^2.1.0" -asn1@~0.2.3: +asn1@^0.2.6, asn1@~0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== @@ -2183,7 +3127,22 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== -async-eventemitter@^0.2.4: +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async-eventemitter@^0.2.2, async-eventemitter@^0.2.4: version "0.2.4" resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== @@ -2195,7 +3154,19 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async@^2.4.0: +async@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" + integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== + dependencies: + lodash "^4.17.11" + +async@^1.4.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== + +async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: version "2.6.4" resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== @@ -2212,6 +3183,16 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + available-typed-arrays@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" @@ -2243,6 +3224,13 @@ axios@0.26.0: dependencies: follow-redirects "^1.14.8" +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + axios@^0.27.2: version "0.27.2" resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" @@ -2251,6 +3239,167 @@ axios@^0.27.2: follow-redirects "^1.14.9" form-data "^4.0.0" +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g== + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.0.14, babel-core@^6.26.0: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + +babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + integrity sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q== + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + integrity sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ== + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + integrity sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA== + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + integrity sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ== + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + integrity sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q== + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + integrity sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + integrity sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + integrity sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + integrity sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg== + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + integrity sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg== + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + integrity sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw== + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + integrity sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ== + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-jest@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.2.1.tgz#213c47e28072de11bdb98c9d29b89f2ab99664f1" @@ -2264,6 +3413,20 @@ babel-jest@^29.2.1: graceful-fs "^4.2.9" slash "^3.0.0" +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + integrity sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA== + dependencies: + babel-runtime "^6.22.0" + babel-plugin-istanbul@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" @@ -2285,6 +3448,244 @@ babel-plugin-jest-hoist@^29.2.0: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + integrity sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw== + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + integrity sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ== + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + integrity sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ== + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + integrity sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw== + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + integrity sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + integrity sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + integrity sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw== + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + integrity sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag== + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + integrity sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw== + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + integrity sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + integrity sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + integrity sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + integrity sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg== + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + integrity sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + integrity sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA== + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + integrity sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg== + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + integrity sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw== + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + integrity sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA== + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + integrity sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ== + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + integrity sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + integrity sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + integrity sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ== + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + integrity sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + integrity sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + integrity sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ== + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + integrity sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ== + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + integrity sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg== + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + integrity sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -2303,6 +3704,42 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" +babel-preset-env@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^3.2.6" + invariant "^2.2.2" + semver "^5.3.0" + babel-preset-jest@^29.2.0: version "29.2.0" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz#3048bea3a1af222e3505e4a767a974c95a7620dc" @@ -2311,6 +3748,83 @@ babel-preset-jest@^29.2.0: babel-plugin-jest-hoist "^29.2.0" babel-preset-current-node-syntax "^1.0.0" +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + integrity sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A== + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + integrity sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg== + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA== + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g== + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babelify@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" + integrity sha512-vID8Fz6pPN5pJMdlUnNFSfrlcx5MUule4k9aKs/zbZPyXxMTcRrB0M4Tarw22L8afr8eYSWxDPYCob3TdrqtlA== + dependencies: + babel-core "^6.0.14" + object-assign "^4.0.0" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +backoff@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" + integrity sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA== + dependencies: + precond "0.2" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -2328,7 +3842,25 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -bcrypt-pbkdf@^1.0.0: +base64-sol@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/base64-sol/-/base64-sol-1.0.1.tgz#91317aa341f0bc763811783c5729f1c2574600f6" + integrity sha512-ld3cCNMeXt4uJXmLZBHFGMvVpK9KsLVEhPpFRXnvSVAqABKbuNZg/+dsq3NuM+wxFLb/UrVkz7m1ciWmkMfTbg== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== @@ -2340,6 +3872,11 @@ bech32@1.1.4: resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== +big.js@^6.1.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.2.1.tgz#7205ce763efb17c2e41f26f121c420c6a7c2744f" + integrity sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ== + bigint-crypto-utils@^3.0.23: version "3.1.8" resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.1.8.tgz#e2e0f40cf45488f9d7f0e32ff84152aa73819d5d" @@ -2372,12 +3909,40 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== +bip39@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" + integrity sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA== + dependencies: + create-hash "^1.1.0" + pbkdf2 "^3.0.9" + randombytes "^2.0.1" + safe-buffer "^5.0.1" + unorm "^1.3.3" + +bl@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" + integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + blakejs@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== -bluebird@^3.5.0: +bluebird@^3.5.0, bluebird@^3.5.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -2387,7 +3952,7 @@ bn.js@4.11.6: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.8.0: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== @@ -2430,6 +3995,22 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -2511,6 +4092,14 @@ browserify-sign@^4.0.0: readable-stream "^3.6.0" safe-buffer "^5.2.0" +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + browserslist@^4.21.3: version "4.21.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" @@ -2551,6 +4140,24 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -2571,7 +4178,14 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== -buffer@^5.0.5, buffer@^5.5.0, buffer@^5.6.0: +buffer-xor@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" + integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== + dependencies: + safe-buffer "^5.1.1" + +buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -2599,6 +4213,11 @@ bufio@^1.0.7: resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.2.0.tgz#b9ad1c06b0d9010363c387c39d2810a7086d143f" integrity sha512-UlFk8z/PwdhYQTXSQQagwGAdtRI83gib2n4uy4rQnenxUM2yQi8lBDzF230BNk+3wAoZDxYRoBwVVUPgHa9MCA== +buildcheck@~0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.6.tgz#89aa6e417cfd1e2196e3f8fe915eb709d2fe4238" + integrity sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A== + busboy@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -2611,6 +4230,36 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +bytewise-core@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" + integrity sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA== + dependencies: + typewise-core "^1.2" + +bytewise@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" + integrity sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ== + dependencies: + bytewise-core "^1.2.2" + typewise "^1.0.3" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + cacheable-lookup@^5.0.3: version "5.0.4" resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" @@ -2642,7 +4291,15 @@ cacheable-request@^7.0.2: normalize-url "^6.0.1" responselike "^2.0.0" -call-bind@^1.0.0, call-bind@^1.0.2: +cachedown@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cachedown/-/cachedown-1.0.0.tgz#d43f036e4510696b31246d7db31ebf0f7ac32d15" + integrity sha512-t+yVk82vQWCJF3PsWHMld+jhhjkkWjcAzz8NbFx1iULOXWl8Tm/FdM4smZNVw3MRr0X+lVTx9PKzvEn4Ng19RQ== + dependencies: + abstract-leveldown "^2.4.1" + lru-cache "^3.2.0" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== @@ -2650,6 +4307,25 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -2663,6 +4339,11 @@ camel-case@^4.1.2: pascal-case "^3.1.2" tslib "^2.0.3" +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg== + camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -2673,6 +4354,11 @@ camelcase@^6.0.0, camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== +caniuse-lite@^1.0.30000844: + version "1.0.30001507" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001507.tgz#fae53f6286e7564783eadea9b447819410a59534" + integrity sha512-SFpUDoSLCaE5XYL2jfqe9ova/pbQHEmbheDf5r4diNwbAgR3qxM9NQtfsiSscjqoya5K7kFcHPUQ+VsUkIJR4A== + caniuse-lite@^1.0.30001400: version "1.0.30001423" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001423.tgz#57176d460aa8cd85ee1a72016b961eb9aca55d91" @@ -2687,6 +4373,11 @@ capital-case@^1.0.4: tslib "^2.0.3" upper-case-first "^2.0.2" +case@^1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" + integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -2697,6 +4388,13 @@ catering@^2.1.0, catering@^2.1.1: resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== +cbor@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" + integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== + dependencies: + nofilter "^3.1.0" + chai@^4.3.4: version "4.3.7" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" @@ -2710,7 +4408,26 @@ chai@^4.3.4: pathval "^1.1.1" type-detect "^4.0.5" -chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.2: +chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2727,14 +4444,6 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0, chalk@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - change-case@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" @@ -2758,12 +4467,24 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== -chokidar@3.5.3, chokidar@^3.4.0: +checkpoint-store@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" + integrity sha512-J/NdY2WvIx654cc6LWSq/IYFFCUf75fFTgwzFnmbqyORH4MwgiQCgswLLKBGzmsyTI5V7i5bp/So6sMbDWhedg== + dependencies: + functional-red-black-tree "^1.0.1" + +chokidar@3.5.3, chokidar@^3.4.0, chokidar@^3.5.2, chokidar@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -2778,7 +4499,7 @@ chokidar@3.5.3, chokidar@^3.4.0: optionalDependencies: fsevents "~2.3.2" -chownr@^1.1.4: +chownr@^1.0.1, chownr@^1.1.1, chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== @@ -2822,6 +4543,16 @@ class-is@^1.1.0: resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + classic-level@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.2.0.tgz#2d52bdec8e7a27f534e67fdeb890abef3e643c27" @@ -2838,6 +4569,36 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== + dependencies: + restore-cursor "^2.0.0" + +cli-table3@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + +cli-width@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" + integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w== + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -2863,7 +4624,7 @@ clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" -clone@2.x: +clone@2.1.2, clone@2.x, clone@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== @@ -2873,11 +4634,24 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== + collect-v8-coverage@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -2914,16 +4688,70 @@ command-exists@^1.2.8: resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== +command-line-args@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46" + integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== + dependencies: + array-back "^2.0.0" + find-replace "^1.0.3" + typical "^2.6.1" + +command-line-args@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== + dependencies: + array-back "^3.1.0" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + +command-line-usage@^6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" + integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== + dependencies: + array-back "^4.0.2" + chalk "^2.4.2" + table-layout "^1.0.2" + typical "^5.2.0" + +commander@2.18.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" + integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== + commander@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== +commander@^9.4.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +concat-stream@^1.5.1, concat-stream@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + confusing-browser-globals@^1.0.10: version "1.0.11" resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" @@ -2959,7 +4787,7 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== -convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== @@ -2984,11 +4812,31 @@ cookiejar@^2.1.1: resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== + +core-js-pure@^3.0.1: + version "3.31.0" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.31.0.tgz#052fd9e82fbaaf86457f5db1fadcd06f15966ff2" + integrity sha512-/AnE9Y4OsJZicCzIe97JP5XoPKQJfTuEG43aEVLFJGOJpyqELod+pE6LEl63DfG1Mp8wX97LDaDpy1GmLEUxlg== + +core-js@^2.4.0, core-js@^2.5.0: + version "2.6.12" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + cors@^2.8.1: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" @@ -2997,6 +4845,24 @@ cors@^2.8.1: object-assign "^4" vary "^1" +cosmiconfig@^5.0.7: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +cpu-features@~0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.8.tgz#a2d464b023b8ad09004c8cdca23b33f192f63546" + integrity sha512-BbHBvtYhUhksqTjr6bhNOjGgMnhwhGTQmOoZGD+K7BCaQDCuZl/Ve1ZxUSMRwVC4D/rkCPQ2MAIeYzrWyK7eEg== + dependencies: + buildcheck "~0.0.6" + nan "^2.17.0" + crc-32@^1.2.0: version "1.2.2" resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" @@ -3038,6 +4904,14 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-fetch@^2.1.0, cross-fetch@^2.1.1: + version "2.2.6" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.6.tgz#2ef0bb39a24ac034787965c457368a28730e220a" + integrity sha512-9JZz+vXCmfKUZ68zAptS7k4Nu8e2qcibe7WVZYps7sAgk5R8GYTc+T1WR0v1rlP9HxgARmOX1UTIJZFytajpNA== + dependencies: + node-fetch "^2.6.7" + whatwg-fetch "^2.0.4" + cross-fetch@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" @@ -3045,6 +4919,17 @@ cross-fetch@^3.1.5: dependencies: node-fetch "2.6.7" +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -3096,37 +4981,59 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +date-fns@2.29.3: + version "2.29.3" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" + integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== + date-format@^4.0.13, date-format@^4.0.14: version "4.0.14" resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.14.tgz#7a8e584434fb169a521c8b7aa481f355810d9400" integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg== -debug@2.6.9, debug@^2.2.0, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@4, debug@4.3.4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^3.2.7: +debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + decamelize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== +decimal.js-light@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" + integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -3158,7 +5065,24 @@ deep-eql@^4.1.2: dependencies: type-detect "^4.0.0" -deep-is@^0.1.3: +deep-equal@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + +deep-extend@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -3178,6 +5102,26 @@ defer-to-connect@^2.0.0: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== +deferred-leveldown@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" + integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== + dependencies: + abstract-leveldown "~2.6.0" + +deferred-leveldown@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz#0b0570087827bf480a23494b398f04c128c19a20" + integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== + dependencies: + abstract-leveldown "~5.0.0" + inherits "^2.0.3" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + define-properties@^1.1.3, define-properties@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" @@ -3186,6 +5130,41 @@ define-properties@^1.1.3, define-properties@^1.1.4: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +define-properties@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +defined@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" + integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -3209,6 +5188,13 @@ destroy@1.2.0: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + integrity sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A== + dependencies: + repeating "^2.0.0" + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -3255,6 +5241,44 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +docker-modem@^1.0.8: + version "1.0.9" + resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-1.0.9.tgz#a1f13e50e6afb6cf3431b2d5e7aac589db6aaba8" + integrity sha512-lVjqCSCIAUDZPAZIeyM125HXfNvOmYYInciphNrLrylUtKyW66meAjSPXWchKVzoIYZx69TPnAepVSSkeawoIw== + dependencies: + JSONStream "1.3.2" + debug "^3.2.6" + readable-stream "~1.0.26-4" + split-ca "^1.0.0" + +docker-modem@^3.0.0: + version "3.0.8" + resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-3.0.8.tgz#ef62c8bdff6e8a7d12f0160988c295ea8705e77a" + integrity sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ== + dependencies: + debug "^4.1.1" + readable-stream "^3.5.0" + split-ca "^1.0.1" + ssh2 "^1.11.0" + +dockerode@^2.5.8: + version "2.5.8" + resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-2.5.8.tgz#1b661e36e1e4f860e25f56e0deabe9f87f1d0acc" + integrity sha512-+7iOUYBeDTScmOmQqpUYQaE7F4vvIt6+gIZNHWhqAQEI887tiPFB9OvXI/HzQYqfUNvukMK+9myLW63oTJPZpw== + dependencies: + concat-stream "~1.6.2" + docker-modem "^1.0.8" + tar-fs "~1.16.3" + +dockerode@^3.3.4: + version "3.3.5" + resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-3.3.5.tgz#7ae3f40f2bec53ae5e9a741ce655fff459745629" + integrity sha512-/0YNa3ZDNeLr/tSckmD69+Gq+qVNhvKfAHNeZJBnp7EOP6RGKV8ORrJHkUn20So5wU+xxT7+1n5u8PjHbfjbSA== + dependencies: + "@balena/dockerignore" "^1.0.2" + docker-modem "^3.0.0" + tar-fs "~2.0.1" + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -3287,6 +5311,23 @@ dotenv@16.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411" integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q== +dotenv@16.0.3: + version "16.0.3" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" + integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== + +dotenv@^14.2.0: + version "14.3.2" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-14.3.2.tgz#7c30b3a5f777c79a3429cb2db358eef6751e8369" + integrity sha512-vwEppIphpFdvaMCaHfCEv9IgwcxMljMw2TnAQBB4VWPvzXQLTb82jwmdOKzlEVUL3gNFT4l4TPKO+Bn+sqcrVQ== + +dotignore@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" + integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== + dependencies: + minimatch "^3.0.4" + duplexer3@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" @@ -3305,6 +5346,11 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== +electron-to-chromium@^1.3.47: + version "1.4.439" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.439.tgz#d0748e8128c18f92354d3412dfb2104c3fb90e8f" + integrity sha512-BHpErPSNhb9FB25+OwQP6mCAf3ZXfGbmuvc4LzBNVJwpCcXQJm++LerimocYRG9FRxUVRKZqaB7d0+pImSTPSg== + electron-to-chromium@^1.4.251: version "1.4.284" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" @@ -3328,16 +5374,37 @@ emittery@^0.10.2: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933" integrity sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw== +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +encode-utf8@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== +encoding-down@5.0.4, encoding-down@~5.0.0: + version "5.0.4" + resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-5.0.4.tgz#1e477da8e9e9d0f7c8293d320044f8b2cd8e9614" + integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== + dependencies: + abstract-leveldown "^5.0.0" + inherits "^2.0.3" + level-codec "^9.0.0" + level-errors "^2.0.0" + xtend "^4.0.1" + encoding@^0.1.11: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" @@ -3345,14 +5412,14 @@ encoding@^0.1.11: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.1.0: +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" -enquirer@^2.3.0: +enquirer@^2.3.0, enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -3364,7 +5431,14 @@ env-paths@^2.2.0: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== -error-ex@^1.3.1: +errno@~0.1.1: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -3432,6 +5506,60 @@ es-abstract@^1.20.4: string.prototype.trimstart "^1.0.6" unbox-primitive "^1.0.2" +es-abstract@^1.21.2: + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== + dependencies: + array-buffer-byte-length "^1.0.0" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.2.0" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + es-shim-unscopables@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" @@ -3494,7 +5622,7 @@ escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== @@ -3553,6 +5681,14 @@ eslint-plugin-import@^2.26.0: resolve "^1.22.0" tsconfig-paths "^3.14.1" +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -3569,6 +5705,13 @@ eslint-scope@^7.1.1: esrecurse "^4.3.0" estraverse "^5.2.0" +eslint-utils@^1.3.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: + eslint-visitor-keys "^1.1.0" + eslint-utils@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" @@ -3576,6 +5719,11 @@ eslint-utils@^3.0.0: dependencies: eslint-visitor-keys "^2.0.0" +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + eslint-visitor-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" @@ -3586,6 +5734,48 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== +eslint@^5.6.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" + integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.9.1" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^4.0.3" + eslint-utils "^1.3.1" + eslint-visitor-keys "^1.0.0" + espree "^5.0.1" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^6.2.2" + js-yaml "^3.13.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.11" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^5.5.1" + strip-ansi "^4.0.0" + strip-json-comments "^2.0.1" + table "^5.2.3" + text-table "^0.2.0" + eslint@^8.30.0: version "8.30.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.30.0.tgz#83a506125d089eef7c5b5910eeea824273a33f50" @@ -3631,6 +5821,15 @@ eslint@^8.30.0: strip-json-comments "^3.1.0" text-table "^0.2.0" +espree@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" + integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== + dependencies: + acorn "^6.0.7" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" + espree@^9.4.0: version "9.4.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" @@ -3645,6 +5844,13 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== +esquery@^1.0.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + esquery@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" @@ -3652,7 +5858,7 @@ esquery@^1.4.0: dependencies: estraverse "^5.1.0" -esrecurse@^4.3.0: +esrecurse@^4.1.0, esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== @@ -3679,7 +5885,20 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -eth-ens-namehash@2.0.8: +eth-block-tracker@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz#95cd5e763c7293e0b1b2790a2a39ac2ac188a5e1" + integrity sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug== + dependencies: + eth-query "^2.1.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.3" + ethjs-util "^0.1.3" + json-rpc-engine "^3.6.0" + pify "^2.3.0" + tape "^4.6.3" + +eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" integrity sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw== @@ -3687,6 +5906,35 @@ eth-ens-namehash@2.0.8: idna-uts46-hx "^2.3.1" js-sha3 "^0.5.7" +eth-json-rpc-infura@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz#26702a821067862b72d979c016fd611502c6057f" + integrity sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw== + dependencies: + cross-fetch "^2.1.1" + eth-json-rpc-middleware "^1.5.0" + json-rpc-engine "^3.4.0" + json-rpc-error "^2.0.0" + +eth-json-rpc-middleware@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" + integrity sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q== + dependencies: + async "^2.5.0" + eth-query "^2.1.2" + eth-tx-summary "^3.1.2" + ethereumjs-block "^1.6.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.2" + ethereumjs-vm "^2.1.0" + fetch-ponyfill "^4.0.0" + json-rpc-engine "^3.6.0" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + tape "^4.6.3" + eth-lib@0.2.8: version "0.2.8" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" @@ -3708,6 +5956,60 @@ eth-lib@^0.1.26: ws "^3.0.0" xhr-request-promise "^0.1.2" +eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" + integrity sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA== + dependencies: + json-rpc-random-id "^1.0.0" + xtend "^4.0.1" + +eth-sig-util@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.0.tgz#75133b3d7c20a5731af0690c385e184ab942b97e" + integrity sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ== + dependencies: + buffer "^5.2.1" + elliptic "^6.4.0" + ethereumjs-abi "0.6.5" + ethereumjs-util "^5.1.1" + tweetnacl "^1.0.0" + tweetnacl-util "^0.15.0" + +eth-sig-util@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" + integrity sha512-iNZ576iTOGcfllftB73cPB5AN+XUQAT/T8xzsILsghXC1o8gJUqe3RHlcDqagu+biFpYQ61KQrZZJza8eRSYqw== + dependencies: + ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" + ethereumjs-util "^5.1.1" + +eth-tx-summary@^3.1.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" + integrity sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg== + dependencies: + async "^2.1.2" + clone "^2.0.0" + concat-stream "^1.5.1" + end-of-stream "^1.1.0" + eth-query "^2.0.2" + ethereumjs-block "^1.4.1" + ethereumjs-tx "^1.1.1" + ethereumjs-util "^5.0.1" + ethereumjs-vm "^2.6.0" + through2 "^2.0.3" + +ethashjs@~0.0.7: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.8.tgz#227442f1bdee409a548fb04136e24c874f3aa6f9" + integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw== + dependencies: + async "^2.1.2" + buffer-xor "^2.0.1" + ethereumjs-util "^7.0.2" + miller-rabin "^4.0.0" + ethereum-bloom-filters@^1.0.6: version "1.0.10" resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" @@ -3715,6 +6017,16 @@ ethereum-bloom-filters@^1.0.6: dependencies: js-sha3 "^0.8.0" +ethereum-common@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" + integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== + +ethereum-common@^0.0.18: + version "0.0.18" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" + integrity sha512-EoltVQTRNg2Uy4o84qpa2aXymXDJhxm7eos/ACOg0DG4baAbMjhbdAEsx9GeE8sC3XCxnYvrrzZDH8D8MtA2iQ== + ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" @@ -3754,7 +6066,26 @@ ethereum-types@^2.1.6: "@types/node" "*" bignumber.js "~8.0.2" -ethereumjs-abi@^0.6.8: +ethereum-waffle@3.4.4: + version "3.4.4" + resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.4.tgz#1378b72040697857b7f5e8f473ca8f97a37b5840" + integrity sha512-PA9+jCjw4WC3Oc5ocSMBj5sXvueWQeAbvCA+hUlb6oFgwwKyq5ka3bWQ7QZcjzIX+TdFkxP4IbFmoY2D8Dkj9Q== + dependencies: + "@ethereum-waffle/chai" "^3.4.4" + "@ethereum-waffle/compiler" "^3.4.4" + "@ethereum-waffle/mock-contract" "^3.4.4" + "@ethereum-waffle/provider" "^3.4.4" + ethers "^5.0.1" + +ethereumjs-abi@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" + integrity sha512-rCjJZ/AE96c/AAZc6O3kaog4FhOsAViaysBxqJNy2+LHP0ttH0zkZ7nXdVHOAyt6lFwLO0nlCwWszysG/ao1+g== + dependencies: + bn.js "^4.10.0" + ethereumjs-util "^4.3.0" + +ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: version "0.6.8" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== @@ -3762,20 +6093,96 @@ ethereumjs-abi@^0.6.8: bn.js "^4.11.8" ethereumjs-util "^6.0.0" -ethereumjs-util@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" - integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== +"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": + version "0.6.8" + resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0" dependencies: - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "^0.1.3" + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-account@3.0.0, ethereumjs-account@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz#728f060c8e0c6e87f1e987f751d3da25422570a9" + integrity sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA== + dependencies: + ethereumjs-util "^6.0.0" + rlp "^2.2.1" + safe-buffer "^5.1.1" + +ethereumjs-account@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" + integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== + dependencies: + ethereumjs-util "^5.0.0" rlp "^2.0.0" safe-buffer "^5.1.1" -ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: +ethereumjs-block@2.2.2, ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.0, ethereumjs-block@~2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" + integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== + dependencies: + async "^2.0.1" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.1" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" + integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== + dependencies: + async "^2.0.1" + ethereum-common "0.2.0" + ethereumjs-tx "^1.2.2" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-blockchain@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz#30f2228dc35f6dcf94423692a6902604ae34960f" + integrity sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ== + dependencies: + async "^2.6.1" + ethashjs "~0.0.7" + ethereumjs-block "~2.2.2" + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.1.0" + flow-stoplight "^1.0.0" + level-mem "^3.0.1" + lru-cache "^5.1.1" + rlp "^2.2.2" + semaphore "^1.1.0" + +ethereumjs-common@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd" + integrity sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ== + +ethereumjs-common@^1.1.0, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" + integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== + +ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" + integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== + dependencies: + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.0.0" + +ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" + integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== + dependencies: + ethereum-common "^0.0.18" + ethereumjs-util "^5.0.0" + +ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0, ethereumjs-util@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== @@ -3788,7 +6195,31 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: ethjs-util "0.1.6" rlp "^2.2.3" -ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: +ethereumjs-util@^4.3.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz#f4bf9b3b515a484e3cc8781d61d9d980f7c83bd0" + integrity sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w== + dependencies: + bn.js "^4.8.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + rlp "^2.0.0" + +ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" + integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== + dependencies: + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "^0.1.3" + rlp "^2.0.0" + safe-buffer "^5.1.1" + +ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== @@ -3799,7 +6230,60 @@ ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: ethereum-cryptography "^0.1.3" rlp "^2.2.4" -ethers@^5.6.5, ethers@^5.7.0: +ethereumjs-vm@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz#e885e861424e373dbc556278f7259ff3fca5edab" + integrity sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + core-js-pure "^3.0.1" + ethereumjs-account "^3.0.0" + ethereumjs-block "^2.2.2" + ethereumjs-blockchain "^4.0.3" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.2" + ethereumjs-util "^6.2.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + util.promisify "^1.0.0" + +ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" + integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + ethereumjs-account "^2.0.3" + ethereumjs-block "~2.2.0" + ethereumjs-common "^1.1.0" + ethereumjs-util "^6.0.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + +ethereumjs-wallet@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz#685e9091645cee230ad125c007658833991ed474" + integrity sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA== + dependencies: + aes-js "^3.1.1" + bs58check "^2.1.2" + ethereum-cryptography "^0.1.3" + ethereumjs-util "^6.0.0" + randombytes "^2.0.6" + safe-buffer "^5.1.2" + scryptsy "^1.2.1" + utf8 "^3.0.0" + uuid "^3.3.2" + +ethers@5.7.2, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2, ethers@^5.5.3, ethers@^5.6.5, ethers@^5.7.0, ethers@^5.7.1: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -3876,6 +6360,11 @@ eventemitter3@4.0.4: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== +events@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" @@ -3919,6 +6408,19 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + expect@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/expect/-/expect-29.2.1.tgz#25752d0df92d3daa5188dc8804de1f30759658cf" @@ -3930,7 +6432,7 @@ expect@^29.2.1: jest-message-util "^29.2.1" jest-util "^29.2.1" -express@^4.14.0, express@^4.18.2: +express@^4.14.0, express@^4.18.1, express@^4.18.2: version "4.18.2" resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== @@ -3974,11 +6476,49 @@ ext@^1.1.2: dependencies: type "^2.7.2" -extend@~3.0.2: +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -3989,11 +6529,23 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== +fake-merkle-patricia-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" + integrity sha512-Tgq37lkc9pUIgIKw5uitNUKcgcYL3R6JvXtKQbOf/ZSavXbidsksgp/pAY6p//uhw0I4yoMsvTSovvVIsk/qxA== + dependencies: + checkpoint-store "^1.1.0" + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" @@ -4010,7 +6562,7 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-sta resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6: +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== @@ -4029,6 +6581,27 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fetch-ponyfill@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" + integrity sha512-knK9sGskIg2T7OnYLdZ2hZXn0CtDrAIBxYQLpmEf0BqfdWnwmM1weccUl5+4EdA44tzNSFAuxITPbXtPehUB3g== + dependencies: + node-fetch "~1.7.1" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -4036,6 +6609,16 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -4056,6 +6639,21 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" +find-replace@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" + integrity sha512-KrUnjzDCD9426YnCP56zGYy/eieTnhtK6Vn++j+JJzmlsWWwEkDnsyVF575spT6HJ6Ow9tlbT3TQTDsa+O4UWA== + dependencies: + array-back "^1.0.4" + test-value "^2.1.0" + +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -4064,6 +6662,14 @@ find-up@5.0.0, find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA== + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -4079,6 +6685,30 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-yarn-workspace-root@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" + integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== + dependencies: + fs-extra "^4.0.3" + micromatch "^3.1.4" + +find-yarn-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -4092,28 +6722,59 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== +flatted@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + flatted@^3.1.0, flatted@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== -follow-redirects@^1.12.1, follow-redirects@^1.14.8, follow-redirects@^1.14.9, follow-redirects@^1.15.0: +flow-stoplight@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" + integrity sha512-rDjbZUKpN8OYhB0IE/vY/I8UWO/602IIJEU/76Tv4LvYnwHCk0BCsvz4eRr9n+FQcri7L5cyaXOo0+/Kh4HisA== + +fmix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c" + integrity sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w== + dependencies: + imul "^1.0.0" + +follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.14.8, follow-redirects@^1.14.9, follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== -for-each@^0.3.3: +for-each@^0.3.3, for-each@~0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -4147,11 +6808,23 @@ fp-ts@^1.0.0: resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== + dependencies: + map-cache "^0.2.2" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" @@ -4163,7 +6836,16 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^4.0.2: +fs-extra@^10.0.0, fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^4.0.2, fs-extra@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== @@ -4172,7 +6854,7 @@ fs-extra@^4.0.2: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^7.0.1: +fs-extra@^7.0.0, fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== @@ -4190,6 +6872,16 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^9.0.0, fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-minipass@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" @@ -4222,21 +6914,63 @@ function.prototype.name@^1.1.5: es-abstract "^1.19.0" functions-have-names "^1.2.2" -functional-red-black-tree@^1.0.1: +functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== -functions-have-names@^1.2.2: +functions-have-names@^1.2.2, functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +ganache-core@^2.13.2: + version "2.13.2" + resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.13.2.tgz#27e6fc5417c10e6e76e2e646671869d7665814a3" + integrity sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw== + dependencies: + abstract-leveldown "3.0.0" + async "2.6.2" + bip39 "2.5.0" + cachedown "1.0.0" + clone "2.1.2" + debug "3.2.6" + encoding-down "5.0.4" + eth-sig-util "3.0.0" + ethereumjs-abi "0.6.8" + ethereumjs-account "3.0.0" + ethereumjs-block "2.2.2" + ethereumjs-common "1.5.0" + ethereumjs-tx "2.1.2" + ethereumjs-util "6.2.1" + ethereumjs-vm "4.2.0" + heap "0.2.6" + keccak "3.0.1" + level-sublevel "6.6.4" + levelup "3.1.1" + lodash "4.17.20" + lru-cache "5.1.1" + merkle-patricia-tree "3.0.0" + patch-package "6.2.2" + seedrandom "3.0.1" + source-map-support "0.5.12" + tmp "0.1.0" + web3-provider-engine "14.2.1" + websocket "1.0.32" + optionalDependencies: + ethereumjs-wallet "0.6.5" + web3 "1.2.11" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -4256,6 +6990,16 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@ has "^1.0.3" has-symbols "^1.0.3" +get-intrinsic@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -4288,6 +7032,11 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -4309,6 +7058,18 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" +glob@7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" @@ -4321,7 +7082,7 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3, glob@^7.1.4: +glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.2.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -4341,7 +7102,7 @@ global@~4.4.0: min-document "^2.19.0" process "^0.11.10" -globals@^11.1.0: +globals@^11.1.0, globals@^11.7.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== @@ -4353,6 +7114,18 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" @@ -4406,6 +7179,11 @@ got@^11.8.5: p-cancelable "^2.0.0" responselike "^2.0.0" +graceful-fs@^4.1.11: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" @@ -4429,6 +7207,117 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" +hardhat-deploy@0.11.22: + version "0.11.22" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.22.tgz#9799c0266a0fc40c84690de54760f1b4dae5e487" + integrity sha512-ZhHVNB7Jo2l8Is+KIAk9F8Q3d7pptyiX+nsNbIFXztCz81kaP+6kxNODRBqRCy7SOD3It4+iKCL6tWsPAA/jVQ== + dependencies: + "@types/qs" "^6.9.7" + axios "^0.21.1" + chalk "^4.1.2" + chokidar "^3.5.2" + debug "^4.3.2" + enquirer "^2.3.6" + ethers "^5.5.3" + form-data "^4.0.0" + fs-extra "^10.0.0" + match-all "^1.2.6" + murmur-128 "^0.2.1" + qs "^6.9.4" + zksync-web3 "^0.8.1" + +hardhat-deploy@^0.11.14: + version "0.11.31" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.31.tgz#1f05adc280bf7c3de502693271aa6700a043db20" + integrity sha512-86LObxQri29nxDzP7cjUyfHJ8jBF5aW60ahn883dqlw4rzc5I6ylLFQc6T2aMC2gEZI1oBc2gI2idmUulXP35g== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/contracts" "^5.7.0" + "@ethersproject/providers" "^5.7.2" + "@ethersproject/solidity" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wallet" "^5.7.0" + "@types/qs" "^6.9.7" + axios "^0.21.1" + chalk "^4.1.2" + chokidar "^3.5.2" + debug "^4.3.2" + enquirer "^2.3.6" + ethers "^5.5.3" + form-data "^4.0.0" + fs-extra "^10.0.0" + match-all "^1.2.6" + murmur-128 "^0.2.1" + qs "^6.9.4" + zksync-web3 "^0.14.3" + +hardhat-watcher@^2.1.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/hardhat-watcher/-/hardhat-watcher-2.5.0.tgz#3ee76c3cb5b99f2875b78d176207745aa484ed4a" + integrity sha512-Su2qcSMIo2YO2PrmJ0/tdkf+6pSt8zf9+4URR5edMVti6+ShI8T3xhPrwugdyTOFuyj8lKHrcTZNKUFYowYiyA== + dependencies: + chokidar "^3.5.3" + +hardhat@^2.10.2: + version "2.16.0" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.16.0.tgz#c5611d433416b31f6ce92f733b1f1b5236ad6230" + integrity sha512-7VQEJPQRAZdtrYUZaU9GgCpP3MBNy/pTdscARNJQMWKj5C+R7V32G5uIZKIqZ4QiqXa6CBfxxe+G+ahxUbHZHA== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-blockchain" "7.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-evm" "2.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-statemanager" "2.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + "@nomicfoundation/ethereumjs-vm" "7.0.1" + "@nomicfoundation/solidity-analyzer" "^0.1.0" + "@sentry/node" "^5.18.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + abort-controller "^3.0.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + ethereumjs-abi "^0.6.8" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "7.2.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + keccak "^3.0.2" + lodash "^4.17.11" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + solc "0.7.3" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + tsort "0.0.1" + undici "^5.14.0" + uuid "^8.3.2" + ws "^7.4.6" + hardhat@^2.9.6: version "2.12.6" resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.6.tgz#ea3c058bbd81850867389d10f76037cfa52a0019" @@ -4485,6 +7374,13 @@ hardhat@^2.9.6: uuid "^8.3.2" ws "^7.4.6" +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== + dependencies: + ansi-regex "^2.0.0" + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -4507,6 +7403,11 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" @@ -4519,7 +7420,38 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" -has@^1.0.3: +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.3, has@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -4564,6 +7496,11 @@ header-case@^2.0.4: capital-case "^1.0.4" tslib "^2.0.3" +heap@0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" + integrity sha512-MzzWcnfB1e4EG2vHi3dXHoBupmuXNZzx6pY6HldVS55JKKBoq3xOyzfSaZRkJp37HIhEYC78knabHff3zc4dQQ== + hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -4573,6 +7510,19 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + integrity sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -4639,7 +7589,12 @@ husky@^8.0.2: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.2.tgz#5816a60db02650f1f22c8b69b928fd6bcd77a236" integrity sha512-Tkv80jtvbnkK3mYWxPZePGFpQ/tT3HNSs/sasF9P2YfkMezDl3ON37YN6jUUI4eTg5LcyVynlb6r4eyvOmspvg== -iconv-lite@0.4.24: +hyperlinker@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e" + integrity sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ== + +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -4665,6 +7620,11 @@ ieee754@^1.1.13, ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + ignore@^5.1.4: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" @@ -4675,11 +7635,29 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== +immediate@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + +immediate@~3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" + integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== + immutable@^4.0.0-rc.12: version "4.2.2" resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.2.tgz#2da9ff4384a4330c36d4d1bc88e90f9e0b0ccd16" integrity sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og== +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -4696,6 +7674,11 @@ import-local@^3.0.2: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" +imul@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9" + integrity sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA== + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -4714,11 +7697,30 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +inquirer@^6.2.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -4728,6 +7730,27 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" +internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + dependencies: + get-intrinsic "^1.2.0" + has "^1.0.3" + side-channel "^1.0.4" + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ== + io-ts@1.10.4: version "1.10.4" resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" @@ -4740,6 +7763,20 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + is-arguments@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -4748,6 +7785,15 @@ is-arguments@^1.0.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -4775,6 +7821,11 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -4785,6 +7836,20 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.11.0: + version "2.12.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" + integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== + dependencies: + has "^1.0.3" + is-core-module@^2.8.1, is-core-module@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" @@ -4792,6 +7857,20 @@ is-core-module@^2.8.1, is-core-module@^2.9.0: dependencies: has "^1.0.3" +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + is-date-object@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" @@ -4799,11 +7878,73 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-finite@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + +is-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" + integrity sha512-XoFPJQmsAShb3jEQRfzf2rqXavq7fIqF/jOekp308JlThqrODnMpweVSGilKTCXELfLhltGP2AGgbQGVP8F1dg== + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -4850,6 +7991,13 @@ is-number-object@^1.0.4: dependencies: has-tostringtag "^1.0.0" +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== + dependencies: + kind-of "^3.0.2" + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -4865,7 +8013,14 @@ is-plain-obj@^2.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== -is-regex@^1.1.4: +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.0.4, is-regex@^1.1.4, is-regex@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== @@ -4904,6 +8059,17 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" +is-typed-array@^1.1.10: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array@^1.1.3, is-typed-array@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.9.tgz#246d77d2871e7d9f5aeb1d54b9f52c71329ece67" @@ -4925,6 +8091,16 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== + is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -4932,11 +8108,50 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^2.1.1, is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + isomorphic-fetch@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" @@ -4945,6 +8160,11 @@ isomorphic-fetch@2.2.1: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" +isomorphic-ws@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -5399,11 +8619,16 @@ js-sha3@^0.7.0: resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.7.0.tgz#0a5c57b36f79882573b2d84051f8bb85dd1bd63a" integrity sha512-Wpks3yBDm0UcL5qlVhwW9Jr9n9i4FfeWBFOOXP5puDS/SiudJGhw7DPyBqn3487qD4F0lsC0q3zxink37f7zeA== -js-tokens@^4.0.0: +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== + js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -5411,7 +8636,7 @@ js-yaml@4.1.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -js-yaml@^3.13.1: +js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -5419,16 +8644,31 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +jsbi@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-4.3.0.tgz#b54ee074fb6fcbc00619559305c8f7e912b04741" + integrity sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g== + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + integrity sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + json-buffer@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" @@ -5439,16 +8679,50 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" + integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== + dependencies: + async "^2.0.1" + babel-preset-env "^1.7.0" + babelify "^7.3.0" + json-rpc-error "^2.0.0" + promise-to-callback "^1.0.0" + safe-event-emitter "^1.0.1" + +json-rpc-error@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" + integrity sha512-EwUeWP+KgAZ/xqFpaP6YDAXMtCJi+o/QQpCQFIYyxr01AdADi2y413eM8hSqJcoQym9WMePAJWoaODEJufC4Ug== + dependencies: + inherits "^2.0.1" + +json-rpc-random-id@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" + integrity sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-schema@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" @@ -5459,11 +8733,23 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stable-stringify@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" + integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== + dependencies: + jsonify "^0.0.1" + json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw== + json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -5490,6 +8776,25 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" + integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== + jsprim@^1.2.2: version "1.4.2" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" @@ -5500,6 +8805,14 @@ jsprim@^1.2.2: json-schema "0.4.0" verror "1.10.0" +keccak@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff" + integrity sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + keccak@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" @@ -5532,6 +8845,37 @@ keyv@^3.0.0: dependencies: json-buffer "3.0.0" +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" @@ -5544,11 +8888,118 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw== + dependencies: + invert-kv "^1.0.0" + lens.ts@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/lens.ts/-/lens.ts-0.5.1.tgz#957cd81838ea7359b0c280f24f9478bc6e92bafc" integrity sha512-cxzQxbitr78SnkulxKsdPC6v/+1CHmB4j2sMt2KXcbiCXLHphYZtOWYNIB1PumO5hCHescODqwhURB/OH/j5VA== +level-codec@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" + integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== + dependencies: + buffer "^5.6.0" + +level-codec@~7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" + integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== + +level-errors@^1.0.3: + version "1.1.2" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" + integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== + dependencies: + errno "~0.1.1" + +level-errors@^2.0.0, level-errors@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" + integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== + dependencies: + errno "~0.1.1" + +level-errors@~1.0.3: + version "1.0.5" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" + integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== + dependencies: + errno "~0.1.1" + +level-iterator-stream@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz#ccfff7c046dcf47955ae9a86f46dfa06a31688b4" + integrity sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.5" + xtend "^4.0.0" + +level-iterator-stream@~1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" + integrity sha512-1qua0RHNtr4nrZBgYlpV0qHHeHpcRRWTxEZJ8xsemoHAXNL5tbooh4tPEEqIqsbWCAJBmUmkwYK/sW5OrFjWWw== + dependencies: + inherits "^2.0.1" + level-errors "^1.0.3" + readable-stream "^1.0.33" + xtend "^4.0.0" + +level-iterator-stream@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz#2c98a4f8820d87cdacab3132506815419077c730" + integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== + dependencies: + inherits "^2.0.1" + readable-stream "^2.3.6" + xtend "^4.0.0" + +level-mem@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-3.0.1.tgz#7ce8cf256eac40f716eb6489654726247f5a89e5" + integrity sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg== + dependencies: + level-packager "~4.0.0" + memdown "~3.0.0" + +level-packager@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-4.0.1.tgz#7e7d3016af005be0869bc5fa8de93d2a7f56ffe6" + integrity sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q== + dependencies: + encoding-down "~5.0.0" + levelup "^3.0.0" + +level-post@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/level-post/-/level-post-1.0.7.tgz#19ccca9441a7cc527879a0635000f06d5e8f27d0" + integrity sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew== + dependencies: + ltgt "^2.1.2" + +level-sublevel@6.6.4: + version "6.6.4" + resolved "https://registry.yarnpkg.com/level-sublevel/-/level-sublevel-6.6.4.tgz#f7844ae893919cd9d69ae19d7159499afd5352ba" + integrity sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA== + dependencies: + bytewise "~1.1.0" + level-codec "^9.0.0" + level-errors "^2.0.0" + level-iterator-stream "^2.0.3" + ltgt "~2.1.1" + pull-defer "^0.2.2" + pull-level "^2.0.3" + pull-stream "^3.6.8" + typewiselite "~1.0.0" + xtend "~4.0.0" + level-supports@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" @@ -5562,6 +9013,23 @@ level-transcoder@^1.0.1: buffer "^6.0.3" module-error "^1.0.1" +level-ws@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" + integrity sha512-XUTaO/+Db51Uiyp/t7fCMGVFOTdtLS/NIACxE/GHsij15mKzxksZifKVjlXDF41JMUP/oM1Oc4YNGdKnc3dVLw== + dependencies: + readable-stream "~1.0.15" + xtend "~2.1.1" + +level-ws@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-1.0.0.tgz#19a22d2d4ac57b18cc7c6ecc4bd23d899d8f603b" + integrity sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q== + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.8" + xtend "^4.0.1" + level@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/level/-/level-8.0.0.tgz#41b4c515dabe28212a3e881b61c161ffead14394" @@ -5570,11 +9038,42 @@ level@^8.0.0: browser-level "^1.0.1" classic-level "^1.2.0" +levelup@3.1.1, levelup@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" + integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== + dependencies: + deferred-leveldown "~4.0.0" + level-errors "~2.0.0" + level-iterator-stream "~3.0.0" + xtend "~4.0.0" + +levelup@^1.2.1: + version "1.3.9" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" + integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== + dependencies: + deferred-leveldown "~1.2.1" + level-codec "~7.0.0" + level-errors "~1.0.3" + level-iterator-stream "~1.3.0" + prr "~1.0.1" + semver "~5.4.1" + xtend "~4.0.0" + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -5588,6 +9087,17 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A== + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -5610,6 +9120,21 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.assign@^4.0.3, lodash.assign@^4.0.6: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + integrity sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw== + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.flatmap@4.5.0, lodash.flatmap@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e" + integrity sha512-/OcpcAGWlrZyoHGeHh3cAoa6nGdX6QYtmzNP84Jqol6UEQQ2gIaU3H+0eICcjcKGl0/XF8LWOujNn9lffsnaOg== + lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -5620,7 +9145,17 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.21: +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash@4.17.20: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5644,6 +9179,23 @@ log4js@6.6.1: rfdc "^1.3.0" streamroller "^3.1.2" +looper@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" + integrity sha512-6DzMHJcjbQX/UPHc1rRCBfKlLwDkvuGZ715cIR36wSdYqWXFT35uLXq5P/2orl3tz+t+VOVPxw4yPinQlUDGDQ== + +looper@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" + integrity sha512-LJ9wplN/uSn72oJRsXTx+snxPet5c8XiZmOKCm906NVYu+ag6SB6vUcnJcWxgnl2NfbIyeobAn7Bwv6xRj2XJg== + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + loupe@^2.3.1: version "2.3.6" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" @@ -5668,13 +9220,20 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== -lru-cache@^5.1.1: +lru-cache@5.1.1, lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" +lru-cache@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" + integrity sha512-91gyOKTc2k66UG6kHiH4h3S2eltcPwE1STVfMYC/NG+nZwf8IIuiamfmpGZjpbbxzSyEJaLC0tNSmhjlQUTJow== + dependencies: + pseudomap "^1.0.1" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -5687,6 +9246,16 @@ lru_map@^0.3.3: resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== +ltgt@^2.1.2, ltgt@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" + integrity sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA== + +ltgt@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" + integrity sha512-5VjHC5GsENtIi5rbJd+feEpDKhfr7j0odoUR2Uh978g+2p93nd5o34cTjQWohXsPsCZeqoDnIqEf88mPCe0Pfw== + make-dir@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -5706,6 +9275,23 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== + dependencies: + object-visit "^1.0.0" + +match-all@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" + integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== + mcl-wasm@^0.7.1: version "0.7.9" resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" @@ -5725,6 +9311,30 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== +memdown@^1.0.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" + integrity sha512-iVrGHZB8i4OQfM155xx8akvG9FIj+ht14DX5CQkCTG4EHzZ3d3sgckIf/Lm9ivZalEsFuEVnWv2B2WZvbrro2w== + dependencies: + abstract-leveldown "~2.7.1" + functional-red-black-tree "^1.0.1" + immediate "^3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + +memdown@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-3.0.0.tgz#93aca055d743b20efc37492e9e399784f2958309" + integrity sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA== + dependencies: + abstract-leveldown "~5.0.0" + functional-red-black-tree "~1.0.1" + immediate "~3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + memory-level@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" @@ -5754,6 +9364,33 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +merkle-patricia-tree@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz#448d85415565df72febc33ca362b8b614f5a58f8" + integrity sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ== + dependencies: + async "^2.6.1" + ethereumjs-util "^5.2.0" + level-mem "^3.0.1" + level-ws "^1.0.0" + readable-stream "^3.0.6" + rlp "^2.0.0" + semaphore ">=1.0.1" + +merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" + integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== + dependencies: + async "^1.4.2" + ethereumjs-util "^5.0.0" + level-ws "0.0.0" + levelup "^1.2.1" + memdown "^1.0.0" + readable-stream "^2.0.0" + rlp "^2.0.0" + semaphore ">=1.0.1" + merkletreejs@^0.2.27: version "0.2.32" resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.2.32.tgz#cf1c0760e2904e4a1cc269108d6009459fd06223" @@ -5770,7 +9407,26 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== -micromatch@^4.0.4: +micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.2, micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -5803,6 +9459,11 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -5854,6 +9515,11 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== +minimist@~1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" @@ -5869,6 +9535,19 @@ minizlib@^1.3.3: dependencies: minipass "^2.9.0" +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" @@ -5876,12 +9555,12 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*: +mkdirp@*, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@^0.5.5: +mkdirp@^0.5.1, mkdirp@^0.5.5: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -6003,6 +9682,25 @@ multimatch@^4.0.0: arrify "^2.0.1" minimatch "^3.0.4" +murmur-128@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d" + integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg== + dependencies: + encode-utf8 "^1.0.2" + fmix "^0.1.0" + imul "^1.0.0" + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== + +nan@^2.17.0: + version "2.17.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" + integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== + nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" @@ -6013,6 +9711,23 @@ nanoid@3.3.3: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + napi-macros@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" @@ -6038,6 +9753,11 @@ next-tick@^1.1.0: resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -6058,6 +9778,13 @@ node-cache@^5.1.2: dependencies: clone "2.x" +node-fetch@2.6.6: + version "2.6.6" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89" + integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA== + dependencies: + whatwg-url "^5.0.0" + node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -6065,7 +9792,7 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@^1.0.1: +node-fetch@^1.0.1, node-fetch@~1.7.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== @@ -6073,6 +9800,13 @@ node-fetch@^1.0.1: encoding "^0.1.11" is-stream "^1.0.1" +node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: + version "2.6.11" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25" + integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w== + dependencies: + whatwg-url "^5.0.0" + node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40" @@ -6088,6 +9822,21 @@ node-releases@^2.0.6: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== +nofilter@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" + integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== + +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -6110,6 +9859,11 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== + number-to-bn@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" @@ -6123,21 +9877,55 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4, object-assign@^4.0.0, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + object-inspect@^1.12.2, object-inspect@^1.9.0: version "1.12.2" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== +object-inspect@^1.12.3, object-inspect@~1.12.3: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + integrity sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== + dependencies: + isobject "^3.0.0" + object.assign@^4.1.2, object.assign@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" @@ -6157,6 +9945,24 @@ object.entries@^1.1.5: define-properties "^1.1.4" es-abstract "^1.20.4" +object.getownpropertydescriptors@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz#5e5c384dd209fa4efffead39e3a0512770ccc312" + integrity sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ== + dependencies: + array.prototype.reduce "^1.0.5" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.21.2" + safe-array-concat "^1.0.0" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== + dependencies: + isobject "^3.0.1" + object.values@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" @@ -6171,6 +9977,13 @@ obliterator@^2.0.0: resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== +oboe@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" + integrity sha512-ymBJ4xSC6GBXLT9Y7lirj+xbqBLa+jADGJldGEYG7u8sZbS9GyG+u1Xk9c5cbriKwSpCg41qUhPjvU5xOpvIyQ== + dependencies: + http-https "^1.0.0" + oboe@2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" @@ -6192,6 +10005,13 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== + dependencies: + mimic-fn "^1.0.0" + onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -6199,6 +10019,35 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +open@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +open@^8.4.0: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +optionator@^0.8.2: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -6211,7 +10060,19 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -os-tmpdir@~1.0.2: +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g== + dependencies: + lcid "^1.0.0" + +os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== @@ -6316,6 +10177,21 @@ parse-headers@^2.0.0: resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9" integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA== +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -6339,6 +10215,54 @@ pascal-case@^3.1.2: no-case "^3.0.4" tslib "^2.0.3" +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== + +patch-package@6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.2.tgz#71d170d650c65c26556f0d0fbbb48d92b6cc5f39" + integrity sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^2.4.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^1.2.1" + fs-extra "^7.0.1" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.0" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + +patch-package@^6.2.2: + version "6.5.1" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" + integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^4.1.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^2.0.0" + fs-extra "^9.0.0" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.6" + open "^7.4.2" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + yaml "^1.10.2" + +path-browserify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + path-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/path-case/-/path-case-3.0.4.tgz#9168645334eb942658375c56f80b4c0cb5f82c6f" @@ -6347,6 +10271,13 @@ path-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ== + dependencies: + pinkie-promise "^2.0.0" + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -6357,11 +10288,21 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-is-absolute@^1.0.0: +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== +path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== + +path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -6377,6 +10318,15 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg== + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -6387,7 +10337,7 @@ pathval@^1.1.1: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -pbkdf2@^3.0.17, pbkdf2@^3.0.3: +pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -6413,6 +10363,23 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pify@^2.0.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== + pirates@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" @@ -6430,16 +10397,46 @@ popper.js@1.14.3: resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" integrity sha512-3lmujhsHXzb83+sI0PzfrE3O1XHZG8m8MXNMTupvA6LrM1/nnsiqYaacYc/RIente9VqnTDPztGEM8uvPAMGyg== +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== + +postinstall-postinstall@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" + integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== + +precond@0.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" + integrity sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + prepend-http@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== +prettier@^1.14.3: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== + +prettier@^2.1.2, prettier@^2.3.1: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + prettier@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc" @@ -6476,12 +10473,35 @@ pretty-quick@^3.1.3: mri "^1.1.5" multimatch "^4.0.0" +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -prompts@^2.0.1: +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +promise-to-callback@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" + integrity sha512-uhMIZmKM5ZteDMfLgJnoSq9GCwsNKrYau73Awf1jIy6/eUcuuZ3P+CD9zUv0kJsIUbU+x6uLNIhXhLHDs1pNPA== + dependencies: + is-fn "^1.0.0" + set-immediate-shim "^1.0.1" + +prompts@^2.0.1, prompts@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -6502,6 +10522,16 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== + +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== + psl@^1.1.28: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -6519,6 +10549,62 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" +pull-cat@^1.1.9: + version "1.1.11" + resolved "https://registry.yarnpkg.com/pull-cat/-/pull-cat-1.1.11.tgz#b642dd1255da376a706b6db4fa962f5fdb74c31b" + integrity sha512-i3w+xZ3DCtTVz8S62hBOuNLRHqVDsHMNZmgrZsjPnsxXUgbWtXEee84lo1XswE7W2a3WHyqsNuDJTjVLAQR8xg== + +pull-defer@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/pull-defer/-/pull-defer-0.2.3.tgz#4ee09c6d9e227bede9938db80391c3dac489d113" + integrity sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA== + +pull-level@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pull-level/-/pull-level-2.0.4.tgz#4822e61757c10bdcc7cf4a03af04c92734c9afac" + integrity sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg== + dependencies: + level-post "^1.0.7" + pull-cat "^1.1.9" + pull-live "^1.0.1" + pull-pushable "^2.0.0" + pull-stream "^3.4.0" + pull-window "^2.1.4" + stream-to-pull-stream "^1.7.1" + +pull-live@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pull-live/-/pull-live-1.0.1.tgz#a4ecee01e330155e9124bbbcf4761f21b38f51f5" + integrity sha512-tkNz1QT5gId8aPhV5+dmwoIiA1nmfDOzJDlOOUpU5DNusj6neNd3EePybJ5+sITr2FwyCs/FVpx74YMCfc8YeA== + dependencies: + pull-cat "^1.1.9" + pull-stream "^3.4.0" + +pull-pushable@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.2.0.tgz#5f2f3aed47ad86919f01b12a2e99d6f1bd776581" + integrity sha512-M7dp95enQ2kaHvfCt2+DJfyzgCSpWVR2h2kWYnVsW6ZpxQBx5wOu0QWOvQPVoPnBLUZYitYP2y7HyHkLQNeGXg== + +pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: + version "3.7.0" + resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.7.0.tgz#85de0e44ff38a4d2ad08cc43fc458e1922f9bf0b" + integrity sha512-Eco+/R004UaCK2qEDE8vGklcTG2OeZSVm1kTUQNrykEjDwcFXDZhygFDsW49DbXyJMEhHeRL3z5cRVqPAhXlIw== + +pull-window@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/pull-window/-/pull-window-2.1.4.tgz#fc3b86feebd1920c7ae297691e23f705f88552f0" + integrity sha512-cbDzN76BMlcGG46OImrgpkMf/VkCnupj8JhsrpBw3aWBM9ye345aYnqitmZCgauBkc0HbbRRn9hCnsa3k2FNUg== + dependencies: + looper "^2.0.0" + +pump@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" + integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -6532,6 +10618,11 @@ punycode@2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" integrity sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA== +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -6544,6 +10635,13 @@ qs@6.11.0, qs@^6.7.0: dependencies: side-channel "^1.0.4" +qs@^6.11.0, qs@^6.9.4: + version "6.11.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" + integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== + dependencies: + side-channel "^1.0.4" + qs@~6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" @@ -6568,7 +10666,7 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== @@ -6608,6 +10706,55 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A== + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ== + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +readable-stream@^1.0.33: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -6617,6 +10764,16 @@ readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@~1.0.15, readable-stream@~1.0.26-4: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -6624,6 +10781,47 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +reduce-flatten@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== + +regenerate@^1.2.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.2.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" + integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + functions-have-names "^1.2.3" + regexp.prototype.flags@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" @@ -6633,12 +10831,55 @@ regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== -request@^2.79.0: +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + integrity sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ== + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + integrity sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g== + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + integrity sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw== + dependencies: + jsesc "~0.5.0" + +repeat-element@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A== + dependencies: + is-finite "^1.0.0" + +request@^2.79.0, request@^2.85.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -6669,11 +10910,21 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -require-from-string@^2.0.0: +require-from-string@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + integrity sha512-H7AkJWMobeskkttHyhTVtS0fxpFLjxhbfMa6Bk3wimP7sdPRGL3EyCg3sAQenFfAe+xQ+oAc85Nmtvq0ROM83Q== + +require-from-string@^2.0.0, require-from-string@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== + resolve-alpn@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" @@ -6686,6 +10937,11 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -6696,6 +10952,11 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== + resolve.exports@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" @@ -6708,6 +10969,15 @@ resolve@1.17.0: dependencies: path-parse "^1.0.6" +resolve@^1.10.0, resolve@^1.8.1, resolve@~1.22.1: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^1.20.0, resolve@^1.22.0: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" @@ -6731,6 +11001,26 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +resumer@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" + integrity sha512-Fn9X8rX8yYF4m81rZCK/5VmrmsSbqS/i3rDLl6ZZHAXgC2nTAx3dhwG8q8odP/RmdLa2YrybDJaAMg+X1ajY3w== + dependencies: + through "~2.3.4" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -6741,7 +11031,14 @@ rfdc@^1.3.0: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== -rimraf@^2.2.8: +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +rimraf@^2.2.8, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -6763,13 +11060,18 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rlp@^2.0.0, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.7: +rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.7: version "2.2.7" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== dependencies: bn.js "^5.2.0" +run-async@^2.2.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-parallel-limit@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" @@ -6789,16 +11091,40 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== +rxjs@^6.4.0: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + +safe-array-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" + integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + has-symbols "^1.0.3" + isarray "^2.0.5" + safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0: +safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-event-emitter@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" + integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== + dependencies: + events "^3.0.0" + safe-regex-test@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" @@ -6808,6 +11134,13 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== + dependencies: + ret "~0.1.10" + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -6823,6 +11156,13 @@ scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== +scryptsy@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" + integrity sha512-aldIRgMozSJ/Gl6K6qmJZysRP82lz83Wb42vl4PWN8SaLFHIaOzLPc9nUUW2jQN88CuGm5q5HefJ9jZ3nWSmTw== + dependencies: + pbkdf2 "^3.0.3" + secp256k1@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" @@ -6832,6 +11172,21 @@ secp256k1@^4.0.1: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" +seedrandom@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.1.tgz#eb3dde015bcf55df05a233514e5df44ef9dce083" + integrity sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg== + +semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" + integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + semver@7.x, semver@^7.3.5, semver@^7.3.7: version "7.3.8" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" @@ -6839,16 +11194,16 @@ semver@7.x, semver@^7.3.5, semver@^7.3.7: dependencies: lru-cache "^6.0.0" -semver@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@~5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== + send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -6905,6 +11260,26 @@ servify@^0.1.12: request "^2.79.0" xhr "^2.3.3" +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + integrity sha512-Li5AOqrZWCVA2n5kryzEmqai6bKSIvpz5oUJHPVj6+dsbD3X1ixtsY5tEnsaNpH3pFAHmG8eIHUrtEtohrg+UQ== + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + setimmediate@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" @@ -6928,6 +11303,13 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -6935,6 +11317,11 @@ shebang-command@^2.0.0: dependencies: shebang-regex "^3.0.0" +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + shebang-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" @@ -6973,11 +11360,39 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg== + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + snake-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" @@ -6986,6 +11401,36 @@ snake-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + solc@0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" @@ -7001,6 +11446,70 @@ solc@0.7.3: semver "^5.5.0" tmp "0.0.33" +solc@^0.4.20: + version "0.4.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.26.tgz#5390a62a99f40806b86258c737c1cf653cc35cb5" + integrity sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA== + dependencies: + fs-extra "^0.30.0" + memorystream "^0.3.1" + require-from-string "^1.1.0" + semver "^5.3.0" + yargs "^4.7.1" + +solc@^0.6.3: + version "0.6.12" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.6.12.tgz#48ac854e0c729361b22a7483645077f58cba080e" + integrity sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +solhint@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-2.3.1.tgz#6fee8fc2635112bf5812f7cba8359c14e9d9a491" + integrity sha512-wP/G+Dqj8LNWlCI9Mt6XiQRWQfZwv1rkZe/V+HKtip5SAZJVvp144PdH28KE45ZvR99Hhrp/Mujt74fSmXsFiw== + dependencies: + ajv "^6.6.1" + antlr4 "4.7.1" + chalk "^2.4.2" + commander "2.18.0" + cosmiconfig "^5.0.7" + eslint "^5.6.0" + fast-diff "^1.1.2" + glob "^7.1.3" + ignore "^4.0.6" + js-yaml "^3.12.0" + lodash "^4.17.11" + semver "^6.3.0" + optionalDependencies: + prettier "^1.14.3" + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@0.5.12: + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -7009,6 +11518,13 @@ source-map-support@0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + source-map-support@^0.5.13: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -7017,16 +11533,75 @@ source-map-support@^0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + +source-map@^0.5.6, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +spdx-correct@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.13" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz#7189a474c46f8d47c7b0da4b987bb45e908bd2d5" + integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w== + +split-ca@^1.0.0, split-ca@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" + integrity sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +ssh2@^1.11.0: + version "1.14.0" + resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-1.14.0.tgz#8f68440e1b768b66942c9e4e4620b2725b3555bb" + integrity sha512-AqzD1UCqit8tbOKoj6ztDDi1ffJZ2rV2SwlgrVVrHPkV5vWqGJOVp5pmtj18PunkPJAuKQsnInyKV+/Nb2bUnA== + dependencies: + asn1 "^0.2.6" + bcrypt-pbkdf "^1.0.2" + optionalDependencies: + cpu-features "~0.0.8" + nan "^2.17.0" + sshpk@^1.7.0: version "1.17.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" @@ -7056,11 +11631,27 @@ stacktrace-parser@^0.1.10: dependencies: type-fest "^0.7.1" +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +stream-to-pull-stream@^1.7.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz#4161aa2d2eb9964de60bfa1af7feaf917e874ece" + integrity sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg== + dependencies: + looper "^3.0.0" + pull-stream "^3.2.3" + streamroller@^3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.1.3.tgz#d95689a8c29b30d093525d0baffe6616fd62ca7e" @@ -7080,6 +11671,11 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== +string-format@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" + integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -7088,6 +11684,32 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -7097,6 +11719,15 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string.prototype.trim@^1.2.7, string.prototype.trim@~1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string.prototype.trimend@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" @@ -7140,6 +11771,39 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -7147,6 +11811,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== + dependencies: + is-utf8 "^0.2.0" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -7174,6 +11845,11 @@ strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1. resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + supports-color@8.1.1, supports-color@^8.0.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -7181,6 +11857,11 @@ supports-color@8.1.1, supports-color@^8.0.0: dependencies: has-flag "^4.0.0" +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -7205,17 +11886,113 @@ swarm-js@^0.1.40: resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.42.tgz#497995c62df6696f6e22372f457120e43e727979" integrity sha512-BV7c/dVlA3R6ya1lMlSSNPLYrntt0LUq4YMgy3iwpCIc6rZnS5W2wUoctarZ5pXlpKtxDDf9hNziEkcfrxdhqQ== dependencies: - bluebird "^3.5.0" - buffer "^5.0.5" - eth-lib "^0.1.26" - fs-extra "^4.0.2" - got "^11.8.5" - mime-types "^2.1.16" - mkdirp-promise "^5.0.1" - mock-fs "^4.1.0" - setimmediate "^1.0.5" - tar "^4.0.2" - xhr-request "^1.0.1" + bluebird "^3.5.0" + buffer "^5.0.5" + eth-lib "^0.1.26" + fs-extra "^4.0.2" + got "^11.8.5" + mime-types "^2.1.16" + mkdirp-promise "^5.0.1" + mock-fs "^4.1.0" + setimmediate "^1.0.5" + tar "^4.0.2" + xhr-request "^1.0.1" + +table-layout@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + +table@^6.8.0: + version "6.8.1" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" + integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +tape@^4.6.3: + version "4.16.2" + resolved "https://registry.yarnpkg.com/tape/-/tape-4.16.2.tgz#7565e6af20426565557266e9dda7215869b297b6" + integrity sha512-TUChV+q0GxBBCEbfCYkGLkv8hDJYjMdSWdE0/Lr331sB389dsvFUHNV9ph5iQqKzt8Ss9drzcda/YeexclBFqg== + dependencies: + call-bind "~1.0.2" + deep-equal "~1.1.1" + defined "~1.0.1" + dotignore "~0.1.2" + for-each "~0.3.3" + glob "~7.2.3" + has "~1.0.3" + inherits "~2.0.4" + is-regex "~1.1.4" + minimist "~1.2.7" + object-inspect "~1.12.3" + resolve "~1.22.1" + resumer "~0.0.0" + string.prototype.trim "~1.2.7" + through "~2.3.8" + +tar-fs@~1.16.3: + version "1.16.3" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" + integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw== + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + +tar-fs@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" + integrity sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.0.0" + +tar-stream@^1.1.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + +tar-stream@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" tar@^4.0.2: version "4.4.19" @@ -7230,6 +12007,20 @@ tar@^4.0.2: safe-buffer "^5.2.1" yallist "^3.1.1" +tenderly@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tenderly/-/tenderly-0.0.3.tgz#8c85e287e080073502420d5c6f13f4762d0f59cd" + integrity sha512-dVf2uxrIOeLDRNDEXcQlV2xJt50TIx8zGQKlNj1deYTV3FYu2L0zheHBHaDU12GqAff2iiGYk+fKqFkK0bB0+w== + dependencies: + axios "^0.27.2" + cli-table3 "^0.6.2" + commander "^9.4.0" + express "^4.18.1" + hyperlinker "^1.0.0" + js-yaml "^4.1.0" + open "^8.4.0" + prompts "^2.4.2" + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -7239,38 +12030,106 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +test-value@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" + integrity sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w== + dependencies: + array-back "^1.0.3" + typical "^2.6.0" + +testrpc@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/testrpc/-/testrpc-0.0.1.tgz#83e2195b1f5873aec7be1af8cbe6dcf39edb7aed" + integrity sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA== + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +through2@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +"through@>=2.2.7 <3", through@^2.3.6, through@~2.3.4, through@~2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== -tmp@0.0.33: +tiny-invariant@1.3.1, tiny-invariant@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" + integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== + +tiny-warning@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + +tmp@0.0.33, tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" +tmp@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" + integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== + dependencies: + rimraf "^2.6.3" + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== + dependencies: + kind-of "^3.0.2" + to-readable-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -7278,6 +12137,21 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toformat@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/toformat/-/toformat-2.0.0.tgz#7a043fd2dfbe9021a4e36e508835ba32056739d8" + integrity sha512-03SWBVop6nU8bpyZCx7SodpYznbZF5R4ljwNLBcTQzKOD9xuihRo/psX58llS1BMFhhAI08H3luot5GoXJz2pQ== + toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -7301,16 +12175,61 @@ treeify@^1.1.0: resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== + +ts-command-line-args@^2.2.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz#e64456b580d1d4f6d948824c274cf6fa5f45f7f0" + integrity sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw== + dependencies: + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.0" + string-format "^2.0.0" + ts-essentials@9.1.2: version "9.1.2" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-9.1.2.tgz#46db6944b73b4cd603f3d959ef1123c16ba56f59" integrity sha512-EaSmXsAhEiirrTY1Oaa7TSpei9dzuCuFPmjKRJRPamERYtfaGS8/KpOSbjergLz/Y76/aZlV9i/krgzsuWEBbg== +ts-essentials@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" + integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== + +ts-essentials@^6.0.3: + version "6.0.7" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.7.tgz#5f4880911b7581a873783740ce8b94da163d18a6" + integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== + +ts-essentials@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== + ts-essentials@^9.1.2: version "9.3.0" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-9.3.0.tgz#7e639c1a76b1805c3c60d6e1b5178da2e70aea02" integrity sha512-XeiCboEyBG8UqXZtXl59bWEi4ZgOqRsogFDI6WDGIF1LmzbYiAkIwjkXN6zZWWl4re/lsOqMlYfe8KA0XiiEPw== +ts-generator@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" + integrity sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ== + dependencies: + "@types/mkdirp" "^0.5.2" + "@types/prettier" "^2.1.1" + "@types/resolve" "^0.0.8" + chalk "^2.4.1" + glob "^7.1.2" + mkdirp "^0.5.1" + prettier "^2.1.2" + resolve "^1.8.1" + ts-essentials "^1.0.0" + ts-jest@^29.0.3: version "29.0.3" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.0.3.tgz#63ea93c5401ab73595440733cefdba31fcf9cb77" @@ -7354,7 +12273,7 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1, tslib@^1.9.3: +tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -7383,7 +12302,7 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -tweetnacl-util@^0.15.1: +tweetnacl-util@^0.15.0, tweetnacl-util@^0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== @@ -7393,7 +12312,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== -tweetnacl@^1.0.3: +tweetnacl@^1.0.0, tweetnacl@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== @@ -7405,6 +12324,13 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== + dependencies: + prelude-ls "~1.1.2" + type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -7443,6 +12369,44 @@ type@^2.7.2: resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== +typechain@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.1.1.tgz#9c2e8012c2c4c586536fc18402dcd7034c4ff0bd" + integrity sha512-uF/sUvnXTOVF2FHKhQYnxHk4su4JjZR8vr4mA2mBaRwHTbwh0jIlqARz9XJr1tA0l7afJGvEa1dTSi4zt039LQ== + dependencies: + "@types/prettier" "^2.1.1" + debug "^4.3.1" + fs-extra "^7.0.0" + glob "7.1.7" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.3.1" + ts-command-line-args "^2.2.0" + ts-essentials "^7.0.1" + +typechain@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-3.0.0.tgz#d5a47700831f238e43f7429b987b4bb54849b92e" + integrity sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg== + dependencies: + command-line-args "^4.0.7" + debug "^4.1.1" + fs-extra "^7.0.0" + js-sha3 "^0.8.0" + lodash "^4.17.15" + ts-essentials "^6.0.3" + ts-generator "^0.1.1" + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -7450,11 +12414,48 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + typescript@4.6.4: version "4.6.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg== +typewise-core@^1.2, typewise-core@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" + integrity sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg== + +typewise@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" + integrity sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ== + dependencies: + typewise-core "^1.2.0" + +typewiselite@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typewiselite/-/typewiselite-1.0.0.tgz#c8882fa1bb1092c06005a97f34ef5c8508e3664e" + integrity sha512-J9alhjVHupW3Wfz6qFRGgQw0N3gr8hOkw6zm7FZ6UR1Cse/oD9/JVok7DNE9TT9IbciDHX2Ex9+ksE6cRmtymw== + +typical@^2.6.0, typical@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" + integrity sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg== + +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + +typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== + ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" @@ -7475,6 +12476,11 @@ underscore@1.12.1: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== +underscore@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== + undici@^5.14.0: version "5.16.0" resolved "https://registry.yarnpkg.com/undici/-/undici-5.16.0.tgz#6b64f9b890de85489ac6332bd45ca67e4f7d9943" @@ -7482,16 +12488,51 @@ undici@^5.14.0: dependencies: busboy "^1.6.0" +undici@^5.4.0: + version "5.22.1" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.22.1.tgz#877d512effef2ac8be65e695f3586922e1a57d7b" + integrity sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw== + dependencies: + busboy "^1.6.0" + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unorm@^1.3.3: + version "1.6.0" + resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" + integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + update-browserslist-db@^1.0.9: version "1.0.10" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" @@ -7521,6 +12562,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== + url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -7533,6 +12579,19 @@ url-set-query@^1.0.0: resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" integrity sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg== +url@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.1.tgz#26f90f615427eca1b9f4d6a28288c147e2302a32" + integrity sha512-rWS3H04/+mzzJkv0eZ7vEDGiQbgquI1fGfOad6zKvgYQi1SzMmhl7c/DdRGxhaWrVH6z0qWITo8rpnxK/RfEhA== + dependencies: + punycode "^1.4.1" + qs "^6.11.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + utf-8-validate@^5.0.2: version "5.0.10" resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" @@ -7540,16 +12599,29 @@ utf-8-validate@^5.0.2: dependencies: node-gyp-build "^4.3.0" -utf8@3.0.0: +utf8@3.0.0, utf8@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== -util-deprecate@^1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +util.promisify@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.2.tgz#02b3dbadbb80071eee4c43aed58747afdfc516db" + integrity sha512-PBdZ03m1kBnQ5cjjO0ZvJMJS+QsbyIcFwi4hY4U76OQsCO9JrOYjbCFgIF76ccFg9xnJo7ZHPkqyj1GqmdS7MA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + for-each "^0.3.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + object.getownpropertydescriptors "^2.1.6" + safe-array-concat "^1.0.0" + util@^0.12.0: version "0.12.5" resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" @@ -7605,6 +12677,14 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + varint@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" @@ -7624,6 +12704,21 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +viem@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/viem/-/viem-1.0.2.tgz#0798c80598daddc05b7132b642ae2f60811c4fbe" + integrity sha512-3Bn+CuInU8zsdKqqzFDWL018x4B9HDjPIISztReGcBjikY+04tP7CrQQCf1lbinK3wWrEoFU9VDiptCciNjUQA== + dependencies: + "@adraffy/ens-normalize" "1.9.0" + "@noble/curves" "1.0.0" + "@noble/hashes" "1.3.0" + "@scure/bip32" "1.3.0" + "@scure/bip39" "1.2.0" + "@wagmi/chains" "1.1.0" + abitype "0.8.7" + isomorphic-ws "5.0.0" + ws "8.12.0" + walker@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -7631,6 +12726,16 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" +web3-bzz@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" + integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== + dependencies: + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + underscore "1.9.1" + web3-bzz@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.6.0.tgz#584b51339f21eedff159abc9239b4b7ef6ded840" @@ -7640,6 +12745,15 @@ web3-bzz@1.6.0: got "9.6.0" swarm-js "^0.1.40" +web3-core-helpers@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" + integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== + dependencies: + underscore "1.9.1" + web3-eth-iban "1.2.11" + web3-utils "1.2.11" + web3-core-helpers@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.6.0.tgz#77e161b6ba930a4008a0df804ab379e0aa7e1e7f" @@ -7648,6 +12762,18 @@ web3-core-helpers@1.6.0: web3-eth-iban "1.6.0" web3-utils "1.6.0" +web3-core-method@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" + integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== + dependencies: + "@ethersproject/transactions" "^5.0.0-beta.135" + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-utils "1.2.11" + web3-core-method@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.6.0.tgz#ebe4ea51f5a4fa809bb68185576186359d3982e9" @@ -7660,6 +12786,13 @@ web3-core-method@1.6.0: web3-core-subscriptions "1.6.0" web3-utils "1.6.0" +web3-core-promievent@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" + integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== + dependencies: + eventemitter3 "4.0.4" + web3-core-promievent@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.6.0.tgz#8b6053ae83cb47164540167fc361469fc604d2dd" @@ -7667,6 +12800,17 @@ web3-core-promievent@1.6.0: dependencies: eventemitter3 "4.0.4" +web3-core-requestmanager@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" + integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== + dependencies: + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-providers-http "1.2.11" + web3-providers-ipc "1.2.11" + web3-providers-ws "1.2.11" + web3-core-requestmanager@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.6.0.tgz#8ef3a3b89cd08983bd94574f9c5893f70a8a6aea" @@ -7678,6 +12822,15 @@ web3-core-requestmanager@1.6.0: web3-providers-ipc "1.6.0" web3-providers-ws "1.6.0" +web3-core-subscriptions@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" + integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-core-subscriptions@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.6.0.tgz#8c23b15b434a7c9f937652ecca45d7108e2c54df" @@ -7686,6 +12839,19 @@ web3-core-subscriptions@1.6.0: eventemitter3 "4.0.4" web3-core-helpers "1.6.0" +web3-core@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" + integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== + dependencies: + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-requestmanager "1.2.11" + web3-utils "1.2.11" + web3-core@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.6.0.tgz#144eb00f651c9812faf7176abd7ee99d5f45e212" @@ -7699,6 +12865,15 @@ web3-core@1.6.0: web3-core-requestmanager "1.6.0" web3-utils "1.6.0" +web3-eth-abi@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" + integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== + dependencies: + "@ethersproject/abi" "5.0.0-beta.153" + underscore "1.9.1" + web3-utils "1.2.11" + web3-eth-abi@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.4.0.tgz#83f9f0ce48fd6d6b233a30a33bd674b3518e472b" @@ -7716,6 +12891,23 @@ web3-eth-abi@1.6.0: "@ethersproject/abi" "5.0.7" web3-utils "1.6.0" +web3-eth-accounts@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" + integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== + dependencies: + crypto-browserify "3.12.0" + eth-lib "0.2.8" + ethereumjs-common "^1.3.2" + ethereumjs-tx "^2.1.1" + scrypt-js "^3.0.1" + underscore "1.9.1" + uuid "3.3.2" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + web3-eth-accounts@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.6.0.tgz#530927f4c5b78df93b3ea1203abbb467de29cd04" @@ -7733,6 +12925,21 @@ web3-eth-accounts@1.6.0: web3-core-method "1.6.0" web3-utils "1.6.0" +web3-eth-contract@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" + integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== + dependencies: + "@types/bn.js" "^4.11.5" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-utils "1.2.11" + web3-eth-contract@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.6.0.tgz#deb946867ad86d32bcbba899d733b681b25ea674" @@ -7747,6 +12954,21 @@ web3-eth-contract@1.6.0: web3-eth-abi "1.6.0" web3-utils "1.6.0" +web3-eth-ens@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" + integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-contract "1.2.11" + web3-utils "1.2.11" + web3-eth-ens@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.6.0.tgz#af13852168d56fa71b9198eb097e96fb93831c2a" @@ -7761,6 +12983,14 @@ web3-eth-ens@1.6.0: web3-eth-contract "1.6.0" web3-utils "1.6.0" +web3-eth-iban@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" + integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== + dependencies: + bn.js "^4.11.9" + web3-utils "1.2.11" + web3-eth-iban@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.6.0.tgz#edbe46cedc5b148d53fa455edea6b4eef53b2be7" @@ -7769,6 +12999,18 @@ web3-eth-iban@1.6.0: bn.js "^4.11.9" web3-utils "1.6.0" +web3-eth-personal@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" + integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + web3-eth-personal@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.6.0.tgz#b75a61c0737b8b8bcc11d05db2ed7bfce7e4b262" @@ -7781,6 +13023,25 @@ web3-eth-personal@1.6.0: web3-net "1.6.0" web3-utils "1.6.0" +web3-eth@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" + integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== + dependencies: + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-accounts "1.2.11" + web3-eth-contract "1.2.11" + web3-eth-ens "1.2.11" + web3-eth-iban "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + web3-eth@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.6.0.tgz#4c9d5fb4eccf9f8744828281757e6ea76af58cbd" @@ -7799,6 +13060,15 @@ web3-eth@1.6.0: web3-net "1.6.0" web3-utils "1.6.0" +web3-net@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" + integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + web3-net@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.6.0.tgz#2c28f8787073110a7c2310336889d2dad647e500" @@ -7808,6 +13078,40 @@ web3-net@1.6.0: web3-core-method "1.6.0" web3-utils "1.6.0" +web3-provider-engine@14.2.1: + version "14.2.1" + resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz#ef351578797bf170e08d529cb5b02f8751329b95" + integrity sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw== + dependencies: + async "^2.5.0" + backoff "^2.5.0" + clone "^2.0.0" + cross-fetch "^2.1.0" + eth-block-tracker "^3.0.0" + eth-json-rpc-infura "^3.1.0" + eth-sig-util "^1.4.2" + ethereumjs-block "^1.2.2" + ethereumjs-tx "^1.2.0" + ethereumjs-util "^5.1.5" + ethereumjs-vm "^2.3.4" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + readable-stream "^2.2.9" + request "^2.85.0" + semaphore "^1.0.3" + ws "^5.1.1" + xhr "^2.2.0" + xtend "^4.0.1" + +web3-providers-http@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" + integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== + dependencies: + web3-core-helpers "1.2.11" + xhr2-cookies "1.1.0" + web3-providers-http@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.6.0.tgz#8db4e589abf7197f5d65b12af1bf9726c45f4160" @@ -7816,6 +13120,15 @@ web3-providers-http@1.6.0: web3-core-helpers "1.6.0" xhr2-cookies "1.1.0" +web3-providers-ipc@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" + integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== + dependencies: + oboe "2.1.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-providers-ipc@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.6.0.tgz#6a3410fd47a67c4a36719fb97f99534ae12aac98" @@ -7824,6 +13137,16 @@ web3-providers-ipc@1.6.0: oboe "2.1.5" web3-core-helpers "1.6.0" +web3-providers-ws@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" + integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + websocket "^1.0.31" + web3-providers-ws@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.6.0.tgz#dc15dc18c30089efda992015fd5254bd2b77af5f" @@ -7833,6 +13156,16 @@ web3-providers-ws@1.6.0: web3-core-helpers "1.6.0" websocket "^1.0.32" +web3-shh@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" + integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-net "1.2.11" + web3-shh@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.6.0.tgz#838a3435dce1039f669a48e53e948062de197931" @@ -7843,6 +13176,20 @@ web3-shh@1.6.0: web3-core-subscriptions "1.6.0" web3-net "1.6.0" +web3-utils@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" + integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== + dependencies: + bn.js "^4.11.9" + eth-lib "0.2.8" + ethereum-bloom-filters "^1.0.6" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + underscore "1.9.1" + utf8 "3.0.0" + web3-utils@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.4.0.tgz#e8cb381c81b242dc1d4ecb397200356d404410e6" @@ -7870,6 +13217,19 @@ web3-utils@1.6.0: randombytes "^2.1.0" utf8 "3.0.0" +web3-utils@^1.0.0-beta.31: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.0.tgz#ca4c1b431a765c14ac7f773e92e0fd9377ccf578" + integrity sha512-kSaCM0uMcZTNUSmn5vMEhlo02RObGNRRCkdX0V9UTAU0+lrvn0HSaudyCo6CQzuXUsnuY2ERJGCGPfeWmv19Rg== + dependencies: + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereumjs-util "^7.1.0" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + web3-utils@^1.3.4: version "1.8.1" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.8.1.tgz#f2f7ca7eb65e6feb9f3d61056d0de6bbd57125ff" @@ -7883,6 +13243,19 @@ web3-utils@^1.3.4: randombytes "^2.1.0" utf8 "3.0.0" +web3@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" + integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== + dependencies: + web3-bzz "1.2.11" + web3-core "1.2.11" + web3-eth "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-shh "1.2.11" + web3-utils "1.2.11" + web3@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3/-/web3-1.6.0.tgz#d8fa0cd9e7bf252f9fe43bb77dc42bc6671affde" @@ -7901,7 +13274,19 @@ webidl-conversions@^3.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== -websocket@^1.0.32: +websocket@1.0.32: + version "1.0.32" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.32.tgz#1f16ddab3a21a2d929dec1687ab21cfdc6d3dbb1" + integrity sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +websocket@^1.0.31, websocket@^1.0.32: version "1.0.34" resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== @@ -7918,6 +13303,11 @@ whatwg-fetch@>=0.10.0: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== +whatwg-fetch@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -7937,6 +13327,11 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ== + which-typed-array@^1.1.2: version "1.1.8" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.8.tgz#0cfd53401a6f334d90ed1125754a42ed663eb01f" @@ -7949,6 +13344,25 @@ which-typed-array@^1.1.2: has-tostringtag "^1.0.0" is-typed-array "^1.1.9" +which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -7956,16 +13370,37 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -word-wrap@^1.2.3: +window-size@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" + integrity sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw== + +word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +wordwrapjs@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.2.0" + workerpool@6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw== + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -7988,11 +13423,23 @@ write-file-atomic@^4.0.1: imurmurhash "^0.1.4" signal-exit "^3.0.7" +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + ws@7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@8.12.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" + integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== + ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" @@ -8002,6 +13449,13 @@ ws@^3.0.0: safe-buffer "~5.1.0" ultron "~1.1.0" +ws@^5.1.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" + integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== + dependencies: + async-limiter "~1.0.0" + ws@^7.4.6: version "7.5.9" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" @@ -8034,7 +13488,7 @@ xhr2-cookies@1.1.0: dependencies: cookiejar "^2.1.1" -xhr@^2.0.4, xhr@^2.3.3: +xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: version "2.6.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== @@ -8049,11 +13503,23 @@ xmlhttprequest@1.8.0: resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA== -xtend@^4.0.0: +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + integrity sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ== + dependencies: + object-keys "~0.4.0" + +y18n@^3.2.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -8074,11 +13540,24 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== +yargs-parser@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" + integrity sha512-9pIKIJhnI5tonzG6OnCFlz/yln8xHYcGl+pn3xR0Vzff0vzN1PbNRaelgfgRUwZ3s4i3jvxT9WhmUGL4whnasA== + dependencies: + camelcase "^3.0.0" + lodash.assign "^4.0.6" + yargs-parser@^20.2.2: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" @@ -8125,6 +13604,26 @@ yargs@^17.0.1, yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.0.0" +yargs@^4.7.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" + integrity sha512-LqodLrnIDM3IFT+Hf/5sxBnEGECrfdC1uIbgZeJmESCSo4HoCAaKEus8MylXHAkdacGc0ye+Qa+dpkuom8uVYA== + dependencies: + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + lodash.assign "^4.0.3" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.1" + which-module "^1.0.0" + window-size "^0.2.0" + y18n "^3.2.1" + yargs-parser "^2.4.1" + yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" @@ -8134,3 +13633,18 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zksync-web3@^0.14.3: + version "0.14.3" + resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.14.3.tgz#64ac2a16d597464c3fc4ae07447a8007631c57c9" + integrity sha512-hT72th4AnqyLW1d5Jlv8N2B/qhEnl2NePK2A3org7tAa24niem/UAaHMkEvmWI3SF9waYUPtqAtjpf+yvQ9zvQ== + +zksync-web3@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.8.1.tgz#db289d8f6caf61f4d5ddc471fa3448d93208dc14" + integrity sha512-1A4aHPQ3MyuGjpv5X/8pVEN+MdZqMjfVmiweQSRjOlklXYu65wT9BGEOtCmMs5d3gIvLp4ssfTeuR5OCKOD2kw== + +zod@3.21.4: + version "3.21.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db" + integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw== From 02184a772be3e6c13dbeed55412caa8a85e1e915 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 23 Jun 2023 17:49:48 +0300 Subject: [PATCH 027/833] update router --- src/dex/solidly/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index 6e71d0301..fb940e66e 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -130,7 +130,7 @@ export const SolidlyConfig: DexConfigMap = { subgraphURL: 'https://api.thegraph.com/subgraphs/name/ramsesexchange/api-subgraph', factoryAddress: '0xAAA20D08e59F6561f242b08513D36266C5A29415', - router: '0xAAA87963EFeB6f7E0a2711F397663105Acb1805e', + router: '0xb2634B3CBc1E401AB3C2743DB44d459C5c9aA662', initCode: '0x1565b129f2d1790f12d45301b9b084335626f0c92410bc43130763b69971135d', poolGasCost: 180 * 1000, From 478500bbf48f62813e119a5e14b0e8f36a3dc3e9 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 23 Jun 2023 18:05:28 +0300 Subject: [PATCH 028/833] improve tests --- src/dex/solidly/solidly-e2e.test.ts | 256 +++++++++++++++++++--------- 1 file changed, 174 insertions(+), 82 deletions(-) diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index 7dd530380..a49e7104d 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -1179,93 +1179,185 @@ describe('Solidly E2E', () => { }), ); }); + describe('Ramses', () => { const dexKey = 'Ramses'; - describe('simpleSwap', () => { - it('NATIVE -> TOKEN', async () => { - await testE2E( - tokens.ETH, - tokens.USDC, - holders.ETH, - '3000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - it('TOKEN -> NATIVE', async () => { - await testE2E( - tokens.USDC, - tokens.ETH, - holders.USDC, - '9900000000', - SwapSide.SELL, - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - it('TOKEN -> TOKEN', async () => { - await testE2E( - tokens.WETH, - tokens.USDC, - holders.WETH, - '3000000000000000000', - SwapSide.SELL, - dexKey, + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ ContractMethod.simpleSwap, - - network, - provider, - ); - }); - }); - describe('multiSwap', () => { - it('NATIVE -> TOKEN', async () => { - await testE2E( - tokens.ETH, - tokens.USDC, - holders.ETH, - '3000000000000000000', - SwapSide.SELL, - dexKey, ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + ]); - network, - provider, - ); - }); - it('TOKEN -> NATIVE', async () => { - await testE2E( - tokens.USDC, - tokens.ETH, - holders.USDC, - '9900000000', - SwapSide.SELL, - dexKey, - ContractMethod.multiSwap, - network, - provider, - ); - }); - it('TOKEN -> TOKEN', async () => { - await testE2E( - tokens.WETH, - tokens.USDC, - holders.WETH, - '3000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.multiSwap, - network, - provider, - ); - }); - }); + const pairs: { name: string; sellAmount: string }[][] = [ + [ + { + name: 'ETH', + sellAmount: '1000000000000000000', + }, + { + name: 'USDC', + sellAmount: '100000000', + }, + ], + [ + { + name: 'WETH', + sellAmount: '1000000000000000000', + }, + { + name: 'USDC', + sellAmount: '100000000', + }, + ], + [ + { + name: 'USDT', + sellAmount: '100000000', + }, + { + name: 'USDC', + sellAmount: '100000000', + }, + ], + [ + { + name: 'USDC', + sellAmount: '100000000', + }, + { + name: 'DAI', + sellAmount: '100000000000000000000', + }, + ], + ]; + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + pair[0].sellAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + pair[1].sellAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }); + }), + ); + + // describe('simpleSwap', () => { + // it('NATIVE -> TOKEN', async () => { + // await testE2E( + // tokens.ETH, + // tokens.USDC, + // holders.ETH, + // '3000000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.simpleSwap, + // network, + // provider, + // ); + // }); + // it('TOKEN -> NATIVE', async () => { + // await testE2E( + // tokens.USDC, + // tokens.ETH, + // holders.USDC, + // '9900000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.simpleSwap, + // network, + // provider, + // ); + // }); + // it('TOKEN -> TOKEN', async () => { + // await testE2E( + // tokens.WETH, + // tokens.USDC, + // holders.WETH, + // '3000000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.simpleSwap, + // + // network, + // provider, + // ); + // }); + // }); + // describe('multiSwap', () => { + // it('NATIVE -> TOKEN', async () => { + // await testE2E( + // tokens.ETH, + // tokens.USDC, + // holders.ETH, + // '3000000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.multiSwap, + // + // network, + // provider, + // ); + // }); + // it('TOKEN -> NATIVE', async () => { + // await testE2E( + // tokens.USDC, + // tokens.ETH, + // holders.USDC, + // '9900000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.multiSwap, + // network, + // provider, + // ); + // }); + // it('TOKEN -> TOKEN', async () => { + // await testE2E( + // tokens.WETH, + // tokens.USDC, + // holders.WETH, + // '3000000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.multiSwap, + // network, + // provider, + // ); + // }); + // }); }); }); -}); \ No newline at end of file +}); From 06623bbbfeb5e5455b5f5d2391631e64ee6ef411 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 23 Jun 2023 18:07:25 +0300 Subject: [PATCH 029/833] 2.22.4-ramses --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a63ebc2f4..99c1ae757 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.22.3", + "version": "2.22.4-ramses", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 70043c63ca191bb26fe97a687b6b828c3b14e52d Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 23 Jun 2023 18:10:28 +0300 Subject: [PATCH 030/833] remove commented tests --- src/dex/solidly/solidly-e2e.test.ts | 85 ----------------------------- 1 file changed, 85 deletions(-) diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index a49e7104d..eb8586814 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -1273,91 +1273,6 @@ describe('Solidly E2E', () => { }); }), ); - - // describe('simpleSwap', () => { - // it('NATIVE -> TOKEN', async () => { - // await testE2E( - // tokens.ETH, - // tokens.USDC, - // holders.ETH, - // '3000000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.simpleSwap, - // network, - // provider, - // ); - // }); - // it('TOKEN -> NATIVE', async () => { - // await testE2E( - // tokens.USDC, - // tokens.ETH, - // holders.USDC, - // '9900000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.simpleSwap, - // network, - // provider, - // ); - // }); - // it('TOKEN -> TOKEN', async () => { - // await testE2E( - // tokens.WETH, - // tokens.USDC, - // holders.WETH, - // '3000000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.simpleSwap, - // - // network, - // provider, - // ); - // }); - // }); - // describe('multiSwap', () => { - // it('NATIVE -> TOKEN', async () => { - // await testE2E( - // tokens.ETH, - // tokens.USDC, - // holders.ETH, - // '3000000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.multiSwap, - // - // network, - // provider, - // ); - // }); - // it('TOKEN -> NATIVE', async () => { - // await testE2E( - // tokens.USDC, - // tokens.ETH, - // holders.USDC, - // '9900000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.multiSwap, - // network, - // provider, - // ); - // }); - // it('TOKEN -> TOKEN', async () => { - // await testE2E( - // tokens.WETH, - // tokens.USDC, - // holders.WETH, - // '3000000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.multiSwap, - // network, - // provider, - // ); - // }); - // }); }); }); }); From 01b8d2f93ae881939e294f7f0124e3e347d07d03 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 26 Jun 2023 13:37:29 +0300 Subject: [PATCH 031/833] debug --- src/dex/solidly/forks-override/ramses.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/solidly/forks-override/ramses.ts b/src/dex/solidly/forks-override/ramses.ts index 46452acc7..44c06e8bf 100644 --- a/src/dex/solidly/forks-override/ramses.ts +++ b/src/dex/solidly/forks-override/ramses.ts @@ -1,10 +1,10 @@ -import { Velodrome } from './velodrome'; import { Network } from '../../../constants'; import { getDexKeysWithNetwork } from '../../../utils'; import { SolidlyConfig } from '../config'; import _ from 'lodash'; +import { Chronos } from './chronos'; -export class Ramses extends Velodrome { +export class Ramses extends Chronos { public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork(_.pick(SolidlyConfig, ['Ramses'])); -} \ No newline at end of file +} From 96d1fd8541034d4a238bbdad07cbd04417cb75fe Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 26 Jun 2023 17:58:02 +0300 Subject: [PATCH 032/833] debug --- src/dex/solidly/config.ts | 4 +++- src/dex/solidly/forks-override/ramses.ts | 2 ++ src/dex/solidly/solidly-integration.test.ts | 9 +++++---- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index fb940e66e..4cc734bca 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -134,7 +134,9 @@ export const SolidlyConfig: DexConfigMap = { initCode: '0x1565b129f2d1790f12d45301b9b084335626f0c92410bc43130763b69971135d', poolGasCost: 180 * 1000, - feeCode: 0, + feeCode: 1, + stableFee: 1, + volatileFee: 20, }, }, }; diff --git a/src/dex/solidly/forks-override/ramses.ts b/src/dex/solidly/forks-override/ramses.ts index 44c06e8bf..dcd51ea26 100644 --- a/src/dex/solidly/forks-override/ramses.ts +++ b/src/dex/solidly/forks-override/ramses.ts @@ -3,6 +3,8 @@ import { getDexKeysWithNetwork } from '../../../utils'; import { SolidlyConfig } from '../config'; import _ from 'lodash'; import { Chronos } from './chronos'; +import { SolidlyPair } from '../types'; +import { Interface } from '@ethersproject/abi'; export class Ramses extends Chronos { public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = diff --git a/src/dex/solidly/solidly-integration.test.ts b/src/dex/solidly/solidly-integration.test.ts index 695f83e2e..5fcb8a9bd 100644 --- a/src/dex/solidly/solidly-integration.test.ts +++ b/src/dex/solidly/solidly-integration.test.ts @@ -13,6 +13,7 @@ import { SpiritSwapV2 } from './forks-override/spiritSwapV2'; import { Cone } from './forks-override/cone'; import { Chronos } from './forks-override/chronos'; import { Ramses } from './forks-override/ramses'; +import * as util from 'util'; const amounts18 = [0n, BI_POWS[18], 2000000000000000000n]; const amounts6 = [0n, BI_POWS[6], 2000000n]; @@ -769,7 +770,7 @@ describe('Solidly integration tests', () => { }); }); }); - + describe('Ramses', function () { const dexKey = 'Ramses'; const ramses = new Ramses(network, dexKey, dexHelper); @@ -780,7 +781,7 @@ describe('Solidly integration tests', () => { const TokenBSymbol = 'WETH'; const tokenB = Tokens[network][TokenBSymbol]; - const amounts = amounts18; + const amounts = amounts6; it('getPoolIdentifiers and getPricesVolume', async function () { const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); @@ -807,11 +808,11 @@ describe('Solidly integration tests', () => { ); console.log( `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, - poolPrices, + util.inspect(poolPrices, false, null, true), ); expect(poolPrices).not.toBeNull(); - checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + // checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); // Check if onchain pricing equals to calculated ones From 33c47b8463dbb941dd0425447f91002a47ba3fdc Mon Sep 17 00:00:00 2001 From: 0xshad0w Date: Wed, 28 Jun 2023 14:13:07 +0100 Subject: [PATCH 033/833] 3 - updates --- src/dex/index.ts | 2 + src/dex/ramses-v2/config.ts | 6 +- src/dex/ramses-v2/ramses-v2-e2e.test.ts | 8 +- src/dex/ramses-v2/ramses-v2-events.test.ts | 244 +++++--- .../ramses-v2/ramses-v2-integration.test.ts | 557 ++++++++++++------ 5 files changed, 553 insertions(+), 264 deletions(-) diff --git a/src/dex/index.ts b/src/dex/index.ts index d06e99259..b70e5b3cb 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -70,6 +70,7 @@ import { SwaapV2 } from './swaap-v2/swaap-v2'; import { SpiritSwapV3 } from './quickswap/spiritswap-v3'; import { TraderJoeV21 } from './trader-joe-v2.1'; import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3'; +import { RamsesV2 } from './ramses-v2/ramses-v2'; const LegacyDexes = [ CurveV2, @@ -137,6 +138,7 @@ const Dexes = [ MaverickV1, Camelot, SwaapV2, + RamsesV2, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< diff --git a/src/dex/ramses-v2/config.ts b/src/dex/ramses-v2/config.ts index 4433aac63..3a4b036b7 100644 --- a/src/dex/ramses-v2/config.ts +++ b/src/dex/ramses-v2/config.ts @@ -12,11 +12,11 @@ export const RamsesV2Config: DexConfigMap = { quoter: '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', router: '0xAA23611badAFB62D37E7295A682D21960ac85A90', supportedFees: RAMSES_SUPPORTED_FEES, - stateMulticall: '0x80898f80cFA3Fa3AbF410d90e69aDc432AE5D4c2', - uniswapMulticall: '0xac1cE734566f390A94b00eb9bf561c2625BF44ea', + stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', chunksCount: 10, initHash: - '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + '0x1565b129f2d1790f12d45301b9b084335626f0c92410bc43130763b69971135d', subgraphURL: 'https://api.thegraph.com/subgraphs/name/ramsesexchange/concentrated-liquidity-graph', }, diff --git a/src/dex/ramses-v2/ramses-v2-e2e.test.ts b/src/dex/ramses-v2/ramses-v2-e2e.test.ts index 8088a7897..0919df4b9 100644 --- a/src/dex/ramses-v2/ramses-v2-e2e.test.ts +++ b/src/dex/ramses-v2/ramses-v2-e2e.test.ts @@ -23,9 +23,9 @@ describe('RamsesV2 E2E', () => { network, ); - it('BUY DAI -> USDC', async () => { + it('BUY USDT -> USDC', async () => { await testE2E( - tokens['DAI'], + tokens['USDT'], tokens['USDC'], holders['DAI'], '100000000000', @@ -36,10 +36,10 @@ describe('RamsesV2 E2E', () => { provider, ); }); - it('SELL WETH -> SHIBA', async () => { + it('SELL WETH -> RDNT', async () => { await testE2E( tokens['WETH'], - tokens['SHIBA'], + tokens['RDNT'], holders['WETH'], '1000000000000000000', SwapSide.SELL, diff --git a/src/dex/ramses-v2/ramses-v2-events.test.ts b/src/dex/ramses-v2/ramses-v2-events.test.ts index ef49cebc1..5d1e041e5 100644 --- a/src/dex/ramses-v2/ramses-v2-events.test.ts +++ b/src/dex/ramses-v2/ramses-v2-events.test.ts @@ -2,105 +2,181 @@ import dotenv from 'dotenv'; dotenv.config(); +import _ from 'lodash'; import { RamsesV2EventPool } from './ramses-v2-pool'; +import { RamsesV2Config } from './config'; import { Network } from '../../constants'; -import { Address } from '../../types'; import { DummyDexHelper } from '../../dex-helper/index'; import { testEventSubscriber } from '../../../tests/utils-events'; import { PoolState } from './types'; - -/* - README - ====== - - This test script adds unit tests for RamsesV2 event based - system. This is done by fetching the state on-chain before the - event block, manually pushing the block logs to the event-subscriber, - comparing the local state with on-chain state. - - Most of the logic for testing is abstracted by `testEventSubscriber`. - You need to do two things to make the tests work: - - 1. Fetch the block numbers where certain events were released. You - can modify the `./scripts/fetch-event-blocknumber.ts` to get the - block numbers for different events. Make sure to get sufficient - number of blockNumbers to cover all possible cases for the event - mutations. - - 2. Complete the implementation for fetchPoolState function. The - function should fetch the on-chain state of the event subscriber - using just the blocknumber. - - The template tests only include the test for a single event - subscriber. There can be cases where multiple event subscribers - exist for a single DEX. In such cases additional tests should be - added. - - You can run this individual test script by running: - `npx jest src/dex//-events.test.ts` - - (This comment should be removed from the final implementation) -*/ - -jest.setTimeout(50 * 1000); - -async function fetchPoolState( - ramsesV2Pools: RamsesV2EventPool, +import { Interface } from '@ethersproject/abi'; +import ERC20ABI from '../../abi/erc20.json'; +import StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; +import { AbiItem } from 'web3-utils'; + +jest.setTimeout(300 * 1000); +const dexKey = 'RamsesV2'; +const network = Network.ARBITRUM; +const config = RamsesV2Config[dexKey][network]; + +async function fetchPoolStateFromContract( + uniswapV3Pool: RamsesV2EventPool, blockNumber: number, poolAddress: string, ): Promise { - // TODO: complete me! - return {}; + const message = `UniswapV3: ${poolAddress} blockNumber ${blockNumber}`; + console.log(`Fetching state ${message}`); + // Be careful to not request state prior to contract deployment + // Otherwise need to use manual state sourcing from multicall + // We had that mechanism, but removed it with this commit + // You can restore it, but better just to find block after state multicall + // deployment + const state = uniswapV3Pool.generateState(blockNumber); + console.log(`Done ${message}`); + return state; } -// eventName -> blockNumbers -type EventMappings = Record; +describe('UniswapV3 Event', function () { + const poolAddress = '0x1251ef3b87157b86f189bdea80b54673b0b59698'; + const poolFeeCode = 500n; + const token0 = '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1'; + const token1 = '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8'; + + const blockNumbers: { [eventName: string]: number[] } = { + // topic0 - 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67 + ['Swap']: [ + 15846349, 15846351, 15846352, 15846353, 15846355, 15846357, 15846358, + 15846360, 15846360, 15846361, 15846362, 15846364, 15846365, 15846366, + 15846367, 15846368, 15846369, 15846370, 15846372, 15846373, 15846374, + 15846375, 15846376, 15846381, 15846382, 15846383, 15846386, 15846387, + 15846388, 15846390, 15846391, 15846392, 15846393, 15846398, 15846400, + 15846403, 15846405, 15846407, 15846408, 15846411, 15846412, 15846413, + 15846415, + ], + // topic0 - 0x0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c + ['Burn']: [ + 15845483, 15845493, 15845539, 15845573, 15845650, 15845679, 15845680, + 15845758, 15845850, 15845865, 15845874, 15845980, 15846159, 15846217, + 15846263, 15846279, 15846297, 15846309, 15846351, 15846394, 15846398, + ], + // topic0 - 0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde + ['Mint']: [ + 15845479, 15845540, 15845624, 15845650, 15845655, 15845679, 15845680, + 15845758, 15845814, 15845867, 15845939, 15845946, 15845964, 15845980, + 15846000, 15846020, 15846044, 15846138, 15846159, 15846181, 15846217, + 15846229, 15846263, 15846279, 15846336, 15846351, 15846405, + ], + // topic0 - 0x973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b133 + ['SetFeeProtocol']: [], + // topic0 - 0xac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a + // There are some events on blockNumbers: 13125816, 12733621, 12591465 + // But stateMulticall is not deployed at that time. So I just remove that check + // I think it is not important actually + ['IncreaseObservationCardinalityNext']: [], + ['Collect']: [ + 16440688, 16440718, 16440799, 16440818, 16440824, 16440834, 16440840, + 16440931, 16440955, 16441031, 16441106, 16441124, 16441186, 16441187, + 16441202, 16441249, + ], + ['Flash']: [ + 16417763, 16419900, 16422564, 16432928, 16434338, 16434528, 16434610, + 16437224, 16437229, + ], + }; -describe('RamsesV2 EventPool Mainnet', function () { - const dexKey = 'RamsesV2'; - const network = Network.MAINNET; - const dexHelper = new DummyDexHelper(network); - const logger = dexHelper.getLogger(dexKey); - let ramsesV2Pool: RamsesV2EventPool; + describe('UniswapV3EventPool', function () { + Object.keys(blockNumbers).forEach((event: string) => { + blockNumbers[event].forEach((blockNumber: number) => { + it(`${event}:${blockNumber} - should return correct state`, async function () { + const dexHelper = new DummyDexHelper(network); + // await dexHelper.init(); + + const logger = dexHelper.getLogger(dexKey); + + const uniswapV3Pool = new RamsesV2EventPool( + dexHelper, + dexKey, + new dexHelper.web3Provider.eth.Contract( + StateMulticallABI as AbiItem[], + config.stateMulticall, + ), + new Interface(ERC20ABI), + config.factory, + poolFeeCode, + token0, + token1, + logger, + undefined, + config.initHash, + ); + + // It is done in generateState. But here have to make it manually + uniswapV3Pool.poolAddress = poolAddress.toLowerCase(); + uniswapV3Pool.addressesSubscribed[0] = poolAddress; + + await testEventSubscriber( + uniswapV3Pool, + uniswapV3Pool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolStateFromContract( + uniswapV3Pool, + _blockNumber, + poolAddress, + ), + blockNumber, + `${dexKey}_${poolAddress}`, + dexHelper.provider, + ); + }); + }); + }); + }); - // poolAddress -> EventMappings - const eventsToTest: Record = { - // TODO: complete me! - }; + // We had issue with this event. Test to tackle that special case + it('Special event case for Mint', async () => { + const _poolAddress = + '0x64750f4098A7F98352f7CD5797f421cEb8D94f64'.toLowerCase(); + const _feeCode = 100n; + const _token0 = '0x4200000000000000000000000000000000000006'; + const _token1 = '0x94b008aa00579c1307b0ef2c499ad98a8ce58e58'; + const blockNumber = 32203881; - beforeEach(async () => { - ramsesV2Pool = new RamsesV2EventPool( - dexKey, - network, + const dexHelper = new DummyDexHelper(Network.ARBITRUM); + // await dexHelper.init(); + + const logger = dexHelper.getLogger(dexKey); + + const _config = RamsesV2Config[dexKey][Network.ARBITRUM]; + + const uniswapV3Pool = new RamsesV2EventPool( dexHelper, + dexKey, + new dexHelper.web3Provider.eth.Contract( + StateMulticallABI as AbiItem[], + config.stateMulticall, + ), + new Interface(ERC20ABI), + _config.factory, + _feeCode, + _token0, + _token1, logger, - /* TODO: Put here additional constructor arguments if needed */ + undefined, + config.initHash, ); - }); - Object.entries(eventsToTest).forEach( - ([poolAddress, events]: [string, EventMappings]) => { - describe(`Events for ${poolAddress}`, () => { - Object.entries(events).forEach( - ([eventName, blockNumbers]: [string, number[]]) => { - describe(`${eventName}`, () => { - blockNumbers.forEach((blockNumber: number) => { - it(`State after ${blockNumber}`, async function () { - await testEventSubscriber( - ramsesV2Pool, - ramsesV2Pool.addressesSubscribed, - (_blockNumber: number) => - fetchPoolState(ramsesV2Pool, _blockNumber, poolAddress), - blockNumber, - `${dexKey}_${poolAddress}`, - dexHelper.provider, - ); - }); - }); - }); - }, - ); - }); - }, - ); + // It is done in generateState. But here have to make it manually + uniswapV3Pool.poolAddress = _poolAddress.toLowerCase(); + uniswapV3Pool.addressesSubscribed[0] = _poolAddress; + + await testEventSubscriber( + uniswapV3Pool, + uniswapV3Pool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolStateFromContract(uniswapV3Pool, _blockNumber, _poolAddress), + blockNumber, + `${dexKey}_${_poolAddress}`, + dexHelper.provider, + ); + }); }); diff --git a/src/dex/ramses-v2/ramses-v2-integration.test.ts b/src/dex/ramses-v2/ramses-v2-integration.test.ts index debf0fd9b..d5d40ff66 100644 --- a/src/dex/ramses-v2/ramses-v2-integration.test.ts +++ b/src/dex/ramses-v2/ramses-v2-integration.test.ts @@ -7,40 +7,49 @@ import { DummyDexHelper } from '../../dex-helper/index'; import { Network, SwapSide } from '../../constants'; import { BI_POWS } from '../../bigint-constants'; import { RamsesV2 } from './ramses-v2'; -import { - checkPoolPrices, - checkPoolsLiquidity, - checkConstantPoolPrices, -} from '../../../tests/utils'; +import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; +import UniswapV3QuoterABI from '../../abi/uniswap-v3/UniswapV3Quoter.abi.json'; +import { Address } from '@paraswap/core'; -/* - README - ====== +const network = Network.ARBITRUM; +const TokenASymbol = 'USDC'; +const TokenA = Tokens[network][TokenASymbol]; - This test script adds tests for RamsesV2 general integration - with the DEX interface. The test cases below are example tests. - It is recommended to add tests which cover RamsesV2 specific - logic. +const TokenBSymbol = 'WETH'; +const TokenB = Tokens[network][TokenBSymbol]; - You can run this individual test script by running: - `npx jest src/dex//-integration.test.ts` +const amounts = [ + 0n, + 10_000n * BI_POWS[6], + 20_000n * BI_POWS[6], + 30_000n * BI_POWS[6], +]; - (This comment should be removed from the final implementation) -*/ +const amountsBuy = [0n, 1n * BI_POWS[18], 2n * BI_POWS[18], 3n * BI_POWS[18]]; + +const dexHelper = new DummyDexHelper(network); +const dexKey = 'RamsesV2'; + +const quoterIface = new Interface(UniswapV3QuoterABI); function getReaderCalldata( exchangeAddress: string, readerIface: Interface, amounts: bigint[], funcName: string, - // TODO: Put here additional arguments you need + tokenIn: Address, + tokenOut: Address, + fee: bigint, ) { return amounts.map(amount => ({ target: exchangeAddress, callData: readerIface.encodeFunctionData(funcName, [ - // TODO: Put here additional arguments to encode them + tokenIn, + tokenOut, + fee, amount, + 0n, ]), })); } @@ -50,7 +59,6 @@ function decodeReaderResult( readerIface: Interface, funcName: string, ) { - // TODO: Adapt this function for your needs return results.map(result => { const parsed = readerIface.decodeFunctionResult(funcName, result); return BigInt(parsed[0]._hex); @@ -58,194 +66,397 @@ function decodeReaderResult( } async function checkOnChainPricing( - ramsesV2: RamsesV2, + uniswapV3: RamsesV2, funcName: string, blockNumber: number, prices: bigint[], - amounts: bigint[], + tokenIn: Address, + tokenOut: Address, + fee: bigint, + _amounts: bigint[], ) { - const exchangeAddress = ''; // TODO: Put here the real exchange address + // Quoter address + const exchangeAddress = '0xAA2f0eb52db02650959463F9801442f5dF7D5CBe'; + const readerIface = quoterIface; - // TODO: Replace dummy interface with the real one - // Normally you can get it from ramsesV2.Iface or from eventPool. - // It depends on your implementation - const readerIface = new Interface(''); + const sum = prices.reduce((acc, curr) => (acc += curr), 0n); + + if (sum === 0n) { + console.log( + `Prices were not calculated for tokenIn=${tokenIn}, tokenOut=${tokenOut}, fee=${fee.toString()}. Most likely price impact is too big for requested amount`, + ); + return false; + } const readerCallData = getReaderCalldata( exchangeAddress, readerIface, - amounts.slice(1), + _amounts.slice(1), funcName, + tokenIn, + tokenOut, + fee, ); - const readerResult = ( - await ramsesV2.dexHelper.multiContract.methods - .aggregate(readerCallData) - .call({}, blockNumber) - ).returnData; + + let readerResult; + try { + readerResult = ( + await dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blockNumber) + ).returnData; + } catch (e) { + console.log( + `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, + e, + ); + return false; + } const expectedPrices = [0n].concat( decodeReaderResult(readerResult, readerIface, funcName), ); - expect(prices).toEqual(expectedPrices); -} + let firstZeroIndex = prices.slice(1).indexOf(0n); -async function testPricingOnNetwork( - ramsesV2: RamsesV2, - network: Network, - dexKey: string, - blockNumber: number, - srcTokenSymbol: string, - destTokenSymbol: string, - side: SwapSide, - amounts: bigint[], - funcNameToCheck: string, -) { - const networkTokens = Tokens[network]; + // we skipped first, so add +1 on result + firstZeroIndex = firstZeroIndex === -1 ? prices.length : firstZeroIndex; - const pools = await ramsesV2.getPoolIdentifiers( - networkTokens[srcTokenSymbol], - networkTokens[destTokenSymbol], - side, - blockNumber, - ); - console.log( - `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `, - pools, + // Compare only the ones for which we were able to calculate prices + expect(prices.slice(0, firstZeroIndex)).toEqual( + expectedPrices.slice(0, firstZeroIndex), ); + return true; +} - expect(pools.length).toBeGreaterThan(0); +describe('RamsesV2', function () { + let blockNumber: number; + let uniswapV3: RamsesV2; - const poolPrices = await ramsesV2.getPricesVolume( - networkTokens[srcTokenSymbol], - networkTokens[destTokenSymbol], - amounts, - side, - blockNumber, - pools, - ); - console.log( - `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `, - poolPrices, - ); + beforeEach(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + uniswapV3 = new RamsesV2(network, dexKey, dexHelper); + }); - expect(poolPrices).not.toBeNull(); - if (ramsesV2.hasConstantPriceLargeAmounts) { - checkConstantPoolPrices(poolPrices!, amounts, dexKey); - } else { - checkPoolPrices(poolPrices!, amounts, side, dexKey); - } + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + const pools = await uniswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - // Check if onchain pricing equals to calculated ones - await checkOnChainPricing( - ramsesV2, - funcNameToCheck, - blockNumber, - poolPrices![0].prices, - amounts, - ); -} + expect(pools.length).toBeGreaterThan(0); -describe('RamsesV2', function () { - const dexKey = 'RamsesV2'; - let blockNumber: number; - let ramsesV2: RamsesV2; + const poolPrices = await uniswapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - describe('Mainnet', () => { - const network = Network.MAINNET; - const dexHelper = new DummyDexHelper(network); + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); - const tokens = Tokens[network]; + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + uniswapV3, + 'quoteExactInputSingle', + blockNumber, + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); - // TODO: Put here token Symbol to check against - // Don't forget to update relevant tokens in constant-e2e.ts - const srcTokenSymbol = 'srcTokenSymbol'; - const destTokenSymbol = 'destTokenSymbol'; + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); - const amountsForSell = [ + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + const pools = await uniswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await uniswapV3.getPricesVolume( + TokenA, + TokenB, + amountsBuy, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amountsBuy, SwapSide.BUY, dexKey); + + // Check if onchain pricing equals to calculated ones + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + uniswapV3, + 'quoteExactOutputSingle', + blockNumber, + price.prices, + TokenA.address, + TokenB.address, + fee, + amountsBuy, + ); + if (res === false) falseChecksCounter++; + }), + ); + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume SELL stable pairs', async function () { + const TokenASymbol = 'USDT'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDC'; + const TokenB = Tokens[network][TokenBSymbol]; + + const amounts = [ 0n, - 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6000000n, + 12000000n, + 18000000n, + 24000000n, + 30000000n, + 36000000n, + 42000000n, + 48000000n, + 54000000n, + 60000000n, + 66000000n, + 72000000n, + 78000000n, + 84000000n, + 90000000n, + 96000000n, + 102000000n, + 108000000n, + 114000000n, + 120000000n, + 126000000n, + 132000000n, + 138000000n, + 144000000n, + 150000000n, + 156000000n, + 162000000n, + 168000000n, + 174000000n, + 180000000n, + 186000000n, + 192000000n, + 198000000n, + 204000000n, + 210000000n, + 216000000n, + 222000000n, + 228000000n, + 234000000n, + 240000000n, + 246000000n, + 252000000n, + 258000000n, + 264000000n, + 270000000n, + 276000000n, + 282000000n, + 288000000n, + 294000000n, + 300000000n, ]; - const amountsForBuy = [ + const pools = await uniswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await uniswapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices( + poolPrices!.filter(pp => pp.unit !== 0n), + amounts, + SwapSide.SELL, + dexKey, + ); + + // Check if onchain pricing equals to calculated ones + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + uniswapV3, + 'quoteExactInputSingle', + blockNumber, + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume BUY stable pairs', async function () { + const TokenASymbol = 'USDC'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDT'; + const TokenB = Tokens[network][TokenBSymbol]; + + const amountsBuy = [ 0n, - 1n * BI_POWS[tokens[destTokenSymbol].decimals], - 2n * BI_POWS[tokens[destTokenSymbol].decimals], - 3n * BI_POWS[tokens[destTokenSymbol].decimals], - 4n * BI_POWS[tokens[destTokenSymbol].decimals], - 5n * BI_POWS[tokens[destTokenSymbol].decimals], - 6n * BI_POWS[tokens[destTokenSymbol].decimals], - 7n * BI_POWS[tokens[destTokenSymbol].decimals], - 8n * BI_POWS[tokens[destTokenSymbol].decimals], - 9n * BI_POWS[tokens[destTokenSymbol].decimals], - 10n * BI_POWS[tokens[destTokenSymbol].decimals], + 6000000n, + 12000000n, + 18000000n, + 24000000n, + 30000000n, + 36000000n, + 42000000n, + 48000000n, + 54000000n, + 60000000n, + 66000000n, + 72000000n, + 78000000n, + 84000000n, + 90000000n, + 96000000n, + 102000000n, + 108000000n, + 114000000n, + 120000000n, + 126000000n, + 132000000n, + 138000000n, + 144000000n, + 150000000n, + 156000000n, + 162000000n, + 168000000n, + 174000000n, + 180000000n, + 186000000n, + 192000000n, + 198000000n, + 204000000n, + 210000000n, + 216000000n, + 222000000n, + 228000000n, + 234000000n, + 240000000n, + 246000000n, + 252000000n, + 258000000n, + 264000000n, + 270000000n, + 276000000n, + 282000000n, + 288000000n, + 294000000n, + 300000000n, ]; - beforeAll(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - ramsesV2 = new RamsesV2(network, dexKey, dexHelper); - if (ramsesV2.initializePricing) { - await ramsesV2.initializePricing(blockNumber); - } - }); - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - await testPricingOnNetwork( - ramsesV2, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.SELL, - amountsForSell, - '', // TODO: Put here proper function name to check pricing - ); - }); - - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - await testPricingOnNetwork( - ramsesV2, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.BUY, - amountsForBuy, - '', // TODO: Put here proper function name to check pricing - ); - }); - - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - const newRamsesV2 = new RamsesV2(network, dexKey, dexHelper); - if (newRamsesV2.updatePoolState) { - await newRamsesV2.updatePoolState(); - } - const poolLiquidity = await newRamsesV2.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, - ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - - if (!newRamsesV2.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, - dexKey, + const pools = await uniswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await uniswapV3.getPricesVolume( + TokenA, + TokenB, + amountsBuy, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices( + poolPrices!.filter(pp => pp.unit !== 0n), + amountsBuy, + SwapSide.BUY, + dexKey, + ); + + // Check if onchain pricing equals to calculated ones + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + uniswapV3, + 'quoteExactOutputSingle', + blockNumber, + price.prices, + TokenA.address, + TokenB.address, + fee, + amountsBuy, ); - } - }); + if (res === false) falseChecksCounter++; + }), + ); + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getTopPoolsForToken', async function () { + const poolLiquidity = await uniswapV3.getTopPoolsForToken( + Tokens[Network.ARBITRUM]['USDC'].address, + 10, + ); + console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + if (!uniswapV3.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); + } }); }); From ed3757a15f5429a14b02d56a80eb51a6cf8f4222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stas=20SU=C8=98COV?= Date: Wed, 5 Jul 2023 22:18:11 +0100 Subject: [PATCH 034/833] Added Velodrome V2. --- src/dex/index.ts | 2 ++ src/dex/solidly/config.ts | 12 ++++++++++++ src/dex/solidly/forks-override/velodromeV2.ts | 10 ++++++++++ src/dex/solidly/solidly.ts | 1 + 4 files changed, 25 insertions(+) create mode 100644 src/dex/solidly/forks-override/velodromeV2.ts diff --git a/src/dex/index.ts b/src/dex/index.ts index ce53200b6..6e8703133 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -45,6 +45,7 @@ import { Solidly } from './solidly/solidly'; import { Thena } from './solidly/forks-override/thena'; import { Chronos } from './solidly/forks-override/chronos'; import { Velodrome } from './solidly/forks-override/velodrome'; +import { VelodromeV2 } from './solidly/forks-override/velodromeV2'; import { SpiritSwapV2 } from './solidly/forks-override/spiritSwapV2'; import { Synthetix } from './synthetix/synthetix'; import { Cone } from './solidly/forks-override/cone'; @@ -129,6 +130,7 @@ const Dexes = [ Thena, Chronos, Velodrome, + VelodromeV2, Cone, SoliSnek, Synthetix, diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index f8e364db3..226b0bd4f 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -72,6 +72,18 @@ export const SolidlyConfig: DexConfigMap = { feeCode: 2, }, }, + VelodromeV2: { + [Network.OPTIMISM]: { + subgraphURL: 'https://api.thegraph.com/subgraphs/name/dmihal/velodrome', + factoryAddress: '0xF1046053aa5682b4F9a81b5481394DA16BE5FF5a', + router: '0xa062aE8A9c5e11aaA026fc2670B0D65cCc8B2858', + initCode: + '0x1a8f01f7eab324003d9388f229ea17991eee9c9d14586f429799f3656790eba0', + poolGasCost: 180 * 1000, + // Variable fees. + feeCode: 0, + }, + }, Cone: { [Network.BSC]: { subgraphURL: 'https://api.thegraph.com/subgraphs/name/cone-exchange/cone', diff --git a/src/dex/solidly/forks-override/velodromeV2.ts b/src/dex/solidly/forks-override/velodromeV2.ts new file mode 100644 index 000000000..45dad7644 --- /dev/null +++ b/src/dex/solidly/forks-override/velodromeV2.ts @@ -0,0 +1,10 @@ +import { Solidly } from '../solidly'; +import { Network } from '../../../constants'; +import { getDexKeysWithNetwork } from '../../../utils'; +import { SolidlyConfig } from '../config'; +import _ from 'lodash'; + +export class Velodrome extends Solidly { + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(_.pick(SolidlyConfig, ['VelodromeV2'])); +} diff --git a/src/dex/solidly/solidly.ts b/src/dex/solidly/solidly.ts index d5c12ccf2..a8f2df141 100644 --- a/src/dex/solidly/solidly.ts +++ b/src/dex/solidly/solidly.ts @@ -66,6 +66,7 @@ export class Solidly extends UniswapV2 { getDexKeysWithNetwork( _.omit(SolidlyConfig, [ 'Velodrome', + 'VelodromeV2', 'SpiritSwapV2', 'Cone', 'SolidlyV2', From 54b9ec88cca0fc6945c22444648e73b85ca59c9e Mon Sep 17 00:00:00 2001 From: PawelK-DevBrother <106755978+PawelK-DevBrother@users.noreply.github.com> Date: Wed, 12 Jul 2023 14:16:07 +0200 Subject: [PATCH 035/833] Fix bids to asks --- src/dex/generic-rfq/example-api.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/generic-rfq/example-api.test.ts b/src/dex/generic-rfq/example-api.test.ts index 9fff282b0..81809dba4 100644 --- a/src/dex/generic-rfq/example-api.test.ts +++ b/src/dex/generic-rfq/example-api.test.ts @@ -157,7 +157,7 @@ export const startTestServer = (account: ethers.Wallet) => { new BigNumber(_prices.asks![0][0]), ); } else { - const reversedPrices = _prices.bids!.map(price => + const reversedPrices = _prices.asks!.map(price => reversePrice([new BigNumber(price[0]), new BigNumber(price[1])]), ); value = new BigNumber(payload.makerAmount).times( From 7fc495b290fb3ae797b33702eee89a1c8f7e93be Mon Sep 17 00:00:00 2001 From: sameepsi Date: Fri, 21 Jul 2023 14:39:04 +0530 Subject: [PATCH 036/833] Config for QuickPerps on Polygon zkevm --- src/dex/gmx/config.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/dex/gmx/config.ts b/src/dex/gmx/config.ts index 5ae6f1a9d..83f115d6c 100644 --- a/src/dex/gmx/config.ts +++ b/src/dex/gmx/config.ts @@ -21,6 +21,16 @@ export const GMXConfig: DexConfigMap = { usdg: '0x45096e7aA921f27590f8F19e457794EB09678141', }, }, + QuickPerps: { + [Network.ZKEVM]: { + vault: '0x99B31498B0a1Dae01fc3433e3Cb60F095340935C', + reader: '0xf1CFB75854DE535475B88Bb6FBad317eea98c0F9', + priceFeed: '0x5b1F500134bdD7f4359F5B2adC65f839737290f4', + fastPriceFeed: '0x73903fEc691a80Ec47bc830bf3F0baD127A06e30', + fastPriceEvents: '0x08bC8ef0b71238055f9Ee6BBc90869D8d0DBdCCa', + usdg: '0x48aC594dd00c4aAcF40f83337fc6dA31F9F439A7', + }, + }, }; export const Adapters: { @@ -44,4 +54,12 @@ export const Adapters: { }, ], }, + [Network.ZKEVM]: { + [SwapSide.SELL]: [ + { + name: 'PolygonZkEvmAdapter01', + index: 2, + }, + ], + }, }; From c2e6b41333effaf7ca9f97213a0695131e1f707d Mon Sep 17 00:00:00 2001 From: sameepsi Date: Fri, 21 Jul 2023 14:54:09 +0530 Subject: [PATCH 037/833] Updated config for QuickPerps --- src/dex/gmx/gmx.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dex/gmx/gmx.ts b/src/dex/gmx/gmx.ts index 2372dbea8..71ea31083 100644 --- a/src/dex/gmx/gmx.ts +++ b/src/dex/gmx/gmx.ts @@ -1,4 +1,5 @@ import { Interface } from '@ethersproject/abi'; +import _ from 'lodash'; import { Token, Address, @@ -34,7 +35,7 @@ export class GMX extends SimpleExchange implements IDex { readonly isFeeOnTransferSupported = false; public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(GMXConfig); + getDexKeysWithNetwork(_.pick(GMXConfig, ['GMX', 'QuickPerps'])); public static erc20Interface = new Interface(ERC20ABI); From e47d805485d0ca35dd97e58d398fdffd6cf0d9d3 Mon Sep 17 00:00:00 2001 From: sameepsi Date: Fri, 21 Jul 2023 15:59:19 +0530 Subject: [PATCH 038/833] Added new impl for QuickPerps --- src/abi/quickPerps/fast-price-events.json | 70 + src/abi/quickPerps/fast-price-feed.json | 748 +++++++ src/abi/quickPerps/reader.json | 313 +++ src/abi/quickPerps/vault-price-feed.json | 477 ++++ src/abi/quickPerps/vault.json | 1953 +++++++++++++++++ src/dex/QuickPerps/config.ts | 31 + src/dex/QuickPerps/fast-price-feed.ts | 279 +++ src/dex/QuickPerps/pool.ts | 360 +++ src/dex/QuickPerps/quickPerps-e2e.test.ts | 166 ++ src/dex/QuickPerps/quickPerps-events.test.ts | 115 + .../QuickPerps/quickPerps-integration.test.ts | 117 + src/dex/QuickPerps/quickPerps.ts | 296 +++ src/dex/QuickPerps/types.ts | 94 + src/dex/QuickPerps/usdq.ts | 83 + src/dex/QuickPerps/vault-price-feed.ts | 384 ++++ src/dex/QuickPerps/vault-utils.ts | 53 + src/dex/QuickPerps/vault.ts | 290 +++ src/dex/gmx/config.ts | 18 - src/dex/gmx/gmx.ts | 3 +- 19 files changed, 5830 insertions(+), 20 deletions(-) create mode 100644 src/abi/quickPerps/fast-price-events.json create mode 100644 src/abi/quickPerps/fast-price-feed.json create mode 100644 src/abi/quickPerps/reader.json create mode 100644 src/abi/quickPerps/vault-price-feed.json create mode 100644 src/abi/quickPerps/vault.json create mode 100644 src/dex/QuickPerps/config.ts create mode 100644 src/dex/QuickPerps/fast-price-feed.ts create mode 100644 src/dex/QuickPerps/pool.ts create mode 100644 src/dex/QuickPerps/quickPerps-e2e.test.ts create mode 100644 src/dex/QuickPerps/quickPerps-events.test.ts create mode 100644 src/dex/QuickPerps/quickPerps-integration.test.ts create mode 100644 src/dex/QuickPerps/quickPerps.ts create mode 100644 src/dex/QuickPerps/types.ts create mode 100644 src/dex/QuickPerps/usdq.ts create mode 100644 src/dex/QuickPerps/vault-price-feed.ts create mode 100644 src/dex/QuickPerps/vault-utils.ts create mode 100644 src/dex/QuickPerps/vault.ts diff --git a/src/abi/quickPerps/fast-price-events.json b/src/abi/quickPerps/fast-price-events.json new file mode 100644 index 000000000..f9ff530fe --- /dev/null +++ b/src/abi/quickPerps/fast-price-events.json @@ -0,0 +1,70 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "price", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "priceFeed", + "type": "address" + } + ], + "name": "PriceUpdate", + "type": "event" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_price", "type": "uint256" } + ], + "name": "emitPriceEvent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "gov", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "isPriceFeed", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_gov", "type": "address" } + ], + "name": "setGov", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_priceFeed", "type": "address" }, + { "internalType": "bool", "name": "_isPriceFeed", "type": "bool" } + ], + "name": "setIsPriceFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/abi/quickPerps/fast-price-feed.json b/src/abi/quickPerps/fast-price-feed.json new file mode 100644 index 000000000..502cec0ed --- /dev/null +++ b/src/abi/quickPerps/fast-price-feed.json @@ -0,0 +1,748 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_priceDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxPriceUpdateDelay", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minBlockInterval", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxDeviationBasisPoints", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_fastPriceEvents", + "type": "address" + }, + { "internalType": "address", "name": "_tokenManager", "type": "address" }, + { + "internalType": "address", + "name": "_positionRouter", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "signer", + "type": "address" + } + ], + "name": "DisableFastPrice", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "signer", + "type": "address" + } + ], + "name": "EnableFastPrice", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "refPrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fastPrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "cumulativeRefDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "cumulativeFastDelta", + "type": "uint256" + } + ], + "name": "MaxCumulativeDeltaDiffExceeded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "refPrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fastPrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "cumulativeRefDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "cumulativeFastDelta", + "type": "uint256" + } + ], + "name": "PriceData", + "type": "event" + }, + { + "inputs": [], + "name": "BASIS_POINTS_DIVISOR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BITMASK_32", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CUMULATIVE_DELTA_PRECISION", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CUMULATIVE_FAST_DELTA", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CUMULATIVE_REF_DELTA", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PRICE_DURATION", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REF_PRICE", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PRICE_PRECISION", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableFastPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disableFastPriceVoteCount", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "disableFastPriceVotes", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "enableFastPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fastPriceEvents", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "favorFastPrice", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_refPrice", "type": "uint256" }, + { "internalType": "bool", "name": "_maximise", "type": "bool" } + ], + "name": "getPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "getPriceData", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gov", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minAuthorizations", + "type": "uint256" + }, + { "internalType": "address[]", "name": "_signers", "type": "address[]" }, + { "internalType": "address[]", "name": "_updaters", "type": "address[]" } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "isSigner", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isSpreadEnabled", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "isUpdater", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastUpdatedAt", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastUpdatedBlock", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "maxCumulativeDeltaDiffs", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxDeviationBasisPoints", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxPriceUpdateDelay", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxTimeDeviation", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minAuthorizations", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minBlockInterval", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "positionRouter", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "priceData", + "outputs": [ + { "internalType": "uint160", "name": "refPrice", "type": "uint160" }, + { "internalType": "uint32", "name": "refTime", "type": "uint32" }, + { + "internalType": "uint32", + "name": "cumulativeRefDelta", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "cumulativeFastDelta", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "priceDataInterval", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "priceDuration", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "prices", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_priceBitArray", + "type": "uint256[]" + }, + { "internalType": "uint256", "name": "_timestamp", "type": "uint256" } + ], + "name": "setCompactedPrices", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_fastPriceEvents", + "type": "address" + } + ], + "name": "setFastPriceEvents", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_gov", "type": "address" } + ], + "name": "setGov", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bool", "name": "_isSpreadEnabled", "type": "bool" } + ], + "name": "setIsSpreadEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_lastUpdatedAt", "type": "uint256" } + ], + "name": "setLastUpdatedAt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address[]", "name": "_tokens", "type": "address[]" }, + { + "internalType": "uint256[]", + "name": "_maxCumulativeDeltaDiffs", + "type": "uint256[]" + } + ], + "name": "setMaxCumulativeDeltaDiffs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxDeviationBasisPoints", + "type": "uint256" + } + ], + "name": "setMaxDeviationBasisPoints", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxPriceUpdateDelay", + "type": "uint256" + } + ], + "name": "setMaxPriceUpdateDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxTimeDeviation", + "type": "uint256" + } + ], + "name": "setMaxTimeDeviation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minAuthorizations", + "type": "uint256" + } + ], + "name": "setMinAuthorizations", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minBlockInterval", + "type": "uint256" + } + ], + "name": "setMinBlockInterval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_priceDataInterval", + "type": "uint256" + } + ], + "name": "setPriceDataInterval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_priceDuration", "type": "uint256" } + ], + "name": "setPriceDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address[]", "name": "_tokens", "type": "address[]" }, + { "internalType": "uint256[]", "name": "_prices", "type": "uint256[]" }, + { "internalType": "uint256", "name": "_timestamp", "type": "uint256" } + ], + "name": "setPrices", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_priceBits", "type": "uint256" }, + { "internalType": "uint256", "name": "_timestamp", "type": "uint256" } + ], + "name": "setPricesWithBits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_priceBits", "type": "uint256" }, + { "internalType": "uint256", "name": "_timestamp", "type": "uint256" }, + { + "internalType": "uint256", + "name": "_endIndexForIncreasePositions", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endIndexForDecreasePositions", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxIncreasePositions", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxDecreasePositions", + "type": "uint256" + } + ], + "name": "setPricesWithBitsAndExecute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { "internalType": "bool", "name": "_isActive", "type": "bool" } + ], + "name": "setSigner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_spreadBasisPointsIfChainError", + "type": "uint256" + } + ], + "name": "setSpreadBasisPointsIfChainError", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_spreadBasisPointsIfInactive", + "type": "uint256" + } + ], + "name": "setSpreadBasisPointsIfInactive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_tokenManager", "type": "address" } + ], + "name": "setTokenManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address[]", "name": "_tokens", "type": "address[]" }, + { + "internalType": "uint256[]", + "name": "_tokenPrecisions", + "type": "uint256[]" + } + ], + "name": "setTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { "internalType": "bool", "name": "_isActive", "type": "bool" } + ], + "name": "setUpdater", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vaultPriceFeed", + "type": "address" + } + ], + "name": "setVaultPriceFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "spreadBasisPointsIfChainError", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "spreadBasisPointsIfInactive", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokenManager", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "tokenPrecisions", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "tokens", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultPriceFeed", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/abi/quickPerps/reader.json b/src/abi/quickPerps/reader.json new file mode 100644 index 000000000..6e851476a --- /dev/null +++ b/src/abi/quickPerps/reader.json @@ -0,0 +1,313 @@ +[ + { + "inputs": [], + "name": "BASIS_POINTS_DIVISOR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "POSITION_PROPS_LENGTH", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PRICE_PRECISION", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "USDQ_DECIMALS", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "_vault", + "type": "address" + }, + { "internalType": "address", "name": "_tokenIn", "type": "address" }, + { "internalType": "address", "name": "_tokenOut", "type": "address" }, + { "internalType": "uint256", "name": "_amountIn", "type": "uint256" } + ], + "name": "getAmountOut", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "_vault", + "type": "address" + }, + { "internalType": "address", "name": "_tokenIn", "type": "address" }, + { "internalType": "address", "name": "_tokenOut", "type": "address" }, + { "internalType": "uint256", "name": "_amountIn", "type": "uint256" } + ], + "name": "getFeeBasisPoints", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_vault", "type": "address" }, + { "internalType": "address[]", "name": "_tokens", "type": "address[]" } + ], + "name": "getFees", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_vault", "type": "address" }, + { "internalType": "address", "name": "_weth", "type": "address" }, + { "internalType": "uint256", "name": "_usdqAmount", "type": "uint256" }, + { "internalType": "address[]", "name": "_tokens", "type": "address[]" } + ], + "name": "getFullVaultTokenInfo", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_vault", "type": "address" }, + { "internalType": "address", "name": "_weth", "type": "address" }, + { "internalType": "address[]", "name": "_tokens", "type": "address[]" } + ], + "name": "getFundingRates", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVault", + "name": "_vault", + "type": "address" + }, + { "internalType": "address", "name": "_tokenIn", "type": "address" }, + { "internalType": "address", "name": "_tokenOut", "type": "address" } + ], + "name": "getMaxAmountIn", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_vault", "type": "address" }, + { "internalType": "address", "name": "_account", "type": "address" }, + { + "internalType": "address[]", + "name": "_collateralTokens", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "_indexTokens", + "type": "address[]" + }, + { "internalType": "bool[]", "name": "_isLong", "type": "bool[]" } + ], + "name": "getPositions", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVaultPriceFeed", + "name": "_priceFeed", + "type": "address" + }, + { "internalType": "address[]", "name": "_tokens", "type": "address[]" } + ], + "name": "getPrices", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { + "internalType": "address[]", + "name": "_yieldTrackers", + "type": "address[]" + } + ], + "name": "getStakingInfo", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { "internalType": "address[]", "name": "_tokens", "type": "address[]" } + ], + "name": "getTokenBalances", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { "internalType": "address[]", "name": "_tokens", "type": "address[]" } + ], + "name": "getTokenBalancesWithSupplies", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_token", + "type": "address" + }, + { + "internalType": "address[]", + "name": "_excludedAccounts", + "type": "address[]" + } + ], + "name": "getTokenSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_token", + "type": "address" + }, + { "internalType": "address[]", "name": "_accounts", "type": "address[]" } + ], + "name": "getTotalBalance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_yieldTokens", + "type": "address[]" + } + ], + "name": "getTotalStaked", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_vault", "type": "address" }, + { "internalType": "address", "name": "_weth", "type": "address" }, + { "internalType": "uint256", "name": "_usdqAmount", "type": "uint256" }, + { "internalType": "address[]", "name": "_tokens", "type": "address[]" } + ], + "name": "getVaultTokenInfo", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_vault", "type": "address" }, + { "internalType": "address", "name": "_weth", "type": "address" }, + { "internalType": "uint256", "name": "_usdqAmount", "type": "uint256" }, + { "internalType": "address[]", "name": "_tokens", "type": "address[]" } + ], + "name": "getVaultTokenInfoV2", + "outputs": [ + { "internalType": "uint256[]", "name": "", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gov", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hasMaxGlobalShortSizes", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_hasMaxGlobalShortSizes", + "type": "bool" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_gov", "type": "address" } + ], + "name": "setGov", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/abi/quickPerps/vault-price-feed.json b/src/abi/quickPerps/vault-price-feed.json new file mode 100644 index 000000000..d917d96cf --- /dev/null +++ b/src/abi/quickPerps/vault-price-feed.json @@ -0,0 +1,477 @@ +[ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [], + "name": "BASIS_POINTS_DIVISOR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_ADJUSTMENT_BASIS_POINTS", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_ADJUSTMENT_INTERVAL", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_SPREAD_BASIS_POINTS", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ONE_USD", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PRICE_PRECISION", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "adjustmentBasisPoints", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bnb", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bnbBusd", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "btc", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "btcBnb", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "chainlinkFlags", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eth", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ethBnb", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "favorPrimaryPrice", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "getAmmPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "bool", "name": "_maximise", "type": "bool" }, + { "internalType": "uint256", "name": "_primaryPrice", "type": "uint256" } + ], + "name": "getAmmPriceV2", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "getLatestPrimaryPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_pair", "type": "address" }, + { "internalType": "bool", "name": "_divByReserve0", "type": "bool" } + ], + "name": "getPairPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "bool", "name": "_maximise", "type": "bool" }, + { "internalType": "bool", "name": "_includeAmmPrice", "type": "bool" }, + { "internalType": "bool", "name": "", "type": "bool" } + ], + "name": "getPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "bool", "name": "_maximise", "type": "bool" }, + { "internalType": "bool", "name": "_includeAmmPrice", "type": "bool" } + ], + "name": "getPriceV1", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "bool", "name": "_maximise", "type": "bool" }, + { "internalType": "bool", "name": "_includeAmmPrice", "type": "bool" } + ], + "name": "getPriceV2", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "bool", "name": "_maximise", "type": "bool" } + ], + "name": "getPrimaryPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { + "internalType": "uint256", + "name": "_referencePrice", + "type": "uint256" + }, + { "internalType": "bool", "name": "_maximise", "type": "bool" } + ], + "name": "getSecondaryPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gov", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "isAdjustmentAdditive", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isAmmEnabled", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isSecondaryPriceEnabled", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "lastAdjustmentTimings", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxStrictPriceDeviation", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "priceDecimals", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "priceFeeds", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "priceSampleSpace", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "secondaryPriceFeed", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "bool", "name": "_isAdditive", "type": "bool" }, + { "internalType": "uint256", "name": "_adjustmentBps", "type": "uint256" } + ], + "name": "setAdjustment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_chainlinkFlags", + "type": "address" + } + ], + "name": "setChainlinkFlags", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bool", "name": "_favorPrimaryPrice", "type": "bool" } + ], + "name": "setFavorPrimaryPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_gov", "type": "address" } + ], + "name": "setGov", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bool", "name": "_isEnabled", "type": "bool" } + ], + "name": "setIsAmmEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bool", "name": "_isEnabled", "type": "bool" } + ], + "name": "setIsSecondaryPriceEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxStrictPriceDeviation", + "type": "uint256" + } + ], + "name": "setMaxStrictPriceDeviation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_bnbBusd", "type": "address" }, + { "internalType": "address", "name": "_ethBnb", "type": "address" }, + { "internalType": "address", "name": "_btcBnb", "type": "address" } + ], + "name": "setPairs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_priceSampleSpace", + "type": "uint256" + } + ], + "name": "setPriceSampleSpace", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_secondaryPriceFeed", + "type": "address" + } + ], + "name": "setSecondaryPriceFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { + "internalType": "uint256", + "name": "_spreadBasisPoints", + "type": "uint256" + } + ], + "name": "setSpreadBasisPoints", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_spreadThresholdBasisPoints", + "type": "uint256" + } + ], + "name": "setSpreadThresholdBasisPoints", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "address", "name": "_priceFeed", "type": "address" }, + { + "internalType": "uint256", + "name": "_priceDecimals", + "type": "uint256" + }, + { "internalType": "bool", "name": "_isStrictStable", "type": "bool" } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_btc", "type": "address" }, + { "internalType": "address", "name": "_eth", "type": "address" }, + { "internalType": "address", "name": "_bnb", "type": "address" } + ], + "name": "setTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bool", "name": "_useV2Pricing", "type": "bool" } + ], + "name": "setUseV2Pricing", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "spreadBasisPoints", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "spreadThresholdBasisPoints", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "strictStableTokens", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "useV2Pricing", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/abi/quickPerps/vault.json b/src/abi/quickPerps/vault.json new file mode 100644 index 000000000..5b770bfd8 --- /dev/null +++ b/src/abi/quickPerps/vault.json @@ -0,0 +1,1953 @@ +[ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "usdqAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeBasisPoints", + "type": "uint256" + } + ], + "name": "BuyUSDQ", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "size", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "collateral", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "averagePrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "entryFundingRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reserveAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "realisedPnl", + "type": "int256" + } + ], + "name": "ClosePosition", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeUsd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeTokens", + "type": "uint256" + } + ], + "name": "CollectMarginFees", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeUsd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeTokens", + "type": "uint256" + } + ], + "name": "CollectSwapFees", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DecreaseGuaranteedUsd", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DecreasePoolAmount", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "collateralToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "indexToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "collateralDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sizeDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isLong", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "price", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "DecreasePosition", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DecreaseReservedAmount", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DecreaseUsdqAmount", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DirectPoolDeposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "IncreaseGuaranteedUsd", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "IncreasePoolAmount", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "collateralToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "indexToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "collateralDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sizeDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isLong", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "price", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "IncreasePosition", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "IncreaseReservedAmount", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "IncreaseUsdqAmount", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "collateralToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "indexToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isLong", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "size", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "collateral", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reserveAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "realisedPnl", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "markPrice", + "type": "uint256" + } + ], + "name": "LiquidatePosition", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "usdqAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeBasisPoints", + "type": "uint256" + } + ], + "name": "SellUSDQ", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutAfterFees", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeBasisPoints", + "type": "uint256" + } + ], + "name": "Swap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fundingRate", + "type": "uint256" + } + ], + "name": "UpdateFundingRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bool", + "name": "hasProfit", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "delta", + "type": "uint256" + } + ], + "name": "UpdatePnl", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "size", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "collateral", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "averagePrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "entryFundingRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reserveAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "realisedPnl", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "markPrice", + "type": "uint256" + } + ], + "name": "UpdatePosition", + "type": "event" + }, + { + "inputs": [], + "name": "BASIS_POINTS_DIVISOR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FUNDING_RATE_PRECISION", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_FEE_BASIS_POINTS", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_FUNDING_RATE_FACTOR", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_LIQUIDATION_FEE_USD", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_FUNDING_RATE_INTERVAL", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_LEVERAGE", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PRICE_PRECISION", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "USDQ_DECIMALS", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_router", "type": "address" } + ], + "name": "addRouter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amount", "type": "uint256" }, + { "internalType": "address", "name": "_tokenDiv", "type": "address" }, + { "internalType": "address", "name": "_tokenMul", "type": "address" } + ], + "name": "adjustForDecimals", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "allWhitelistedTokens", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allWhitelistedTokensLength", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" } + ], + "name": "approvedRouters", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "bufferAmounts", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "address", "name": "_receiver", "type": "address" } + ], + "name": "buyUSDQ", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "clearTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "cumulativeFundingRates", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { + "internalType": "address", + "name": "_collateralToken", + "type": "address" + }, + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { + "internalType": "uint256", + "name": "_collateralDelta", + "type": "uint256" + }, + { "internalType": "uint256", "name": "_sizeDelta", "type": "uint256" }, + { "internalType": "bool", "name": "_isLong", "type": "bool" }, + { "internalType": "address", "name": "_receiver", "type": "address" } + ], + "name": "decreasePosition", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "directPoolDeposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "errorController", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "errors", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "feeReserves", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fundingInterval", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fundingRateFactor", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { "internalType": "uint256", "name": "_size", "type": "uint256" }, + { "internalType": "uint256", "name": "_averagePrice", "type": "uint256" }, + { "internalType": "bool", "name": "_isLong", "type": "bool" }, + { + "internalType": "uint256", + "name": "_lastIncreasedTime", + "type": "uint256" + } + ], + "name": "getDelta", + "outputs": [ + { "internalType": "bool", "name": "", "type": "bool" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_collateralToken", + "type": "address" + }, + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { "internalType": "bool", "name": "_isLong", "type": "bool" } + ], + "name": "getEntryFundingRate", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_usdqDelta", "type": "uint256" }, + { + "internalType": "uint256", + "name": "_feeBasisPoints", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_taxBasisPoints", + "type": "uint256" + }, + { "internalType": "bool", "name": "_increment", "type": "bool" } + ], + "name": "getFeeBasisPoints", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { + "internalType": "address", + "name": "_collateralToken", + "type": "address" + }, + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { "internalType": "bool", "name": "_isLong", "type": "bool" }, + { "internalType": "uint256", "name": "_size", "type": "uint256" }, + { + "internalType": "uint256", + "name": "_entryFundingRate", + "type": "uint256" + } + ], + "name": "getFundingFee", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "getGlobalShortDelta", + "outputs": [ + { "internalType": "bool", "name": "", "type": "bool" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "getMaxPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "getMinPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { "internalType": "uint256", "name": "_size", "type": "uint256" }, + { "internalType": "uint256", "name": "_averagePrice", "type": "uint256" }, + { "internalType": "bool", "name": "_isLong", "type": "bool" }, + { "internalType": "uint256", "name": "_nextPrice", "type": "uint256" }, + { "internalType": "uint256", "name": "_sizeDelta", "type": "uint256" }, + { + "internalType": "uint256", + "name": "_lastIncreasedTime", + "type": "uint256" + } + ], + "name": "getNextAveragePrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "getNextFundingRate", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { "internalType": "uint256", "name": "_nextPrice", "type": "uint256" }, + { "internalType": "uint256", "name": "_sizeDelta", "type": "uint256" } + ], + "name": "getNextGlobalShortAveragePrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { + "internalType": "address", + "name": "_collateralToken", + "type": "address" + }, + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { "internalType": "bool", "name": "_isLong", "type": "bool" } + ], + "name": "getPosition", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "bool", "name": "", "type": "bool" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { + "internalType": "address", + "name": "_collateralToken", + "type": "address" + }, + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { "internalType": "bool", "name": "_isLong", "type": "bool" } + ], + "name": "getPositionDelta", + "outputs": [ + { "internalType": "bool", "name": "", "type": "bool" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { + "internalType": "address", + "name": "_collateralToken", + "type": "address" + }, + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { "internalType": "bool", "name": "_isLong", "type": "bool" }, + { "internalType": "uint256", "name": "_sizeDelta", "type": "uint256" } + ], + "name": "getPositionFee", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { + "internalType": "address", + "name": "_collateralToken", + "type": "address" + }, + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { "internalType": "bool", "name": "_isLong", "type": "bool" } + ], + "name": "getPositionKey", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { + "internalType": "address", + "name": "_collateralToken", + "type": "address" + }, + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { "internalType": "bool", "name": "_isLong", "type": "bool" } + ], + "name": "getPositionLeverage", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_usdqAmount", "type": "uint256" } + ], + "name": "getRedemptionAmount", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "getRedemptionCollateral", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "getRedemptionCollateralUsd", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "getTargetUsdqAmount", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" } + ], + "name": "getUtilisation", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "globalShortAveragePrices", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "globalShortSizes", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gov", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "guaranteedUsd", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hasDynamicFees", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "inManagerMode", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "inPrivateLiquidationMode", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "includeAmmPrice", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { + "internalType": "address", + "name": "_collateralToken", + "type": "address" + }, + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { "internalType": "uint256", "name": "_sizeDelta", "type": "uint256" }, + { "internalType": "bool", "name": "_isLong", "type": "bool" } + ], + "name": "increasePosition", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_router", "type": "address" }, + { "internalType": "address", "name": "_usdq", "type": "address" }, + { "internalType": "address", "name": "_priceFeed", "type": "address" }, + { + "internalType": "uint256", + "name": "_liquidationFeeUsd", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_fundingRateFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_stableFundingRateFactor", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isLeverageEnabled", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "isLiquidator", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "isManager", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isSwapEnabled", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "lastFundingTimes", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { + "internalType": "address", + "name": "_collateralToken", + "type": "address" + }, + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { "internalType": "bool", "name": "_isLong", "type": "bool" }, + { "internalType": "address", "name": "_feeReceiver", "type": "address" } + ], + "name": "liquidatePosition", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "liquidationFeeUsd", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "marginFeeBasisPoints", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxGasPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "maxGlobalShortSizes", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLeverage", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "maxUsdqAmounts", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "minProfitBasisPoints", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minProfitTime", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mintBurnFeeBasisPoints", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "poolAmounts", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "name": "positions", + "outputs": [ + { "internalType": "uint256", "name": "size", "type": "uint256" }, + { "internalType": "uint256", "name": "collateral", "type": "uint256" }, + { "internalType": "uint256", "name": "averagePrice", "type": "uint256" }, + { + "internalType": "uint256", + "name": "entryFundingRate", + "type": "uint256" + }, + { "internalType": "uint256", "name": "reserveAmount", "type": "uint256" }, + { "internalType": "int256", "name": "realisedPnl", "type": "int256" }, + { + "internalType": "uint256", + "name": "lastIncreasedTime", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "priceFeed", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_router", "type": "address" } + ], + "name": "removeRouter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "reservedAmounts", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "router", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "address", "name": "_receiver", "type": "address" } + ], + "name": "sellUSDQ", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_amount", "type": "uint256" } + ], + "name": "setBufferAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_errorCode", "type": "uint256" }, + { "internalType": "string", "name": "_error", "type": "string" } + ], + "name": "setError", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_errorController", + "type": "address" + } + ], + "name": "setErrorController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_taxBasisPoints", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_stableTaxBasisPoints", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_mintBurnFeeBasisPoints", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_swapFeeBasisPoints", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_stableSwapFeeBasisPoints", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_marginFeeBasisPoints", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_liquidationFeeUsd", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minProfitTime", + "type": "uint256" + }, + { "internalType": "bool", "name": "_hasDynamicFees", "type": "bool" } + ], + "name": "setFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_fundingInterval", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_fundingRateFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_stableFundingRateFactor", + "type": "uint256" + } + ], + "name": "setFundingRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_gov", "type": "address" } + ], + "name": "setGov", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bool", "name": "_inManagerMode", "type": "bool" } + ], + "name": "setInManagerMode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_inPrivateLiquidationMode", + "type": "bool" + } + ], + "name": "setInPrivateLiquidationMode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bool", "name": "_isLeverageEnabled", "type": "bool" } + ], + "name": "setIsLeverageEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bool", "name": "_isSwapEnabled", "type": "bool" } + ], + "name": "setIsSwapEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_liquidator", "type": "address" }, + { "internalType": "bool", "name": "_isActive", "type": "bool" } + ], + "name": "setLiquidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_manager", "type": "address" }, + { "internalType": "bool", "name": "_isManager", "type": "bool" } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_maxGasPrice", "type": "uint256" } + ], + "name": "setMaxGasPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_amount", "type": "uint256" } + ], + "name": "setMaxGlobalShortSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_maxLeverage", "type": "uint256" } + ], + "name": "setMaxLeverage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_priceFeed", "type": "address" } + ], + "name": "setPriceFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { + "internalType": "uint256", + "name": "_tokenDecimals", + "type": "uint256" + }, + { "internalType": "uint256", "name": "_tokenWeight", "type": "uint256" }, + { "internalType": "uint256", "name": "_minProfitBps", "type": "uint256" }, + { + "internalType": "uint256", + "name": "_maxUsdqAmount", + "type": "uint256" + }, + { "internalType": "bool", "name": "_isStable", "type": "bool" }, + { "internalType": "bool", "name": "_isShortable", "type": "bool" } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_amount", "type": "uint256" } + ], + "name": "setUsdqAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVaultUtils", + "name": "_vaultUtils", + "type": "address" + } + ], + "name": "setVaultUtils", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "shortableTokens", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stableFundingRateFactor", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stableSwapFeeBasisPoints", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stableTaxBasisPoints", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "stableTokens", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_tokenIn", "type": "address" }, + { "internalType": "address", "name": "_tokenOut", "type": "address" }, + { "internalType": "address", "name": "_receiver", "type": "address" } + ], + "name": "swap", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "swapFeeBasisPoints", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "taxBasisPoints", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "tokenBalances", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "tokenDecimals", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_tokenAmount", "type": "uint256" } + ], + "name": "tokenToUsdMin", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "tokenWeights", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalTokenWeights", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_collateralToken", + "type": "address" + }, + { "internalType": "address", "name": "_indexToken", "type": "address" } + ], + "name": "updateCumulativeFundingRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_newVault", "type": "address" }, + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_amount", "type": "uint256" } + ], + "name": "upgradeVault", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_usdAmount", "type": "uint256" }, + { "internalType": "uint256", "name": "_price", "type": "uint256" } + ], + "name": "usdToToken", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_usdAmount", "type": "uint256" } + ], + "name": "usdToTokenMax", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_usdAmount", "type": "uint256" } + ], + "name": "usdToTokenMin", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "usdq", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "usdqAmounts", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "useSwapPricing", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_account", "type": "address" }, + { + "internalType": "address", + "name": "_collateralToken", + "type": "address" + }, + { "internalType": "address", "name": "_indexToken", "type": "address" }, + { "internalType": "bool", "name": "_isLong", "type": "bool" }, + { "internalType": "bool", "name": "_raise", "type": "bool" } + ], + "name": "validateLiquidation", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultUtils", + "outputs": [ + { "internalType": "contract IVaultUtils", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "whitelistedTokenCount", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "whitelistedTokens", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "address", "name": "_receiver", "type": "address" } + ], + "name": "withdrawFees", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/dex/QuickPerps/config.ts b/src/dex/QuickPerps/config.ts new file mode 100644 index 000000000..1f44ef1bf --- /dev/null +++ b/src/dex/QuickPerps/config.ts @@ -0,0 +1,31 @@ +import { DexParams } from './types'; +import { DexConfigMap } from '../../types'; +import { Network, SwapSide } from '../../constants'; + +export const QuickPerpsConfig: DexConfigMap = { + QuickPerps: { + [Network.ZKEVM]: { + vault: '0x99B31498B0a1Dae01fc3433e3Cb60F095340935C', + reader: '0xf1CFB75854DE535475B88Bb6FBad317eea98c0F9', + priceFeed: '0x5b1F500134bdD7f4359F5B2adC65f839737290f4', + fastPriceFeed: '0x73903fEc691a80Ec47bc830bf3F0baD127A06e30', + fastPriceEvents: '0x08bC8ef0b71238055f9Ee6BBc90869D8d0DBdCCa', + usdq: '0x48aC594dd00c4aAcF40f83337fc6dA31F9F439A7', + }, + }, +}; + +export const Adapters: { + [chainId: number]: { + [side: string]: { name: string; index: number }[] | null; + }; +} = { + [Network.ZKEVM]: { + [SwapSide.SELL]: [ + { + name: 'PolygonZkEvmAdapter01', + index: 2, + }, + ], + }, +}; diff --git a/src/dex/QuickPerps/fast-price-feed.ts b/src/dex/QuickPerps/fast-price-feed.ts new file mode 100644 index 000000000..7140ddf70 --- /dev/null +++ b/src/dex/QuickPerps/fast-price-feed.ts @@ -0,0 +1,279 @@ +import _ from 'lodash'; +import { Interface } from '@ethersproject/abi'; +import { DeepReadonly } from 'ts-essentials'; +import { PartialEventSubscriber } from '../../composed-event-subscriber'; +import { + Address, + MultiCallInput, + MultiCallOutput, + Logger, + Log, + BlockHeader, +} from '../../types'; +import { FastPriceFeedConfig, FastPriceFeedState } from './types'; +import FastPriceFeedAbi from '../../abi/quickPerps/fast-price-feed.json'; +import FastPriceEventsAbi from '../../abi/quickPerps/fast-price-events.json'; +import { Lens } from '../../lens'; + +export class FastPriceFeed extends PartialEventSubscriber< + State, + FastPriceFeedState +> { + static readonly interface = new Interface(FastPriceFeedAbi); + static readonly fastPriceEventsInterface = new Interface(FastPriceEventsAbi); + + BASIS_POINTS_DIVISOR = 10000n; + protected priceDuration: number; + protected maxDeviationBasisPoints: bigint; + protected favorFastPrice: Record; + private spreadBasisPointsIfInactive: bigint; + private spreadBasisPointsIfChainError: bigint; + private maxPriceUpdateDelay: number; + + constructor( + private fastPriceFeedAddress: Address, + fastPriceEventsAddress: Address, + private tokenAddresses: Address[], + config: FastPriceFeedConfig, + lens: Lens, DeepReadonly>, + logger: Logger, + ) { + super([fastPriceEventsAddress], lens, logger); + this.priceDuration = config.priceDuration; + this.maxDeviationBasisPoints = config.maxDeviationBasisPoints; + this.favorFastPrice = config.favorFastPrice; + this.spreadBasisPointsIfInactive = config.spreadBasisPointsIfInactive; + this.spreadBasisPointsIfChainError = config.spreadBasisPointsIfChainError; + this.maxPriceUpdateDelay = config.maxPriceUpdateDelay; + } + + public processLog( + state: DeepReadonly, + log: Readonly, + blockHeader: Readonly, + ): DeepReadonly | null { + try { + const parsed = FastPriceFeed.fastPriceEventsInterface.parseLog(log); + switch (parsed.name) { + case 'PriceUpdate': { + const _state: FastPriceFeedState = _.cloneDeep(state); + _state.lastUpdatedAt = + typeof blockHeader.timestamp === 'string' + ? parseInt(blockHeader.timestamp) + : blockHeader.timestamp; + const tokenAddress = parsed.args.token.toLowerCase(); + if (tokenAddress in state.prices) + _state.prices[tokenAddress] = BigInt(parsed.args.price.toString()); + return _state; + } + default: + return null; + } + } catch (e) { + this.logger.error('Failed to parse log', e); + return null; + } + } + + getPrice( + _state: DeepReadonly, + _token: Address, + _refPrice: bigint, + _maximise: boolean, + ) { + const state = this.lens.get()(_state); + + const timestamp = Math.floor(Date.now() / 1000); + + if (timestamp > state.lastUpdatedAt + this.maxPriceUpdateDelay) { + if (_maximise) { + return ( + (_refPrice * + (this.BASIS_POINTS_DIVISOR + this.spreadBasisPointsIfChainError)) / + this.BASIS_POINTS_DIVISOR + ); + } + + return ( + (_refPrice * + (this.BASIS_POINTS_DIVISOR - this.spreadBasisPointsIfChainError)) / + this.BASIS_POINTS_DIVISOR + ); + } + + if (timestamp > state.lastUpdatedAt + this.priceDuration) { + if (_maximise) { + return ( + (_refPrice * + (this.BASIS_POINTS_DIVISOR + this.spreadBasisPointsIfInactive)) / + this.BASIS_POINTS_DIVISOR + ); + } + + return ( + (_refPrice * + (this.BASIS_POINTS_DIVISOR - this.spreadBasisPointsIfInactive)) / + this.BASIS_POINTS_DIVISOR + ); + } + + const fastPrice = state.prices[_token]; + if (fastPrice === 0n) return _refPrice; + + let diffBasisPoints = + _refPrice > fastPrice ? _refPrice - fastPrice : fastPrice - _refPrice; + diffBasisPoints = (diffBasisPoints * this.BASIS_POINTS_DIVISOR) / _refPrice; + + // create a spread between the _refPrice and the fastPrice if the maxDeviationBasisPoints is exceeded + // or if watchers have flagged an issue with the fast price + const hasSpread = + !this.favorFastPrice[_token] || + diffBasisPoints > this.maxDeviationBasisPoints; + + if (hasSpread) { + // return the higher of the two prices + if (_maximise) { + return _refPrice > fastPrice ? _refPrice : fastPrice; + } + + // return the lower of the two prices + return _refPrice < fastPrice ? _refPrice : fastPrice; + } + + return fastPrice; + } + + static getConfigMulticallInputs( + fastPriceFeedAddress: Address, + tokenAddresses: Address[], + ): MultiCallInput[] { + return [ + { + target: fastPriceFeedAddress, + callData: FastPriceFeed.interface.encodeFunctionData('priceDuration'), + }, + { + target: fastPriceFeedAddress, + callData: FastPriceFeed.interface.encodeFunctionData( + 'maxDeviationBasisPoints', + ), + }, + { + target: fastPriceFeedAddress, + callData: FastPriceFeed.interface.encodeFunctionData( + 'spreadBasisPointsIfInactive', + ), + }, + { + target: fastPriceFeedAddress, + callData: FastPriceFeed.interface.encodeFunctionData( + 'spreadBasisPointsIfChainError', + ), + }, + { + target: fastPriceFeedAddress, + callData: FastPriceFeed.interface.encodeFunctionData( + 'maxPriceUpdateDelay', + ), + }, + ...tokenAddresses.map(t => ({ + target: fastPriceFeedAddress, + callData: FastPriceFeed.interface.encodeFunctionData('favorFastPrice', [ + t, + ]), + })), + ]; + } + + static getConfig( + multicallOutputs: MultiCallOutput[], + tokenAddresses: Address[], + ): FastPriceFeedConfig { + return { + priceDuration: parseInt( + FastPriceFeed.interface + .decodeFunctionResult('priceDuration', multicallOutputs[0])[0] + .toString(), + ), + maxDeviationBasisPoints: BigInt( + FastPriceFeed.interface + .decodeFunctionResult( + 'maxDeviationBasisPoints', + multicallOutputs[1], + )[0] + .toString(), + ), + spreadBasisPointsIfInactive: BigInt( + FastPriceFeed.interface + .decodeFunctionResult( + 'spreadBasisPointsIfInactive', + multicallOutputs[2], + )[0] + .toString(), + ), + spreadBasisPointsIfChainError: BigInt( + FastPriceFeed.interface + .decodeFunctionResult( + 'spreadBasisPointsIfChainError', + multicallOutputs[3], + )[0] + .toString(), + ), + maxPriceUpdateDelay: parseInt( + FastPriceFeed.interface + .decodeFunctionResult('maxPriceUpdateDelay', multicallOutputs[4])[0] + .toString(), + ), + favorFastPrice: multicallOutputs + .slice(5) + .reduce>((acc, curr, i) => { + acc[tokenAddresses[i]] = FastPriceFeed.interface.decodeFunctionResult( + 'favorFastPrice', + curr, + )[0]; + return acc; + }, {}), + }; + } + + public getGenerateStateMultiCallInputs(): MultiCallInput[] { + const pricesEntries = this.tokenAddresses.map((t: Address) => ({ + target: this.fastPriceFeedAddress, + callData: FastPriceFeed.interface.encodeFunctionData('prices', [t]), + })); + return [ + ...pricesEntries, + { + target: this.fastPriceFeedAddress, + callData: FastPriceFeed.interface.encodeFunctionData('lastUpdatedAt'), + }, + ]; + } + + public generateState( + multicallOutputs: MultiCallOutput[], + blockNumber?: number | 'latest', + ): DeepReadonly { + let fastPriceFeedState: FastPriceFeedState = { + prices: {}, + lastUpdatedAt: 0, + }; + this.tokenAddresses.forEach( + (t: Address, i: number) => + (fastPriceFeedState.prices[t] = BigInt( + FastPriceFeed.interface + .decodeFunctionResult('prices', multicallOutputs[i])[0] + .toString(), + )), + ); + fastPriceFeedState.lastUpdatedAt = parseInt( + FastPriceFeed.interface + .decodeFunctionResult( + 'lastUpdatedAt', + multicallOutputs[this.tokenAddresses.length], + )[0] + .toString(), + ); + return fastPriceFeedState; + } +} diff --git a/src/dex/QuickPerps/pool.ts b/src/dex/QuickPerps/pool.ts new file mode 100644 index 000000000..20d2fbb92 --- /dev/null +++ b/src/dex/QuickPerps/pool.ts @@ -0,0 +1,360 @@ +import { DeepReadonly } from 'ts-essentials'; +import { Lens, lens } from '../../lens'; +import { Address, Log, Logger, MultiCallInput } from '../../types'; +import { ComposedEventSubscriber } from '../../composed-event-subscriber'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { PoolState, DexParams, PoolConfig } from './types'; +import { ChainLinkSubscriber } from '../../lib/chainlink'; +import { FastPriceFeed } from './fast-price-feed'; +import { VaultPriceFeed } from './vault-price-feed'; +import { Vault } from './vault'; +import { USDQ } from './usdq'; +import { Contract } from 'web3-eth-contract'; +import ReaderABI from '../../abi/quickPerps/reader.json'; + +const MAX_AMOUNT_IN_CACHE_TTL = 5 * 60; + +export class QuickPerpsEventPool extends ComposedEventSubscriber { + PRICE_PRECISION = 10n ** 30n; + USDQ_DECIMALS = 18; + BASIS_POINTS_DIVISOR = 10000n; + + vault: Vault; + reader: Contract; + + constructor( + parentName: string, + protected network: number, + protected dexHelper: IDexHelper, + logger: Logger, + config: PoolConfig, + ) { + const chainlinkMap = Object.entries(config.chainlink).reduce( + ( + acc: { [address: string]: ChainLinkSubscriber }, + [key, value], + ) => { + acc[key] = new ChainLinkSubscriber( + value.proxy, + value.aggregator, + lens>().primaryPrices[key], + dexHelper.getLogger(`${key} ChainLink for ${parentName}-${network}`), + ); + return acc; + }, + {}, + ); + const fastPriceFeed = new FastPriceFeed( + config.fastPriceFeed, + config.fastPriceEvents, + config.tokenAddresses, + config.fastPriceFeedConfig, + lens>().secondaryPrices, + dexHelper.getLogger(`${parentName}-${network} fastPriceFeed`), + ); + const vaultPriceFeed = new VaultPriceFeed( + config.vaultPriceFeedConfig, + chainlinkMap, + fastPriceFeed, + ); + const usdq = new USDQ( + config.usdqAddress, + lens>().usdq, + dexHelper.getLogger(`${parentName}-${network} USDQ`), + ); + const vault = new Vault( + config.vaultAddress, + config.tokenAddresses, + config.vaultConfig, + vaultPriceFeed, + usdq, + lens>().vault, + dexHelper.getLogger(`${parentName}-${network} vault`), + ); + super( + parentName, + 'pool', + dexHelper.getLogger(`${parentName}-${network}`), + dexHelper, + [...Object.values(chainlinkMap), fastPriceFeed, usdq, vault], + { + primaryPrices: {}, + secondaryPrices: { + lastUpdatedAt: 0, + prices: {}, + }, + vault: { + usdqAmounts: {}, + }, + usdq: { + totalSupply: 0n, + }, + }, + ); + this.vault = vault; + this.reader = new this.dexHelper.web3Provider.eth.Contract( + ReaderABI as any, + config.readerAddress, + ); + } + + async getStateOrGenerate(blockNumber: number): Promise> { + const evenState = this.getState(blockNumber); + if (evenState) return evenState; + const onChainState = await this.generateState(blockNumber); + this.setState(onChainState, blockNumber); + return onChainState; + } + + async getMaxAmountIn(_tokenIn: Address, _tokenOut: Address): Promise { + const cacheKey = `maxAmountIn_${_tokenIn}_${_tokenOut}`; + const maxAmountCached = await this.dexHelper.cache.get( + this.parentName, + this.network, + cacheKey, + ); + if (maxAmountCached) return BigInt(maxAmountCached); + const maxAmount: string = await this.reader.methods + .getMaxAmountIn(this.vault.vaultAddress, _tokenIn, _tokenOut) + .call(); + this.dexHelper.cache.setex( + this.parentName, + this.network, + cacheKey, + MAX_AMOUNT_IN_CACHE_TTL, + maxAmount, + ); + return BigInt(maxAmount); + } + + // Reference to the original implementation + // https://github.com/gmx-io/gmx-contracts/blob/master/contracts/peripherals/Reader.sol#L71 + async getAmountOut( + _tokenIn: Address, + _tokenOut: Address, + _amountsIn: bigint[], + blockNumber: number, + ): Promise { + const maxAmountIn = await this.getMaxAmountIn(_tokenIn, _tokenOut); + const state = await this.getStateOrGenerate(blockNumber); + const priceIn = this.vault.getMinPrice(state, _tokenIn); + const priceOut = this.vault.getMaxPrice(state, _tokenOut); + + const tokenInDecimals = this.vault.tokenDecimals[_tokenIn]; + const tokenOutDecimals = this.vault.tokenDecimals[_tokenOut]; + + const isStableSwap = + this.vault.stableTokens[_tokenIn] && this.vault.stableTokens[_tokenOut]; + const baseBps = isStableSwap + ? this.vault.stableSwapFeeBasisPoints + : this.vault.swapFeeBasisPoints; + const taxBps = isStableSwap + ? this.vault.stableTaxBasisPoints + : this.vault.taxBasisPoints; + const USDQUnit = BigInt(10 ** this.USDQ_DECIMALS); + const tokenInUnit = BigInt(10 ** tokenInDecimals); + const tokenOutUnit = BigInt(10 ** tokenOutDecimals); + + return _amountsIn.map(_amountIn => { + if (_amountIn > maxAmountIn) return 0n; + let feeBasisPoints; + { + let usdqAmount = (_amountIn * priceIn) / this.PRICE_PRECISION; + usdqAmount = (usdqAmount * USDQUnit) / tokenInUnit; + + const feesBasisPoints0 = this.vault.getFeeBasisPoints( + state, + _tokenIn, + usdqAmount, + baseBps, + taxBps, + true, + ); + const feesBasisPoints1 = this.vault.getFeeBasisPoints( + state, + _tokenOut, + usdqAmount, + baseBps, + taxBps, + false, + ); + // use the higher of the two fee basis points + feeBasisPoints = + feesBasisPoints0 > feesBasisPoints1 + ? feesBasisPoints0 + : feesBasisPoints1; + } + + let amountOut = (_amountIn * priceIn) / priceOut; + amountOut = (amountOut * tokenOutUnit) / tokenInUnit; + + const amountOutAfterFees = + (amountOut * (this.BASIS_POINTS_DIVISOR - feeBasisPoints)) / + this.BASIS_POINTS_DIVISOR; + return amountOutAfterFees; + }); + } + + static async getWhitelistedTokens( + vaultAddress: Address, + blockNumber: number | 'latest', + multiContract: Contract, + ) { + // get tokens count + const tokenCountResult = ( + await multiContract.methods + .aggregate([ + { + callData: Vault.interface.encodeFunctionData( + 'allWhitelistedTokensLength', + ), + target: vaultAddress, + }, + ]) + .call({}, blockNumber) + ).returnData; + const tokensCount = parseInt( + Vault.interface + .decodeFunctionResult('allWhitelistedTokensLength', tokenCountResult[0]) + .toString(), + ); + + // get tokens + const getTokensCalldata = new Array(tokensCount).fill(0).map((_, i) => { + return { + callData: Vault.interface.encodeFunctionData('allWhitelistedTokens', [ + i, + ]), + target: vaultAddress, + }; + }); + const tokensResult = ( + await multiContract.methods + .aggregate(getTokensCalldata) + .call({}, blockNumber) + ).returnData; + const tokens: Address[] = tokensResult.map((t: any) => + Vault.interface + .decodeFunctionResult('allWhitelistedTokens', t)[0] + .toLowerCase(), + ); + return tokens; + } + + static async getConfig( + dexParams: DexParams, + blockNumber: number | 'latest', + multiContract: Contract, + ): Promise { + const tokens = await this.getWhitelistedTokens( + dexParams.vault, + blockNumber, + multiContract, + ); + + // get price chainlink price feed + const getPriceFeedCalldata = tokens.map(t => { + return { + callData: VaultPriceFeed.interface.encodeFunctionData('priceFeeds', [ + t, + ]), + target: dexParams.priceFeed, + }; + }); + const priceFeedResult = ( + await multiContract.methods + .aggregate(getPriceFeedCalldata) + .call({}, blockNumber) + ).returnData; + const priceFeeds = priceFeedResult.map((p: any) => + VaultPriceFeed.interface + .decodeFunctionResult('priceFeeds', p)[0] + .toString() + .toLowerCase(), + ); + + // get config for all event listeners + let multicallSlices: [number, number][] = []; + let multiCallData: MultiCallInput[] = []; + let i = 0; + for (let priceFeed of priceFeeds) { + const chainlinkConfigCallData = + ChainLinkSubscriber.getReadAggregatorMultiCallInput(priceFeed); + multiCallData.push(chainlinkConfigCallData); + multicallSlices.push([i, i + 1]); + i += 1; + } + + const fastPriceFeedConfigCallData = FastPriceFeed.getConfigMulticallInputs( + dexParams.fastPriceFeed, + tokens, + ); + multiCallData.push(...fastPriceFeedConfigCallData); + multicallSlices.push([i, i + fastPriceFeedConfigCallData.length]); + i += fastPriceFeedConfigCallData.length; + + const vaultPriceFeedConfigCallData = + VaultPriceFeed.getConfigMulticallInputs(dexParams.priceFeed, tokens); + multiCallData.push(...vaultPriceFeedConfigCallData); + multicallSlices.push([i, i + vaultPriceFeedConfigCallData.length]); + i += vaultPriceFeedConfigCallData.length; + + const vaultConfigCallData = Vault.getConfigMulticallInputs( + dexParams.vault, + tokens, + ); + multiCallData.push(...vaultConfigCallData); + multicallSlices.push([i, i + vaultConfigCallData.length]); + i += vaultConfigCallData.length; + + const configResults = ( + await multiContract.methods.aggregate(multiCallData).call({}, blockNumber) + ).returnData; + + const chainlink: { + [address: string]: { proxy: Address; aggregator: Address }; + } = {}; + for (let token of tokens) { + const aggregator = ChainLinkSubscriber.readAggregator( + configResults.slice(...multicallSlices.shift()!)[0], + ); + chainlink[token] = { + proxy: priceFeeds.shift(), + aggregator, + }; + } + + const fastPriceFeedConfigResults = configResults.slice( + ...multicallSlices.shift()!, + ); + const fastPriceFeedConfig = FastPriceFeed.getConfig( + fastPriceFeedConfigResults, + tokens, + ); + + const vaultPriceFeedConfigResults = configResults.slice( + ...multicallSlices.shift()!, + ); + const vaultPriceFeedConfig = VaultPriceFeed.getConfig( + vaultPriceFeedConfigResults, + tokens, + ); + + const vaultConfigResults = configResults.slice(...multicallSlices.shift()!); + const vaultConfig = Vault.getConfig(vaultConfigResults, tokens); + + return { + vaultAddress: dexParams.vault, + readerAddress: dexParams.reader, + priceFeed: dexParams.priceFeed, + fastPriceFeed: dexParams.fastPriceFeed, + fastPriceEvents: dexParams.fastPriceEvents, + usdqAddress: dexParams.usdq, + tokenAddresses: tokens, + vaultConfig, + vaultPriceFeedConfig, + fastPriceFeedConfig, + chainlink, + }; + } +} diff --git a/src/dex/QuickPerps/quickPerps-e2e.test.ts b/src/dex/QuickPerps/quickPerps-e2e.test.ts new file mode 100644 index 000000000..2f84ff765 --- /dev/null +++ b/src/dex/QuickPerps/quickPerps-e2e.test.ts @@ -0,0 +1,166 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { testE2E } from '../../../tests/utils-e2e'; +import { + Tokens, + Holders, + NativeTokenSymbols, +} from '../../../tests/constants-e2e'; +import { Network, ContractMethod, SwapSide } from '../../constants'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; + +describe('QuickPerps E2E', () => { + const dexKey = 'QuickPerps'; + + describe('QuickPerps AVALANCHE', () => { + const network = Network.AVALANCHE; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'WETHe'; + const tokenBSymbol: string = 'USDCe'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '1000000000000000000'; + const tokenBAmount: string = '2000000000'; + const nativeTokenAmount = '1000000000000000000'; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(nativeTokenSymbol + ' -> TOKEN', async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it('TOKEN -> ' + nativeTokenSymbol, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it('TOKEN -> TOKEN', async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); + + describe('QuickPerps ARBITRUM', () => { + const network = Network.ARBITRUM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'WETH'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '2000000000'; + const tokenBAmount: string = '1000000000000000000'; + const nativeTokenAmount = '1000000000000000000'; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(nativeTokenSymbol + ' -> TOKEN', async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it('TOKEN -> ' + nativeTokenSymbol, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it('TOKEN -> TOKEN', async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); +}); diff --git a/src/dex/QuickPerps/quickPerps-events.test.ts b/src/dex/QuickPerps/quickPerps-events.test.ts new file mode 100644 index 000000000..2964f35f6 --- /dev/null +++ b/src/dex/QuickPerps/quickPerps-events.test.ts @@ -0,0 +1,115 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { QuickPerpsEventPool } from './pool'; +import { QuickPerpsConfig } from './config'; +import { Network } from '../../constants'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { testEventSubscriber } from '../../../tests/utils-events'; +import { PoolState } from './types'; + +jest.setTimeout(50 * 1000); +const dexKey = 'QuickPerps'; +const network = Network.AVALANCHE; +const params = QuickPerpsConfig[dexKey][network]; + +async function fetchPoolState( + quickPerpsPool: QuickPerpsEventPool, + blockNumber: number, +): Promise { + return quickPerpsPool.generateState(blockNumber); +} + +// timestamp can't be compared exactly as the event released +// doesn't have the timestamp. It is safe to consider the +// timestamp as the blockTime as the max deviation is bounded +// on the contract +const stateWithoutTimestamp = (state: PoolState) => ({ + ...state, + secondaryPrices: { + prices: state.secondaryPrices.prices, + // timestamp (this is removed) + }, +}); + +function compareState(state: PoolState, expectedState: PoolState) { + expect(stateWithoutTimestamp(state)).toEqual( + stateWithoutTimestamp(expectedState), + ); +} + +describe('QuickPerps Event', function () { + const blockNumbers: { [eventName: string]: number[] } = { + IncreaseUsdqAmount: [ + 19403150, 19403175, 19403183, 19403215, 19403232, 19403246, 19403344, + 19403484, 19403545, 19403553, 19403586, 19403662, 19403712, 19403721, + 19403757, 19403775, 19403782, 19403800, 19403807, 19403808, 19403826, + 19403844, 19403848, 19403852, 19403860, 19403863, 19403875, 19403877, + 19403885, 19403900, 19403904, 19403938, 19403963, 19403970, 19403973, + 19403978, 19403999, 19404000, 19404023, 19404026, 19404046, 19404056, + 19404060, 19404078, 19404083, 19404097, 19404149, 19404164, 19404178, + 19404182, 19404229, 19404243, 19404264, 19404272, 19404287, 19404347, + 19404378, 19404379, 19404389, 19404408, 19404463, 19404491, 19404560, + 19404625, 19404657, 19404687, 19404700, 19404714, 19404763, 19404889, + 19404892, 19404893, 19404894, 19404897, 19404904, 19404916, 19404917, + 19404927, 19404935, 19404946, 19404949, 19404951, 19404959, 19404973, + 19405017, 19405027, 19405034, + ], + DecreaseUsdqAmount: [ + 19403150, 19403175, 19403183, 19403215, 19403232, 19403246, 19403344, + 19403545, 19403553, 19403662, 19403712, 19403721, 19403757, 19403775, + 19403782, 19403800, 19403807, 19403808, 19403826, 19403844, 19403848, + 19403852, 19403860, 19403863, 19403875, 19403877, 19403885, 19403900, + 19403904, 19403938, 19403963, 19403970, 19403973, 19403978, 19403999, + 19404000, 19404023, 19404026, 19404046, 19404056, 19404060, 19404078, + 19404083, 19404097, 19404149, 19404164, 19404178, 19404182, 19404229, + 19404243, 19404264, 19404272, 19404287, 19404347, 19404378, 19404379, + 19404389, 19404408, 19404463, 19404491, 19404560, 19404625, 19404657, + 19404687, 19404700, 19404714, 19404763, 19404889, 19404892, 19404893, + 19404894, 19404897, 19404904, 19404916, 19404917, 19404927, 19404935, + 19404946, 19404949, 19404951, 19404959, 19404973, 19405017, 19405027, + 19405034, + ], + Transfer: [19403484, 19403586, 19405046, 19405100, 19405154, 19405318], + PriceUpdate: [ + 19403134, 19403135, 19403140, 19403141, 19403144, 19403148, 19403151, + 19403154, 19403163, 19403169, 19403170, 19403171, 19403178, 19403185, + 19403186, 19403202, + ], + }; + + describe('QuickPerpsEventPool', function () { + Object.keys(blockNumbers).forEach((event: string) => { + blockNumbers[event].forEach((blockNumber: number) => { + it(`Should return the correct state after the ${blockNumber}:${event}`, async function () { + const dexHelper = new DummyDexHelper(network); + const logger = dexHelper.getLogger(dexKey); + + const config = await QuickPerpsEventPool.getConfig( + params, + blockNumber, + dexHelper.multiContract, + ); + const quickPerpsPool = new QuickPerpsEventPool( + dexKey, + network, + dexHelper, + logger, + config, + ); + + await testEventSubscriber( + quickPerpsPool, + quickPerpsPool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolState(quickPerpsPool, _blockNumber), + blockNumber, + `${dexKey}_${params.vault}`, + dexHelper.provider, + compareState, + ); + }); + }); + }); + }); +}); diff --git a/src/dex/QuickPerps/quickPerps-integration.test.ts b/src/dex/QuickPerps/quickPerps-integration.test.ts new file mode 100644 index 000000000..5c488326f --- /dev/null +++ b/src/dex/QuickPerps/quickPerps-integration.test.ts @@ -0,0 +1,117 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { Interface } from '@ethersproject/abi'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { Network, SwapSide } from '../../constants'; +import { BI_POWS } from '../../bigint-constants'; +import { QuickPerps } from './quickPerps'; +import { QuickPerpsConfig } from './config'; +import { + checkPoolPrices, + checkPoolsLiquidity, + checkConstantPoolPrices, +} from '../../../tests/utils'; +import { Tokens } from '../../../tests/constants-e2e'; +import ReaderABI from '../../abi/quickPerps/reader.json'; + +const network = Network.AVALANCHE; +const TokenASymbol = 'USDCe'; +const TokenA = Tokens[network][TokenASymbol]; + +const TokenBSymbol = 'WAVAX'; +const TokenB = Tokens[network][TokenBSymbol]; + +const amounts = [ + 0n, + 1000000000n, + 2000000000n, + 3000000000n, + 4000000000n, + 5000000000n, +]; + +const dexKey = 'QuickPerps'; +const params = QuickPerpsConfig[dexKey][network]; +const readerInterface = new Interface(ReaderABI); +const readerAddress = '0x67b789D48c926006F5132BFCe4e976F0A7A63d5D'; + +describe('QuickPerps', function () { + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + const dexHelper = new DummyDexHelper(network); + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const quickPerps = new QuickPerps(network, dexKey, dexHelper); + + await quickPerps.initializePricing(blocknumber); + + const pools = await quickPerps.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blocknumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await quickPerps.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + if (quickPerps.hasConstantPriceLargeAmounts) { + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + } else { + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + } + + // Do on chain pricing based on reader to compare + const readerCallData = amounts.map(a => ({ + target: readerAddress, + callData: readerInterface.encodeFunctionData('getAmountOut', [ + params.vault, + TokenA.address, + TokenB.address, + a.toString(), + ]), + })); + + const readerResult = ( + await dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blocknumber) + ).returnData; + const expectedPrices = readerResult.map((p: any) => + BigInt( + readerInterface.decodeFunctionResult('getAmountOut', p)[0].toString(), + ), + ); + + expect(poolPrices![0].prices).toEqual(expectedPrices); + }); + + it('getTopPoolsForToken', async function () { + const dexHelper = new DummyDexHelper(network); + const quickPerps = new QuickPerps(network, dexKey, dexHelper); + + await quickPerps.updatePoolState(); + const poolLiquidity = await quickPerps.getTopPoolsForToken( + TokenA.address, + 10, + ); + console.log( + `${TokenASymbol} Top Pools:`, + JSON.stringify(poolLiquidity, null, 2), + ); + + if (!quickPerps.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); + } + }); +}); diff --git a/src/dex/QuickPerps/quickPerps.ts b/src/dex/QuickPerps/quickPerps.ts new file mode 100644 index 000000000..f31ba1523 --- /dev/null +++ b/src/dex/QuickPerps/quickPerps.ts @@ -0,0 +1,296 @@ +import { Interface } from '@ethersproject/abi'; +import _ from 'lodash'; +import { + Token, + Address, + ExchangePrices, + PoolPrices, + AdapterExchangeParam, + SimpleExchangeParam, + PoolLiquidity, + Logger, +} from '../../types'; +import { SwapSide, Network } from '../../constants'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { getDexKeysWithNetwork, getBigIntPow } from '../../utils'; +import { IDex } from '../idex'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { QuickPerpsData, DexParams } from './types'; +import { QuickPerpsEventPool } from './pool'; +import { SimpleExchange } from '../simple-exchange'; +import { QuickPerpsConfig, Adapters } from './config'; +import { Vault } from './vault'; +import ERC20ABI from '../../abi/erc20.json'; + +const QuickPerpsGasCost = 300 * 1000; + +export class QuickPerps extends SimpleExchange implements IDex { + protected pool: QuickPerpsEventPool | null = null; + protected supportedTokensMap: { [address: string]: boolean } = {}; + // supportedTokens is only used by the pooltracker + protected supportedTokens: Token[] = []; + + readonly hasConstantPriceLargeAmounts = false; + readonly needWrapNative = true; + readonly isFeeOnTransferSupported = false; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(QuickPerpsConfig); + + public static erc20Interface = new Interface(ERC20ABI); + + vaultUSDBalance: number = 0; + + logger: Logger; + + constructor( + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + protected adapters = Adapters[network], + protected params: DexParams = QuickPerpsConfig[dexKey][network], + ) { + super(dexHelper, dexKey); + this.logger = dexHelper.getLogger(dexKey); + } + + // Initialize pricing is called once in the start of + // pricing service. It is intended to setup the integration + // for pricing requests. + async initializePricing(blockNumber: number) { + const config = await QuickPerpsEventPool.getConfig( + this.params, + blockNumber, + this.dexHelper.multiContract, + ); + config.tokenAddresses.forEach( + (token: Address) => (this.supportedTokensMap[token] = true), + ); + this.pool = new QuickPerpsEventPool( + this.dexKey, + this.network, + this.dexHelper, + this.logger, + config, + ); + await this.pool.initialize(blockNumber); + } + + // Returns the list of contract adapters (name and index) + // for a buy/sell. Return null if there are no adapters. + getAdapters(side: SwapSide): { name: string; index: number }[] | null { + return this.adapters[side]; + } + + // Returns list of pool identifiers that can be used + // for a given swap. poolIdentifiers must be unique + // across DEXes. + async getPoolIdentifiers( + srcToken: Token, + destToken: Token, + side: SwapSide, + blockNumber: number, + ): Promise { + if (side === SwapSide.BUY || !this.pool) return []; + const srcAddress = this.dexHelper.config + .wrapETH(srcToken) + .address.toLowerCase(); + const destAddress = this.dexHelper.config + .wrapETH(destToken) + .address.toLowerCase(); + if ( + srcAddress !== destAddress && + this.supportedTokensMap[srcAddress] && + this.supportedTokensMap[destAddress] + ) { + return [`${this.dexKey}_${srcAddress}`, `${this.dexKey}_${destAddress}`]; + } + return []; + } + + // Returns pool prices for amounts. + // If limitPools is defined only pools in limitPools + // should be used. If limitPools is undefined then + // any pools can be used. + async getPricesVolume( + srcToken: Token, + destToken: Token, + amounts: bigint[], + side: SwapSide, + blockNumber: number, + limitPools?: string[], + ): Promise> { + if (side === SwapSide.BUY || !this.pool) return null; + const srcAddress = this.dexHelper.config + .wrapETH(srcToken) + .address.toLowerCase(); + const destAddress = this.dexHelper.config + .wrapETH(destToken) + .address.toLowerCase(); + if ( + srcAddress === destAddress || + !( + this.supportedTokensMap[srcAddress] && + this.supportedTokensMap[destAddress] + ) + ) + return null; + const srcPoolIdentifier = `${this.dexKey}_${srcAddress}`; + const destPoolIdentifier = `${this.dexKey}_${destAddress}`; + const pools = [srcPoolIdentifier, destPoolIdentifier]; + if (limitPools && pools.some(p => !limitPools.includes(p))) return null; + + const unitVolume = getBigIntPow(srcToken.decimals); + const prices = await this.pool.getAmountOut( + srcAddress, + destAddress, + [unitVolume, ...amounts], + blockNumber, + ); + + if (!prices) return null; + + return [ + { + prices: prices.slice(1), + unit: prices[0], + gasCost: QuickPerpsGasCost, + exchange: this.dexKey, + data: {}, + poolAddresses: [this.params.vault], + }, + ]; + } + + // Returns estimated gas cost of calldata for this DEX in multiSwap + getCalldataGasCost( + poolPrices: PoolPrices, + ): number | number[] { + return CALLDATA_GAS_COST.DEX_NO_PAYLOAD; + } + + getAdapterParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: QuickPerpsData, + side: SwapSide, + ): AdapterExchangeParam { + return { + targetExchange: this.params.vault, + payload: '0x', + networkFee: '0', + }; + } + + getSimpleParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: QuickPerpsData, + side: SwapSide, + ): SimpleExchangeParam { + return { + callees: [srcToken, this.params.vault], + calldata: [ + QuickPerps.erc20Interface.encodeFunctionData('transfer', [ + this.params.vault, + srcAmount, + ]), + Vault.interface.encodeFunctionData('swap', [ + srcToken, + destToken, + this.augustusAddress, + ]), + ], + values: ['0', '0'], + networkFee: '0', + }; + } + + async updatePoolState(): Promise { + if (!this.supportedTokens.length) { + const tokenAddresses = await QuickPerpsEventPool.getWhitelistedTokens( + this.params.vault, + 'latest', + this.dexHelper.multiContract, + ); + + const decimalsCallData = + QuickPerps.erc20Interface.encodeFunctionData('decimals'); + const tokenBalanceMultiCall = tokenAddresses.map(t => ({ + target: t, + callData: decimalsCallData, + })); + const res = ( + await this.dexHelper.multiContract.methods + .aggregate(tokenBalanceMultiCall) + .call() + ).returnData; + + const tokenDecimals = res.map((r: any) => + parseInt( + QuickPerps.erc20Interface + .decodeFunctionResult('decimals', r)[0] + .toString(), + ), + ); + + this.supportedTokens = tokenAddresses.map((t, i) => ({ + address: t, + decimals: tokenDecimals[i], + })); + } + + const erc20BalanceCalldata = QuickPerps.erc20Interface.encodeFunctionData( + 'balanceOf', + [this.params.vault], + ); + const tokenBalanceMultiCall = this.supportedTokens.map(t => ({ + target: t.address, + callData: erc20BalanceCalldata, + })); + const res = ( + await this.dexHelper.multiContract.methods + .aggregate(tokenBalanceMultiCall) + .call() + ).returnData; + const tokenBalances = res.map((r: any) => + BigInt( + QuickPerps.erc20Interface + .decodeFunctionResult('balanceOf', r)[0] + .toString(), + ), + ); + const tokenBalancesUSD = await Promise.all( + this.supportedTokens.map((t, i) => + this.dexHelper.getTokenUSDPrice(t, tokenBalances[i]), + ), + ); + this.vaultUSDBalance = tokenBalancesUSD.reduce( + (sum: number, curr: number) => sum + curr, + ); + } + + // Returns list of top pools based on liquidity. Max + // limit number pools should be returned. + async getTopPoolsForToken( + _tokenAddress: Address, + limit: number, + ): Promise { + const tokenAddress = _tokenAddress.toLowerCase(); + if (!this.supportedTokens.some(t => t.address === tokenAddress)) return []; + return [ + { + exchange: this.dexKey, + address: this.params.vault, + connectorTokens: this.supportedTokens.filter( + t => t.address !== tokenAddress, + ), + liquidityUSD: this.vaultUSDBalance, + }, + ]; + } +} diff --git a/src/dex/QuickPerps/types.ts b/src/dex/QuickPerps/types.ts new file mode 100644 index 000000000..284933bb4 --- /dev/null +++ b/src/dex/QuickPerps/types.ts @@ -0,0 +1,94 @@ +import { Address } from '../../types'; +import { ChainLinkState } from '../../lib/chainlink'; + +export type PoolState = { + primaryPrices: { [poolAddress: string]: ChainLinkState }; + secondaryPrices: FastPriceFeedState; + vault: VaultState; + usdq: USDQState; +}; + +export type FastPriceFeedState = { + lastUpdatedAt: number; + prices: { [tokenAddress: string]: bigint }; +}; + +export type VaultState = { + usdqAmounts: { [tokenAddress: string]: bigint }; +}; + +export type USDQState = { + totalSupply: bigint; +}; + +export type QuickPerpsData = { + // TODO: QuickPerpsData is the dex data that is + // returned by the API that can be used for + // tx building. The data structure should be minimal. + // Complete me! +}; + +export type DexParams = { + vault: Address; + reader: Address; + priceFeed: Address; + fastPriceFeed: Address; + fastPriceEvents: Address; + // Last three param can be fetched on chain by calling + // vaultAddress.priceFeed() => priceFeed + // priceFeed.secondaryPriceFeed() => fastPriceFeed + // fastPriceFeed.fastPriceEvents() => fastPriceEvents + // It is added as constants to avoid unnecessary + // sequential onchain calls + usdq: Address; +}; + +export type FastPriceFeedConfig = { + priceDuration: number; + maxDeviationBasisPoints: bigint; + favorFastPrice: Record; + spreadBasisPointsIfInactive: bigint; + spreadBasisPointsIfChainError: bigint; + maxPriceUpdateDelay: number; +}; + +export type VaultPriceFeedConfig = { + isAmmEnabled: boolean; + isSecondaryPriceEnabled: boolean; + strictStableTokens: { [address: string]: boolean }; + spreadBasisPoints: { [address: string]: bigint }; + adjustmentBasisPoints: { [address: string]: bigint }; + isAdjustmentAdditive: { [address: string]: boolean }; + priceDecimals: { [address: string]: number }; + maxStrictPriceDeviation: bigint; + useV2Pricing: boolean; + priceSampleSpace: number; +}; + +export type VaultConfig = { + tokenDecimals: { [address: string]: number }; + stableTokens: { [address: string]: boolean }; + tokenWeights: { [address: string]: bigint }; + stableSwapFeeBasisPoints: bigint; + swapFeeBasisPoints: bigint; + stableTaxBasisPoints: bigint; + taxBasisPoints: bigint; + hasDynamicFees: bigint; + includeAmmPrice: boolean; + useSwapPricing: boolean; + totalTokenWeights: bigint; +}; + +export type PoolConfig = { + vaultAddress: Address; + readerAddress: Address; + priceFeed: Address; + fastPriceFeed: Address; + fastPriceEvents: Address; + usdqAddress: Address; + tokenAddresses: Address[]; + vaultConfig: VaultConfig; + vaultPriceFeedConfig: VaultPriceFeedConfig; + fastPriceFeedConfig: FastPriceFeedConfig; + chainlink: { [address: string]: { proxy: Address; aggregator: Address } }; +}; diff --git a/src/dex/QuickPerps/usdq.ts b/src/dex/QuickPerps/usdq.ts new file mode 100644 index 000000000..da09397ff --- /dev/null +++ b/src/dex/QuickPerps/usdq.ts @@ -0,0 +1,83 @@ +import _ from 'lodash'; +import { Interface } from '@ethersproject/abi'; +import { DeepReadonly } from 'ts-essentials'; +import { PartialEventSubscriber } from '../../composed-event-subscriber'; +import { + Address, + MultiCallInput, + MultiCallOutput, + Logger, + Log, + BlockHeader, +} from '../../types'; +import { USDQState } from './types'; +import ERC20ABI from '../../abi/erc20.json'; +import { Lens } from '../../lens'; +import { NULL_ADDRESS } from '../../constants'; + +export class USDQ extends PartialEventSubscriber { + static readonly interface = new Interface(ERC20ABI); + + constructor( + private usdqAddress: Address, + lens: Lens, DeepReadonly>, + logger: Logger, + ) { + super([usdqAddress], lens, logger); + } + + getTotalSupply(state: DeepReadonly) { + return this.lens.get()(state).totalSupply; + } + + public processLog( + state: DeepReadonly, + log: Readonly, + blockHeader: Readonly, + ): DeepReadonly | null { + try { + const parsed = USDQ.interface.parseLog(log); + const _state: USDQState = _.cloneDeep(state); + switch (parsed.name) { + case 'Transfer': { + const fromAddress = parsed.args.src; + const toAddress = parsed.args.dst; + if (fromAddress === NULL_ADDRESS) { + _state.totalSupply += BigInt(parsed.args.wad.toString()); + } else if (toAddress === NULL_ADDRESS) { + _state.totalSupply -= BigInt(parsed.args.wad.toString()); + } + return _state; + } + default: + return null; + } + } catch (e) { + this.logger.error('Failed to parse log', e); + return null; + } + } + + public getGenerateStateMultiCallInputs(): MultiCallInput[] { + return [ + { + target: this.usdqAddress, + callData: USDQ.interface.encodeFunctionData('totalSupply'), + }, + ]; + } + + public generateState( + multicallOutputs: MultiCallOutput[], + blockNumber?: number | 'latest', + ): DeepReadonly { + return { + totalSupply: BigInt( + USDQ.interface.decodeFunctionResult( + 'totalSupply', + multicallOutputs[0], + )[0], + ), + }; + } +} diff --git a/src/dex/QuickPerps/vault-price-feed.ts b/src/dex/QuickPerps/vault-price-feed.ts new file mode 100644 index 000000000..5071cb135 --- /dev/null +++ b/src/dex/QuickPerps/vault-price-feed.ts @@ -0,0 +1,384 @@ +import { Interface } from '@ethersproject/abi'; +import { Address, MultiCallInput, MultiCallOutput } from '../../types'; +import { PoolState, VaultPriceFeedConfig } from './types'; +import { FastPriceFeed } from './fast-price-feed'; +import VaultPriceFeedAbi from '../../abi/quickPerps/vault-price-feed.json'; +import { ChainLinkSubscriber } from '../../lib/chainlink'; +import { DeepReadonly } from 'ts-essentials'; + +export class VaultPriceFeed { + BASIS_POINTS_DIVISOR = 10000n; + PRICE_PRECISION = 10n ** 30n; + ONE_USD = this.PRICE_PRECISION; + + static interface = new Interface(VaultPriceFeedAbi); + + protected isAmmEnabled: boolean; + protected isSecondaryPriceEnabled: boolean; + protected strictStableTokens: { [address: string]: boolean }; + protected spreadBasisPoints: { [address: string]: bigint }; + protected adjustmentBasisPoints: { [address: string]: bigint }; + protected isAdjustmentAdditive: { [address: string]: boolean }; + protected priceDecimals: { [address: string]: number }; + protected maxStrictPriceDeviation: bigint; + protected useV2Pricing: boolean; + protected priceSampleSpace: number; + + constructor( + config: VaultPriceFeedConfig, + protected primaryPrices: { [token: string]: ChainLinkSubscriber }, + protected secondaryPrice: FastPriceFeed, + ) { + this.isAmmEnabled = config.isAmmEnabled; + this.isSecondaryPriceEnabled = config.isSecondaryPriceEnabled; + this.strictStableTokens = config.strictStableTokens; + this.spreadBasisPoints = config.spreadBasisPoints; + this.adjustmentBasisPoints = config.adjustmentBasisPoints; + this.isAdjustmentAdditive = config.isAdjustmentAdditive; + this.priceDecimals = config.priceDecimals; + this.maxStrictPriceDeviation = config.maxStrictPriceDeviation; + this.useV2Pricing = config.useV2Pricing; + this.priceSampleSpace = config.priceSampleSpace; + } + + getPrice( + state: DeepReadonly, + _token: Address, + _maximise: boolean, + _includeAmmPrice: boolean, + _useSwapPricing: boolean, + ): bigint { + let price = this.useV2Pricing + ? this.getPriceV2(state, _token, _maximise, _includeAmmPrice) + : this.getPriceV1(state, _token, _maximise, _includeAmmPrice); + + const adjustmentBps = this.adjustmentBasisPoints[_token]; + if (adjustmentBps > 0n) { + const isAdditive = this.isAdjustmentAdditive[_token]; + if (isAdditive) { + price = + (price * (this.BASIS_POINTS_DIVISOR + adjustmentBps)) / + this.BASIS_POINTS_DIVISOR; + } else { + price = + (price * (this.BASIS_POINTS_DIVISOR - adjustmentBps)) / + this.BASIS_POINTS_DIVISOR; + } + } + + return price; + } + + getPriceV2( + state: DeepReadonly, + _token: Address, + _maximise: boolean, + _includeAmmPrice: boolean, + ): bigint { + throw new Error( + 'getPriceV2 implementation is not complete, devs should disable the dex or complete the implementation', + ); + } + + getPriceV1( + state: DeepReadonly, + _token: Address, + _maximise: boolean, + _includeAmmPrice: boolean, + ): bigint { + let price = this.getPrimaryPrice(state, _token, _maximise); + + if (_includeAmmPrice && this.isAmmEnabled) { + const ammPrice = this.getAmmPrice(state, _token); + if (ammPrice > 0n) { + if (_maximise && ammPrice > price) { + price = ammPrice; + } + if (!_maximise && ammPrice < price) { + price = ammPrice; + } + } + } + + if (this.isSecondaryPriceEnabled) { + price = this.getSecondaryPrice(state, _token, price, _maximise); + } + + if (this.strictStableTokens[_token]) { + const delta = + price > this.ONE_USD ? price - this.ONE_USD : this.ONE_USD - price; + if (delta <= this.maxStrictPriceDeviation) { + return this.ONE_USD; + } + + // if _maximise and price is e.g. 1.02, return 1.02 + if (_maximise && price > this.ONE_USD) { + return price; + } + + // if !_maximise and price is e.g. 0.98, return 0.98 + if (!_maximise && price < this.ONE_USD) { + return price; + } + + return this.ONE_USD; + } + + const _spreadBasisPoints = this.spreadBasisPoints[_token]; + + if (_maximise) { + return ( + (price * (this.BASIS_POINTS_DIVISOR + _spreadBasisPoints)) / + this.BASIS_POINTS_DIVISOR + ); + } + + return ( + (price * (this.BASIS_POINTS_DIVISOR - _spreadBasisPoints)) / + this.BASIS_POINTS_DIVISOR + ); + } + + getAmmPrice(state: DeepReadonly, token: Address): bigint { + throw new Error( + 'getAmmPrice implementation is not complete, devs should disable the dex or complete the implementation', + ); + } + + getPrimaryPrice( + state: DeepReadonly, + _token: Address, + _maximise: boolean, + ): bigint { + // const priceFeedAddress = this.priceFeeds[_token]; + // require(priceFeedAddress != address(0), "VaultPriceFeed: invalid price feed"); + + // if (chainlinkFlags != address(0)) { + // bool isRaised = IChainlinkFlags(chainlinkFlags).getFlag(FLAG_ARBITRUM_SEQ_OFFLINE); + // if (isRaised) { + // // If flag is raised we shouldn't perform any critical operations + // revert("Chainlink feeds are not being updated"); + // } + // } + + // IPriceFeed priceFeed = IPriceFeed(priceFeedAddress); + let price = 0n; + // const roundId = priceFeed.latestRound; + + // for (let i = 0; i < this.priceSampleSpace; i++) { + // if (roundId <= i) { + // break; + // } + + // if (i == 0) { + // const _p = priceFeed.latestAnswer(); + // require(_p > 0, "VaultPriceFeed: invalid price"); + // p = uint256(_p); + // } else { + // (, int256 _p, , ,) = priceFeed.getRoundData(roundId - i); + // require(_p > 0, "VaultPriceFeed: invalid price"); + // p = uint256(_p); + // } + + // if (price == 0n) { + // price = p; + // continue; + // } + + // if (_maximise && p > price) { + // price = p; + // continue; + // } + + // if (!_maximise && p < price) { + // price = p; + // } + // } + if (this.priceSampleSpace > 1) { + throw new Error( + 'Chainlink price feed is not implemented for historical prices', + ); + } + price = this.primaryPrices[_token].getLatestRoundData(state); + + // require(price > 0n, "VaultPriceFeed: could not fetch price"); + if (price <= 0n) throw new Error('VaultPriceFeed: could not fetch price'); + // normalise price precision + const _priceDecimals = this.priceDecimals[_token]; + return (price * this.PRICE_PRECISION) / BigInt(10 ** _priceDecimals); + } + + getSecondaryPrice( + state: DeepReadonly, + _token: Address, + _referencePrice: bigint, + _maximise: boolean, + ): bigint { + return this.secondaryPrice.getPrice( + state, + _token, + _referencePrice, + _maximise, + ); + } + + static getConfigMulticallInputs( + vaultPriceFeedAddress: Address, + tokenAddresses: Address[], + ): MultiCallInput[] { + return [ + { + target: vaultPriceFeedAddress, + callData: VaultPriceFeed.interface.encodeFunctionData('isAmmEnabled'), + }, + { + target: vaultPriceFeedAddress, + callData: VaultPriceFeed.interface.encodeFunctionData( + 'isSecondaryPriceEnabled', + ), + }, + ...tokenAddresses.map(t => ({ + target: vaultPriceFeedAddress, + callData: VaultPriceFeed.interface.encodeFunctionData( + 'strictStableTokens', + [t], + ), + })), + ...tokenAddresses.map(t => ({ + target: vaultPriceFeedAddress, + callData: VaultPriceFeed.interface.encodeFunctionData( + 'spreadBasisPoints', + [t], + ), + })), + ...tokenAddresses.map(t => ({ + target: vaultPriceFeedAddress, + callData: VaultPriceFeed.interface.encodeFunctionData( + 'isAdjustmentAdditive', + [t], + ), + })), + ...tokenAddresses.map(t => ({ + target: vaultPriceFeedAddress, + callData: VaultPriceFeed.interface.encodeFunctionData( + 'adjustmentBasisPoints', + [t], + ), + })), + ...tokenAddresses.map(t => ({ + target: vaultPriceFeedAddress, + callData: VaultPriceFeed.interface.encodeFunctionData('priceDecimals', [ + t, + ]), + })), + { + target: vaultPriceFeedAddress, + callData: VaultPriceFeed.interface.encodeFunctionData( + 'maxStrictPriceDeviation', + ), + }, + { + target: vaultPriceFeedAddress, + callData: VaultPriceFeed.interface.encodeFunctionData('useV2Pricing'), + }, + { + target: vaultPriceFeedAddress, + callData: + VaultPriceFeed.interface.encodeFunctionData('priceSampleSpace'), + }, + ]; + } + + static getConfig( + multicallOutputs: MultiCallOutput[], + tokenAddress: Address[], + ): VaultPriceFeedConfig { + let i = 0; + return { + isAmmEnabled: VaultPriceFeed.interface.decodeFunctionResult( + 'isAmmEnabled', + multicallOutputs[i++], + )[0], + isSecondaryPriceEnabled: VaultPriceFeed.interface.decodeFunctionResult( + 'isSecondaryPriceEnabled', + multicallOutputs[i++], + )[0], + strictStableTokens: tokenAddress.reduce( + (acc: { [address: string]: boolean }, t: Address) => { + acc[t] = VaultPriceFeed.interface.decodeFunctionResult( + 'strictStableTokens', + multicallOutputs[i++], + )[0]; + return acc; + }, + {}, + ), + spreadBasisPoints: tokenAddress.reduce( + (acc: { [address: string]: bigint }, t: Address) => { + acc[t] = BigInt( + VaultPriceFeed.interface + .decodeFunctionResult( + 'spreadBasisPoints', + multicallOutputs[i++], + )[0] + .toString(), + ); + return acc; + }, + {}, + ), + isAdjustmentAdditive: tokenAddress.reduce( + (acc: { [address: string]: boolean }, t: Address) => { + acc[t] = VaultPriceFeed.interface.decodeFunctionResult( + 'isAdjustmentAdditive', + multicallOutputs[i++], + )[0]; + return acc; + }, + {}, + ), + adjustmentBasisPoints: tokenAddress.reduce( + (acc: { [address: string]: bigint }, t: Address) => { + acc[t] = BigInt( + VaultPriceFeed.interface + .decodeFunctionResult( + 'adjustmentBasisPoints', + multicallOutputs[i++], + )[0] + .toString(), + ); + return acc; + }, + {}, + ), + priceDecimals: tokenAddress.reduce( + (acc: { [address: string]: number }, t: Address) => { + acc[t] = parseInt( + VaultPriceFeed.interface + .decodeFunctionResult('priceDecimals', multicallOutputs[i++])[0] + .toString(), + ); + return acc; + }, + {}, + ), + maxStrictPriceDeviation: BigInt( + VaultPriceFeed.interface + .decodeFunctionResult( + 'maxStrictPriceDeviation', + multicallOutputs[i++], + )[0] + .toString(), + ), + useV2Pricing: VaultPriceFeed.interface.decodeFunctionResult( + 'useV2Pricing', + multicallOutputs[i++], + )[0], + priceSampleSpace: parseInt( + VaultPriceFeed.interface + .decodeFunctionResult('priceSampleSpace', multicallOutputs[i++])[0] + .toString(), + ), + }; + } +} diff --git a/src/dex/QuickPerps/vault-utils.ts b/src/dex/QuickPerps/vault-utils.ts new file mode 100644 index 000000000..1ff64466e --- /dev/null +++ b/src/dex/QuickPerps/vault-utils.ts @@ -0,0 +1,53 @@ +import { Vault } from './vault'; +import { Address } from '../../types'; +import { DeepReadonly } from 'ts-essentials'; + +export class VaultUtils { + constructor(protected vault: Vault) {} + + getFeeBasisPoints( + state: DeepReadonly, + _token: Address, + _usdqDelta: bigint, + _feeBasisPoints: bigint, + _taxBasisPoints: bigint, + _increment: boolean, + ) { + if (!this.vault.hasDynamicFees) { + return _feeBasisPoints; + } + + const initialAmount = this.vault.getUSDQAmount(state, _token); + let nextAmount = initialAmount + _usdqDelta; + if (!_increment) { + nextAmount = _usdqDelta > initialAmount ? 0n : initialAmount - _usdqDelta; + } + + const targetAmount = this.vault.getTargetUsdqAmount(state, _token); + if (targetAmount == 0n) { + return _feeBasisPoints; + } + + const initialDiff = + initialAmount > targetAmount + ? initialAmount - targetAmount + : targetAmount - initialAmount; + const nextDiff = + nextAmount > targetAmount + ? nextAmount - targetAmount + : targetAmount - nextAmount; + + // action improves relative asset balance + if (nextDiff < initialDiff) { + const rebateBps = (_taxBasisPoints * initialDiff) / targetAmount; + return rebateBps > _feeBasisPoints ? 0n : _feeBasisPoints - rebateBps; + } + + let averageDiff = (initialDiff + nextDiff) / 2n; + if (averageDiff > targetAmount) { + averageDiff = targetAmount; + } + const taxBps = (_taxBasisPoints * averageDiff) / targetAmount; + return _feeBasisPoints + taxBps; + } +} diff --git a/src/dex/QuickPerps/vault.ts b/src/dex/QuickPerps/vault.ts new file mode 100644 index 000000000..725d3f27f --- /dev/null +++ b/src/dex/QuickPerps/vault.ts @@ -0,0 +1,290 @@ +import _ from 'lodash'; +import { Interface } from '@ethersproject/abi'; +import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; +import { PartialEventSubscriber } from '../../composed-event-subscriber'; +import { Lens } from '../../lens'; +import VaultABI from '../../abi/quickPerps/vault.json'; +import { VaultUtils } from './vault-utils'; +import { + VaultConfig, + VaultState, + FastPriceFeedConfig, + PoolState, +} from './types'; +import { VaultPriceFeed } from './vault-price-feed'; +import { USDQ } from './usdq'; +import { + MultiCallInput, + MultiCallOutput, + Address, + Logger, + Log, +} from '../../types'; +import { BlockHeader } from 'web3-eth'; + +export class Vault extends PartialEventSubscriber { + static readonly interface: Interface = new Interface(VaultABI); + + protected vaultUtils: VaultUtils; + + public tokenDecimals: { [address: string]: number }; + public stableTokens: { [address: string]: boolean }; + protected tokenWeights: { [address: string]: bigint }; + public stableSwapFeeBasisPoints: bigint; + public swapFeeBasisPoints: bigint; + public stableTaxBasisPoints: bigint; + public taxBasisPoints: bigint; + public hasDynamicFees: bigint; + protected includeAmmPrice: boolean; + protected useSwapPricing: boolean; + protected totalTokenWeights: bigint; + + constructor( + public readonly vaultAddress: Address, + protected tokenAddresses: Address[], + config: VaultConfig, + protected vaultPriceFeed: VaultPriceFeed, + protected usdq: USDQ, + lens: Lens, DeepReadonly>, + logger: Logger, + ) { + super([vaultAddress], lens, logger); + this.vaultUtils = new VaultUtils(this); + this.tokenDecimals = config.tokenDecimals; + this.stableTokens = config.stableTokens; + this.tokenWeights = config.tokenWeights; + this.stableSwapFeeBasisPoints = config.stableSwapFeeBasisPoints; + this.swapFeeBasisPoints = config.swapFeeBasisPoints; + this.stableTaxBasisPoints = config.stableTaxBasisPoints; + this.taxBasisPoints = config.taxBasisPoints; + this.hasDynamicFees = config.hasDynamicFees; + this.includeAmmPrice = config.includeAmmPrice; + this.useSwapPricing = config.useSwapPricing; + this.totalTokenWeights = config.totalTokenWeights; + } + + getMinPrice(state: DeepReadonly, _token: Address): bigint { + return this.vaultPriceFeed.getPrice( + state, + _token, + false, + this.includeAmmPrice, + this.useSwapPricing, + ); + } + + getMaxPrice(state: DeepReadonly, _token: Address): bigint { + return this.vaultPriceFeed.getPrice( + state, + _token, + true, + this.includeAmmPrice, + this.useSwapPricing, + ); + } + + getFeeBasisPoints( + state: DeepReadonly, + _token: Address, + _usdqDelta: bigint, + _feeBasisPoints: bigint, + _taxBasisPoints: bigint, + _increment: boolean, + ): bigint { + return this.vaultUtils.getFeeBasisPoints( + state, + _token, + _usdqDelta, + _feeBasisPoints, + _taxBasisPoints, + _increment, + ); + } + + getTargetUsdqAmount(state: DeepReadonly, _token: Address): bigint { + const supply = this.usdq.getTotalSupply(state); + if (supply == 0n) { + return 0n; + } + const weight = this.tokenWeights[_token]; + return (weight * supply) / this.totalTokenWeights; + } + + static getConfigMulticallInputs( + vaultAddress: Address, + tokenAddresses: Address[], + ): MultiCallInput[] { + return [ + ...tokenAddresses.map(t => ({ + target: vaultAddress, + callData: Vault.interface.encodeFunctionData('tokenDecimals', [t]), + })), + ...tokenAddresses.map(t => ({ + target: vaultAddress, + callData: Vault.interface.encodeFunctionData('stableTokens', [t]), + })), + ...tokenAddresses.map(t => ({ + target: vaultAddress, + callData: Vault.interface.encodeFunctionData('tokenWeights', [t]), + })), + ...[ + 'stableSwapFeeBasisPoints', + 'swapFeeBasisPoints', + 'stableTaxBasisPoints', + 'taxBasisPoints', + 'hasDynamicFees', + 'includeAmmPrice', + 'useSwapPricing', + 'totalTokenWeights', + ].map(fn => ({ + target: vaultAddress, + callData: Vault.interface.encodeFunctionData(fn), + })), + ]; + } + + static getConfig( + multicallOutputs: MultiCallOutput[], + tokenAddresses: Address[], + ): VaultConfig { + let i = 0; + return { + tokenDecimals: tokenAddresses.reduce( + (acc: { [address: string]: number }, t: Address) => { + acc[t] = parseInt( + Vault.interface + .decodeFunctionResult('tokenDecimals', multicallOutputs[i++])[0] + .toString(), + ); + return acc; + }, + {}, + ), + stableTokens: tokenAddresses.reduce( + (acc: { [address: string]: boolean }, t: Address) => { + acc[t] = Vault.interface.decodeFunctionResult( + 'stableTokens', + multicallOutputs[i++], + )[0]; + return acc; + }, + {}, + ), + tokenWeights: tokenAddresses.reduce( + (acc: { [address: string]: bigint }, t: Address) => { + acc[t] = BigInt( + Vault.interface + .decodeFunctionResult('tokenWeights', multicallOutputs[i++])[0] + .toString(), + ); + return acc; + }, + {}, + ), + stableSwapFeeBasisPoints: BigInt( + Vault.interface + .decodeFunctionResult( + 'stableSwapFeeBasisPoints', + multicallOutputs[i++], + )[0] + .toString(), + ), + swapFeeBasisPoints: BigInt( + Vault.interface + .decodeFunctionResult('swapFeeBasisPoints', multicallOutputs[i++])[0] + .toString(), + ), + stableTaxBasisPoints: BigInt( + Vault.interface + .decodeFunctionResult( + 'stableTaxBasisPoints', + multicallOutputs[i++], + )[0] + .toString(), + ), + taxBasisPoints: BigInt( + Vault.interface + .decodeFunctionResult('taxBasisPoints', multicallOutputs[i++])[0] + .toString(), + ), + hasDynamicFees: Vault.interface.decodeFunctionResult( + 'hasDynamicFees', + multicallOutputs[i++], + )[0], + includeAmmPrice: Vault.interface.decodeFunctionResult( + 'includeAmmPrice', + multicallOutputs[i++], + )[0], + useSwapPricing: Vault.interface.decodeFunctionResult( + 'useSwapPricing', + multicallOutputs[i++], + )[0], + totalTokenWeights: BigInt( + Vault.interface + .decodeFunctionResult('totalTokenWeights', multicallOutputs[i++])[0] + .toString(), + ), + }; + } + + public getGenerateStateMultiCallInputs(): MultiCallInput[] { + return this.tokenAddresses.map((t: Address) => ({ + target: this.vaultAddress, + callData: Vault.interface.encodeFunctionData('usdqAmounts', [t]), + })); + } + + public generateState( + multicallOutputs: MultiCallOutput[], + blockNumber?: number | 'latest', + ): DeepReadonly { + let vaultState: VaultState = { + usdqAmounts: {}, + }; + this.tokenAddresses.forEach( + (t: Address, i: number) => + (vaultState.usdqAmounts[t] = BigInt( + Vault.interface + .decodeFunctionResult('usdqAmounts', multicallOutputs[i])[0] + .toString(), + )), + ); + return vaultState; + } + + public getUSDQAmount(state: DeepReadonly, token: Address): bigint { + return this.lens.get()(state).usdqAmounts[token]; + } + + public processLog( + state: DeepReadonly, + log: Readonly, + blockHeader: Readonly, + ): AsyncOrSync { + try { + const parsed = Vault.interface.parseLog(log); + const _state: VaultState = _.cloneDeep(state); + switch (parsed.name) { + case 'IncreaseUsdqAmount': { + const tokenAddress = parsed.args.token.toLowerCase(); + const amount = BigInt(parsed.args.amount.toString()); + if (tokenAddress in state.usdqAmounts) + _state.usdqAmounts[tokenAddress] += amount; + return _state; + } + case 'DecreaseUsdqAmount': { + const tokenAddress = parsed.args.token.toLowerCase(); + const amount = BigInt(parsed.args.amount.toString()); + if (tokenAddress in state.usdqAmounts) + _state.usdqAmounts[tokenAddress] -= amount; + return _state; + } + default: + return null; + } + } catch (e) { + this.logger.error('Failed to parse log', e); + return null; + } + } +} diff --git a/src/dex/gmx/config.ts b/src/dex/gmx/config.ts index 83f115d6c..5ae6f1a9d 100644 --- a/src/dex/gmx/config.ts +++ b/src/dex/gmx/config.ts @@ -21,16 +21,6 @@ export const GMXConfig: DexConfigMap = { usdg: '0x45096e7aA921f27590f8F19e457794EB09678141', }, }, - QuickPerps: { - [Network.ZKEVM]: { - vault: '0x99B31498B0a1Dae01fc3433e3Cb60F095340935C', - reader: '0xf1CFB75854DE535475B88Bb6FBad317eea98c0F9', - priceFeed: '0x5b1F500134bdD7f4359F5B2adC65f839737290f4', - fastPriceFeed: '0x73903fEc691a80Ec47bc830bf3F0baD127A06e30', - fastPriceEvents: '0x08bC8ef0b71238055f9Ee6BBc90869D8d0DBdCCa', - usdg: '0x48aC594dd00c4aAcF40f83337fc6dA31F9F439A7', - }, - }, }; export const Adapters: { @@ -54,12 +44,4 @@ export const Adapters: { }, ], }, - [Network.ZKEVM]: { - [SwapSide.SELL]: [ - { - name: 'PolygonZkEvmAdapter01', - index: 2, - }, - ], - }, }; diff --git a/src/dex/gmx/gmx.ts b/src/dex/gmx/gmx.ts index 71ea31083..2372dbea8 100644 --- a/src/dex/gmx/gmx.ts +++ b/src/dex/gmx/gmx.ts @@ -1,5 +1,4 @@ import { Interface } from '@ethersproject/abi'; -import _ from 'lodash'; import { Token, Address, @@ -35,7 +34,7 @@ export class GMX extends SimpleExchange implements IDex { readonly isFeeOnTransferSupported = false; public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(_.pick(GMXConfig, ['GMX', 'QuickPerps'])); + getDexKeysWithNetwork(GMXConfig); public static erc20Interface = new Interface(ERC20ABI); From cd06853d6e86350b535b84fe897dd60fb3a73be8 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 3 Aug 2023 11:45:49 +0300 Subject: [PATCH 039/833] 2.27.1-ramses --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 99c1ae757..0e4592226 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.22.4-ramses", + "version": "2.27.1-ramses", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From cacd81b20426a52e5e4f2c2fb94fb5aacdcce38b Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 3 Aug 2023 12:25:39 +0300 Subject: [PATCH 040/833] debug --- src/dex/solidly/forks-override/chronos.ts | 8 ++++++-- src/dex/solidly/forks-override/ramses.ts | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/dex/solidly/forks-override/chronos.ts b/src/dex/solidly/forks-override/chronos.ts index 845b46e01..3eda10d54 100644 --- a/src/dex/solidly/forks-override/chronos.ts +++ b/src/dex/solidly/forks-override/chronos.ts @@ -21,7 +21,7 @@ const ChronosFactoryABI = [ const chronosFactoryIface = new Interface(ChronosFactoryABI); -type ChronosSubgraphPool = { +export type ChronosSubgraphPool = { id: string; isStable: boolean; token0: { id: string; decimals: string }; @@ -102,6 +102,7 @@ export class Chronos extends Solidly { } }`; + console.log('tokenAddress.toLowerCase(): ', tokenAddress.toLowerCase()); const { data } = await this.dexHelper.httpRequest.post( this.subgraphURL, { @@ -114,6 +115,8 @@ export class Chronos extends Solidly { if (!(data && data.pools0 && data.pools1)) throw new Error("Couldn't fetch the pools from the subgraph"); + console.log('DATA: ', data); + const pools0 = await this.prepareSubgraphPools(data.pools0, (pool,{ address1, decimals1, liquidityUSDToken0, liquidityUSDToken1, }) => ({ @@ -151,7 +154,7 @@ export class Chronos extends Solidly { ); } - private async prepareSubgraphPools( + protected async prepareSubgraphPools( pools: ChronosSubgraphPool[], iterator: ( pool: ChronosSubgraphPool, { @@ -174,6 +177,7 @@ export class Chronos extends Solidly { liquidityUSDToken1: number, }) => PoolLiquidity ): Promise { + console.log('POOLS: ', pools); return Promise.all(pools.map(async ( pool: ChronosSubgraphPool, ) => { diff --git a/src/dex/solidly/forks-override/ramses.ts b/src/dex/solidly/forks-override/ramses.ts index dcd51ea26..ea4c8e321 100644 --- a/src/dex/solidly/forks-override/ramses.ts +++ b/src/dex/solidly/forks-override/ramses.ts @@ -2,9 +2,18 @@ import { Network } from '../../../constants'; import { getDexKeysWithNetwork } from '../../../utils'; import { SolidlyConfig } from '../config'; import _ from 'lodash'; -import { Chronos } from './chronos'; -import { SolidlyPair } from '../types'; -import { Interface } from '@ethersproject/abi'; +import { Chronos, ChronosSubgraphPool } from './chronos'; +import { PoolLiquidity } from '../../../types'; +import BigNumber from 'bignumber.js'; + +export type RamsesSubgraphPool = { + id: string; + isStable: boolean; + token0: string; + reserve0: string; + reserve1: string; + token1: string; +}; export class Ramses extends Chronos { public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = From 3b397e621ad53495fb9f38389e4b4385ee29eb2d Mon Sep 17 00:00:00 2001 From: ruvlol <31368712+ruvlol@users.noreply.github.com> Date: Tue, 8 Aug 2023 13:19:52 +0500 Subject: [PATCH 041/833] Retro --- src/dex/uniswap-v3/config.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index c1c74165f..e88e6b135 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -119,6 +119,21 @@ export const UniswapV3Config: DexConfigMap = { 'https://api.studio.thegraph.com/query/44554/uniswap-v3/version/latest', }, }, + 'Retro': { + [Network.POLYGON]: { + factory: '0x91e1B99072f238352f59e58de875691e20Dc19c1', + quoter: '0xfe08be075758935cb6cb9318d1fbb60920416d4e', + router: '0x1891783cb3497Fdad1F25C933225243c2c7c4102', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0x817e07951f93017a93327ac8cc31e946540203a19e1ecc37bc1761965c2d1090`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/ruvlol/univ3-test', + }, + }, }; export const Adapters: Record = { From 15c4790301ac0cfe7ad7af8338ec4484be0d5930 Mon Sep 17 00:00:00 2001 From: Pabheto Date: Wed, 9 Aug 2023 18:10:15 +0200 Subject: [PATCH 042/833] Chronos V3 pools integration --- src/dex/uniswap-v3/config.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index bb0e43977..c13498886 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -118,6 +118,22 @@ export const UniswapV3Config: DexConfigMap = { 'https://api.thegraph.com/subgraphs/name/pancakeswap/exchange-v3-bsc', }, }, + Chronos: { + [Network.ARBITRUM]: { + factory: '0x4Db9D624F67E00dbF8ef7AE0e0e8eE54aF1dee49', + deployer: '0x0fFc5A81f38d5b6Ac15edACdd35A76578f59BbF2', + quoter: '0x6E7f0Ca45171a4440c0CDdF3A46A8dC5D4c2d4A0', + router: '0xE0aBdFD837D451640CF43cB1Ec4eE87976eFbb41', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x46b44eb4Cc3bEbB9f04C419f691aB85Ff885A4D6', + uniswapMulticall: '0xd703C06A1Dcd0A52A2f445Bfd21F7e6C73fB6662', + chunksCount: 10, + initHash: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + subgraphURL: + 'https://subgraph.chronos.exchange/subgraphs/name/chronos-v3', + }, + }, }; export const Adapters: Record = { From 81b50277d985a903951d45984b43f6f408bcb2d9 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 9 Aug 2023 20:37:04 +0300 Subject: [PATCH 043/833] debug --- src/abi/RamsesV2Pool.abi.json | 1554 +++++++++++++++++ src/dex/ramses-v2/ramses-v2-e2e.test.ts | 111 +- src/dex/ramses-v2/ramses-v2-pool.ts | 12 + src/dex/ramses-v2/ramses-v2.ts | 12 +- .../uniswap-v3/uniswap-v3-integration.test.ts | 29 +- src/lib/multi-wrapper.ts | 9 +- tests/constants-e2e.ts | 4 +- tests/utils-e2e.ts | 1 + 8 files changed, 1683 insertions(+), 49 deletions(-) create mode 100644 src/abi/RamsesV2Pool.abi.json diff --git a/src/abi/RamsesV2Pool.abi.json b/src/abi/RamsesV2Pool.abi.json new file mode 100644 index 000000000..b69ed21f7 --- /dev/null +++ b/src/abi/RamsesV2Pool.abi.json @@ -0,0 +1,1554 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": "sender", + "type": "address" + }, + { + "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": "CollectProtocol", + "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": "uint256", + "name": "period", + "type": "uint256" + } + ], + "name": "boostInfos", + "outputs": [ + { + "internalType": "uint128", + "name": "totalBoostAmount", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "totalVeRamAmount", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + } + ], + "name": "boostInfos", + "outputs": [ + { + "internalType": "uint128", + "name": "boostAmount", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "veRamAmount", + "type": "int128" + }, + { + "internalType": "int256", + "name": "secondsDebtX96", + "type": "int256" + }, + { + "internalType": "int256", + "name": "boostedSecondsDebtX96", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "boostedLiquidity", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "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": "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": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "veRamTokenId", + "type": "uint256" + } + ], + "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" + } + ], + "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": "uint256", + "name": "index", + "type": "uint256" + }, + { + "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": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint128", + "name": "amount0Requested", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Requested", + "type": "uint128" + } + ], + "name": "collectProtocol", + "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": "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": [ + { + "internalType": "uint16", + "name": "observationCardinalityNext", + "type": "uint16" + } + ], + "name": "increaseObservationCardinalityNext", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_nfpManager", + "type": "address" + }, + { + "internalType": "address", + "name": "_veRam", + "type": "address" + }, + { + "internalType": "address", + "name": "_voter", + "type": "address" + }, + { + "internalType": "address", + "name": "_token0", + "type": "address" + }, + { + "internalType": "address", + "name": "_token1", + "type": "address" + }, + { + "internalType": "uint24", + "name": "_fee", + "type": "uint24" + }, + { + "internalType": "int24", + "name": "_tickSpacing", + "type": "int24" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint160", + "name": "sqrtPriceX96", + "type": "uint160" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "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": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "veRamTokenId", + "type": "uint256" + }, + { + "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": "nfpManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "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" + }, + { + "internalType": "uint160", + "name": "secondsPerBoostedLiquidityPeriodX128", + "type": "uint160" + } + ], + "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[]" + }, + { + "internalType": "uint160[]", + "name": "secondsPerBoostedLiquidityPeriodX128s", + "type": "uint160[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "period", + "type": "uint32" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + } + ], + "name": "periodCumulativesInside", + "outputs": [ + { + "internalType": "uint160", + "name": "secondsPerLiquidityInsideX128", + "type": "uint160" + }, + { + "internalType": "uint160", + "name": "secondsPerBoostedLiquidityInsideX128", + "type": "uint160" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + } + ], + "name": "periods", + "outputs": [ + { + "internalType": "uint32", + "name": "previousPeriod", + "type": "uint32" + }, + { + "internalType": "int24", + "name": "startTick", + "type": "int24" + }, + { + "internalType": "int24", + "name": "lastTick", + "type": "int24" + }, + { + "internalType": "uint160", + "name": "endSecondsPerLiquidityPeriodX128", + "type": "uint160" + }, + { + "internalType": "uint160", + "name": "endSecondsPerBoostedLiquidityPeriodX128", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "boostedInRange", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + } + ], + "name": "positionPeriodDebt", + "outputs": [ + { + "internalType": "int256", + "name": "secondsDebtX96", + "type": "int256" + }, + { + "internalType": "int256", + "name": "boostedSecondsDebtX96", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + } + ], + "name": "positionPeriodSecondsInRange", + "outputs": [ + { + "internalType": "uint256", + "name": "periodSecondsInsideX96", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "periodBoostedSecondsInsideX96", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "key", + "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" + }, + { + "internalType": "uint256", + "name": "attachedVeRamId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolFees", + "outputs": [ + { + "internalType": "uint128", + "name": "token0", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "token1", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "slots", + "type": "bytes32[]" + } + ], + "name": "readStorage", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "returnData", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "setFeeProtocol", + "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": "uint8", + "name": "feeProtocol", + "type": "uint8" + }, + { + "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": "uint160", + "name": "secondsPerBoostedLiquidityInsideX128", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "secondsInside", + "type": "uint32" + } + ], + "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": "int16", + "name": "tick", + "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": "tick", + "type": "int24" + } + ], + "name": "ticks", + "outputs": [ + { + "internalType": "uint128", + "name": "liquidityGross", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "liquidityNet", + "type": "int128" + }, + { + "internalType": "uint128", + "name": "boostedLiquidityGross", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "boostedLiquidityNet", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside0X128", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside1X128", + "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": "veRam", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/dex/ramses-v2/ramses-v2-e2e.test.ts b/src/dex/ramses-v2/ramses-v2-e2e.test.ts index 0919df4b9..3b3d64ad9 100644 --- a/src/dex/ramses-v2/ramses-v2-e2e.test.ts +++ b/src/dex/ramses-v2/ramses-v2-e2e.test.ts @@ -14,7 +14,7 @@ import { generateConfig } from '../../config'; describe('RamsesV2 E2E', () => { const dexKey = 'RamsesV2'; - describe('UniswapV3 MAINNET', () => { + describe('Arbitrum', () => { const network = Network.ARBITRUM; const tokens = Tokens[network]; const holders = Holders[network]; @@ -23,45 +23,78 @@ describe('RamsesV2 E2E', () => { network, ); - it('BUY USDT -> USDC', async () => { - await testE2E( - tokens['USDT'], - tokens['USDC'], - holders['DAI'], - '100000000000', - SwapSide.BUY, - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - it('SELL WETH -> RDNT', async () => { - await testE2E( - tokens['WETH'], - tokens['RDNT'], - holders['WETH'], - '1000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '11000000'; + const tokenBAmount: string = '21000000'; + const nativeTokenAmount = '11000000000000000000'; - it('directSwap SELL WETH -> USDC', async () => { - await testE2E( - tokens['WETH'], - tokens['USDC'], - holders['WETH'], - '1000000000000000000', + const sideToContractMethods = new Map([ + [ SwapSide.SELL, - dexKey, - ContractMethod.directUniV3Swap, - network, - provider, - ); - }); + [ + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + // ContractMethod.directUniV3Swap, + ], + ], + // [ + // SwapSide.BUY, + // [ + // ContractMethod.simpleBuy, + // ContractMethod.buy, + // ContractMethod.directUniV3Buy, + // ], + // ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + // await testE2E( + // tokens[nativeTokenSymbol], + // tokens[tokenASymbol], + // holders[nativeTokenSymbol], + // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + // await testE2E( + // tokens[tokenASymbol], + // tokens[nativeTokenSymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); }); }); diff --git a/src/dex/ramses-v2/ramses-v2-pool.ts b/src/dex/ramses-v2/ramses-v2-pool.ts index b68af23a3..55a4636b8 100644 --- a/src/dex/ramses-v2/ramses-v2-pool.ts +++ b/src/dex/ramses-v2/ramses-v2-pool.ts @@ -198,6 +198,12 @@ export class RamsesV2EventPool extends StatefulEventSubscriber { private _getStateRequestCallData() { if (!this._stateRequestCallData) { + console.log('this.factoryAddress:', this.factoryAddress); + console.log('this.token0:', this.token0); + console.log('this.token1:', this.token1); + console.log('this.feeCode:', this.feeCode); + console.log('this.getBitmapRangeToRequest():', this.getBitmapRangeToRequest()); + const callData: MultiCallParams< bigint | DecodedStateMultiCallResultWithRelativeBitmaps >[] = [ @@ -242,6 +248,8 @@ export class RamsesV2EventPool extends StatefulEventSubscriber { async generateState(blockNumber: number): Promise> { const callData = this._getStateRequestCallData(); + console.log('CALL DATA: ', callData); + const [resBalance0, resBalance1, resState] = await this.dexHelper.multiWrapper.tryAggregate< bigint | DecodedStateMultiCallResultWithRelativeBitmaps @@ -253,6 +261,10 @@ export class RamsesV2EventPool extends StatefulEventSubscriber { false, ); + console.log('RES BALANCE 0: ', resBalance0); + console.log('RES BALANCE 0: ', resBalance1); + console.log('RES STATE: ', resState); + // Quite ugly solution, but this is the one that fits to current flow. // I think UniswapV3 callbacks subscriptions are complexified for no reason. // Need to be revisited later diff --git a/src/dex/ramses-v2/ramses-v2.ts b/src/dex/ramses-v2/ramses-v2.ts index 6a62dade8..ae19a3581 100644 --- a/src/dex/ramses-v2/ramses-v2.ts +++ b/src/dex/ramses-v2/ramses-v2.ts @@ -167,9 +167,11 @@ export class RamsesV2 fee: bigint, blockNumber: number, ): Promise { + console.log('INITAL FEE: ', fee); let pool = this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)]; + if (pool === undefined) { const [token0, token1] = this._sortTokens(srcAddress, destAddress); @@ -179,7 +181,6 @@ export class RamsesV2 this.notExistingPoolSetKey, key, ); - const poolDoesNotExist = notExistingPoolScore !== null; if (poolDoesNotExist) { @@ -222,6 +223,10 @@ export class RamsesV2 }, }); } catch (e) { + console.log('POOL FEE: ', fee); + console.log('SRC: ', srcAddress); + console.log('DEST: ', destAddress); + console.log('E: ', e); if (e instanceof Error && e.message.endsWith('Pool does not exist')) { // no need to await we want the set to have the pool key but it's not blocking this.dexHelper.cache.zadd( @@ -262,6 +267,7 @@ export class RamsesV2 this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = pool; } + console.log('RESULT POOL: ', pool); return pool; } @@ -314,6 +320,9 @@ export class RamsesV2 ) ).filter(pool => pool); + + console.log('GET POOL Identifiers POOLS: ', pools); + if (pools.length === 0) return []; return pools.map(pool => @@ -470,6 +479,7 @@ export class RamsesV2 blockNumber: number, limitPools?: string[], ): Promise> { + console.log('RAMSES get prices volume'); try { const _srcToken = this.dexHelper.config.wrapETH(srcToken); const _destToken = this.dexHelper.config.wrapETH(destToken); diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index 35dee3c93..cffdab3df 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -88,8 +88,18 @@ async function checkOnChainPricing( return false; } + // const readerCallData = getReaderCalldata( + // exchangeAddress, + // readerIface, + // _amounts.slice(1), + // funcName, + // tokenIn, + // tokenOut, + // fee, + // ); + const readerCallData = getReaderCalldata( - exchangeAddress, + '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', readerIface, _amounts.slice(1), funcName, @@ -138,9 +148,22 @@ describe('UniswapV3', function () { blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); uniswapV3 = new UniswapV3(network, dexKey, dexHelper); uniswapV3Mainnet = new UniswapV3( - Network.MAINNET, + Network.ARBITRUM, dexKey, - new DummyDexHelper(Network.MAINNET), + new DummyDexHelper(Network.ARBITRUM), + ); + }); + + + it('fgggg', async () => { + const readerCallData = getReaderCalldata( + '', + readerIface, + _amounts.slice(1), + funcName, + tokenIn, + tokenOut, + fee, ); }); diff --git a/src/lib/multi-wrapper.ts b/src/lib/multi-wrapper.ts index 80aff4725..e3b79e21e 100644 --- a/src/lib/multi-wrapper.ts +++ b/src/lib/multi-wrapper.ts @@ -65,11 +65,12 @@ export class MultiWrapper { } const aggregatedResult = await Promise.all( - allCalls.map(batch => - this.multi.methods + allCalls.map(batch => { + console.log('BATCH: ', JSON.stringify(batch)); + return this.multi.methods .tryAggregate(mandatory, batch) - .call(undefined, blockNumber), - ), + .call(undefined, blockNumber); + }) ); let globalInd = 0; diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 2fd50078d..51371aebd 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1005,9 +1005,9 @@ export const Holders: { ETH: '0xF977814e90dA44bFA03b6295A0616a897441aceC', DAI: '0x07d7f291e731a41d3f0ea4f1ae5b6d920ffb3fe0', WETH: '0xc31e54c7a869b9fcbecc14363cf510d1c41fa443', - USDC: '0x62383739d68dd0f844103db8dfb05a7eded5bbe6', + USDC: '0xb874005cbea25c357b31c62145b3aef219d105cf', OHM: '0xebce5f29ff5ca9aa330ebdf7ec6b5f474bff271e', - USDT: '0x62383739d68dd0f844103db8dfb05a7eded5bbe6', + USDT: '0x5ff47d4ab75bcaff6807c81f1367abb53439883c', POPS: '0x4b78b52e7de4d8b7d367297cb8a87c1875a9d591', FRAX: '0x59bf0545fca0e5ad48e13da269facd2e8c886ba4', nUSD: '0x9dd329f5411466d9e0c488ff72519ca9fef0cb40', diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index 12143c4dc..a22e91f0e 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -340,6 +340,7 @@ export async function testE2E( } } + console.log('DEX KEY: ', dexKey); const useAPI = testingEndpoint && !poolIdentifiers; // The API currently doesn't allow for specifying poolIdentifiers const paraswap: IParaSwapSDK = useAPI From 25a49caa85467e915654aa26f4a1fb8daddad74c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 14 Aug 2023 16:34:49 +0300 Subject: [PATCH 044/833] debug --- src/dex/ramses-v2/config.ts | 3 ++- src/dex/ramses-v2/ramses-v2-e2e.test.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dex/ramses-v2/config.ts b/src/dex/ramses-v2/config.ts index 3a4b036b7..c7de564a8 100644 --- a/src/dex/ramses-v2/config.ts +++ b/src/dex/ramses-v2/config.ts @@ -12,7 +12,8 @@ export const RamsesV2Config: DexConfigMap = { quoter: '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', router: '0xAA23611badAFB62D37E7295A682D21960ac85A90', supportedFees: RAMSES_SUPPORTED_FEES, - stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', + // stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', + stateMulticall: '0x2A7A9478Aaff076f8A80c03e7d65BD7d8D01650d', uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', chunksCount: 10, initHash: diff --git a/src/dex/ramses-v2/ramses-v2-e2e.test.ts b/src/dex/ramses-v2/ramses-v2-e2e.test.ts index 3b3d64ad9..869f0b20e 100644 --- a/src/dex/ramses-v2/ramses-v2-e2e.test.ts +++ b/src/dex/ramses-v2/ramses-v2-e2e.test.ts @@ -23,7 +23,7 @@ describe('RamsesV2 E2E', () => { network, ); - const tokenASymbol: string = 'USDC'; + const tokenASymbol: string = 'USDCe'; const tokenBSymbol: string = 'USDT'; const nativeTokenSymbol = NativeTokenSymbols[network]; From d312cc92ffdb06231877979685a04091d18fd626 Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 15 Aug 2023 13:58:42 +0100 Subject: [PATCH 045/833] feat: replace positiveSlippageToUser with takeSurplus --- src/router/buy.ts | 10 +++------- src/router/directswap.ts | 10 +++------- src/router/irouter.ts | 2 +- src/router/megaswap.ts | 10 +++------- src/router/multiswap.ts | 10 +++------- src/router/payload-encoder.ts | 14 +++++++------- src/router/simpleswap.ts | 12 ++++-------- src/router/simpleswapnft.ts | 10 +++------- src/transaction-builder.ts | 6 +++--- 9 files changed, 30 insertions(+), 54 deletions(-) diff --git a/src/router/buy.ts b/src/router/buy.ts index 4bb1759f3..6063cd1ce 100644 --- a/src/router/buy.ts +++ b/src/router/buy.ts @@ -42,7 +42,7 @@ export class Buy extends PayloadEncoder implements IRouter { referrerAddress: Address | undefined, partnerAddress: Address, partnerFeePercent: string, - positiveSlippageToUser: boolean, + takeSurplus: boolean, beneficiary: Address, permit: string, deadline: string, @@ -69,13 +69,9 @@ export class Buy extends PayloadEncoder implements IRouter { encodePartnerAddressForFeeLogic({ partnerAddress, partnerFeePercent, - positiveSlippageToUser, + takeSurplus, }), - encodeFeePercent( - partnerFeePercent, - positiveSlippageToUser, - SwapSide.BUY, - ), + encodeFeePercent(partnerFeePercent, takeSurplus, SwapSide.BUY), ]; const buyData: ContractBuyData = { diff --git a/src/router/directswap.ts b/src/router/directswap.ts index 2af9245bd..a0a44edc2 100644 --- a/src/router/directswap.ts +++ b/src/router/directswap.ts @@ -29,7 +29,7 @@ export class DirectSwap implements IRouter { referrerAddress: Address | undefined, partnerAddress: Address, partnerFeePercent: string, - positiveSlippageToUser: boolean, + takeSurplus: boolean, beneficiary: Address, permit: string, deadline: string, @@ -76,13 +76,9 @@ export class DirectSwap implements IRouter { encodePartnerAddressForFeeLogic({ partnerAddress, partnerFeePercent, - positiveSlippageToUser, + takeSurplus, }), - encodeFeePercent( - partnerFeePercent, - positiveSlippageToUser, - priceRoute.side, - ), + encodeFeePercent(partnerFeePercent, takeSurplus, priceRoute.side), ]; return dex.getDirectParam!( diff --git a/src/router/irouter.ts b/src/router/irouter.ts index 01e1ff8f0..b17283e14 100644 --- a/src/router/irouter.ts +++ b/src/router/irouter.ts @@ -9,7 +9,7 @@ export interface IRouter { referrerAddress: Address | undefined, partner: Address, partnerFeePercent: string, - positiveSlippageToUser: boolean, + takeSurplus: boolean, beneficiary: Address, permit: string, deadline: string, diff --git a/src/router/megaswap.ts b/src/router/megaswap.ts index 58433b270..ce8cbee10 100644 --- a/src/router/megaswap.ts +++ b/src/router/megaswap.ts @@ -42,7 +42,7 @@ export class MegaSwap extends PayloadEncoder implements IRouter { referrerAddress: Address | undefined, partnerAddress: Address, partnerFeePercent: string, - positiveSlippageToUser: boolean, + takeSurplus: boolean, beneficiary: Address, permit: string, deadline: string, @@ -58,13 +58,9 @@ export class MegaSwap extends PayloadEncoder implements IRouter { encodePartnerAddressForFeeLogic({ partnerAddress, partnerFeePercent, - positiveSlippageToUser, + takeSurplus, }), - encodeFeePercent( - partnerFeePercent, - positiveSlippageToUser, - SwapSide.SELL, - ), + encodeFeePercent(partnerFeePercent, takeSurplus, SwapSide.SELL), ]; const sellData: ContractMegaSwapSellData = { diff --git a/src/router/multiswap.ts b/src/router/multiswap.ts index d90695d0c..429e8b3c0 100644 --- a/src/router/multiswap.ts +++ b/src/router/multiswap.ts @@ -45,7 +45,7 @@ export class MultiSwap referrerAddress: Address | undefined, partnerAddress: Address, partnerFeePercent: string, - positiveSlippageToUser: boolean, + takeSurplus: boolean, beneficiary: Address, permit: string, deadline: string, @@ -66,13 +66,9 @@ export class MultiSwap encodePartnerAddressForFeeLogic({ partnerAddress, partnerFeePercent, - positiveSlippageToUser, + takeSurplus, }), - encodeFeePercent( - partnerFeePercent, - positiveSlippageToUser, - SwapSide.SELL, - ), + encodeFeePercent(partnerFeePercent, takeSurplus, SwapSide.SELL), ]; const sellData: ContractSellData = { diff --git a/src/router/payload-encoder.ts b/src/router/payload-encoder.ts index 3a9a9bc93..cf057846c 100644 --- a/src/router/payload-encoder.ts +++ b/src/router/payload-encoder.ts @@ -29,14 +29,14 @@ const HALF_SPLIT = '5000'; export function encodePartnerAddressForFeeLogic({ partnerAddress, partnerFeePercent, - positiveSlippageToUser, + takeSurplus, }: { partnerAddress: string; partnerFeePercent: string; - positiveSlippageToUser: boolean; + takeSurplus: boolean; }): string { const isPartnerTakeNoFeeNoPos = - +partnerFeePercent === 0 && positiveSlippageToUser == true; + +partnerFeePercent === 0 && takeSurplus == false; // nullify partner address to fallback default circuit contract without partner/referrer (no harm as no fee taken at all) const partner = isPartnerTakeNoFeeNoPos ? NULL_ADDRESS : partnerAddress; @@ -51,11 +51,11 @@ export function encodePartnerAddressForFeeLogic({ export function encodeFeePercent( partnerFeePercent: string, - positiveSlippageToUser: boolean, + takeSurplus: boolean, side: SwapSide, ) { const isNoFeeAndPositiveSlippageToPartner = - positiveSlippageToUser === false && BigInt(partnerFeePercent) === 0n; + takeSurplus === true && BigInt(partnerFeePercent) === 0n; let fee = isNoFeeAndPositiveSlippageToPartner ? BigInt(HALF_SPLIT) @@ -70,9 +70,9 @@ export function encodeFeePercent( fee |= OneShift17; } - // Set 14th bit if positiveSlippageToUser is true + // Set 14th bit if takeSurplus is false // Upd: not used onchain anymore but better to keep to prevent collisions and ensure continuity of analytics - if (positiveSlippageToUser) fee |= OneShift14; + if (!takeSurplus) fee |= OneShift14; // Set 15th bit to take fee from srcToken if (side === SwapSide.BUY && !isNoFeeAndPositiveSlippageToPartner) diff --git a/src/router/simpleswap.ts b/src/router/simpleswap.ts index 1b8e9e108..6047de047 100644 --- a/src/router/simpleswap.ts +++ b/src/router/simpleswap.ts @@ -223,7 +223,7 @@ export abstract class SimpleRouterBase referrerAddress: Address | undefined, partnerAddress: Address, partnerFeePercent: string, - positiveSlippageToUser: boolean, + takeSurplus: boolean, beneficiary: Address, permit: string, deadline: string, @@ -272,7 +272,7 @@ export abstract class SimpleRouter extends SimpleRouterBase { referrerAddress: Address | undefined, partnerAddress: Address, partnerFeePercent: string, - positiveSlippageToUser: boolean, + takeSurplus: boolean, beneficiary: Address, permit: string, deadline: string, @@ -292,13 +292,9 @@ export abstract class SimpleRouter extends SimpleRouterBase { encodePartnerAddressForFeeLogic({ partnerAddress, partnerFeePercent, - positiveSlippageToUser, + takeSurplus, }), - encodeFeePercent( - partnerFeePercent, - positiveSlippageToUser, - this.side, - ), + encodeFeePercent(partnerFeePercent, takeSurplus, this.side), ]; const sellData: ConstractSimpleData = { diff --git a/src/router/simpleswapnft.ts b/src/router/simpleswapnft.ts index 1fce10a08..fa33bab0f 100644 --- a/src/router/simpleswapnft.ts +++ b/src/router/simpleswapnft.ts @@ -60,7 +60,7 @@ export class SimpleBuyNFT extends SimpleRouterBase { referrerAddress: Address | undefined, partnerAddress: Address, partnerFeePercent: string, - positiveSlippageToUser: boolean, + takeSurplus: boolean, beneficiary: Address, permit: string, deadline: string, @@ -102,13 +102,9 @@ export class SimpleBuyNFT extends SimpleRouterBase { encodePartnerAddressForFeeLogic({ partnerAddress, partnerFeePercent, - positiveSlippageToUser, + takeSurplus, }), - encodeFeePercent( - partnerFeePercent, - positiveSlippageToUser, - SwapSide.BUY, - ), + encodeFeePercent(partnerFeePercent, takeSurplus, SwapSide.BUY), ]; const buyData: ContractSimpleBuyNFTData = { diff --git a/src/transaction-builder.ts b/src/transaction-builder.ts index 41da59942..db64867ea 100644 --- a/src/transaction-builder.ts +++ b/src/transaction-builder.ts @@ -17,7 +17,7 @@ export class TransactionBuilder { referrerAddress, partnerAddress, partnerFeePercent, - positiveSlippageToUser, + takeSurplus, gasPrice, maxFeePerGas, maxPriorityFeePerGas, @@ -33,7 +33,7 @@ export class TransactionBuilder { referrerAddress?: Address; partnerAddress: Address; partnerFeePercent: string; - positiveSlippageToUser?: boolean; + takeSurplus?: boolean; gasPrice?: string; // // @TODO: improve types? so that either gasPrice or ALL of max.*FeePerGas MUST be returned? maxFeePerGas?: string; maxPriorityFeePerGas?: string; @@ -53,7 +53,7 @@ export class TransactionBuilder { referrerAddress, partnerAddress, partnerFeePercent, - positiveSlippageToUser ?? true, + takeSurplus ?? false, _beneficiary, permit || '0x', deadline, From c918801afee415e399473eeab7f4c93a5187ebb3 Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 15 Aug 2023 14:07:43 +0100 Subject: [PATCH 046/833] 2.28.9-take-surplus.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 33ccd9c76..049280ec1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.8", + "version": "2.28.9-take-surplus.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From c808f2e2ef9d500a05c7eb9ca11318f854f24fcc Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 15 Aug 2023 18:43:51 +0300 Subject: [PATCH 047/833] update --- src/abi/RamsesV2StateMulticall.abi.json | 891 ++++++++++++++++++++++++ src/dex/ramses-v2/config.ts | 3 +- src/dex/ramses-v2/ramses-v2-e2e.test.ts | 80 +-- src/dex/ramses-v2/ramses-v2-pool.ts | 12 - src/dex/ramses-v2/ramses-v2.ts | 14 +- src/dex/ramses-v2/utils.ts | 9 +- src/lib/multi-wrapper.ts | 1 - 7 files changed, 942 insertions(+), 68 deletions(-) create mode 100644 src/abi/RamsesV2StateMulticall.abi.json diff --git a/src/abi/RamsesV2StateMulticall.abi.json b/src/abi/RamsesV2StateMulticall.abi.json new file mode 100644 index 000000000..f83e859c2 --- /dev/null +++ b/src/abi/RamsesV2StateMulticall.abi.json @@ -0,0 +1,891 @@ +[ + { + "inputs": [ + { + "internalType": "contract IRamsesV2Factory", + "name": "factory", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "int16", + "name": "tickBitmapStart", + "type": "int16" + }, + { + "internalType": "int16", + "name": "tickBitmapEnd", + "type": "int16" + } + ], + "name": "getAdditionalBitmapWithTicks", + "outputs": [ + { + "components": [ + { + "internalType": "int16", + "name": "index", + "type": "int16" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "internalType": "struct IRamsesV2StateMulticall.TickBitMapMappings[]", + "name": "tickBitmap", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "int24", + "name": "index", + "type": "int24" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "liquidityGross", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "liquidityNet", + "type": "int128" + }, + { + "internalType": "uint128", + "name": "cleanUnusedSlot", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "cleanUnusedSlot2", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside0X128", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside1X128", + "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" + } + ], + "internalType": "struct IRamsesV2StateMulticall.TickInfo", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct IRamsesV2StateMulticall.TickInfoMappings[]", + "name": "ticks", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRamsesV2Factory", + "name": "factory", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "int16", + "name": "tickBitmapStart", + "type": "int16" + }, + { + "internalType": "int16", + "name": "tickBitmapEnd", + "type": "int16" + } + ], + "name": "getAdditionalBitmapWithoutTicks", + "outputs": [ + { + "components": [ + { + "internalType": "int16", + "name": "index", + "type": "int16" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "internalType": "struct IRamsesV2StateMulticall.TickBitMapMappings[]", + "name": "tickBitmap", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRamsesV2Factory", + "name": "factory", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "int16", + "name": "tickBitmapStart", + "type": "int16" + }, + { + "internalType": "int16", + "name": "tickBitmapEnd", + "type": "int16" + } + ], + "name": "getFullState", + "outputs": [ + { + "components": [ + { + "internalType": "contract IRamsesV2Pool", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + }, + { + "components": [ + { + "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": "uint8", + "name": "feeProtocol", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "unlocked", + "type": "bool" + } + ], + "internalType": "struct IRamsesV2StateMulticall.Slot0", + "name": "slot0", + "type": "tuple" + }, + { + "internalType": "uint128", + "name": "liquidity", + "type": "uint128" + }, + { + "internalType": "int24", + "name": "tickSpacing", + "type": "int24" + }, + { + "internalType": "uint128", + "name": "maxLiquidityPerTick", + "type": "uint128" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "blockTimestamp", + "type": "uint32" + }, + { + "internalType": "int56", + "name": "tickCumulative", + "type": "int56" + }, + { + "internalType": "uint160", + "name": "secondsPerLiquidityCumulativeX128", + "type": "uint160" + }, + { + "internalType": "bool", + "name": "initialized", + "type": "bool" + }, + { + "internalType": "uint160", + "name": "secondsPerBoostedLiquidityPeriodX128", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "boostedInRange", + "type": "uint32" + } + ], + "internalType": "struct IRamsesV2StateMulticall.Observation", + "name": "observation", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "int16", + "name": "index", + "type": "int16" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "internalType": "struct IRamsesV2StateMulticall.TickBitMapMappings[]", + "name": "tickBitmap", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "int24", + "name": "index", + "type": "int24" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "liquidityGross", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "liquidityNet", + "type": "int128" + }, + { + "internalType": "uint128", + "name": "cleanUnusedSlot", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "cleanUnusedSlot2", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside0X128", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside1X128", + "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" + } + ], + "internalType": "struct IRamsesV2StateMulticall.TickInfo", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct IRamsesV2StateMulticall.TickInfoMappings[]", + "name": "ticks", + "type": "tuple[]" + } + ], + "internalType": "struct IRamsesV2StateMulticall.StateResult", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRamsesV2Factory", + "name": "factory", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "int16", + "name": "leftBitmapAmount", + "type": "int16" + }, + { + "internalType": "int16", + "name": "rightBitmapAmount", + "type": "int16" + } + ], + "name": "getFullStateWithRelativeBitmaps", + "outputs": [ + { + "components": [ + { + "internalType": "contract IRamsesV2Pool", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + }, + { + "components": [ + { + "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": "uint8", + "name": "feeProtocol", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "unlocked", + "type": "bool" + } + ], + "internalType": "struct IRamsesV2StateMulticall.Slot0", + "name": "slot0", + "type": "tuple" + }, + { + "internalType": "uint128", + "name": "liquidity", + "type": "uint128" + }, + { + "internalType": "int24", + "name": "tickSpacing", + "type": "int24" + }, + { + "internalType": "uint128", + "name": "maxLiquidityPerTick", + "type": "uint128" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "blockTimestamp", + "type": "uint32" + }, + { + "internalType": "int56", + "name": "tickCumulative", + "type": "int56" + }, + { + "internalType": "uint160", + "name": "secondsPerLiquidityCumulativeX128", + "type": "uint160" + }, + { + "internalType": "bool", + "name": "initialized", + "type": "bool" + }, + { + "internalType": "uint160", + "name": "secondsPerBoostedLiquidityPeriodX128", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "boostedInRange", + "type": "uint32" + } + ], + "internalType": "struct IRamsesV2StateMulticall.Observation", + "name": "observation", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "int16", + "name": "index", + "type": "int16" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "internalType": "struct IRamsesV2StateMulticall.TickBitMapMappings[]", + "name": "tickBitmap", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "int24", + "name": "index", + "type": "int24" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "liquidityGross", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "liquidityNet", + "type": "int128" + }, + { + "internalType": "uint128", + "name": "cleanUnusedSlot", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "cleanUnusedSlot2", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside0X128", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside1X128", + "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" + } + ], + "internalType": "struct IRamsesV2StateMulticall.TickInfo", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct IRamsesV2StateMulticall.TickInfoMappings[]", + "name": "ticks", + "type": "tuple[]" + } + ], + "internalType": "struct IRamsesV2StateMulticall.StateResult", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRamsesV2Factory", + "name": "factory", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "int16", + "name": "tickBitmapStart", + "type": "int16" + }, + { + "internalType": "int16", + "name": "tickBitmapEnd", + "type": "int16" + } + ], + "name": "getFullStateWithoutTicks", + "outputs": [ + { + "components": [ + { + "internalType": "contract IRamsesV2Pool", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + }, + { + "components": [ + { + "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": "uint8", + "name": "feeProtocol", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "unlocked", + "type": "bool" + } + ], + "internalType": "struct IRamsesV2StateMulticall.Slot0", + "name": "slot0", + "type": "tuple" + }, + { + "internalType": "uint128", + "name": "liquidity", + "type": "uint128" + }, + { + "internalType": "int24", + "name": "tickSpacing", + "type": "int24" + }, + { + "internalType": "uint128", + "name": "maxLiquidityPerTick", + "type": "uint128" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "blockTimestamp", + "type": "uint32" + }, + { + "internalType": "int56", + "name": "tickCumulative", + "type": "int56" + }, + { + "internalType": "uint160", + "name": "secondsPerLiquidityCumulativeX128", + "type": "uint160" + }, + { + "internalType": "bool", + "name": "initialized", + "type": "bool" + }, + { + "internalType": "uint160", + "name": "secondsPerBoostedLiquidityPeriodX128", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "boostedInRange", + "type": "uint32" + } + ], + "internalType": "struct IRamsesV2StateMulticall.Observation", + "name": "observation", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "int16", + "name": "index", + "type": "int16" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "internalType": "struct IRamsesV2StateMulticall.TickBitMapMappings[]", + "name": "tickBitmap", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "int24", + "name": "index", + "type": "int24" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "liquidityGross", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "liquidityNet", + "type": "int128" + }, + { + "internalType": "uint128", + "name": "cleanUnusedSlot", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "cleanUnusedSlot2", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside0X128", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside1X128", + "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" + } + ], + "internalType": "struct IRamsesV2StateMulticall.TickInfo", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct IRamsesV2StateMulticall.TickInfoMappings[]", + "name": "ticks", + "type": "tuple[]" + } + ], + "internalType": "struct IRamsesV2StateMulticall.StateResult", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/dex/ramses-v2/config.ts b/src/dex/ramses-v2/config.ts index c7de564a8..668a276c8 100644 --- a/src/dex/ramses-v2/config.ts +++ b/src/dex/ramses-v2/config.ts @@ -12,8 +12,7 @@ export const RamsesV2Config: DexConfigMap = { quoter: '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', router: '0xAA23611badAFB62D37E7295A682D21960ac85A90', supportedFees: RAMSES_SUPPORTED_FEES, - // stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', - stateMulticall: '0x2A7A9478Aaff076f8A80c03e7d65BD7d8D01650d', + stateMulticall: '0x50EE4112Cab9c79812F23bE079aB3911395ACc8e', uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', chunksCount: 10, initHash: diff --git a/src/dex/ramses-v2/ramses-v2-e2e.test.ts b/src/dex/ramses-v2/ramses-v2-e2e.test.ts index 869f0b20e..3adeae01f 100644 --- a/src/dex/ramses-v2/ramses-v2-e2e.test.ts +++ b/src/dex/ramses-v2/ramses-v2-e2e.test.ts @@ -27,59 +27,59 @@ describe('RamsesV2 E2E', () => { const tokenBSymbol: string = 'USDT'; const nativeTokenSymbol = NativeTokenSymbols[network]; - const tokenAAmount: string = '11000000'; - const tokenBAmount: string = '21000000'; - const nativeTokenAmount = '11000000000000000000'; + const tokenAAmount: string = '1100000'; + const tokenBAmount: string = '1000000'; + const nativeTokenAmount = '1100000000000'; const sideToContractMethods = new Map([ [ SwapSide.SELL, [ ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - // ContractMethod.directUniV3Swap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, ], ], - // [ - // SwapSide.BUY, - // [ - // ContractMethod.simpleBuy, - // ContractMethod.buy, - // ContractMethod.directUniV3Buy, - // ], - // ], ]); sideToContractMethods.forEach((contractMethods, side) => contractMethods.forEach((contractMethod: ContractMethod) => { describe(`${contractMethod}`, () => { - // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - // await testE2E( - // tokens[nativeTokenSymbol], - // tokens[tokenASymbol], - // holders[nativeTokenSymbol], - // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - // await testE2E( - // tokens[tokenASymbol], - // tokens[nativeTokenSymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { await testE2E( tokens[tokenASymbol], diff --git a/src/dex/ramses-v2/ramses-v2-pool.ts b/src/dex/ramses-v2/ramses-v2-pool.ts index 55a4636b8..b68af23a3 100644 --- a/src/dex/ramses-v2/ramses-v2-pool.ts +++ b/src/dex/ramses-v2/ramses-v2-pool.ts @@ -198,12 +198,6 @@ export class RamsesV2EventPool extends StatefulEventSubscriber { private _getStateRequestCallData() { if (!this._stateRequestCallData) { - console.log('this.factoryAddress:', this.factoryAddress); - console.log('this.token0:', this.token0); - console.log('this.token1:', this.token1); - console.log('this.feeCode:', this.feeCode); - console.log('this.getBitmapRangeToRequest():', this.getBitmapRangeToRequest()); - const callData: MultiCallParams< bigint | DecodedStateMultiCallResultWithRelativeBitmaps >[] = [ @@ -248,8 +242,6 @@ export class RamsesV2EventPool extends StatefulEventSubscriber { async generateState(blockNumber: number): Promise> { const callData = this._getStateRequestCallData(); - console.log('CALL DATA: ', callData); - const [resBalance0, resBalance1, resState] = await this.dexHelper.multiWrapper.tryAggregate< bigint | DecodedStateMultiCallResultWithRelativeBitmaps @@ -261,10 +253,6 @@ export class RamsesV2EventPool extends StatefulEventSubscriber { false, ); - console.log('RES BALANCE 0: ', resBalance0); - console.log('RES BALANCE 0: ', resBalance1); - console.log('RES STATE: ', resState); - // Quite ugly solution, but this is the one that fits to current flow. // I think UniswapV3 callbacks subscriptions are complexified for no reason. // Need to be revisited later diff --git a/src/dex/ramses-v2/ramses-v2.ts b/src/dex/ramses-v2/ramses-v2.ts index ae19a3581..cc3ce8852 100644 --- a/src/dex/ramses-v2/ramses-v2.ts +++ b/src/dex/ramses-v2/ramses-v2.ts @@ -45,7 +45,7 @@ import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; import UniswapV3QuoterABI from '../../abi/uniswap-v3/UniswapV3Quoter.abi.json'; import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; import DirectSwapABI from '../../abi/DirectSwap.json'; -import UniswapV3StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; +import RamsesV2StateMulticallABI from '../../abi/RamsesV2StateMulticall.abi.json'; import { DirectMethods, UNISWAPV3_EFFICIENCY_FACTOR, @@ -115,7 +115,7 @@ export class RamsesV2 this.config.uniswapMulticall, ); this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( - UniswapV3StateMulticallABI as AbiItem[], + RamsesV2StateMulticallABI as AbiItem[], this.config.stateMulticall, ); @@ -167,7 +167,6 @@ export class RamsesV2 fee: bigint, blockNumber: number, ): Promise { - console.log('INITAL FEE: ', fee); let pool = this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)]; @@ -223,10 +222,6 @@ export class RamsesV2 }, }); } catch (e) { - console.log('POOL FEE: ', fee); - console.log('SRC: ', srcAddress); - console.log('DEST: ', destAddress); - console.log('E: ', e); if (e instanceof Error && e.message.endsWith('Pool does not exist')) { // no need to await we want the set to have the pool key but it's not blocking this.dexHelper.cache.zadd( @@ -267,7 +262,6 @@ export class RamsesV2 this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = pool; } - console.log('RESULT POOL: ', pool); return pool; } @@ -320,9 +314,6 @@ export class RamsesV2 ) ).filter(pool => pool); - - console.log('GET POOL Identifiers POOLS: ', pools); - if (pools.length === 0) return []; return pools.map(pool => @@ -479,7 +470,6 @@ export class RamsesV2 blockNumber: number, limitPools?: string[], ): Promise> { - console.log('RAMSES get prices volume'); try { const _srcToken = this.dexHelper.config.wrapETH(srcToken); const _destToken = this.dexHelper.config.wrapETH(destToken); diff --git a/src/dex/ramses-v2/utils.ts b/src/dex/ramses-v2/utils.ts index afd953e07..badfd0956 100644 --- a/src/dex/ramses-v2/utils.ts +++ b/src/dex/ramses-v2/utils.ts @@ -56,16 +56,22 @@ export function decodeStateMultiCallResultWithRelativeBitmaps( int56 tickCumulative, uint160 secondsPerLiquidityCumulativeX128, bool initialized, + uint160 secondsPerBoostedLiquidityPeriodX128, + uint32 boostedInRange, ) observation, tuple( int16 index, - uint256 value, + uint256 value )[] tickBitmap, tuple( int24 index, tuple( uint128 liquidityGross, int128 liquidityNet, + uint128 cleanUnusedSlot, + uint128 cleanUnusedSlot2, + uint256 feeGrowthOutside0X128, + uint256 feeGrowthOutside1X128, int56 tickCumulativeOutside, uint160 secondsPerLiquidityOutsideX128, uint32 secondsOutside, @@ -77,6 +83,7 @@ export function decodeStateMultiCallResultWithRelativeBitmaps( ], toDecode, )[0]; + // This conversion is not precise, because when we decode, we have more values // But I typed only the ones that are used later return decoded as DecodedStateMultiCallResultWithRelativeBitmaps; diff --git a/src/lib/multi-wrapper.ts b/src/lib/multi-wrapper.ts index e3b79e21e..4529f81ba 100644 --- a/src/lib/multi-wrapper.ts +++ b/src/lib/multi-wrapper.ts @@ -66,7 +66,6 @@ export class MultiWrapper { const aggregatedResult = await Promise.all( allCalls.map(batch => { - console.log('BATCH: ', JSON.stringify(batch)); return this.multi.methods .tryAggregate(mandatory, batch) .call(undefined, blockNumber); From 610f9ab535b68d790a8d5ffeb9161f5d2f25f634 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 15 Aug 2023 18:45:59 +0300 Subject: [PATCH 048/833] 2.28.9-ramses-v2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 33ccd9c76..77df47bde 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.8", + "version": "2.28.9-ramses-v2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 8062522523b1945f410950f250d03c268d20ee5e Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 16 Aug 2023 13:18:25 +0100 Subject: [PATCH 049/833] fix: tick bitmap --- src/dex/algebra/algebra-integration.test.ts | 102 ++++++++++++++++++++ src/dex/algebra/config.ts | 2 +- src/dex/algebra/lib/TickTable.ts | 15 ++- tests/constants-e2e.ts | 8 +- 4 files changed, 118 insertions(+), 9 deletions(-) diff --git a/src/dex/algebra/algebra-integration.test.ts b/src/dex/algebra/algebra-integration.test.ts index 97017d03a..9946b7252 100644 --- a/src/dex/algebra/algebra-integration.test.ts +++ b/src/dex/algebra/algebra-integration.test.ts @@ -155,6 +155,108 @@ async function testPricingOnNetwork( ); } +describe('CamelotV3', function () { + const dexKey = 'CamelotV3'; + let blockNumber: number; + let algebra: Algebra; + + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + + const srcTokenSymbol = 'USDCe'; + const destTokenSymbol = 'GRAIL'; + // const destTokenSymbol = 'USDC'; + + const amountsForSell = [ + 0n, + 10_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 20000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 30_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 40_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 50_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 60_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 70_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 80_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 90_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 100_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals], + 2n * BI_POWS[tokens[destTokenSymbol].decimals], + 3n * BI_POWS[tokens[destTokenSymbol].decimals], + 4n * BI_POWS[tokens[destTokenSymbol].decimals], + 5n * BI_POWS[tokens[destTokenSymbol].decimals], + 6n * BI_POWS[tokens[destTokenSymbol].decimals], + 7n * BI_POWS[tokens[destTokenSymbol].decimals], + 8n * BI_POWS[tokens[destTokenSymbol].decimals], + 9n * BI_POWS[tokens[destTokenSymbol].decimals], + 10n * BI_POWS[tokens[destTokenSymbol].decimals], + ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + algebra = new Algebra(network, dexKey, dexHelper); + if (algebra.initializePricing) { + await algebra.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + algebra, + network, + dexKey, + dexHelper, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + 'quoteExactInputSingle', + ); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + algebra, + network, + dexKey, + dexHelper, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + 'quoteExactOutputSingle', + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newAlgebra = new Algebra(network, dexKey, dexHelper); + const poolLiquidity = await newAlgebra.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newAlgebra.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); + }); +}); + describe('Algebra', function () { const dexKey = 'QuickSwapV3'; let blockNumber: number; diff --git a/src/dex/algebra/config.ts b/src/dex/algebra/config.ts index f8f942067..83ade331a 100644 --- a/src/dex/algebra/config.ts +++ b/src/dex/algebra/config.ts @@ -82,7 +82,7 @@ export const AlgebraConfig: DexConfigMap = { uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', deployer: '0x6dd3fb9653b10e806650f107c3b5a0a6ff974f65', version: 'v1.9', - forceRPC: true, + forceRPC: false, }, }, }; diff --git a/src/dex/algebra/lib/TickTable.ts b/src/dex/algebra/lib/TickTable.ts index c90dd50c9..5bb8365f8 100644 --- a/src/dex/algebra/lib/TickTable.ts +++ b/src/dex/algebra/lib/TickTable.ts @@ -91,11 +91,12 @@ export class TickTable { ), ); } - const [rowNumber, bitNumber] = TickTable.position(tick); - isWordPosOut(rowNumber, state.startTickBitmap, isPriceQuery); - let tickBitmapValue = state.tickBitmap[rowNumber.toString()]; - tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; if (lte) { + const [rowNumber, bitNumber] = TickTable.position(tick); + isWordPosOut(rowNumber, state.startTickBitmap, isPriceQuery); + let tickBitmapValue = state.tickBitmap[rowNumber.toString()]; + tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; + const _row = tickBitmapValue << (255n - bitNumber); if (_row != 0n) { tick -= BigInt.asIntN(24, 255n - TickTable.getMostSignificantBit(_row)); @@ -106,6 +107,12 @@ export class TickTable { } } else { tick += 1n; + + const [rowNumber, bitNumber] = TickTable.position(tick); + isWordPosOut(rowNumber, state.startTickBitmap, isPriceQuery); + let tickBitmapValue = state.tickBitmap[rowNumber.toString()]; + tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; + const _row = tickBitmapValue >> bitNumber; if (_row !== 0n) { tick += BigInt.asIntN( diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 004aa98b0..cf0284848 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -785,14 +785,14 @@ export const Tokens: { address: '0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f', decimals: 8, }, - USDCe: { - address: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', - decimals: 6, - }, LEX: { address: '0x6bB7A17AcC227fd1F6781D1EEDEAE01B42047eE0', decimals: 18, }, + GRAIL: { + address: '0x3d9907f9a368ad0a51be60f7da3b97cf940982d8', + decimals: 18, + }, }, [Network.OPTIMISM]: { DAI: { From 9352c584bb75679e718217b914693ebb22520fa8 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 16 Aug 2023 13:19:49 +0100 Subject: [PATCH 050/833] fix: leave only one test case --- src/dex/algebra/algebra-integration.test.ts | 317 ++++++++++---------- 1 file changed, 159 insertions(+), 158 deletions(-) diff --git a/src/dex/algebra/algebra-integration.test.ts b/src/dex/algebra/algebra-integration.test.ts index 9946b7252..3a067f806 100644 --- a/src/dex/algebra/algebra-integration.test.ts +++ b/src/dex/algebra/algebra-integration.test.ts @@ -172,34 +172,35 @@ describe('CamelotV3', function () { const amountsForSell = [ 0n, - 10_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 10_000n * BI_POWS[tokens[srcTokenSymbol].decimals], 20000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 30_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 40_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 50_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 60_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 70_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 80_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 90_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 100_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 30_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 40_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 50_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 60_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 70_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 80_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 90_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 100_000n * BI_POWS[tokens[srcTokenSymbol].decimals], ]; - const amountsForBuy = [ - 0n, - 1n * BI_POWS[tokens[destTokenSymbol].decimals], - 2n * BI_POWS[tokens[destTokenSymbol].decimals], - 3n * BI_POWS[tokens[destTokenSymbol].decimals], - 4n * BI_POWS[tokens[destTokenSymbol].decimals], - 5n * BI_POWS[tokens[destTokenSymbol].decimals], - 6n * BI_POWS[tokens[destTokenSymbol].decimals], - 7n * BI_POWS[tokens[destTokenSymbol].decimals], - 8n * BI_POWS[tokens[destTokenSymbol].decimals], - 9n * BI_POWS[tokens[destTokenSymbol].decimals], - 10n * BI_POWS[tokens[destTokenSymbol].decimals], - ]; + // const amountsForBuy = [ + // 0n, + // 1n * BI_POWS[tokens[destTokenSymbol].decimals], + // 2n * BI_POWS[tokens[destTokenSymbol].decimals], + // 3n * BI_POWS[tokens[destTokenSymbol].decimals], + // 4n * BI_POWS[tokens[destTokenSymbol].decimals], + // 5n * BI_POWS[tokens[destTokenSymbol].decimals], + // 6n * BI_POWS[tokens[destTokenSymbol].decimals], + // 7n * BI_POWS[tokens[destTokenSymbol].decimals], + // 8n * BI_POWS[tokens[destTokenSymbol].decimals], + // 9n * BI_POWS[tokens[destTokenSymbol].decimals], + // 10n * BI_POWS[tokens[destTokenSymbol].decimals], + // ]; beforeAll(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + // blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + blockNumber = 121923156; algebra = new Algebra(network, dexKey, dexHelper); if (algebra.initializePricing) { await algebra.initializePricing(blockNumber); @@ -221,140 +222,140 @@ describe('CamelotV3', function () { ); }); - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - await testPricingOnNetwork( - algebra, - network, - dexKey, - dexHelper, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.BUY, - amountsForBuy, - 'quoteExactOutputSingle', - ); - }); - - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - const newAlgebra = new Algebra(network, dexKey, dexHelper); - const poolLiquidity = await newAlgebra.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, - ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - - if (!newAlgebra.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, - dexKey, - ); - } - }); - }); -}); - -describe('Algebra', function () { - const dexKey = 'QuickSwapV3'; - let blockNumber: number; - let algebra: Algebra; - - describe('Polygon', () => { - const network = Network.POLYGON; - const dexHelper = new DummyDexHelper(network); - - const tokens = Tokens[network]; - - const srcTokenSymbol = 'WMATIC'; - const destTokenSymbol = 'DAI'; - // const destTokenSymbol = 'USDC'; - - const amountsForSell = [ - 0n, - 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - 10n * BI_POWS[tokens[srcTokenSymbol].decimals], - ]; - - const amountsForBuy = [ - 0n, - 1n * BI_POWS[tokens[destTokenSymbol].decimals], - 2n * BI_POWS[tokens[destTokenSymbol].decimals], - 3n * BI_POWS[tokens[destTokenSymbol].decimals], - 4n * BI_POWS[tokens[destTokenSymbol].decimals], - 5n * BI_POWS[tokens[destTokenSymbol].decimals], - 6n * BI_POWS[tokens[destTokenSymbol].decimals], - 7n * BI_POWS[tokens[destTokenSymbol].decimals], - 8n * BI_POWS[tokens[destTokenSymbol].decimals], - 9n * BI_POWS[tokens[destTokenSymbol].decimals], - 10n * BI_POWS[tokens[destTokenSymbol].decimals], - ]; - - beforeAll(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - algebra = new Algebra(network, dexKey, dexHelper); - if (algebra.initializePricing) { - await algebra.initializePricing(blockNumber); - } - }); - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - await testPricingOnNetwork( - algebra, - network, - dexKey, - dexHelper, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.SELL, - amountsForSell, - 'quoteExactInputSingle', - ); - }); - - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - await testPricingOnNetwork( - algebra, - network, - dexKey, - dexHelper, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.BUY, - amountsForBuy, - 'quoteExactOutputSingle', - ); - }); - - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - const newAlgebra = new Algebra(network, dexKey, dexHelper); - const poolLiquidity = await newAlgebra.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, - ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - - if (!newAlgebra.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, - dexKey, - ); - } - }); + // it('getPoolIdentifiers and getPricesVolume BUY', async function () { + // await testPricingOnNetwork( + // algebra, + // network, + // dexKey, + // dexHelper, + // blockNumber, + // srcTokenSymbol, + // destTokenSymbol, + // SwapSide.BUY, + // amountsForBuy, + // 'quoteExactOutputSingle', + // ); + // }); + // + // it('getTopPoolsForToken', async function () { + // // We have to check without calling initializePricing, because + // // pool-tracker is not calling that function + // const newAlgebra = new Algebra(network, dexKey, dexHelper); + // const poolLiquidity = await newAlgebra.getTopPoolsForToken( + // tokens[srcTokenSymbol].address, + // 10, + // ); + // console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + // + // if (!newAlgebra.hasConstantPriceLargeAmounts) { + // checkPoolsLiquidity( + // poolLiquidity, + // Tokens[network][srcTokenSymbol].address, + // dexKey, + // ); + // } + // }); + // }); + // }); + // + // describe('Algebra', function () { + // const dexKey = 'QuickSwapV3'; + // let blockNumber: number; + // let algebra: Algebra; + // + // describe('Polygon', () => { + // const network = Network.POLYGON; + // const dexHelper = new DummyDexHelper(network); + // + // const tokens = Tokens[network]; + // + // const srcTokenSymbol = 'WMATIC'; + // const destTokenSymbol = 'DAI'; + // // const destTokenSymbol = 'USDC'; + // + // const amountsForSell = [ + // 0n, + // 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + // ]; + // + // const amountsForBuy = [ + // 0n, + // 1n * BI_POWS[tokens[destTokenSymbol].decimals], + // 2n * BI_POWS[tokens[destTokenSymbol].decimals], + // 3n * BI_POWS[tokens[destTokenSymbol].decimals], + // 4n * BI_POWS[tokens[destTokenSymbol].decimals], + // 5n * BI_POWS[tokens[destTokenSymbol].decimals], + // 6n * BI_POWS[tokens[destTokenSymbol].decimals], + // 7n * BI_POWS[tokens[destTokenSymbol].decimals], + // 8n * BI_POWS[tokens[destTokenSymbol].decimals], + // 9n * BI_POWS[tokens[destTokenSymbol].decimals], + // 10n * BI_POWS[tokens[destTokenSymbol].decimals], + // ]; + // + // beforeAll(async () => { + // blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + // algebra = new Algebra(network, dexKey, dexHelper); + // if (algebra.initializePricing) { + // await algebra.initializePricing(blockNumber); + // } + // }); + // + // it('getPoolIdentifiers and getPricesVolume SELL', async function () { + // await testPricingOnNetwork( + // algebra, + // network, + // dexKey, + // dexHelper, + // blockNumber, + // srcTokenSymbol, + // destTokenSymbol, + // SwapSide.SELL, + // amountsForSell, + // 'quoteExactInputSingle', + // ); + // }); + // + // it('getPoolIdentifiers and getPricesVolume BUY', async function () { + // await testPricingOnNetwork( + // algebra, + // network, + // dexKey, + // dexHelper, + // blockNumber, + // srcTokenSymbol, + // destTokenSymbol, + // SwapSide.BUY, + // amountsForBuy, + // 'quoteExactOutputSingle', + // ); + // }); + // + // it('getTopPoolsForToken', async function () { + // // We have to check without calling initializePricing, because + // // pool-tracker is not calling that function + // const newAlgebra = new Algebra(network, dexKey, dexHelper); + // const poolLiquidity = await newAlgebra.getTopPoolsForToken( + // tokens[srcTokenSymbol].address, + // 10, + // ); + // console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + // + // if (!newAlgebra.hasConstantPriceLargeAmounts) { + // checkPoolsLiquidity( + // poolLiquidity, + // Tokens[network][srcTokenSymbol].address, + // dexKey, + // ); + // } + // }); }); }); From 12f25290f934fd8b9aae6b8ec6704fff27e3ec89 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 16 Aug 2023 14:51:11 +0100 Subject: [PATCH 051/833] fix: use propoer bitwise operators --- src/dex/algebra/algebra-integration.test.ts | 336 ++++++++++---------- src/dex/algebra/algebra.ts | 2 +- src/dex/algebra/lib/TickTable.ts | 113 +++---- 3 files changed, 213 insertions(+), 238 deletions(-) diff --git a/src/dex/algebra/algebra-integration.test.ts b/src/dex/algebra/algebra-integration.test.ts index 3a067f806..ede850b48 100644 --- a/src/dex/algebra/algebra-integration.test.ts +++ b/src/dex/algebra/algebra-integration.test.ts @@ -15,21 +15,6 @@ import { import { Tokens } from '../../../tests/constants-e2e'; import { Address } from '@paraswap/core'; -/* - README - ====== - - This test script adds tests for Algebra general integration - with the DEX interface. The test cases below are example tests. - It is recommended to add tests which cover Algebra specific - logic. - - You can run this individual test script by running: - `npx jest src/dex//-integration.test.ts` - - (This comment should be removed from the final implementation) -*/ - function getReaderCalldata( exchangeAddress: string, readerIface: Interface, @@ -70,7 +55,7 @@ async function checkOnChainPricing( tokenOut: Address, amounts: bigint[], ) { - const exchangeAddress = '0xa15f0d7377b2a0c0c10db057f641bed21028fc89'; // Quoter address + const exchangeAddress = algebra.config.quoter; const readerIface = algebra.quoterIface; @@ -172,35 +157,34 @@ describe('CamelotV3', function () { const amountsForSell = [ 0n, - // 10_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 20000n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 30_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 40_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 50_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 60_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 70_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 80_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 90_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 100_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 20_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 30_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 40_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 50_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 60_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 70_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 80_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 90_000n * BI_POWS[tokens[srcTokenSymbol].decimals], + 100_000n * BI_POWS[tokens[srcTokenSymbol].decimals], ]; - // const amountsForBuy = [ - // 0n, - // 1n * BI_POWS[tokens[destTokenSymbol].decimals], - // 2n * BI_POWS[tokens[destTokenSymbol].decimals], - // 3n * BI_POWS[tokens[destTokenSymbol].decimals], - // 4n * BI_POWS[tokens[destTokenSymbol].decimals], - // 5n * BI_POWS[tokens[destTokenSymbol].decimals], - // 6n * BI_POWS[tokens[destTokenSymbol].decimals], - // 7n * BI_POWS[tokens[destTokenSymbol].decimals], - // 8n * BI_POWS[tokens[destTokenSymbol].decimals], - // 9n * BI_POWS[tokens[destTokenSymbol].decimals], - // 10n * BI_POWS[tokens[destTokenSymbol].decimals], - // ]; + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals], + 2n * BI_POWS[tokens[destTokenSymbol].decimals], + 3n * BI_POWS[tokens[destTokenSymbol].decimals], + 4n * BI_POWS[tokens[destTokenSymbol].decimals], + 5n * BI_POWS[tokens[destTokenSymbol].decimals], + 6n * BI_POWS[tokens[destTokenSymbol].decimals], + 7n * BI_POWS[tokens[destTokenSymbol].decimals], + 8n * BI_POWS[tokens[destTokenSymbol].decimals], + 9n * BI_POWS[tokens[destTokenSymbol].decimals], + 10n * BI_POWS[tokens[destTokenSymbol].decimals], + ]; beforeAll(async () => { - // blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - blockNumber = 121923156; + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); algebra = new Algebra(network, dexKey, dexHelper); if (algebra.initializePricing) { await algebra.initializePricing(blockNumber); @@ -222,140 +206,140 @@ describe('CamelotV3', function () { ); }); - // it('getPoolIdentifiers and getPricesVolume BUY', async function () { - // await testPricingOnNetwork( - // algebra, - // network, - // dexKey, - // dexHelper, - // blockNumber, - // srcTokenSymbol, - // destTokenSymbol, - // SwapSide.BUY, - // amountsForBuy, - // 'quoteExactOutputSingle', - // ); - // }); - // - // it('getTopPoolsForToken', async function () { - // // We have to check without calling initializePricing, because - // // pool-tracker is not calling that function - // const newAlgebra = new Algebra(network, dexKey, dexHelper); - // const poolLiquidity = await newAlgebra.getTopPoolsForToken( - // tokens[srcTokenSymbol].address, - // 10, - // ); - // console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - // - // if (!newAlgebra.hasConstantPriceLargeAmounts) { - // checkPoolsLiquidity( - // poolLiquidity, - // Tokens[network][srcTokenSymbol].address, - // dexKey, - // ); - // } - // }); - // }); - // }); - // - // describe('Algebra', function () { - // const dexKey = 'QuickSwapV3'; - // let blockNumber: number; - // let algebra: Algebra; - // - // describe('Polygon', () => { - // const network = Network.POLYGON; - // const dexHelper = new DummyDexHelper(network); - // - // const tokens = Tokens[network]; - // - // const srcTokenSymbol = 'WMATIC'; - // const destTokenSymbol = 'DAI'; - // // const destTokenSymbol = 'USDC'; - // - // const amountsForSell = [ - // 0n, - // 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 10n * BI_POWS[tokens[srcTokenSymbol].decimals], - // ]; - // - // const amountsForBuy = [ - // 0n, - // 1n * BI_POWS[tokens[destTokenSymbol].decimals], - // 2n * BI_POWS[tokens[destTokenSymbol].decimals], - // 3n * BI_POWS[tokens[destTokenSymbol].decimals], - // 4n * BI_POWS[tokens[destTokenSymbol].decimals], - // 5n * BI_POWS[tokens[destTokenSymbol].decimals], - // 6n * BI_POWS[tokens[destTokenSymbol].decimals], - // 7n * BI_POWS[tokens[destTokenSymbol].decimals], - // 8n * BI_POWS[tokens[destTokenSymbol].decimals], - // 9n * BI_POWS[tokens[destTokenSymbol].decimals], - // 10n * BI_POWS[tokens[destTokenSymbol].decimals], - // ]; - // - // beforeAll(async () => { - // blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - // algebra = new Algebra(network, dexKey, dexHelper); - // if (algebra.initializePricing) { - // await algebra.initializePricing(blockNumber); - // } - // }); - // - // it('getPoolIdentifiers and getPricesVolume SELL', async function () { - // await testPricingOnNetwork( - // algebra, - // network, - // dexKey, - // dexHelper, - // blockNumber, - // srcTokenSymbol, - // destTokenSymbol, - // SwapSide.SELL, - // amountsForSell, - // 'quoteExactInputSingle', - // ); - // }); - // - // it('getPoolIdentifiers and getPricesVolume BUY', async function () { - // await testPricingOnNetwork( - // algebra, - // network, - // dexKey, - // dexHelper, - // blockNumber, - // srcTokenSymbol, - // destTokenSymbol, - // SwapSide.BUY, - // amountsForBuy, - // 'quoteExactOutputSingle', - // ); - // }); - // - // it('getTopPoolsForToken', async function () { - // // We have to check without calling initializePricing, because - // // pool-tracker is not calling that function - // const newAlgebra = new Algebra(network, dexKey, dexHelper); - // const poolLiquidity = await newAlgebra.getTopPoolsForToken( - // tokens[srcTokenSymbol].address, - // 10, - // ); - // console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - // - // if (!newAlgebra.hasConstantPriceLargeAmounts) { - // checkPoolsLiquidity( - // poolLiquidity, - // Tokens[network][srcTokenSymbol].address, - // dexKey, - // ); - // } - // }); + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + algebra, + network, + dexKey, + dexHelper, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + 'quoteExactOutputSingle', + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newAlgebra = new Algebra(network, dexKey, dexHelper); + const poolLiquidity = await newAlgebra.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newAlgebra.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); + }); +}); + +describe('Algebra', function () { + const dexKey = 'QuickSwapV3'; + let blockNumber: number; + let algebra: Algebra; + + describe('Polygon', () => { + const network = Network.POLYGON; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + + const srcTokenSymbol = 'WMATIC'; + const destTokenSymbol = 'DAI'; + // const destTokenSymbol = 'USDC'; + + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals], + 2n * BI_POWS[tokens[destTokenSymbol].decimals], + 3n * BI_POWS[tokens[destTokenSymbol].decimals], + 4n * BI_POWS[tokens[destTokenSymbol].decimals], + 5n * BI_POWS[tokens[destTokenSymbol].decimals], + 6n * BI_POWS[tokens[destTokenSymbol].decimals], + 7n * BI_POWS[tokens[destTokenSymbol].decimals], + 8n * BI_POWS[tokens[destTokenSymbol].decimals], + 9n * BI_POWS[tokens[destTokenSymbol].decimals], + 10n * BI_POWS[tokens[destTokenSymbol].decimals], + ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + algebra = new Algebra(network, dexKey, dexHelper); + if (algebra.initializePricing) { + await algebra.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + algebra, + network, + dexKey, + dexHelper, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + 'quoteExactInputSingle', + ); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + algebra, + network, + dexKey, + dexHelper, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + 'quoteExactOutputSingle', + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newAlgebra = new Algebra(network, dexKey, dexHelper); + const poolLiquidity = await newAlgebra.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newAlgebra.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); }); }); diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 8814861a5..3b4ad6e55 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -88,7 +88,7 @@ export class Algebra extends SimpleExchange implements IDex { protected adapters = Adapters[network] || {}, readonly routerIface = new Interface(UniswapV3RouterABI), // same abi as uniswapV3 readonly quoterIface = new Interface(AlgebraQuoterABI), - protected config = AlgebraConfig[dexKey][network], + readonly config = AlgebraConfig[dexKey][network], ) { super(dexHelper, dexKey); this.logger = dexHelper.getLogger(dexKey + '-' + network); diff --git a/src/dex/algebra/lib/TickTable.ts b/src/dex/algebra/lib/TickTable.ts index 5bb8365f8..afd86c816 100644 --- a/src/dex/algebra/lib/TickTable.ts +++ b/src/dex/algebra/lib/TickTable.ts @@ -130,80 +130,71 @@ export class TickTable { static getSingleSignificantBit(word: bigint): bigint { let singleBitPos = 0n; singleBitPos = Yul.iszero( - word && - BigInt( - '0x5555555555555555555555555555555555555555555555555555555555555555', - ), + word & + 0x5555555555555555555555555555555555555555555555555555555555555555n, ); singleBitPos = - singleBitPos || - Yul.iszero( - word && - BigInt( - '0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff', - ), - ) << 7n; + singleBitPos | + (Yul.iszero( + word & + 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffffn, + ) << + 7n); singleBitPos = - singleBitPos || - Yul.iszero( - word && - BigInt( - '0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff', - ), - ) << 6n; + singleBitPos | + (Yul.iszero( + word & + 0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffffn, + ) << + 6n); singleBitPos = - singleBitPos || - Yul.iszero( - word && - BigInt( - '0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff', - ), - ) << 5n; + singleBitPos | + (Yul.iszero( + word & + 0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffffn, + ) << + 5n); singleBitPos = - singleBitPos || - Yul.iszero( - word && - BigInt( - '0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff', - ), - ) << 4n; + singleBitPos | + (Yul.iszero( + word & + 0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffffn, + ) << + 4n); singleBitPos = - singleBitPos || - Yul.iszero( - word && - BigInt( - '0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff', - ), - ) << 3n; + singleBitPos | + (Yul.iszero( + word & + 0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ffn, + ) << + 3n); singleBitPos = - singleBitPos || - Yul.iszero( - word && - BigInt( - '0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f', - ), - ) << 2n; + singleBitPos | + (Yul.iszero( + word & + 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0fn, + ) << + 2n); singleBitPos = - singleBitPos || - Yul.iszero( - word && - BigInt( - '0x3333333333333333333333333333333333333333333333333333333333333333', - ), - ) << 1n; + singleBitPos | + (Yul.iszero( + word & + 0x3333333333333333333333333333333333333333333333333333333333333333n, + ) << + 1n); return BigInt.asUintN(8, singleBitPos); } static getMostSignificantBit(word: bigint): bigint { - word = word || word >> 1n; - word = word || word >> 2n; - word = word || word >> 4n; - word = word || word >> 8n; - word = word || word >> 16n; - word = word || word >> 32n; - word = word || word >> 64n; - word = word || word >> 128n; + word = word | (word >> 1n); + word = word | (word >> 2n); + word = word | (word >> 4n); + word = word | (word >> 8n); + word = word | (word >> 16n); + word = word | (word >> 32n); + word = word | (word >> 64n); + word = word | (word >> 128n); word = word - (word >> 1n); return TickTable.getSingleSignificantBit(BigInt.asUintN(256, word)); } From 495f4df4dab165c1b6688fe1529141d63617d469 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 16 Aug 2023 14:55:15 +0100 Subject: [PATCH 052/833] chore: remove commented token --- src/dex/algebra/algebra-integration.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dex/algebra/algebra-integration.test.ts b/src/dex/algebra/algebra-integration.test.ts index ede850b48..d64181c11 100644 --- a/src/dex/algebra/algebra-integration.test.ts +++ b/src/dex/algebra/algebra-integration.test.ts @@ -153,7 +153,6 @@ describe('CamelotV3', function () { const srcTokenSymbol = 'USDCe'; const destTokenSymbol = 'GRAIL'; - // const destTokenSymbol = 'USDC'; const amountsForSell = [ 0n, From 9274e31c32e8c5ba7309c19168551bac832f3d29 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 16 Aug 2023 14:55:56 +0100 Subject: [PATCH 053/833] 2.28.10-camelot-v3-tick-bugs.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4aa5e4e84..7f5f60c32 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.9", + "version": "2.28.10-camelot-v3-tick-bugs.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 02b39aa8869c282e6d8e02f1c6eb4a4cb7c0a442 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 17 Aug 2023 14:36:44 +0300 Subject: [PATCH 054/833] debug --- src/dex/index.ts | 4 +- src/dex/ramses-v2/ramses-v2-pool.ts | 39 +- src/dex/uniswap-v3/config.ts | 22 + src/dex/uniswap-v3/forks/ramses-v2/utils.ts | 72 ++ src/dex/uniswap-v3/types.ts | 8 +- src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 799 +++++++++++--------- src/dex/uniswap-v3/uniswap-v3-pool.ts | 17 +- src/dex/uniswap-v3/uniswap-v3.ts | 14 +- tests/utils-e2e.ts | 1 - 9 files changed, 576 insertions(+), 400 deletions(-) create mode 100644 src/dex/uniswap-v3/forks/ramses-v2/utils.ts diff --git a/src/dex/index.ts b/src/dex/index.ts index ea9fad3ef..d7c0d627e 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -69,7 +69,7 @@ import { SwaapV2 } from './swaap-v2/swaap-v2'; import { SpiritSwapV3 } from './quickswap/spiritswap-v3'; import { TraderJoeV21 } from './trader-joe-v2.1'; import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3'; -import { RamsesV2 } from './ramses-v2/ramses-v2'; +// import { RamsesV2 } from './ramses-v2/ramses-v2'; import { Algebra } from './algebra/algebra'; const LegacyDexes = [ @@ -138,7 +138,7 @@ const Dexes = [ MaverickV1, Camelot, SwaapV2, - RamsesV2, + // RamsesV2, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< diff --git a/src/dex/ramses-v2/ramses-v2-pool.ts b/src/dex/ramses-v2/ramses-v2-pool.ts index b68af23a3..7f064a6f1 100644 --- a/src/dex/ramses-v2/ramses-v2-pool.ts +++ b/src/dex/ramses-v2/ramses-v2-pool.ts @@ -30,6 +30,7 @@ import { import { TickBitMap } from './contract-math/TickBitMap'; import { uint256ToBigInt } from '../../lib/decoders'; import { decodeStateMultiCallResultWithRelativeBitmaps } from './utils'; +import { _reduceTickBitmap, _reduceTicks } from '../uniswap-v3/contract-math/utils'; export class RamsesV2EventPool extends StatefulEventSubscriber { handlers: { @@ -267,8 +268,8 @@ export class RamsesV2EventPool extends StatefulEventSubscriber { const tickBitmap = {}; const ticks = {}; - this._reduceTickBitmap(tickBitmap, _state.tickBitmap); - this._reduceTicks(ticks, _state.ticks); + _reduceTickBitmap(tickBitmap, _state.tickBitmap); + _reduceTicks(ticks, _state.ticks); const observations = { [_state.slot0.observationIndex]: { @@ -488,40 +489,6 @@ export class RamsesV2EventPool extends StatefulEventSubscriber { return pool; } - private _reduceTickBitmap( - tickBitmap: Record, - tickBitmapToReduce: TickBitMapMappingsWithBigNumber[], - ) { - return tickBitmapToReduce.reduce>( - (acc, curr) => { - const { index, value } = curr; - acc[index] = bigIntify(value); - return acc; - }, - tickBitmap, - ); - } - - private _reduceTicks( - ticks: Record, - ticksToReduce: TickInfoMappingsWithBigNumber[], - ) { - return ticksToReduce.reduce>((acc, curr) => { - const { index, value } = curr; - acc[index] = { - liquidityGross: bigIntify(value.liquidityGross), - liquidityNet: bigIntify(value.liquidityNet), - tickCumulativeOutside: bigIntify(value.tickCumulativeOutside), - secondsPerLiquidityOutsideX128: bigIntify( - value.secondsPerLiquidityOutsideX128, - ), - secondsOutside: bigIntify(value.secondsOutside), - initialized: value.initialized, - }; - return acc; - }, ticks); - } - private _computePoolAddress( token0: Address, token1: Address, diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index c1c74165f..18a66c612 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -2,6 +2,9 @@ import { DexParams } from './types'; import { DexConfigMap, AdapterMappings } from '../../types'; import { Network, SwapSide } from '../../constants'; import { Address } from '../../types'; +import RamsesV2StateMulticallABI from '../../abi/RamsesV2StateMulticall.abi.json'; +import { AbiItem } from 'web3-utils'; +import { decodeStateMultiCallResultWithRelativeBitmaps } from './forks/ramses-v2/utils'; const SUPPORTED_FEES = [10000n, 3000n, 500n, 100n]; @@ -104,6 +107,25 @@ export const UniswapV3Config: DexConfigMap = { 'https://api.thegraph.com/subgraphs/name/lynnshaoyu/uniswap-v3-avax', }, }, + RamsesV2: { + [Network.ARBITRUM]: { + factory: '0xAA2cd7477c451E703f3B9Ba5663334914763edF8', + deployer: '0xb3e423ab9cE6C03D98326A3A2a0D7D96b0829f22', + quoter: '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', + router: '0xAA23611badAFB62D37E7295A682D21960ac85A90', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x50EE4112Cab9c79812F23bE079aB3911395ACc8e', + stateMultiCallAbi: RamsesV2StateMulticallABI as AbiItem[], + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + decodeStateMultiCallResultWithRelativeBitmaps, + initHash: + '0x1565b129f2d1790f12d45301b9b084335626f0c92410bc43130763b69971135d', + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/ramsesexchange/concentrated-liquidity-graph', + }, + }, 'QuickSwapV3.1': { [Network.ZKEVM]: { factory: '0xD9a2AD9E927Bd7014116CC5c7328f028D4318178', diff --git a/src/dex/uniswap-v3/forks/ramses-v2/utils.ts b/src/dex/uniswap-v3/forks/ramses-v2/utils.ts new file mode 100644 index 000000000..c6032107e --- /dev/null +++ b/src/dex/uniswap-v3/forks/ramses-v2/utils.ts @@ -0,0 +1,72 @@ +import { MultiResult } from '../../../../lib/multi-wrapper'; +import { BytesLike, ethers } from 'ethers'; +import { DecodedStateMultiCallResultWithRelativeBitmaps } from '../../../ramses-v2/types'; +import { extractSuccessAndValue } from '../../../../lib/decoders'; +import { assert } from 'ts-essentials'; + +export function decodeStateMultiCallResultWithRelativeBitmaps( + result: MultiResult | BytesLike, +): DecodedStateMultiCallResultWithRelativeBitmaps { + const [isSuccess, toDecode] = extractSuccessAndValue(result); + + assert( + isSuccess && toDecode !== '0x', + `decodeStateMultiCallResultWithRelativeBitmaps failed to get decodable result: ${result}`, + ); + + const decoded = ethers.utils.defaultAbiCoder.decode( + [ + // I don't want to pass here any interface, so I just use it in ethers format + ` + tuple( + address pool, + uint256 blockTimestamp, + tuple( + uint160 sqrtPriceX96, + int24 tick, + uint16 observationIndex, + uint16 observationCardinality, + uint16 observationCardinalityNext, + uint8 feeProtocol, + bool unlocked, + ) slot0, + uint128 liquidity, + int24 tickSpacing, + uint128 maxLiquidityPerTick, + tuple( + uint32 blockTimestamp, + int56 tickCumulative, + uint160 secondsPerLiquidityCumulativeX128, + bool initialized, + uint160 secondsPerBoostedLiquidityPeriodX128, + uint32 boostedInRange, + ) observation, + tuple( + int16 index, + uint256 value + )[] tickBitmap, + tuple( + int24 index, + tuple( + uint128 liquidityGross, + int128 liquidityNet, + uint128 cleanUnusedSlot, + uint128 cleanUnusedSlot2, + uint256 feeGrowthOutside0X128, + uint256 feeGrowthOutside1X128, + int56 tickCumulativeOutside, + uint160 secondsPerLiquidityOutsideX128, + uint32 secondsOutside, + bool initialized, + ) value, + )[] ticks + ) + `, + ], + toDecode, + )[0]; + + // This conversion is not precise, because when we decode, we have more values + // But I typed only the ones that are used later + return decoded as DecodedStateMultiCallResultWithRelativeBitmaps; +} diff --git a/src/dex/uniswap-v3/types.ts b/src/dex/uniswap-v3/types.ts index c3fd7890c..e5d70200d 100644 --- a/src/dex/uniswap-v3/types.ts +++ b/src/dex/uniswap-v3/types.ts @@ -1,6 +1,8 @@ -import { BigNumber } from 'ethers'; +import { BigNumber, BytesLike } from 'ethers'; import { NumberAsString } from '../../types'; import { Address } from '../../types'; +import { AbiItem } from 'web3-utils'; +import { MultiResult } from '../../lib/multi-wrapper'; export type OracleObservation = { blockTimestamp: bigint; @@ -60,6 +62,8 @@ export type UniswapV3Data = { isApproved?: boolean; }; +export type DecodeStateMultiCallFunc = (result: MultiResult | BytesLike) => DecodedStateMultiCallResultWithRelativeBitmaps; + export type DexParams = { router: Address; quoter: Address; @@ -72,6 +76,8 @@ export type DexParams = { deployer?: Address; subgraphURL: string; initHash: string; + stateMultiCallAbi?: AbiItem[]; + decodeStateMultiCallResultWithRelativeBitmaps? : DecodeStateMultiCallFunc, }; export type UniswapV3SimpleSwapSellParam = { diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index f417648c7..bccf2bf69 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -12,402 +12,493 @@ import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; describe('UniswapV3 E2E', () => { - const dexKey = 'UniswapV3'; - describe('UniswapV3 MAINNET', () => { - const network = Network.MAINNET; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); + describe('UniswapV3', () => { + const dexKey = 'UniswapV3'; - it('BUY DAI -> USDC', async () => { - await testE2E( - tokens['DAI'], - tokens['USDC'], - holders['DAI'], - '100000000000', - SwapSide.BUY, - dexKey, - ContractMethod.simpleBuy, + describe('UniswapV3 MAINNET', () => { + const network = Network.MAINNET; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, network, - provider, - ); - }); - it('SELL WETH -> SHIBA', async () => { - await testE2E( - tokens['WETH'], - tokens['SHIBA'], - holders['WETH'], - '1000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.simpleSwap, - network, - provider, ); + + it('BUY DAI -> USDC', async () => { + await testE2E( + tokens['DAI'], + tokens['USDC'], + holders['DAI'], + '100000000000', + SwapSide.BUY, + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + it('SELL WETH -> SHIBA', async () => { + await testE2E( + tokens['WETH'], + tokens['SHIBA'], + holders['WETH'], + '1000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('directSwap SELL WETH -> USDC', async () => { + await testE2E( + tokens['WETH'], + tokens['USDC'], + holders['WETH'], + '1000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.directUniV3Swap, + network, + provider, + ); + }); }); - it('directSwap SELL WETH -> USDC', async () => { - await testE2E( - tokens['WETH'], - tokens['USDC'], - holders['WETH'], - '1000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.directUniV3Swap, + describe('UniswapV3 POLYGON', () => { + const network = Network.POLYGON; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, network, - provider, ); - }); - }); - - describe('UniswapV3 POLYGON', () => { - const network = Network.POLYGON; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'WETH'; - const nativeTokenSymbol = NativeTokenSymbols[network]; + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'WETH'; + const nativeTokenSymbol = NativeTokenSymbols[network]; - const tokenAAmount: string = '11000000'; - const tokenBAmount: string = '11000000000000000000'; - const nativeTokenAmount = '11000000000000000000'; + const tokenAAmount: string = '11000000'; + const tokenBAmount: string = '11000000000000000000'; + const nativeTokenAmount = '11000000000000000000'; - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, + const sideToContractMethods = new Map([ [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ContractMethod.directUniV3Swap, + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], ], - ], - [ - SwapSide.BUY, [ - ContractMethod.simpleBuy, - ContractMethod.buy, - ContractMethod.directUniV3Buy, + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, + ], ], - ], - ]); + ]); - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); }); - }); - }), - ); - }); + }), + ); + }); - describe('UniswapV3 BSC', () => { - const network = Network.BSC; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); + describe('UniswapV3 BSC', () => { + const network = Network.BSC; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); - const tokenASymbol: string = 'BUSD'; - const tokenBSymbol: string = 'WBNB'; - const nativeTokenSymbol = NativeTokenSymbols[network]; + const tokenASymbol: string = 'BUSD'; + const tokenBSymbol: string = 'WBNB'; + const nativeTokenSymbol = NativeTokenSymbols[network]; - const tokenAAmount: string = '100000000000000000000'; - const tokenBAmount: string = '1000000000000000000'; - const nativeTokenAmount = '1000000000000000000'; + const tokenAAmount: string = '100000000000000000000'; + const tokenBAmount: string = '1000000000000000000'; + const nativeTokenAmount = '1000000000000000000'; - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, + const sideToContractMethods = new Map([ [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], ], - ], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - ]); + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); }); - }); - }), - ); - }); + }), + ); + }); - describe('UniswapV3 Optimism', () => { - const network = Network.OPTIMISM; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); + describe('UniswapV3 Optimism', () => { + const network = Network.OPTIMISM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); - const tokenASymbol: string = 'OP'; - const tokenBSymbol: string = 'ETH'; - const nativeTokenSymbol = NativeTokenSymbols[network]; + const tokenASymbol: string = 'OP'; + const tokenBSymbol: string = 'ETH'; + const nativeTokenSymbol = NativeTokenSymbols[network]; - const tokenAAmount: string = '1000000000000000000'; - const tokenBAmount: string = '1000000000000000000'; - const nativeTokenAmount = '1000000000000000000'; + const tokenAAmount: string = '1000000000000000000'; + const tokenBAmount: string = '1000000000000000000'; + const nativeTokenAmount = '1000000000000000000'; - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, + const sideToContractMethods = new Map([ [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], ], - ], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - ]); + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); + }), + ); + }); + + describe('UniswapV3 Avalanche', () => { + const network = Network.AVALANCHE; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ + [ + { + name: 'AVAX', + sellAmount: '1000000000000000000', + buyAmount: '500000', + }, + { + name: 'USDT', + sellAmount: '1000000', + buyAmount: '10000000000000000000', + }, + ], + [ + { + name: 'AVAX', + sellAmount: '1000000000000000000', + buyAmount: '500000', + }, + { + name: 'USDC', + sellAmount: '1000000', + buyAmount: '1000000000000000000', + }, + ], + [ + { + name: 'WAVAX', + sellAmount: '1000000000000000000', + buyAmount: '500000', + }, + { name: 'USDC', sellAmount: '1000000', buyAmount: '20000000000000000' }, + ], + [ + { + name: 'WAVAX', + sellAmount: '1000000000000000000', + buyAmount: '10000000', + }, + { name: 'USDT', sellAmount: '1000000', buyAmount: '2000000000000' }, + ], + [ + { name: 'USDC', sellAmount: '1000000', buyAmount: '100000000' }, + { name: 'USDT', sellAmount: '100000000', buyAmount: '100000000' }, + ], + ]; + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); }); - }); - }), - ); + }), + ); + }); }); - describe('UniswapV3 Avalanche', () => { - const network = Network.AVALANCHE; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); + describe('RamsesV2', () => { + const dexKey = 'RamsesV2'; + + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'USDCe'; + const tokenBSymbol: string = 'USDT'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '1100000'; + const tokenBAmount: string = '1000000'; + const nativeTokenAmount = '1100000000000'; - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, + const sideToContractMethods = new Map([ [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], ], - ], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - ]); - - const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ - [ - { - name: 'AVAX', - sellAmount: '1000000000000000000', - buyAmount: '500000', - }, - { - name: 'USDT', - sellAmount: '1000000', - buyAmount: '10000000000000000000', - }, - ], - [ - { - name: 'AVAX', - sellAmount: '1000000000000000000', - buyAmount: '500000', - }, - { - name: 'USDC', - sellAmount: '1000000', - buyAmount: '1000000000000000000', - }, - ], - [ - { - name: 'WAVAX', - sellAmount: '1000000000000000000', - buyAmount: '500000', - }, - { name: 'USDC', sellAmount: '1000000', buyAmount: '20000000000000000' }, - ], - [ - { - name: 'WAVAX', - sellAmount: '1000000000000000000', - buyAmount: '10000000', - }, - { name: 'USDT', sellAmount: '1000000', buyAmount: '2000000000000' }, - ], - [ - { name: 'USDC', sellAmount: '1000000', buyAmount: '100000000' }, - { name: 'USDT', sellAmount: '100000000', buyAmount: '100000000' }, - ], - ]; + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, + ], + ], + ]); - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { + sideToContractMethods.forEach((contractMethods, side) => contractMethods.forEach((contractMethod: ContractMethod) => { - pairs.forEach(pair => { - describe(`${contractMethod}`, () => { - it(`${pair[0].name} -> ${pair[1].name}`, async () => { - await testE2E( - tokens[pair[0].name], - tokens[pair[1].name], - holders[pair[0].name], - side === SwapSide.SELL - ? pair[0].sellAmount - : pair[0].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${pair[1].name} -> ${pair[0].name}`, async () => { - await testE2E( - tokens[pair[1].name], - tokens[pair[0].name], - holders[pair[1].name], - side === SwapSide.SELL - ? pair[1].sellAmount - : pair[1].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); }); }); - }); - }), - ); + }), + ); + }); }); }); diff --git a/src/dex/uniswap-v3/uniswap-v3-pool.ts b/src/dex/uniswap-v3/uniswap-v3-pool.ts index 82342ce24..8950e509a 100644 --- a/src/dex/uniswap-v3/uniswap-v3-pool.ts +++ b/src/dex/uniswap-v3/uniswap-v3-pool.ts @@ -1,7 +1,7 @@ import _ from 'lodash'; import { Contract } from 'web3-eth-contract'; import { Interface } from '@ethersproject/abi'; -import { ethers } from 'ethers'; +import { BytesLike, ethers } from 'ethers'; import { assert, DeepReadonly } from 'ts-essentials'; import { Log, Logger, BlockHeader, Address } from '../../types'; import { @@ -11,12 +11,12 @@ import { import { IDexHelper } from '../../dex-helper/idex-helper'; import { PoolState, - DecodedStateMultiCallResultWithRelativeBitmaps, + DecodedStateMultiCallResultWithRelativeBitmaps, DecodeStateMultiCallFunc, } from './types'; import UniswapV3PoolABI from '../../abi/uniswap-v3/UniswapV3Pool.abi.json'; import { bigIntify, catchParseLogError, isSampled } from '../../utils'; import { uniswapV3Math } from './contract-math/uniswap-v3-math'; -import { MultiCallParams } from '../../lib/multi-wrapper'; +import { MultiCallParams, MultiResult } from '../../lib/multi-wrapper'; import { OUT_OF_RANGE_ERROR_POSTFIX, TICK_BITMAP_BUFFER, @@ -60,6 +60,7 @@ export class UniswapV3EventPool extends StatefulEventSubscriber { readonly dexHelper: IDexHelper, parentName: string, readonly stateMultiContract: Contract, + readonly decodeStateMultiCallResultWithRelativeBitmaps: DecodeStateMultiCallFunc | undefined, readonly erc20Interface: Interface, protected readonly factoryAddress: Address, public readonly feeCode: bigint, @@ -226,9 +227,17 @@ export class UniswapV3EventPool extends StatefulEventSubscriber { this.getBitmapRangeToRequest(), ) .encodeABI(), - decodeFunction: decodeStateMultiCallResultWithRelativeBitmaps, + decodeFunction: + this.decodeStateMultiCallResultWithRelativeBitmaps !== undefined + ? this.decodeStateMultiCallResultWithRelativeBitmaps + : decodeStateMultiCallResultWithRelativeBitmaps, }, ]; + + if(this.decodeStateMultiCallResultWithRelativeBitmaps !== undefined) { + console.log('decodeStateMultiCallResultWithRelativeBitmaps: ', decodeStateMultiCallResultWithRelativeBitmaps); + } + this._stateRequestCallData = callData; } return this._stateRequestCallData; diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 486f29cae..90f4d90de 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -91,7 +91,7 @@ export class UniswapV3 public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork( - _.pick(UniswapV3Config, ['UniswapV3', 'QuickSwapV3.1']), + _.pick(UniswapV3Config, ['UniswapV3', 'QuickSwapV3.1', 'RamsesV2']), ); logger: Logger; @@ -117,8 +117,12 @@ export class UniswapV3 UniswapV3MultiABI as AbiItem[], this.config.uniswapMulticall, ); + console.log('DEX KEY: ', dexKey); + console.log('stateMultiCallAbi: ', this.config.stateMultiCallAbi); this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( - UniswapV3StateMulticallABI as AbiItem[], + this.config.stateMultiCallAbi !== undefined + ? this.config.stateMultiCallAbi + : UniswapV3StateMulticallABI as AbiItem[], this.config.stateMulticall, ); @@ -233,12 +237,16 @@ export class UniswapV3 } this.logger.trace(`starting to listen to new pool: ${key}`); + console.log('dex key: ', this.dexKey); + console.log('THIS CONFIG: ', this.config); + console.log('NEW POOL decode: ', this.config.decodeStateMultiCallResultWithRelativeBitmaps); pool = pool || new UniswapV3EventPool( this.dexHelper, this.dexKey, this.stateMultiContract, + this.config.decodeStateMultiCallResultWithRelativeBitmaps, this.erc20Interface, this.config.factory, fee, @@ -1055,6 +1063,8 @@ export class UniswapV3 deployer: this.config.deployer?.toLowerCase(), initHash: this.config.initHash, subgraphURL: this.config.subgraphURL, + stateMultiCallAbi: this.config.stateMultiCallAbi, + decodeStateMultiCallResultWithRelativeBitmaps: this.config.decodeStateMultiCallResultWithRelativeBitmaps, }; return newConfig; } diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index a22e91f0e..12143c4dc 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -340,7 +340,6 @@ export async function testE2E( } } - console.log('DEX KEY: ', dexKey); const useAPI = testingEndpoint && !poolIdentifiers; // The API currently doesn't allow for specifying poolIdentifiers const paraswap: IParaSwapSDK = useAPI From 730ca6a3fa1bd11f44fd014e6507ecb8a24a754a Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 17 Aug 2023 14:40:36 +0300 Subject: [PATCH 055/833] remove console.log --- src/dex/uniswap-v3/uniswap-v3-pool.ts | 4 ---- src/dex/uniswap-v3/uniswap-v3.ts | 5 ----- 2 files changed, 9 deletions(-) diff --git a/src/dex/uniswap-v3/uniswap-v3-pool.ts b/src/dex/uniswap-v3/uniswap-v3-pool.ts index 8950e509a..27623c0a2 100644 --- a/src/dex/uniswap-v3/uniswap-v3-pool.ts +++ b/src/dex/uniswap-v3/uniswap-v3-pool.ts @@ -234,10 +234,6 @@ export class UniswapV3EventPool extends StatefulEventSubscriber { }, ]; - if(this.decodeStateMultiCallResultWithRelativeBitmaps !== undefined) { - console.log('decodeStateMultiCallResultWithRelativeBitmaps: ', decodeStateMultiCallResultWithRelativeBitmaps); - } - this._stateRequestCallData = callData; } return this._stateRequestCallData; diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 90f4d90de..67baf5832 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -117,8 +117,6 @@ export class UniswapV3 UniswapV3MultiABI as AbiItem[], this.config.uniswapMulticall, ); - console.log('DEX KEY: ', dexKey); - console.log('stateMultiCallAbi: ', this.config.stateMultiCallAbi); this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( this.config.stateMultiCallAbi !== undefined ? this.config.stateMultiCallAbi @@ -237,9 +235,6 @@ export class UniswapV3 } this.logger.trace(`starting to listen to new pool: ${key}`); - console.log('dex key: ', this.dexKey); - console.log('THIS CONFIG: ', this.config); - console.log('NEW POOL decode: ', this.config.decodeStateMultiCallResultWithRelativeBitmaps); pool = pool || new UniswapV3EventPool( From 5928d00aa9fb8984923905b42bfebb80bdc58836 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 17 Aug 2023 14:40:56 +0300 Subject: [PATCH 056/833] 2.28.10-ramses-v2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 77df47bde..49e6c222d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.9-ramses-v2", + "version": "2.28.10-ramses-v2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 8ae8059fd04ba20495e6603d6c552da7619ef725 Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 17 Aug 2023 12:54:51 +0100 Subject: [PATCH 057/833] fix: wrap in truncated 256 bit bigint row --- src/dex/algebra/algebra-integration.test.ts | 252 +++++++++++++------- src/dex/algebra/lib/TickTable.ts | 21 +- 2 files changed, 184 insertions(+), 89 deletions(-) diff --git a/src/dex/algebra/algebra-integration.test.ts b/src/dex/algebra/algebra-integration.test.ts index d64181c11..54c674fb7 100644 --- a/src/dex/algebra/algebra-integration.test.ts +++ b/src/dex/algebra/algebra-integration.test.ts @@ -151,92 +151,184 @@ describe('CamelotV3', function () { const tokens = Tokens[network]; - const srcTokenSymbol = 'USDCe'; - const destTokenSymbol = 'GRAIL'; - - const amountsForSell = [ - 0n, - 10_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 20_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 30_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 40_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 50_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 60_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 70_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 80_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 90_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - 100_000n * BI_POWS[tokens[srcTokenSymbol].decimals], - ]; - - const amountsForBuy = [ - 0n, - 1n * BI_POWS[tokens[destTokenSymbol].decimals], - 2n * BI_POWS[tokens[destTokenSymbol].decimals], - 3n * BI_POWS[tokens[destTokenSymbol].decimals], - 4n * BI_POWS[tokens[destTokenSymbol].decimals], - 5n * BI_POWS[tokens[destTokenSymbol].decimals], - 6n * BI_POWS[tokens[destTokenSymbol].decimals], - 7n * BI_POWS[tokens[destTokenSymbol].decimals], - 8n * BI_POWS[tokens[destTokenSymbol].decimals], - 9n * BI_POWS[tokens[destTokenSymbol].decimals], - 10n * BI_POWS[tokens[destTokenSymbol].decimals], - ]; - - beforeAll(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - algebra = new Algebra(network, dexKey, dexHelper); - if (algebra.initializePricing) { - await algebra.initializePricing(blockNumber); - } - }); - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - await testPricingOnNetwork( - algebra, - network, - dexKey, - dexHelper, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.SELL, - amountsForSell, - 'quoteExactInputSingle', - ); - }); + describe('GRAIL => USDCe', () => { + const srcTokenSymbol = 'GRAIL'; + const destTokenSymbol = 'USDCe'; + + const amountsForSell = [ + 0n, + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + 20n * BI_POWS[tokens[srcTokenSymbol].decimals], + 30n * BI_POWS[tokens[srcTokenSymbol].decimals], + 40n * BI_POWS[tokens[srcTokenSymbol].decimals], + 50n * BI_POWS[tokens[srcTokenSymbol].decimals], + 60n * BI_POWS[tokens[srcTokenSymbol].decimals], + 70n * BI_POWS[tokens[srcTokenSymbol].decimals], + 80n * BI_POWS[tokens[srcTokenSymbol].decimals], + 90n * BI_POWS[tokens[srcTokenSymbol].decimals], + 100n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals], + 2n * BI_POWS[tokens[destTokenSymbol].decimals], + 3n * BI_POWS[tokens[destTokenSymbol].decimals], + 4n * BI_POWS[tokens[destTokenSymbol].decimals], + 5n * BI_POWS[tokens[destTokenSymbol].decimals], + 6n * BI_POWS[tokens[destTokenSymbol].decimals], + 7n * BI_POWS[tokens[destTokenSymbol].decimals], + 8n * BI_POWS[tokens[destTokenSymbol].decimals], + 9n * BI_POWS[tokens[destTokenSymbol].decimals], + 10n * BI_POWS[tokens[destTokenSymbol].decimals], + ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + algebra = new Algebra(network, dexKey, dexHelper); + if (algebra.initializePricing) { + await algebra.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + algebra, + network, + dexKey, + dexHelper, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + 'quoteExactInputSingle', + ); + }); - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - await testPricingOnNetwork( - algebra, - network, - dexKey, - dexHelper, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.BUY, - amountsForBuy, - 'quoteExactOutputSingle', - ); + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + algebra, + network, + dexKey, + dexHelper, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + 'quoteExactOutputSingle', + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newAlgebra = new Algebra(network, dexKey, dexHelper); + const poolLiquidity = await newAlgebra.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newAlgebra.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); }); - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - const newAlgebra = new Algebra(network, dexKey, dexHelper); - const poolLiquidity = await newAlgebra.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, - ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + describe('USDCe => GRAIL', () => { + const srcTokenSymbol = 'USDCe'; + const destTokenSymbol = 'GRAIL'; + + const amountsForSell = [ + 0n, + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + 20n * BI_POWS[tokens[srcTokenSymbol].decimals], + 30n * BI_POWS[tokens[srcTokenSymbol].decimals], + 40n * BI_POWS[tokens[srcTokenSymbol].decimals], + 50n * BI_POWS[tokens[srcTokenSymbol].decimals], + 60n * BI_POWS[tokens[srcTokenSymbol].decimals], + 70n * BI_POWS[tokens[srcTokenSymbol].decimals], + 80n * BI_POWS[tokens[srcTokenSymbol].decimals], + 90n * BI_POWS[tokens[srcTokenSymbol].decimals], + 100n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals], + 2n * BI_POWS[tokens[destTokenSymbol].decimals], + 3n * BI_POWS[tokens[destTokenSymbol].decimals], + 4n * BI_POWS[tokens[destTokenSymbol].decimals], + 5n * BI_POWS[tokens[destTokenSymbol].decimals], + 6n * BI_POWS[tokens[destTokenSymbol].decimals], + 7n * BI_POWS[tokens[destTokenSymbol].decimals], + 8n * BI_POWS[tokens[destTokenSymbol].decimals], + 9n * BI_POWS[tokens[destTokenSymbol].decimals], + 10n * BI_POWS[tokens[destTokenSymbol].decimals], + ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + algebra = new Algebra(network, dexKey, dexHelper); + if (algebra.initializePricing) { + await algebra.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + algebra, + network, + dexKey, + dexHelper, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + 'quoteExactInputSingle', + ); + }); - if (!newAlgebra.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + algebra, + network, dexKey, + dexHelper, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + 'quoteExactOutputSingle', ); - } + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newAlgebra = new Algebra(network, dexKey, dexHelper); + const poolLiquidity = await newAlgebra.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newAlgebra.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); }); }); }); diff --git a/src/dex/algebra/lib/TickTable.ts b/src/dex/algebra/lib/TickTable.ts index afd86c816..9066c66db 100644 --- a/src/dex/algebra/lib/TickTable.ts +++ b/src/dex/algebra/lib/TickTable.ts @@ -43,7 +43,7 @@ export class TickTable { // wordPos BigInt.asIntN(16, tick >> 8n), // bitPos - BigInt.asUintN(8, tick & BigInt(0xff)), + BigInt.asUintN(8, tick & 0xffn), ]; } @@ -56,7 +56,7 @@ export class TickTable { tick /= tickSpacing; } const [rowNumber, bitNumber] = TickTable.position(tick); - const mask = 1n << bitNumber; + const mask = BigInt.asUintN(256, 1n << bitNumber); // toggleTick is used only in _updatePosition which is always state changing event // Therefore it is never used in price query @@ -83,11 +83,14 @@ export class TickTable { tickSpacing?: bigint, ): [bigint, boolean] { if (tickSpacing !== undefined) { - tick = Yul.sub( - Yul.sdiv(tick, tickSpacing), - Yul.and( - Yul.slt(tick, 0n), - Yul.not(Yul.iszero(Yul.smod(tick, tickSpacing))), + tick = BigInt.asIntN( + 24, + Yul.sub( + Yul.sdiv(tick, tickSpacing), + Yul.and( + Yul.slt(tick, 0n), + Yul.not(Yul.iszero(Yul.smod(tick, tickSpacing))), + ), ), ); } @@ -97,7 +100,7 @@ export class TickTable { let tickBitmapValue = state.tickBitmap[rowNumber.toString()]; tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; - const _row = tickBitmapValue << (255n - bitNumber); + const _row = BigInt.asUintN(256, tickBitmapValue << (255n - bitNumber)); if (_row != 0n) { tick -= BigInt.asIntN(24, 255n - TickTable.getMostSignificantBit(_row)); return [TickTable.boundTick(tick, tickSpacing), true]; @@ -113,7 +116,7 @@ export class TickTable { let tickBitmapValue = state.tickBitmap[rowNumber.toString()]; tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; - const _row = tickBitmapValue >> bitNumber; + const _row = BigInt.asUintN(256, tickBitmapValue >> bitNumber); if (_row !== 0n) { tick += BigInt.asIntN( 24, From f20b869ec935cd1acdc6f152d4376fe7ecb75b52 Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 17 Aug 2023 12:55:22 +0100 Subject: [PATCH 058/833] 2.28.10-camelot-v3-tick-bugs.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7f5f60c32..286432b96 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.10-camelot-v3-tick-bugs.0", + "version": "2.28.10-camelot-v3-tick-bugs.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 9f29e43bbff000e0b4fe884d64f48178e6ac8afa Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 17 Aug 2023 17:45:15 +0300 Subject: [PATCH 059/833] debug --- src/abi/RamsesV2Quoter.abi.json | 274 ++++++++++++++++++ src/dex/uniswap-v3/config.ts | 3 +- src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 74 ++--- .../uniswap-v3/uniswap-v3-integration.test.ts | 102 ++++++- src/dex/uniswap-v3/uniswap-v3.ts | 18 +- tests/utils-e2e.ts | 1 + 6 files changed, 414 insertions(+), 58 deletions(-) create mode 100644 src/abi/RamsesV2Quoter.abi.json diff --git a/src/abi/RamsesV2Quoter.abi.json b/src/abi/RamsesV2Quoter.abi.json new file mode 100644 index 000000000..ec532278d --- /dev/null +++ b/src/abi/RamsesV2Quoter.abi.json @@ -0,0 +1,274 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "WETH9", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_WETH9", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "path", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + } + ], + "name": "quoteExactInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint160[]", + "name": "sqrtPriceX96AfterList", + "type": "uint160[]" + }, + { + "internalType": "uint32[]", + "name": "initializedTicksCrossedList", + "type": "uint32[]" + }, + { + "internalType": "uint256", + "name": "gasEstimate", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "uint160", + "name": "sqrtPriceLimitX96", + "type": "uint160" + } + ], + "internalType": "struct IQuoterV2.QuoteExactInputSingleParams", + "name": "params", + "type": "tuple" + } + ], + "name": "quoteExactInputSingle", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint160", + "name": "sqrtPriceX96After", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "initializedTicksCrossed", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasEstimate", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "path", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "quoteExactOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint160[]", + "name": "sqrtPriceX96AfterList", + "type": "uint160[]" + }, + { + "internalType": "uint32[]", + "name": "initializedTicksCrossedList", + "type": "uint32[]" + }, + { + "internalType": "uint256", + "name": "gasEstimate", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "uint160", + "name": "sqrtPriceLimitX96", + "type": "uint160" + } + ], + "internalType": "struct IQuoterV2.QuoteExactOutputSingleParams", + "name": "params", + "type": "tuple" + } + ], + "name": "quoteExactOutputSingle", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint160", + "name": "sqrtPriceX96After", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "initializedTicksCrossed", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasEstimate", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "path", + "type": "bytes" + } + ], + "name": "ramsesV2SwapCallback", + "outputs": [], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index 18a66c612..ae4ffceea 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -111,7 +111,8 @@ export const UniswapV3Config: DexConfigMap = { [Network.ARBITRUM]: { factory: '0xAA2cd7477c451E703f3B9Ba5663334914763edF8', deployer: '0xb3e423ab9cE6C03D98326A3A2a0D7D96b0829f22', - quoter: '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', + quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', + // quoter: '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', router: '0xAA23611badAFB62D37E7295A682D21960ac85A90', supportedFees: SUPPORTED_FEES, stateMulticall: '0x50EE4112Cab9c79812F23bE079aB3911395ACc8e', diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index bccf2bf69..3afbd8148 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -439,50 +439,50 @@ describe('UniswapV3 E2E', () => { SwapSide.SELL, [ ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ContractMethod.directUniV3Swap, - ], - ], - [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - ContractMethod.buy, - ContractMethod.directUniV3Buy, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + // ContractMethod.directUniV3Swap, ], ], + // [ + // SwapSide.BUY, + // [ + // ContractMethod.simpleBuy, + // ContractMethod.buy, + // ContractMethod.directUniV3Buy, + // ], + // ], ]); sideToContractMethods.forEach((contractMethods, side) => contractMethods.forEach((contractMethod: ContractMethod) => { describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); + // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + // await testE2E( + // tokens[nativeTokenSymbol], + // tokens[tokenASymbol], + // holders[nativeTokenSymbol], + // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + // await testE2E( + // tokens[tokenASymbol], + // tokens[nativeTokenSymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { await testE2E( tokens[tokenASymbol], diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index cffdab3df..8564dc54b 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -76,7 +76,7 @@ async function checkOnChainPricing( _amounts: bigint[], ) { // Quoter address - const exchangeAddress = '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'; + // const exchangeAddress = '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'; const readerIface = quoterIface; const sum = prices.reduce((acc, curr) => (acc += curr), 0n); @@ -99,7 +99,8 @@ async function checkOnChainPricing( // ); const readerCallData = getReaderCalldata( - '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', + // '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', + '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', readerIface, _amounts.slice(1), funcName, @@ -116,6 +117,7 @@ async function checkOnChainPricing( .call({}, blockNumber) ).returnData; } catch (e) { + console.log('E: ', e); console.log( `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, e, @@ -154,19 +156,6 @@ describe('UniswapV3', function () { ); }); - - it('fgggg', async () => { - const readerCallData = getReaderCalldata( - '', - readerIface, - _amounts.slice(1), - funcName, - tokenIn, - tokenOut, - fee, - ); - }); - it('getPoolIdentifiers and getPricesVolume SELL', async function () { const pools = await uniswapV3.getPoolIdentifiers( TokenA, @@ -489,3 +478,86 @@ describe('UniswapV3', function () { } }); }); + +describe('RamsesV2', () => { + const dexKey = 'RamsesV2'; + let blockNumber: number; + let uniswapV3: UniswapV3; + let uniswapV3Mainnet: UniswapV3; + + const network = Network.ARBITRUM; + const dexHelper = new DummyDexHelper(network); + const TokenASymbol = 'USDCe'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDC'; + const TokenB = Tokens[network][TokenBSymbol]; + + beforeEach(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + uniswapV3 = new UniswapV3(network, dexKey, dexHelper); + uniswapV3Mainnet = new UniswapV3( + Network.ARBITRUM, + dexKey, + dexHelper, + ); + }); + + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + + const amounts = [ + 0n, + 6000000n, + 12000000n, + 18000000n, + 24000000n, + 30000000n, + 36000000n, + 42000000n, + ]; + + const pools = await uniswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await uniswapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + uniswapV3, + 'quoteExactInputSingle', + blockNumber, + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); +}); diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 67baf5832..5b2aaa1e2 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -43,6 +43,7 @@ import { UniswapV3Config, Adapters, PoolsToPreload } from './config'; import { UniswapV3EventPool } from './uniswap-v3-pool'; import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; import UniswapV3QuoterABI from '../../abi/uniswap-v3/UniswapV3Quoter.abi.json'; +import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; import DirectSwapABI from '../../abi/DirectSwap.json'; import UniswapV3StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; @@ -107,7 +108,7 @@ export class UniswapV3 protected dexHelper: IDexHelper, protected adapters = Adapters[network] || {}, readonly routerIface = new Interface(UniswapV3RouterABI), - readonly quoterIface = new Interface(UniswapV3QuoterABI), + readonly quoterIface = new Interface(UniswapV3QuoterV2ABI), protected config = UniswapV3Config[dexKey][network], protected poolsToPreload = PoolsToPreload[dexKey]?.[network] || [], ) { @@ -369,6 +370,7 @@ export class UniswapV3 side: SwapSide, pools: UniswapV3EventPool[], ): Promise | null> { + console.log('POOLS: ', pools); if (pools.length === 0) { return null; } @@ -422,6 +424,7 @@ export class UniswapV3 ), ); + console.log('QUOTER: ', this.config.quoter); const calldata = pools.map(pool => _amounts.map(_amount => ({ target: this.config.quoter, @@ -577,17 +580,18 @@ export class UniswapV3 if (selectedPools.length === 0) return null; + const poolsToUse = selectedPools.reduce( (acc, pool) => { let state = pool.getState(blockNumber); - if (state === null) { + // if (state === null || pool.poolAddress === '0x6059cf1c818979bccac5d1f015e1b322d154592f') { this.logger.trace( `${this.dexKey}: State === null. Fallback to rpc ${pool.name}`, ); acc.poolWithoutState.push(pool); - } else { - acc.poolWithState.push(pool); - } + // } else { + // acc.poolWithState.push(pool); + // } return acc; }, { @@ -596,6 +600,7 @@ export class UniswapV3 }, ); + const rpcResultsPromise = this.getPricingFromRpc( _srcToken, _destToken, @@ -695,6 +700,9 @@ export class UniswapV3 ); const rpcResults = await rpcResultsPromise; + + console.log('RPC RESULTS: ', rpcResults); + const notNullResult = result.filter( res => res !== null, ) as ExchangePrices; diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index 12143c4dc..9aefbaf8f 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -368,6 +368,7 @@ export async function testE2E( poolIdentifiers, transferFees, ); + console.log('priceRoute: ', priceRoute); expect(parseFloat(priceRoute.destAmount)).toBeGreaterThan(0); // Calculate slippage. Default is 1% From 25ff6e000db1011c96c5e36ca1859a85665f58e6 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 17 Aug 2023 17:47:04 +0300 Subject: [PATCH 060/833] BACK-1235: use QuoterV2 for UniswapV3 rpc fallbacks --- src/dex/uniswap-v3/uniswap-v3.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 486f29cae..270a3816d 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -42,7 +42,7 @@ import { import { UniswapV3Config, Adapters, PoolsToPreload } from './config'; import { UniswapV3EventPool } from './uniswap-v3-pool'; import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; -import UniswapV3QuoterABI from '../../abi/uniswap-v3/UniswapV3Quoter.abi.json'; +import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; import DirectSwapABI from '../../abi/DirectSwap.json'; import UniswapV3StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; @@ -107,7 +107,7 @@ export class UniswapV3 protected dexHelper: IDexHelper, protected adapters = Adapters[network] || {}, readonly routerIface = new Interface(UniswapV3RouterABI), - readonly quoterIface = new Interface(UniswapV3QuoterABI), + readonly quoterIface = new Interface(UniswapV3QuoterV2ABI), protected config = UniswapV3Config[dexKey][network], protected poolsToPreload = PoolsToPreload[dexKey]?.[network] || [], ) { From 27b112c84e48231cbfad64f5bdde0a191977bef0 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 17 Aug 2023 19:13:20 +0300 Subject: [PATCH 061/833] 2.28.10-uni-v3-quoter-v2-interface --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4aa5e4e84..84f07d06d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.9", + "version": "2.28.10-uni-v3-quoter-v2-interface", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 6b4c3433544d6e6a0d45f957ca94835d3c2a7065 Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 17 Aug 2023 17:43:53 +0100 Subject: [PATCH 062/833] feat: move force RPC to config service --- src/config.ts | 12 +++++++++++- src/dex/algebra/algebra.ts | 3 +++ src/dex/algebra/config.ts | 1 - src/types.ts | 1 + 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index bef159a5b..45b466f84 100644 --- a/src/config.ts +++ b/src/config.ts @@ -30,6 +30,7 @@ type BaseConfig = { hashFlowAuthToken?: string; hashFlowDisabledMMs: string[]; swaapV2AuthToken?: string; + forceRpcFallbackDexs: string[]; }; const baseConfigs: { [network: number]: BaseConfig } = { @@ -115,6 +116,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { }, }, }, + forceRpcFallbackDexs: [], }, [Network.ROPSTEN]: { network: Network.ROPSTEN, @@ -142,6 +144,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { rfqConfigs: {}, rpcPollingMaxAllowedStateDelayInBlocks: 5, rpcPollingBlocksBackToTriggerUpdate: 3, + forceRpcFallbackDexs: [], }, [Network.BSC]: { network: Network.BSC, @@ -168,6 +171,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { uniswapV2ExchangeRouterAddress: '0x53e693c6C7FFC4446c53B205Cf513105Bf140D7b', rfqConfigs: {}, + forceRpcFallbackDexs: [], }, [Network.POLYGON]: { network: Network.POLYGON, @@ -197,6 +201,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { rpcPollingMaxAllowedStateDelayInBlocks: 2, rpcPollingBlocksBackToTriggerUpdate: 1, swaapV2AuthToken: process.env.API_KEY_SWAAP_V2_AUTH_TOKEN || '', + forceRpcFallbackDexs: [], }, [Network.AVALANCHE]: { network: Network.AVALANCHE, @@ -224,6 +229,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { rfqConfigs: {}, rpcPollingMaxAllowedStateDelayInBlocks: 2, rpcPollingBlocksBackToTriggerUpdate: 1, + forceRpcFallbackDexs: [], }, [Network.FANTOM]: { network: Network.FANTOM, @@ -251,6 +257,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { rfqConfigs: {}, rpcPollingMaxAllowedStateDelayInBlocks: 2, rpcPollingBlocksBackToTriggerUpdate: 1, + forceRpcFallbackDexs: [], }, [Network.ARBITRUM]: { network: Network.ARBITRUM, @@ -279,6 +286,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { rfqConfigs: {}, rpcPollingMaxAllowedStateDelayInBlocks: 4, rpcPollingBlocksBackToTriggerUpdate: 3, + forceRpcFallbackDexs: [], }, [Network.OPTIMISM]: { network: Network.OPTIMISM, @@ -307,6 +315,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { rfqConfigs: {}, rpcPollingMaxAllowedStateDelayInBlocks: 5, rpcPollingBlocksBackToTriggerUpdate: 3, + forceRpcFallbackDexs: [], }, }; @@ -350,6 +359,7 @@ export function generateConfig(network: number): Config { hashFlowAuthToken: baseConfig.hashFlowAuthToken, swaapV2AuthToken: baseConfig.swaapV2AuthToken, hashFlowDisabledMMs: baseConfig.hashFlowDisabledMMs, + forceRpcFallbackDexs: baseConfig.forceRpcFallbackDexs, }; } @@ -359,7 +369,7 @@ export class ConfigHelper { constructor( public isSlave: boolean, public data: Config, - private masterCachePrefix: string, + masterCachePrefix: string, ) { this.masterBlockNumberCacheKey = `${masterCachePrefix}_${data.network}_bn`.toLowerCase(); diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 3b4ad6e55..d64ef8c02 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -104,6 +104,9 @@ export class Algebra extends SimpleExchange implements IDex { this.dexHelper.web3Provider.eth.handleRevert = false; this.config = this._toLowerForAllConfigAddresses(); + // External configuration has priority over internal + this.config.forceRPC = + dexHelper.config.data.forceRpcFallbackDexs.includes(dexKey); this.notExistingPoolSetKey = `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); diff --git a/src/dex/algebra/config.ts b/src/dex/algebra/config.ts index 83ade331a..9b6147a17 100644 --- a/src/dex/algebra/config.ts +++ b/src/dex/algebra/config.ts @@ -82,7 +82,6 @@ export const AlgebraConfig: DexConfigMap = { uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', deployer: '0x6dd3fb9653b10e806650f107c3b5a0a6ff974f65', version: 'v1.9', - forceRPC: false, }, }, }; diff --git a/src/types.ts b/src/types.ts index 6d63f0ba2..9d914b038 100644 --- a/src/types.ts +++ b/src/types.ts @@ -276,6 +276,7 @@ export type Config = { hashFlowDisabledMMs: string[]; uniswapV3EventLoggingSampleRate?: number; swaapV2AuthToken?: string; + forceRpcFallbackDexs: string[]; }; export type BigIntAsString = string; From ef625822c3aad6fc9d606ffca483d1127fb6e5c3 Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 17 Aug 2023 18:05:12 +0100 Subject: [PATCH 063/833] feat: get fallback force from config service --- src/dex/algebra/algebra.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index d64ef8c02..0cbe60fd5 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -105,8 +105,9 @@ export class Algebra extends SimpleExchange implements IDex { this.config = this._toLowerForAllConfigAddresses(); // External configuration has priority over internal - this.config.forceRPC = - dexHelper.config.data.forceRpcFallbackDexs.includes(dexKey); + this.config.forceRPC = dexHelper.config.data.forceRpcFallbackDexs.includes( + dexKey.toLowerCase(), + ); this.notExistingPoolSetKey = `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); From 8d762f8bbcb771bf862e4f8ac707ae950449b1f4 Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 17 Aug 2023 18:05:54 +0100 Subject: [PATCH 064/833] 2.28.10-camelot-v3-tick-bugs.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 286432b96..1e8668077 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.10-camelot-v3-tick-bugs.1", + "version": "2.28.10-camelot-v3-tick-bugs.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From c6bc705ab72727cd31cc201c130d3ec6a569649e Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 18 Aug 2023 12:42:31 +0300 Subject: [PATCH 065/833] 2.28.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 84f07d06d..6449d4439 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.10-uni-v3-quoter-v2-interface", + "version": "2.28.10", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 9b2fd081b2629d13b7dcaf69d2b66a6e4831170b Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 18 Aug 2023 15:06:22 +0300 Subject: [PATCH 066/833] refactor and add integration tests --- src/dex/index.ts | 2 - src/dex/ramses-v2/config.ts | 31 - src/dex/ramses-v2/constants.ts | 41 - src/dex/ramses-v2/contract-math/BitMath.ts | 90 -- .../ramses-v2/contract-math/FixedPoint128.ts | 3 - .../ramses-v2/contract-math/FixedPoint96.ts | 4 - src/dex/ramses-v2/contract-math/FullMath.ts | 30 - .../ramses-v2/contract-math/LiquidityMath.ts | 17 - src/dex/ramses-v2/contract-math/Oracle.ts | 226 ---- .../ramses-v2/contract-math/SqrtPriceMath.ts | 226 ---- src/dex/ramses-v2/contract-math/SwapMath.ts | 139 -- src/dex/ramses-v2/contract-math/Tick.ts | 82 -- src/dex/ramses-v2/contract-math/TickBitMap.ts | 128 -- src/dex/ramses-v2/contract-math/TickMath.ts | 211 --- src/dex/ramses-v2/contract-math/UnsafeMath.ts | 5 - .../contract-math/uniswap-v3-math.ts | 666 ---------- src/dex/ramses-v2/contract-math/utils.ts | 11 - src/dex/ramses-v2/ramses-v2-e2e.test.ts | 100 -- src/dex/ramses-v2/ramses-v2-events.test.ts | 182 --- .../ramses-v2/ramses-v2-integration.test.ts | 462 ------- src/dex/ramses-v2/ramses-v2-pool.ts | 513 -------- src/dex/ramses-v2/ramses-v2.ts | 1136 ----------------- src/dex/ramses-v2/types.ts | 177 --- src/dex/ramses-v2/utils.ts | 90 -- src/dex/uniswap-v3/config.ts | 3 +- src/dex/uniswap-v3/forks/ramses-v2/utils.ts | 2 +- src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 74 +- .../uniswap-v3/uniswap-v3-integration.test.ts | 101 +- src/dex/uniswap-v3/uniswap-v3.ts | 16 +- 29 files changed, 131 insertions(+), 4637 deletions(-) delete mode 100644 src/dex/ramses-v2/config.ts delete mode 100644 src/dex/ramses-v2/constants.ts delete mode 100644 src/dex/ramses-v2/contract-math/BitMath.ts delete mode 100644 src/dex/ramses-v2/contract-math/FixedPoint128.ts delete mode 100644 src/dex/ramses-v2/contract-math/FixedPoint96.ts delete mode 100644 src/dex/ramses-v2/contract-math/FullMath.ts delete mode 100644 src/dex/ramses-v2/contract-math/LiquidityMath.ts delete mode 100644 src/dex/ramses-v2/contract-math/Oracle.ts delete mode 100644 src/dex/ramses-v2/contract-math/SqrtPriceMath.ts delete mode 100644 src/dex/ramses-v2/contract-math/SwapMath.ts delete mode 100644 src/dex/ramses-v2/contract-math/Tick.ts delete mode 100644 src/dex/ramses-v2/contract-math/TickBitMap.ts delete mode 100644 src/dex/ramses-v2/contract-math/TickMath.ts delete mode 100644 src/dex/ramses-v2/contract-math/UnsafeMath.ts delete mode 100644 src/dex/ramses-v2/contract-math/uniswap-v3-math.ts delete mode 100644 src/dex/ramses-v2/contract-math/utils.ts delete mode 100644 src/dex/ramses-v2/ramses-v2-e2e.test.ts delete mode 100644 src/dex/ramses-v2/ramses-v2-events.test.ts delete mode 100644 src/dex/ramses-v2/ramses-v2-integration.test.ts delete mode 100644 src/dex/ramses-v2/ramses-v2-pool.ts delete mode 100644 src/dex/ramses-v2/ramses-v2.ts delete mode 100644 src/dex/ramses-v2/types.ts delete mode 100644 src/dex/ramses-v2/utils.ts diff --git a/src/dex/index.ts b/src/dex/index.ts index d7c0d627e..f32c7d800 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -69,7 +69,6 @@ import { SwaapV2 } from './swaap-v2/swaap-v2'; import { SpiritSwapV3 } from './quickswap/spiritswap-v3'; import { TraderJoeV21 } from './trader-joe-v2.1'; import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3'; -// import { RamsesV2 } from './ramses-v2/ramses-v2'; import { Algebra } from './algebra/algebra'; const LegacyDexes = [ @@ -138,7 +137,6 @@ const Dexes = [ MaverickV1, Camelot, SwaapV2, - // RamsesV2, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< diff --git a/src/dex/ramses-v2/config.ts b/src/dex/ramses-v2/config.ts deleted file mode 100644 index 668a276c8..000000000 --- a/src/dex/ramses-v2/config.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { DexParams } from './types'; -import { DexConfigMap, AdapterMappings } from '../../types'; -import { Network, SwapSide } from '../../constants'; - -const RAMSES_SUPPORTED_FEES = [10000n, 2500n, 500n, 100n]; - -export const RamsesV2Config: DexConfigMap = { - RamsesV2: { - [Network.ARBITRUM]: { - factory: '0xAA2cd7477c451E703f3B9Ba5663334914763edF8', - deployer: '0xb3e423ab9cE6C03D98326A3A2a0D7D96b0829f22', - quoter: '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', - router: '0xAA23611badAFB62D37E7295A682D21960ac85A90', - supportedFees: RAMSES_SUPPORTED_FEES, - stateMulticall: '0x50EE4112Cab9c79812F23bE079aB3911395ACc8e', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initHash: - '0x1565b129f2d1790f12d45301b9b084335626f0c92410bc43130763b69971135d', - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/ramsesexchange/concentrated-liquidity-graph', - }, - }, -}; - -export const Adapters: Record = { - [Network.ARBITRUM]: { - [SwapSide.SELL]: [{ name: 'ArbitrumAdapter01', index: 3 }], - [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 2 }], - }, -}; diff --git a/src/dex/ramses-v2/constants.ts b/src/dex/ramses-v2/constants.ts deleted file mode 100644 index e6f5f8510..000000000 --- a/src/dex/ramses-v2/constants.ts +++ /dev/null @@ -1,41 +0,0 @@ -export const UNISWAPV3_TICK_GAS_COST = 24_000; // Ceiled -export const UNISWAPV3_TICK_BASE_OVERHEAD = 75_000; -export const UNISWAPV3_POOL_SEARCH_OVERHEAD = 10_000; - -// This is used for price calculation. If out of scope, return 0n -export const TICK_BITMAP_TO_USE = 4n; - -// This is used to check if the state is still valid. -export const TICK_BITMAP_BUFFER = 8n; - -export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 128; - -export const UNISWAPV3_SUBGRAPH_URL = - 'https://api.thegraph.com/subgraphs/name/ramsesexchange/concentrated-liquidity-graph'; - -export const UNISWAPV3_EFFICIENCY_FACTOR = 3; - -export const ZERO_TICK_INFO = { - liquidityGross: 0n, - liquidityNet: 0n, - tickCumulativeOutside: 0n, - secondsPerLiquidityOutsideX128: 0n, - secondsOutside: 0n, - initialized: false, -}; - -export const ZERO_ORACLE_OBSERVATION = { - blockTimestamp: 0n, - tickCumulative: 0n, - secondsPerLiquidityCumulativeX128: 0n, - initialized: false, -}; - -export const OUT_OF_RANGE_ERROR_POSTFIX = `INVALID_TICK_BIT_MAP_RANGES`; - -export const DEFAULT_POOL_INIT_CODE_HASH = `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`; - -export enum DirectMethods { - directSell = 'directUniV3Swap', - directBuy = 'directUniV3Buy', -} diff --git a/src/dex/ramses-v2/contract-math/BitMath.ts b/src/dex/ramses-v2/contract-math/BitMath.ts deleted file mode 100644 index d7a2e6d9a..000000000 --- a/src/dex/ramses-v2/contract-math/BitMath.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { - BI_MAX_UINT128, - BI_MAX_UINT16, - BI_MAX_UINT32, - BI_MAX_UINT64, - BI_MAX_UINT8, -} from '../../../bigint-constants'; -import { _require } from '../../../utils'; - -export class BitMath { - static mostSignificantBit(x: bigint): bigint { - _require(x > 0, '', { x }, 'x > 0'); - let r = 0n; - - if (x >= 0x100000000000000000000000000000000n) { - x >>= 128n; - r += 128n; - } - if (x >= 0x10000000000000000n) { - x >>= 64n; - r += 64n; - } - if (x >= 0x100000000n) { - x >>= 32n; - r += 32n; - } - if (x >= 0x10000n) { - x >>= 16n; - r += 16n; - } - if (x >= 0x100n) { - x >>= 8n; - r += 8n; - } - if (x >= 0x10n) { - x >>= 4n; - r += 4n; - } - if (x >= 0x4n) { - x >>= 2n; - r += 2n; - } - if (x >= 0x2n) r += 1n; - - return r; - } - - static leastSignificantBit(x: bigint): bigint { - _require(x > 0, '', { x }, 'x > 0'); - - let r = 255n; - if ((x & BI_MAX_UINT128) > 0n) { - r -= 128n; - } else { - x >>= 128n; - } - if ((x & BI_MAX_UINT64) > 0n) { - r -= 64n; - } else { - x >>= 64n; - } - if ((x & BI_MAX_UINT32) > 0n) { - r -= 32n; - } else { - x >>= 32n; - } - if ((x & BI_MAX_UINT16) > 0n) { - r -= 16n; - } else { - x >>= 16n; - } - if ((x & BI_MAX_UINT8) > 0n) { - r -= 8n; - } else { - x >>= 8n; - } - if ((x & 0xfn) > 0n) { - r -= 4n; - } else { - x >>= 4n; - } - if ((x & 0x3n) > 0n) { - r -= 2n; - } else { - x >>= 2n; - } - if ((x & 0x1n) > 0n) r -= 1n; - return r; - } -} diff --git a/src/dex/ramses-v2/contract-math/FixedPoint128.ts b/src/dex/ramses-v2/contract-math/FixedPoint128.ts deleted file mode 100644 index 2058307bd..000000000 --- a/src/dex/ramses-v2/contract-math/FixedPoint128.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class FixedPoint128 { - static readonly Q128 = 0x100000000000000000000000000000000n; -} diff --git a/src/dex/ramses-v2/contract-math/FixedPoint96.ts b/src/dex/ramses-v2/contract-math/FixedPoint96.ts deleted file mode 100644 index 1a551dcb9..000000000 --- a/src/dex/ramses-v2/contract-math/FixedPoint96.ts +++ /dev/null @@ -1,4 +0,0 @@ -export class FixedPoint96 { - static readonly RESOLUTION = 96n; - static readonly Q96 = 0x1000000000000000000000000n; -} diff --git a/src/dex/ramses-v2/contract-math/FullMath.ts b/src/dex/ramses-v2/contract-math/FullMath.ts deleted file mode 100644 index 7c6a3bdc3..000000000 --- a/src/dex/ramses-v2/contract-math/FullMath.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { BI_MAX_UINT256 } from '../../../bigint-constants'; -import { _require } from '../../../utils'; - -export class FullMath { - static mulDiv(a: bigint, b: bigint, denominator: bigint) { - const result = (a * b) / denominator; - - _require( - result <= BI_MAX_UINT256, - '', - { result, BI_MAX_UINT: BI_MAX_UINT256 }, - 'result <= BI_MAX_UINT', - ); - - return result; - } - - static mulDivRoundingUp(a: bigint, b: bigint, denominator: bigint) { - const result = (a * b + denominator - 1n) / denominator; - - _require( - result <= BI_MAX_UINT256, - '', - { result, BI_MAX_UINT: BI_MAX_UINT256 }, - 'result <= BI_MAX_UINT', - ); - - return result; - } -} diff --git a/src/dex/ramses-v2/contract-math/LiquidityMath.ts b/src/dex/ramses-v2/contract-math/LiquidityMath.ts deleted file mode 100644 index a495e55cc..000000000 --- a/src/dex/ramses-v2/contract-math/LiquidityMath.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { _require } from '../../../utils'; - -export class LiquidityMath { - static addDelta(x: bigint, y: bigint): bigint { - let z; - if (y < 0) { - const _y = BigInt.asUintN(128, -y); - z = x - _y; - _require(z < x, 'LS', { z, x, y, _y }, 'z < x'); - } else { - const _y = BigInt.asUintN(128, y); - z = x + _y; - _require(z >= x, 'LA', { z, x, y, _y }, 'z >= x'); - } - return z; - } -} diff --git a/src/dex/ramses-v2/contract-math/Oracle.ts b/src/dex/ramses-v2/contract-math/Oracle.ts deleted file mode 100644 index 19b1918d1..000000000 --- a/src/dex/ramses-v2/contract-math/Oracle.ts +++ /dev/null @@ -1,226 +0,0 @@ -import { - OracleObservation, - OracleObservationCandidates, - PoolState, -} from '../types'; -import { _require } from '../../../utils'; -import { DeepReadonly } from 'ts-essentials'; -import { ZERO_ORACLE_OBSERVATION } from '../constants'; - -function replaceUndefinedObservationWithZero(state: PoolState, index: number) { - if (state.observations[index] === undefined) { - state.observations[index] = { ...ZERO_ORACLE_OBSERVATION }; - } -} - -export class Oracle { - static transform( - state: DeepReadonly, - last: OracleObservation, - blockTimestamp: bigint, - tick: bigint, - liquidity: bigint, - ): OracleObservation { - const delta = blockTimestamp - last.blockTimestamp; - return { - blockTimestamp: state.blockTimestamp, - tickCumulative: last.tickCumulative + BigInt.asIntN(56, tick) * delta, - secondsPerLiquidityCumulativeX128: - last.secondsPerLiquidityCumulativeX128 + - (BigInt.asUintN(160, delta) << 128n) / - (liquidity > 0n ? liquidity : 1n), - initialized: true, - }; - } - - static write( - state: PoolState, - index: number, - blockTimestamp: bigint, - tick: bigint, - liquidity: bigint, - cardinality: number, - cardinalityNext: number, - ): [number, number] { - const last = state.observations[index]; - - if (last.blockTimestamp == state.blockTimestamp) - return [index, cardinality]; - - let indexUpdated = 0; - let cardinalityUpdated = 0; - - if (cardinalityNext > cardinality && index == cardinality - 1) { - cardinalityUpdated = cardinalityNext; - } else { - cardinalityUpdated = cardinality; - } - - indexUpdated = (index + 1) % cardinalityUpdated; - - state.observations[indexUpdated] = Oracle.transform( - state, - last, - blockTimestamp, - tick, - liquidity, - ); - if (indexUpdated !== index) { - delete state.observations[index]; - } - return [indexUpdated, cardinalityUpdated]; - } - - static lte(time: bigint, a: bigint, b: bigint): boolean { - if (a <= time && b <= time) return a <= b; - - const aAdjusted = a > time ? a : a + 2n ** 32n; - const bAdjusted = b > time ? b : b + 2n ** 32n; - return aAdjusted <= bAdjusted; - } - - static binarySearch( - state: DeepReadonly, - time: bigint, - target: bigint, - index: number, - cardinality: number, - ): OracleObservationCandidates { - let l = (index + 1) % cardinality; - let r = l + cardinality - 1; - let i; - - let beforeOrAt; - let atOrAfter; - while (true) { - i = (l + r) / 2; - - beforeOrAt = state.observations[i % cardinality]; - - // we've landed on an uninitialized tick, keep searching higher (more recently) - if (!beforeOrAt.initialized) { - l = i + 1; - continue; - } - - atOrAfter = state.observations[(i + 1) % cardinality]; - - const targetAtOrAfter = Oracle.lte( - time, - beforeOrAt.blockTimestamp, - target, - ); - - // check if we've found the answer! - if (targetAtOrAfter && Oracle.lte(time, target, atOrAfter.blockTimestamp)) - break; - - if (!targetAtOrAfter) r = i - 1; - else l = i + 1; - } - return { beforeOrAt, atOrAfter }; - } - - static getSurroundingObservations( - state: DeepReadonly, - time: bigint, - target: bigint, - tick: bigint, - index: number, - liquidity: bigint, - cardinality: number, - ): OracleObservationCandidates { - let beforeOrAt = state.observations[index]; - - if (Oracle.lte(time, beforeOrAt.blockTimestamp, target)) { - if (beforeOrAt.blockTimestamp === target) { - return { beforeOrAt, atOrAfter: beforeOrAt }; - } else { - return { - beforeOrAt, - atOrAfter: Oracle.transform( - state, - beforeOrAt, - target, - tick, - liquidity, - ), - }; - } - } - - beforeOrAt = state.observations[(index + 1) % cardinality]; - if (!beforeOrAt.initialized) beforeOrAt = state.observations[0]; - - _require( - Oracle.lte(time, beforeOrAt.blockTimestamp, target), - 'OLD', - { time, beforeOrAtBlockTimestamp: beforeOrAt.blockTimestamp, target }, - 'Oracle.lte(time, beforeOrAt.blockTimestamp, target)', - ); - - return Oracle.binarySearch(state, time, target, index, cardinality); - } - - static observeSingle( - state: DeepReadonly, - time: bigint, - secondsAgo: bigint, - tick: bigint, - index: number, - liquidity: bigint, - cardinality: number, - ): [bigint, bigint] { - if (secondsAgo == 0n) { - let last = state.observations[index]; - if (last.blockTimestamp != time) - last = Oracle.transform(state, last, time, tick, liquidity); - return [last.tickCumulative, last.secondsPerLiquidityCumulativeX128]; - } - - const target = time - secondsAgo; - - const { beforeOrAt, atOrAfter } = Oracle.getSurroundingObservations( - state, - time, - target, - tick, - index, - liquidity, - cardinality, - ); - - if (target === beforeOrAt.blockTimestamp) { - return [ - beforeOrAt.tickCumulative, - beforeOrAt.secondsPerLiquidityCumulativeX128, - ]; - } else if (target === atOrAfter.blockTimestamp) { - return [ - atOrAfter.tickCumulative, - atOrAfter.secondsPerLiquidityCumulativeX128, - ]; - } else { - const observationTimeDelta = - atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp; - const targetDelta = target - beforeOrAt.blockTimestamp; - return [ - beforeOrAt.tickCumulative + - ((atOrAfter.tickCumulative - beforeOrAt.tickCumulative) / - observationTimeDelta) * - targetDelta, - beforeOrAt.secondsPerLiquidityCumulativeX128 + - BigInt.asUintN( - 160, - (BigInt.asUintN( - 256, - atOrAfter.secondsPerLiquidityCumulativeX128 - - beforeOrAt.secondsPerLiquidityCumulativeX128, - ) * - targetDelta) / - observationTimeDelta, - ), - ]; - } - } -} diff --git a/src/dex/ramses-v2/contract-math/SqrtPriceMath.ts b/src/dex/ramses-v2/contract-math/SqrtPriceMath.ts deleted file mode 100644 index 31b801d73..000000000 --- a/src/dex/ramses-v2/contract-math/SqrtPriceMath.ts +++ /dev/null @@ -1,226 +0,0 @@ -import { BI_MAX_UINT160 } from '../../../bigint-constants'; -import { FixedPoint96 } from './FixedPoint96'; -import { FullMath } from './FullMath'; -import { UnsafeMath } from './UnsafeMath'; -import { _require } from '../../../utils'; - -export class SqrtPriceMath { - static getNextSqrtPriceFromAmount0RoundingUp( - sqrtPX96: bigint, - liquidity: bigint, - amount: bigint, - add: boolean, - ): bigint { - if (amount === 0n) return sqrtPX96; - const numerator1 = - BigInt.asUintN(256, liquidity) << FixedPoint96.RESOLUTION; - - const product = amount * sqrtPX96; - if (add) { - if (product / amount === sqrtPX96) { - const denominator = numerator1 + product; - if (denominator >= numerator1) { - return BigInt.asUintN( - 160, - FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator), - ); - } - } - return BigInt.asUintN( - 160, - UnsafeMath.divRoundingUp(numerator1, numerator1 / sqrtPX96 + amount), - ); - } else { - _require( - product / amount === sqrtPX96 && numerator1 > product, - '', - { product, amount, sqrtPX96, numerator1 }, - 'product / amount === sqrtPX96 && numerator1 > product', - ); - const denominator = numerator1 - product; - return BigInt.asUintN( - 160, - FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator), - ); - } - } - - static getNextSqrtPriceFromAmount1RoundingDown( - sqrtPX96: bigint, - liquidity: bigint, - amount: bigint, - add: boolean, - ): bigint { - if (add) { - const quotient = - amount <= BI_MAX_UINT160 - ? (amount << FixedPoint96.RESOLUTION) / liquidity - : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity); - return BigInt.asUintN(160, BigInt.asUintN(256, sqrtPX96) + quotient); - } else { - const quotient = - amount <= BI_MAX_UINT160 - ? UnsafeMath.divRoundingUp( - amount << FixedPoint96.RESOLUTION, - liquidity, - ) - : FullMath.mulDivRoundingUp(amount, FixedPoint96.Q96, liquidity); - - _require( - sqrtPX96 > quotient, - '', - { sqrtPX96, quotient }, - 'sqrtPX96 > quotient', - ); - return BigInt.asUintN(160, sqrtPX96 - quotient); - } - } - - static getNextSqrtPriceFromInput( - sqrtPX96: bigint, - liquidity: bigint, - amountIn: bigint, - zeroForOne: boolean, - ): bigint { - _require(sqrtPX96 > 0n, '', { sqrtPX96 }, 'sqrtPX96 > 0n'); - _require(liquidity > 0n, '', { liquidity }, 'liquidity > 0n'); - - return zeroForOne - ? SqrtPriceMath.getNextSqrtPriceFromAmount0RoundingUp( - sqrtPX96, - liquidity, - amountIn, - true, - ) - : SqrtPriceMath.getNextSqrtPriceFromAmount1RoundingDown( - sqrtPX96, - liquidity, - amountIn, - true, - ); - } - - static getNextSqrtPriceFromOutput( - sqrtPX96: bigint, - liquidity: bigint, - amountOut: bigint, - zeroForOne: boolean, - ): bigint { - _require(sqrtPX96 > 0n, '', { sqrtPX96 }, 'sqrtPX96 > 0n'); - _require(liquidity > 0n, '', { liquidity }, 'liquidity > 0n'); - - return zeroForOne - ? SqrtPriceMath.getNextSqrtPriceFromAmount1RoundingDown( - sqrtPX96, - liquidity, - amountOut, - false, - ) - : SqrtPriceMath.getNextSqrtPriceFromAmount0RoundingUp( - sqrtPX96, - liquidity, - amountOut, - false, - ); - } - - static getAmount0Delta( - sqrtRatioAX96: bigint, - sqrtRatioBX96: bigint, - liquidity: bigint, - roundUp: boolean, - ) { - if (sqrtRatioAX96 > sqrtRatioBX96) { - [sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]; - } - - const numerator1 = - BigInt.asUintN(256, liquidity) << FixedPoint96.RESOLUTION; - const numerator2 = sqrtRatioBX96 - sqrtRatioAX96; - - _require(sqrtRatioAX96 > 0, '', { sqrtRatioAX96 }, 'sqrtRatioAX96 > 0'); - - return roundUp - ? UnsafeMath.divRoundingUp( - FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96), - sqrtRatioAX96, - ) - : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96; - } - - static getAmount1Delta( - sqrtRatioAX96: bigint, - sqrtRatioBX96: bigint, - liquidity: bigint, - roundUp: boolean, - ) { - if (sqrtRatioAX96 > sqrtRatioBX96) - [sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]; - - return roundUp - ? FullMath.mulDivRoundingUp( - liquidity, - sqrtRatioBX96 - sqrtRatioAX96, - FixedPoint96.Q96, - ) - : FullMath.mulDiv( - liquidity, - sqrtRatioBX96 - sqrtRatioAX96, - FixedPoint96.Q96, - ); - } - - // Overloaded with different argument numbers - static _getAmount0DeltaO( - sqrtRatioAX96: bigint, - sqrtRatioBX96: bigint, - liquidity: bigint, - ) { - return liquidity < 0 - ? -BigInt.asIntN( - 256, - SqrtPriceMath.getAmount0Delta( - sqrtRatioAX96, - sqrtRatioBX96, - BigInt.asUintN(128, -liquidity), - false, - ), - ) - : BigInt.asIntN( - 256, - SqrtPriceMath.getAmount0Delta( - sqrtRatioAX96, - sqrtRatioBX96, - BigInt.asUintN(128, liquidity), - true, - ), - ); - } - - // Overloaded with different argument numbers - static _getAmount1DeltaO( - sqrtRatioAX96: bigint, - sqrtRatioBX96: bigint, - liquidity: bigint, - ) { - return liquidity < 0 - ? -BigInt.asIntN( - 256, - SqrtPriceMath.getAmount1Delta( - sqrtRatioAX96, - sqrtRatioBX96, - BigInt.asUintN(128, -liquidity), - false, - ), - ) - : BigInt.asIntN( - 256, - SqrtPriceMath.getAmount1Delta( - sqrtRatioAX96, - sqrtRatioBX96, - BigInt.asUintN(128, liquidity), - true, - ), - ); - } -} diff --git a/src/dex/ramses-v2/contract-math/SwapMath.ts b/src/dex/ramses-v2/contract-math/SwapMath.ts deleted file mode 100644 index 3f19cf8cb..000000000 --- a/src/dex/ramses-v2/contract-math/SwapMath.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { BI_POWS } from '../../../bigint-constants'; -import { FullMath } from './FullMath'; -import { SqrtPriceMath } from './SqrtPriceMath'; - -export class SwapMath { - static computeSwapStep( - sqrtRatioCurrentX96: bigint, - sqrtRatioTargetX96: bigint, - liquidity: bigint, - amountRemaining: bigint, - feePips: bigint, - ): { - sqrtRatioNextX96: bigint; - amountIn: bigint; - amountOut: bigint; - feeAmount: bigint; - } { - const zeroForOne = sqrtRatioCurrentX96 >= sqrtRatioTargetX96; - const exactIn = amountRemaining >= 0n; - - let sqrtRatioNextX96 = 0n; - let amountIn = 0n; - let amountOut = 0n; - let feeAmount = 0n; - - if (exactIn) { - const amountRemainingLessFee = FullMath.mulDiv( - BigInt.asUintN(256, amountRemaining), - BI_POWS[6] - feePips, - BI_POWS[6], - ); - amountIn = zeroForOne - ? SqrtPriceMath.getAmount0Delta( - sqrtRatioTargetX96, - sqrtRatioCurrentX96, - liquidity, - true, - ) - : SqrtPriceMath.getAmount1Delta( - sqrtRatioCurrentX96, - sqrtRatioTargetX96, - liquidity, - true, - ); - if (amountRemainingLessFee >= amountIn) - sqrtRatioNextX96 = sqrtRatioTargetX96; - else - sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromInput( - sqrtRatioCurrentX96, - liquidity, - amountRemainingLessFee, - zeroForOne, - ); - } else { - amountOut = zeroForOne - ? SqrtPriceMath.getAmount1Delta( - sqrtRatioTargetX96, - sqrtRatioCurrentX96, - liquidity, - false, - ) - : SqrtPriceMath.getAmount0Delta( - sqrtRatioCurrentX96, - sqrtRatioTargetX96, - liquidity, - false, - ); - if (BigInt.asUintN(256, -amountRemaining) >= amountOut) - sqrtRatioNextX96 = sqrtRatioTargetX96; - else - sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromOutput( - sqrtRatioCurrentX96, - liquidity, - BigInt.asUintN(256, -amountRemaining), - zeroForOne, - ); - } - - const max = sqrtRatioTargetX96 == sqrtRatioNextX96; - - if (zeroForOne) { - amountIn = - max && exactIn - ? amountIn - : SqrtPriceMath.getAmount0Delta( - sqrtRatioNextX96, - sqrtRatioCurrentX96, - liquidity, - true, - ); - amountOut = - max && !exactIn - ? amountOut - : SqrtPriceMath.getAmount1Delta( - sqrtRatioNextX96, - sqrtRatioCurrentX96, - liquidity, - false, - ); - } else { - amountIn = - max && exactIn - ? amountIn - : SqrtPriceMath.getAmount1Delta( - sqrtRatioCurrentX96, - sqrtRatioNextX96, - liquidity, - true, - ); - amountOut = - max && !exactIn - ? amountOut - : SqrtPriceMath.getAmount0Delta( - sqrtRatioCurrentX96, - sqrtRatioNextX96, - liquidity, - false, - ); - } - - // cap the output amount to not exceed the remaining output amount - if (!exactIn && amountOut > BigInt.asUintN(256, -amountRemaining)) { - amountOut = BigInt.asUintN(256, -amountRemaining); - } - - if (exactIn && sqrtRatioNextX96 != sqrtRatioTargetX96) { - // we didn't reach the target, so take the remainder of the maximum input as fee - feeAmount = BigInt.asUintN(256, amountRemaining) - amountIn; - } else { - feeAmount = FullMath.mulDivRoundingUp( - amountIn, - feePips, - BI_POWS[6] - feePips, - ); - } - - return { sqrtRatioNextX96, amountIn, amountOut, feeAmount }; - } -} diff --git a/src/dex/ramses-v2/contract-math/Tick.ts b/src/dex/ramses-v2/contract-math/Tick.ts deleted file mode 100644 index 43090a37c..000000000 --- a/src/dex/ramses-v2/contract-math/Tick.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { PoolState, TickInfo } from '../types'; -import { LiquidityMath } from './LiquidityMath'; -import { _require } from '../../../utils'; -import { NumberAsString } from '@paraswap/core'; -import { ZERO_TICK_INFO } from '../constants'; - -export class Tick { - static update( - state: PoolState, - tick: bigint, - tickCurrent: bigint, - liquidityDelta: bigint, - secondsPerLiquidityCumulativeX128: bigint, - tickCumulative: bigint, - time: bigint, - upper: boolean, - maxLiquidity: bigint, - ): boolean { - let info = state.ticks[Number(tick)]; - - if (info === undefined) { - info = { ...ZERO_TICK_INFO }; - state.ticks[Number(tick)] = info; - } - - const liquidityGrossBefore = info.liquidityGross; - const liquidityGrossAfter = LiquidityMath.addDelta( - liquidityGrossBefore, - liquidityDelta, - ); - - _require( - liquidityGrossAfter <= maxLiquidity, - 'LO', - { liquidityGrossAfter, maxLiquidity }, - 'liquidityGrossAfter <= maxLiquidity', - ); - - const flipped = (liquidityGrossAfter == 0n) != (liquidityGrossBefore == 0n); - - if (liquidityGrossBefore == 0n) { - if (tick <= tickCurrent) { - info.secondsPerLiquidityOutsideX128 = secondsPerLiquidityCumulativeX128; - info.tickCumulativeOutside = tickCumulative; - info.secondsOutside = time; - } - info.initialized = true; - } - - info.liquidityGross = liquidityGrossAfter; - - info.liquidityNet = upper - ? BigInt.asIntN( - 128, - BigInt.asIntN(256, info.liquidityNet) - liquidityDelta, - ) - : BigInt.asIntN( - 128, - BigInt.asIntN(256, info.liquidityNet) + liquidityDelta, - ); - return flipped; - } - - static clear(state: PoolState, tick: bigint) { - delete state.ticks[Number(tick)]; - } - - static cross( - ticks: Record, - tick: bigint, - secondsPerLiquidityCumulativeX128: bigint, - tickCumulative: bigint, - time: bigint, - ): bigint { - const info = ticks[Number(tick)]; - info.secondsPerLiquidityOutsideX128 = - secondsPerLiquidityCumulativeX128 - info.secondsPerLiquidityOutsideX128; - info.tickCumulativeOutside = tickCumulative - info.tickCumulativeOutside; - info.secondsOutside = time - info.secondsOutside; - return info.liquidityNet; - } -} diff --git a/src/dex/ramses-v2/contract-math/TickBitMap.ts b/src/dex/ramses-v2/contract-math/TickBitMap.ts deleted file mode 100644 index 2d50a779c..000000000 --- a/src/dex/ramses-v2/contract-math/TickBitMap.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { BI_MAX_UINT8 } from '../../../bigint-constants'; -import { PoolState } from '../types'; -import { BitMath } from './BitMath'; -import { _require } from '../../../utils'; -import { DeepReadonly } from 'ts-essentials'; -import { - OUT_OF_RANGE_ERROR_POSTFIX, - TICK_BITMAP_BUFFER, - TICK_BITMAP_TO_USE, -} from '../constants'; - -function isWordPosOut( - wordPos: bigint, - startTickBitmap: bigint, - // For pricing we use wider range to check price impact. If function called from event - // it must always be within buffer - isPriceQuery: boolean, -) { - let lowerTickBitmapLimit; - let upperTickBitmapLimit; - - if (isPriceQuery) { - lowerTickBitmapLimit = - startTickBitmap - (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE); - upperTickBitmapLimit = - startTickBitmap + (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE); - } else { - lowerTickBitmapLimit = startTickBitmap - TICK_BITMAP_BUFFER; - upperTickBitmapLimit = startTickBitmap + TICK_BITMAP_BUFFER; - } - - _require( - wordPos >= lowerTickBitmapLimit && wordPos <= upperTickBitmapLimit, - `wordPos is out of safe state tickBitmap request range: ${OUT_OF_RANGE_ERROR_POSTFIX}`, - { wordPos }, - `wordPos >= LOWER_TICK_REQUEST_LIMIT && wordPos <= UPPER_TICK_REQUEST_LIMIT`, - ); -} - -export class TickBitMap { - static position(tick: bigint): [bigint, bigint] { - return [BigInt.asIntN(16, tick >> 8n), BigInt.asUintN(8, tick % 256n)]; - } - - static flipTick(state: PoolState, tick: bigint, tickSpacing: bigint) { - _require( - tick % tickSpacing === 0n, - '', - { tick, tickSpacing }, - 'tick % tickSpacing == 0n,', - ); - const [wordPos, bitPos] = TickBitMap.position(tick / tickSpacing); - const mask = 1n << bitPos; - - // flipTick is used only in _updatePosition which is always state changing event - // Therefore it is never used in price query - isWordPosOut(wordPos, state.startTickBitmap, false); - - const stringWordPos = wordPos.toString(); - if (state.tickBitmap[stringWordPos] === undefined) { - state.tickBitmap[stringWordPos] = 0n; - } - - state.tickBitmap[stringWordPos] ^= mask; - } - - static nextInitializedTickWithinOneWord( - state: DeepReadonly, - tick: bigint, - tickSpacing: bigint, - lte: boolean, - isPriceQuery: boolean, - ): [bigint, boolean] { - let compressed = tick / tickSpacing; - if (tick < 0n && tick % tickSpacing != 0n) compressed--; - - let next = 0n; - let initialized = false; - - if (lte) { - const [wordPos, bitPos] = TickBitMap.position(compressed); - const mask = (1n << bitPos) - 1n + (1n << bitPos); - - isWordPosOut(wordPos, state.startTickBitmap, isPriceQuery); - let tickBitmapValue = state.tickBitmap[wordPos.toString()]; - tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; - - const masked = tickBitmapValue & mask; - - initialized = masked != 0n; - next = initialized - ? (compressed - - BigInt.asIntN(24, bitPos - BitMath.mostSignificantBit(masked))) * - tickSpacing - : (compressed - BigInt.asIntN(24, bitPos)) * tickSpacing; - } else { - // start from the word of the next tick, since the current tick state doesn't matter - const [wordPos, bitPos] = TickBitMap.position(compressed + 1n); - const mask = ~((1n << bitPos) - 1n); - - isWordPosOut(wordPos, state.startTickBitmap, isPriceQuery); - let tickBitmapValue = state.tickBitmap[wordPos.toString()]; - tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; - - const masked = tickBitmapValue & mask; - - initialized = masked != 0n; - next = initialized - ? (compressed + - 1n + - BigInt.asIntN(24, BitMath.leastSignificantBit(masked) - bitPos)) * - tickSpacing - : (compressed + 1n + BigInt.asIntN(24, BI_MAX_UINT8 - bitPos)) * - tickSpacing; - } - - return [next, initialized]; - } - - static _putZeroIfUndefined( - state: PoolState, - tickBitmapValue: bigint | undefined, - wordPos: bigint, - isPriceQuery: boolean = false, - ): bigint { - return tickBitmapValue === undefined ? 0n : tickBitmapValue; - } -} diff --git a/src/dex/ramses-v2/contract-math/TickMath.ts b/src/dex/ramses-v2/contract-math/TickMath.ts deleted file mode 100644 index 5515ce15c..000000000 --- a/src/dex/ramses-v2/contract-math/TickMath.ts +++ /dev/null @@ -1,211 +0,0 @@ -import { gt } from 'lodash'; -import { BI_MAX_UINT256 } from '../../../bigint-constants'; -import { _gt } from './utils'; -import { _require } from '../../../utils'; - -export class TickMath { - static readonly MIN_TICK = -887272n; - static readonly MAX_TICK = -TickMath.MIN_TICK; - static readonly MIN_SQRT_RATIO = 4295128739n; - static readonly MAX_SQRT_RATIO = - 1461446703485210103287273052203988822378723970342n; - - static getSqrtRatioAtTick(tick: bigint): bigint { - const absTick = - tick < 0n - ? BigInt.asUintN(256, -BigInt.asIntN(256, tick)) - : BigInt.asUintN(256, BigInt.asIntN(256, tick)); - _require( - absTick <= BigInt.asUintN(256, TickMath.MAX_TICK), - 'T', - { absTick }, - 'absTick <= BigInt.asUintN(256, TickMath.MAX_TICK)', - ); - - let ratio = - (absTick & 0x1n) !== 0n - ? 0xfffcb933bd6fad37aa2d162d1a594001n - : 0x100000000000000000000000000000000n; - if ((absTick & 0x2n) !== 0n) - ratio = (ratio * 0xfff97272373d413259a46990580e213an) >> 128n; - if ((absTick & 0x4n) !== 0n) - ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdccn) >> 128n; - if ((absTick & 0x8n) !== 0n) - ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0n) >> 128n; - if ((absTick & 0x10n) !== 0n) - ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644n) >> 128n; - if ((absTick & 0x20n) !== 0n) - ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0n) >> 128n; - if ((absTick & 0x40n) !== 0n) - ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861n) >> 128n; - if ((absTick & 0x80n) !== 0n) - ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053n) >> 128n; - if ((absTick & 0x100n) !== 0n) - ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4n) >> 128n; - if ((absTick & 0x200n) !== 0n) - ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54n) >> 128n; - if ((absTick & 0x400n) !== 0n) - ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3n) >> 128n; - if ((absTick & 0x800n) !== 0n) - ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9n) >> 128n; - if ((absTick & 0x1000n) !== 0n) - ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825n) >> 128n; - if ((absTick & 0x2000n) !== 0n) - ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5n) >> 128n; - if ((absTick & 0x4000n) !== 0n) - ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7n) >> 128n; - if ((absTick & 0x8000n) !== 0n) - ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6n) >> 128n; - if ((absTick & 0x10000n) !== 0n) - ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9n) >> 128n; - if ((absTick & 0x20000n) !== 0n) - ratio = (ratio * 0x5d6af8dedb81196699c329225ee604n) >> 128n; - if ((absTick & 0x40000n) !== 0n) - ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98n) >> 128n; - if ((absTick & 0x80000n) !== 0n) - ratio = (ratio * 0x48a170391f7dc42444e8fa2n) >> 128n; - - if (tick > 0) ratio = BI_MAX_UINT256 / ratio; - return BigInt.asUintN( - 160, - (ratio >> 32n) + (ratio % (1n << 32n) == 0n ? 0n : 1n), - ); - } - - static getTickAtSqrtRatio(sqrtPriceX96: bigint): bigint { - _require( - sqrtPriceX96 >= TickMath.MIN_SQRT_RATIO && - sqrtPriceX96 < TickMath.MAX_SQRT_RATIO, - 'R', - { sqrtPriceX96 }, - 'sqrtPriceX96 >= TickMath.MIN_SQRT_RATIO && sqrtPriceX96 < TickMath.MAX_SQRT_RATIO', - ); - - let ratio = BigInt.asUintN(256, sqrtPriceX96) << 32n; - - let r = ratio; - let msb = 0n; - - let f = _gt(r, 0xffffffffffffffffffffffffffffffffn) << 7n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0xffffffffffffffffn) << 6n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0xffffffffn) << 5n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0xffffn) << 4n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0xffn) << 3n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0xfn) << 2n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0x3n) << 1n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0x1n); - msb = msb | f; - - if (msb >= 128n) r = ratio >> (msb - 127n); - else r = ratio << (127n - msb); - - let log_2 = (BigInt.asIntN(256, msb) - 128n) << 64n; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 63n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 62n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 61n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 60n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 59n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 58n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 57n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 56n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 55n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 54n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 53n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 52n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 51n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 50n); - - const log_sqrt10001 = log_2 * 255738958999603826347141n; // 128.128 number - - const tickLow = BigInt.asIntN( - 24, - (log_sqrt10001 - 3402992956809132418596140100660247210n) >> 128n, - ); - const tickHi = BigInt.asIntN( - 24, - (log_sqrt10001 + 291339464771989622907027621153398088495n) >> 128n, - ); - - return tickLow === tickHi - ? tickLow - : TickMath.getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 - ? tickHi - : tickLow; - } -} diff --git a/src/dex/ramses-v2/contract-math/UnsafeMath.ts b/src/dex/ramses-v2/contract-math/UnsafeMath.ts deleted file mode 100644 index aebd7c579..000000000 --- a/src/dex/ramses-v2/contract-math/UnsafeMath.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class UnsafeMath { - static divRoundingUp(x: bigint, y: bigint) { - return (x + y - 1n) / y; - } -} diff --git a/src/dex/ramses-v2/contract-math/uniswap-v3-math.ts b/src/dex/ramses-v2/contract-math/uniswap-v3-math.ts deleted file mode 100644 index ab3a1f301..000000000 --- a/src/dex/ramses-v2/contract-math/uniswap-v3-math.ts +++ /dev/null @@ -1,666 +0,0 @@ -import _ from 'lodash'; -import { OutputResult, PoolState, Slot0, TickInfo } from '../types'; -import { LiquidityMath } from './LiquidityMath'; -import { Oracle } from './Oracle'; -import { SqrtPriceMath } from './SqrtPriceMath'; -import { SwapMath } from './SwapMath'; -import { Tick } from './Tick'; -import { TickBitMap } from './TickBitMap'; -import { TickMath } from './TickMath'; -import { _require } from '../../../utils'; -import { DeepReadonly } from 'ts-essentials'; -import { NumberAsString, SwapSide } from '@paraswap/core'; -import { BI_MAX_INT } from '../../../bigint-constants'; -import { - MAX_PRICING_COMPUTATION_STEPS_ALLOWED, - OUT_OF_RANGE_ERROR_POSTFIX, -} from '../constants'; - -type ModifyPositionParams = { - tickLower: bigint; - tickUpper: bigint; - liquidityDelta: bigint; -}; - -type PriceComputationState = { - amountSpecifiedRemaining: bigint; - amountCalculated: bigint; - sqrtPriceX96: bigint; - tick: bigint; - protocolFee: bigint; - liquidity: bigint; - isFirstCycleState: boolean; -}; - -type PriceComputationCache = { - liquidityStart: bigint; - blockTimestamp: bigint; - feeProtocol: bigint; - secondsPerLiquidityCumulativeX128: bigint; - tickCumulative: bigint; - computedLatestObservation: boolean; - tickCount: number; -}; - -function _updatePriceComputationObjects< - T extends PriceComputationState | PriceComputationCache, ->(toUpdate: T, updateBy: T) { - for (const k of Object.keys(updateBy) as (keyof T)[]) { - toUpdate[k] = updateBy[k]; - } -} - -function _priceComputationCycles( - poolState: DeepReadonly, - ticksCopy: Record, - slot0Start: Slot0, - state: PriceComputationState, - cache: PriceComputationCache, - sqrtPriceLimitX96: bigint, - zeroForOne: boolean, - exactInput: boolean, -): [ - // result - PriceComputationState, - // Latest calculated full cycle state we can use for bigger amounts - { - latestFullCycleState: PriceComputationState; - latestFullCycleCache: PriceComputationCache; - }, -] { - const latestFullCycleState: PriceComputationState = { ...state }; - - if (cache.tickCount == 0) { - cache.tickCount = 1; - } - const latestFullCycleCache: PriceComputationCache = { ...cache }; - - // We save tick before any change. Later we use this to restore - // state before last step - let lastTicksCopy: { index: number; tick: TickInfo } | undefined; - - let i = 0; - for ( - ; - state.amountSpecifiedRemaining !== 0n && - state.sqrtPriceX96 !== sqrtPriceLimitX96; - ++i - ) { - if ( - latestFullCycleCache.tickCount + i > - MAX_PRICING_COMPUTATION_STEPS_ALLOWED - ) { - state.amountSpecifiedRemaining = 0n; - state.amountCalculated = 0n; - break; - } - - const step = { - sqrtPriceStartX96: 0n, - tickNext: 0n, - initialized: false, - sqrtPriceNextX96: 0n, - amountIn: 0n, - amountOut: 0n, - feeAmount: 0n, - }; - - step.sqrtPriceStartX96 = state.sqrtPriceX96; - - try { - [step.tickNext, step.initialized] = - TickBitMap.nextInitializedTickWithinOneWord( - poolState, - state.tick, - poolState.tickSpacing, - zeroForOne, - true, - ); - } catch (e) { - if ( - e instanceof Error && - e.message.endsWith(OUT_OF_RANGE_ERROR_POSTFIX) - ) { - state.amountSpecifiedRemaining = 0n; - state.amountCalculated = 0n; - break; - } - throw e; - } - - if (step.tickNext < TickMath.MIN_TICK) { - step.tickNext = TickMath.MIN_TICK; - } else if (step.tickNext > TickMath.MAX_TICK) { - step.tickNext = TickMath.MAX_TICK; - } - - step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext); - - const swapStepResult = SwapMath.computeSwapStep( - state.sqrtPriceX96, - ( - zeroForOne - ? step.sqrtPriceNextX96 < sqrtPriceLimitX96 - : step.sqrtPriceNextX96 > sqrtPriceLimitX96 - ) - ? sqrtPriceLimitX96 - : step.sqrtPriceNextX96, - state.liquidity, - state.amountSpecifiedRemaining, - poolState.fee, - ); - - state.sqrtPriceX96 = swapStepResult.sqrtRatioNextX96; - step.amountIn = swapStepResult.amountIn; - step.amountOut = swapStepResult.amountOut; - step.feeAmount = swapStepResult.feeAmount; - - if (exactInput) { - state.amountSpecifiedRemaining -= step.amountIn + step.feeAmount; - state.amountCalculated = state.amountCalculated - step.amountOut; - } else { - state.amountSpecifiedRemaining += step.amountOut; - state.amountCalculated = - state.amountCalculated + step.amountIn + step.feeAmount; - } - - if (cache.feeProtocol > 0n) { - const delta = step.feeAmount / cache.feeProtocol; - step.feeAmount -= delta; - state.protocolFee += delta; - } - - if (state.sqrtPriceX96 === step.sqrtPriceNextX96) { - if (step.initialized) { - if (!cache.computedLatestObservation) { - [cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128] = - Oracle.observeSingle( - poolState, - cache.blockTimestamp, - 0n, - slot0Start.tick, - slot0Start.observationIndex, - cache.liquidityStart, - slot0Start.observationCardinality, - ); - cache.computedLatestObservation = true; - } - - if (state.amountSpecifiedRemaining === 0n) { - const castTickNext = Number(step.tickNext); - lastTicksCopy = { - index: castTickNext, - tick: { ...ticksCopy[castTickNext] }, - }; - } - - let liquidityNet = Tick.cross( - ticksCopy, - step.tickNext, - cache.secondsPerLiquidityCumulativeX128, - cache.tickCumulative, - cache.blockTimestamp, - ); - if (zeroForOne) liquidityNet = -liquidityNet; - - state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet); - } - - state.tick = zeroForOne ? step.tickNext - 1n : step.tickNext; - } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) { - state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96); - } - - if (state.amountSpecifiedRemaining !== 0n) { - _updatePriceComputationObjects(latestFullCycleState, state); - _updatePriceComputationObjects(latestFullCycleCache, cache); - // If it last cycle, check if ticks were changed and then restore previous state - // for next calculations - } else if (lastTicksCopy !== undefined) { - ticksCopy[lastTicksCopy.index] = lastTicksCopy.tick; - } - } - - if (i > 1) { - latestFullCycleCache.tickCount += i - 1; - } - - if (state.amountSpecifiedRemaining !== 0n) { - state.amountSpecifiedRemaining = 0n; - state.amountCalculated = 0n; - } - - return [state, { latestFullCycleState, latestFullCycleCache }]; -} - -class UniswapV3Math { - queryOutputs( - poolState: DeepReadonly, - // Amounts must increase - amounts: bigint[], - zeroForOne: boolean, - side: SwapSide, - ): OutputResult { - const slot0Start = poolState.slot0; - - const isSell = side === SwapSide.SELL; - - // While calculating, ticks are changing, so to not change the actual state, - // we use copy - const ticksCopy = _.cloneDeep(poolState.ticks); - - const sqrtPriceLimitX96 = zeroForOne - ? TickMath.MIN_SQRT_RATIO + 1n - : TickMath.MAX_SQRT_RATIO - 1n; - - const cache: PriceComputationCache = { - liquidityStart: poolState.liquidity, - blockTimestamp: this._blockTimestamp(poolState), - feeProtocol: zeroForOne - ? slot0Start.feeProtocol % 16n - : slot0Start.feeProtocol >> 4n, - secondsPerLiquidityCumulativeX128: 0n, - tickCumulative: 0n, - computedLatestObservation: false, - tickCount: 0, - }; - - const state: PriceComputationState = { - // Will be overwritten later - amountSpecifiedRemaining: 0n, - amountCalculated: 0n, - sqrtPriceX96: slot0Start.sqrtPriceX96, - tick: slot0Start.tick, - protocolFee: 0n, - liquidity: cache.liquidityStart, - isFirstCycleState: true, - }; - - let isOutOfRange = false; - let previousAmount = 0n; - - const outputs = new Array(amounts.length); - const tickCounts = new Array(amounts.length); - for (const [i, amount] of amounts.entries()) { - if (amount === 0n) { - outputs[i] = 0n; - tickCounts[i] = 0; - continue; - } - - const amountSpecified = isSell - ? BigInt.asIntN(256, amount) - : -BigInt.asIntN(256, amount); - - if (state.isFirstCycleState) { - // Set first non zero amount - state.amountSpecifiedRemaining = amountSpecified; - state.isFirstCycleState = false; - } else { - state.amountSpecifiedRemaining = - amountSpecified - (previousAmount - state.amountSpecifiedRemaining); - } - - const exactInput = amountSpecified > 0n; - - _require( - zeroForOne - ? sqrtPriceLimitX96 < slot0Start.sqrtPriceX96 && - sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO - : sqrtPriceLimitX96 > slot0Start.sqrtPriceX96 && - sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO, - 'SPL', - { zeroForOne, sqrtPriceLimitX96, slot0Start }, - 'zeroForOne ? sqrtPriceLimitX96 < slot0Start.sqrtPriceX96 && sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO : sqrtPriceLimitX96 > slot0Start.sqrtPriceX96 && sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO', - ); - - if (!isOutOfRange) { - const [finalState, { latestFullCycleState, latestFullCycleCache }] = - _priceComputationCycles( - poolState, - ticksCopy, - slot0Start, - state, - cache, - sqrtPriceLimitX96, - zeroForOne, - exactInput, - ); - if ( - finalState.amountSpecifiedRemaining === 0n && - finalState.amountCalculated === 0n - ) { - isOutOfRange = true; - outputs[i] = 0n; - tickCounts[i] = 0; - continue; - } - - // We use it on next step to correct state.amountSpecifiedRemaining - previousAmount = amountSpecified; - - // First extract calculated values - const [amount0, amount1] = - zeroForOne === exactInput - ? [ - amountSpecified - finalState.amountSpecifiedRemaining, - finalState.amountCalculated, - ] - : [ - finalState.amountCalculated, - amountSpecified - finalState.amountSpecifiedRemaining, - ]; - - // Update for next amount - _updatePriceComputationObjects(state, latestFullCycleState); - _updatePriceComputationObjects(cache, latestFullCycleCache); - - if (isSell) { - outputs[i] = BigInt.asUintN(256, -(zeroForOne ? amount1 : amount0)); - tickCounts[i] = latestFullCycleCache.tickCount; - continue; - } else { - outputs[i] = zeroForOne - ? BigInt.asUintN(256, amount0) - : BigInt.asUintN(256, amount1); - tickCounts[i] = latestFullCycleCache.tickCount; - continue; - } - } else { - outputs[i] = 0n; - tickCounts[i] = 0; - } - } - - return { - outputs, - tickCounts, - }; - } - - swapFromEvent( - poolState: PoolState, - newSqrtPriceX96: bigint, - newTick: bigint, - newLiquidity: bigint, - zeroForOne: boolean, - ): void { - const slot0Start = poolState.slot0; - - const cache = { - liquidityStart: poolState.liquidity, - blockTimestamp: this._blockTimestamp(poolState), - feeProtocol: 0n, - secondsPerLiquidityCumulativeX128: 0n, - tickCumulative: 0n, - computedLatestObservation: false, - }; - - const state = { - // Because I don't have the exact amount user used, set this number to MAX_NUMBER to proceed - // with calculations. I think it is not a problem since in loop I don't rely on this value - amountSpecifiedRemaining: BI_MAX_INT, - amountCalculated: 0n, - sqrtPriceX96: slot0Start.sqrtPriceX96, - tick: slot0Start.tick, - protocolFee: 0n, - liquidity: cache.liquidityStart, - }; - - // Because I didn't have all variables, adapted loop stop with state.tick !== newTick - // condition. This cycle need only to calculate Tick.cross() function values - // It means that we are interested in cycling only if state.tick !== newTick - // When they become equivalent, we proceed with state updating part as normal - // And if assumptions regarding this cycle are correct, we don't need to process - // the last cycle when state.tick === newTick - while (state.tick !== newTick && state.sqrtPriceX96 !== newSqrtPriceX96) { - const step = { - sqrtPriceStartX96: 0n, - tickNext: 0n, - initialized: false, - sqrtPriceNextX96: 0n, - amountIn: 0n, - amountOut: 0n, - feeAmount: 0n, - }; - - step.sqrtPriceStartX96 = state.sqrtPriceX96; - - [step.tickNext, step.initialized] = - TickBitMap.nextInitializedTickWithinOneWord( - poolState, - state.tick, - poolState.tickSpacing, - zeroForOne, - false, - ); - - if (step.tickNext < TickMath.MIN_TICK) { - step.tickNext = TickMath.MIN_TICK; - } else if (step.tickNext > TickMath.MAX_TICK) { - step.tickNext = TickMath.MAX_TICK; - } - - step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext); - - const swapStepResult = SwapMath.computeSwapStep( - state.sqrtPriceX96, - ( - zeroForOne - ? step.sqrtPriceNextX96 < newSqrtPriceX96 - : step.sqrtPriceNextX96 > newSqrtPriceX96 - ) - ? newSqrtPriceX96 - : step.sqrtPriceNextX96, - state.liquidity, - state.amountSpecifiedRemaining, - poolState.fee, - ); - - state.sqrtPriceX96 = swapStepResult.sqrtRatioNextX96; - - if (state.sqrtPriceX96 == step.sqrtPriceNextX96) { - if (step.initialized) { - if (!cache.computedLatestObservation) { - [cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128] = - Oracle.observeSingle( - poolState, - cache.blockTimestamp, - 0n, - slot0Start.tick, - slot0Start.observationIndex, - cache.liquidityStart, - slot0Start.observationCardinality, - ); - cache.computedLatestObservation = true; - } - - let liquidityNet = Tick.cross( - poolState.ticks, - step.tickNext, - cache.secondsPerLiquidityCumulativeX128, - cache.tickCumulative, - cache.blockTimestamp, - ); - - if (zeroForOne) liquidityNet = -liquidityNet; - - state.liquidity = LiquidityMath.addDelta( - state.liquidity, - liquidityNet, - ); - } - - state.tick = zeroForOne ? step.tickNext - 1n : step.tickNext; - } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) { - state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96); - } - } - - if (slot0Start.tick !== newTick) { - const [observationIndex, observationCardinality] = Oracle.write( - poolState, - slot0Start.observationIndex, - this._blockTimestamp(poolState), - slot0Start.tick, - poolState.liquidity, - slot0Start.observationCardinality, - slot0Start.observationCardinalityNext, - ); - - [ - poolState.slot0.sqrtPriceX96, - poolState.slot0.tick, - poolState.slot0.observationIndex, - poolState.slot0.observationCardinality, - ] = [newSqrtPriceX96, newTick, observationIndex, observationCardinality]; - } else { - poolState.slot0.sqrtPriceX96 = newSqrtPriceX96; - } - - if (poolState.liquidity !== newLiquidity) - poolState.liquidity = newLiquidity; - } - - _modifyPosition( - state: PoolState, - params: ModifyPositionParams, - ): [bigint, bigint] { - const _slot0 = state.slot0; - - this._updatePosition( - state, - params.tickLower, - params.tickUpper, - params.liquidityDelta, - _slot0.tick, - ); - - let amount0 = 0n; - let amount1 = 0n; - if (params.liquidityDelta !== 0n) { - if (_slot0.tick < params.tickLower) { - amount0 = SqrtPriceMath._getAmount0DeltaO( - TickMath.getSqrtRatioAtTick(params.tickLower), - TickMath.getSqrtRatioAtTick(params.tickUpper), - params.liquidityDelta, - ); - } else if (_slot0.tick < params.tickUpper) { - const liquidityBefore = state.liquidity; - - [state.slot0.observationIndex, state.slot0.observationCardinality] = - Oracle.write( - state, - _slot0.observationIndex, - this._blockTimestamp(state), - _slot0.tick, - liquidityBefore, - _slot0.observationCardinality, - _slot0.observationCardinalityNext, - ); - - amount0 = SqrtPriceMath._getAmount0DeltaO( - _slot0.sqrtPriceX96, - TickMath.getSqrtRatioAtTick(params.tickUpper), - params.liquidityDelta, - ); - amount1 = SqrtPriceMath._getAmount1DeltaO( - TickMath.getSqrtRatioAtTick(params.tickLower), - _slot0.sqrtPriceX96, - params.liquidityDelta, - ); - - state.liquidity = LiquidityMath.addDelta( - liquidityBefore, - params.liquidityDelta, - ); - } else { - amount1 = SqrtPriceMath._getAmount1DeltaO( - TickMath.getSqrtRatioAtTick(params.tickLower), - TickMath.getSqrtRatioAtTick(params.tickUpper), - params.liquidityDelta, - ); - } - } - return [amount0, amount1]; - } - - private _isTickToProcess(state: PoolState, tick: bigint): boolean { - return tick >= state.lowestKnownTick && tick <= state.highestKnownTick; - } - - private _updatePosition( - state: PoolState, - tickLower: bigint, - tickUpper: bigint, - liquidityDelta: bigint, - tick: bigint, - ): void { - // if we need to update the ticks, do it - let flippedLower = false; - let flippedUpper = false; - if (liquidityDelta !== 0n) { - const time = this._blockTimestamp(state); - const [tickCumulative, secondsPerLiquidityCumulativeX128] = - Oracle.observeSingle( - state, - time, - 0n, - state.slot0.tick, - state.slot0.observationIndex, - state.liquidity, - state.slot0.observationCardinality, - ); - - if (this._isTickToProcess(state, tickLower)) { - flippedLower = Tick.update( - state, - tickLower, - tick, - liquidityDelta, - secondsPerLiquidityCumulativeX128, - tickCumulative, - time, - false, - state.maxLiquidityPerTick, - ); - } - if (this._isTickToProcess(state, tickUpper)) { - flippedUpper = Tick.update( - state, - tickUpper, - tick, - liquidityDelta, - secondsPerLiquidityCumulativeX128, - tickCumulative, - time, - true, - state.maxLiquidityPerTick, - ); - } - - if (flippedLower) { - TickBitMap.flipTick(state, tickLower, state.tickSpacing); - } - if (flippedUpper) { - TickBitMap.flipTick(state, tickUpper, state.tickSpacing); - } - } - - // clear any tick data that is no longer needed - if (liquidityDelta < 0n) { - if (flippedLower) { - Tick.clear(state, tickLower); - } - if (flippedUpper) { - Tick.clear(state, tickUpper); - } - } - } - - private _blockTimestamp(state: DeepReadonly) { - return BigInt.asUintN(32, state.blockTimestamp); - } -} - -export const uniswapV3Math = new UniswapV3Math(); diff --git a/src/dex/ramses-v2/contract-math/utils.ts b/src/dex/ramses-v2/contract-math/utils.ts deleted file mode 100644 index 0f4caff99..000000000 --- a/src/dex/ramses-v2/contract-math/utils.ts +++ /dev/null @@ -1,11 +0,0 @@ -export function _mulmod(x: bigint, y: bigint, m: bigint): bigint { - return m === 0n ? 0n : (x * y) % m; -} - -export function _lt(x: bigint, y: bigint) { - return x < y ? 1n : 0n; -} - -export function _gt(x: bigint, y: bigint) { - return x > y ? 1n : 0n; -} diff --git a/src/dex/ramses-v2/ramses-v2-e2e.test.ts b/src/dex/ramses-v2/ramses-v2-e2e.test.ts deleted file mode 100644 index 3adeae01f..000000000 --- a/src/dex/ramses-v2/ramses-v2-e2e.test.ts +++ /dev/null @@ -1,100 +0,0 @@ -import dotenv from 'dotenv'; -dotenv.config(); - -import { testE2E } from '../../../tests/utils-e2e'; -import { - Tokens, - Holders, - NativeTokenSymbols, -} from '../../../tests/constants-e2e'; -import { Network, ContractMethod, SwapSide } from '../../constants'; -import { StaticJsonRpcProvider } from '@ethersproject/providers'; -import { generateConfig } from '../../config'; - -describe('RamsesV2 E2E', () => { - const dexKey = 'RamsesV2'; - - describe('Arbitrum', () => { - const network = Network.ARBITRUM; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const tokenASymbol: string = 'USDCe'; - const tokenBSymbol: string = 'USDT'; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const tokenAAmount: string = '1100000'; - const tokenBAmount: string = '1000000'; - const nativeTokenAmount = '1100000000000'; - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ContractMethod.directUniV3Swap, - ], - ], - [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - ContractMethod.buy, - ContractMethod.directUniV3Buy, - ], - ], - ]); - - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }), - ); - }); -}); diff --git a/src/dex/ramses-v2/ramses-v2-events.test.ts b/src/dex/ramses-v2/ramses-v2-events.test.ts deleted file mode 100644 index 5d1e041e5..000000000 --- a/src/dex/ramses-v2/ramses-v2-events.test.ts +++ /dev/null @@ -1,182 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); - -import _ from 'lodash'; -import { RamsesV2EventPool } from './ramses-v2-pool'; -import { RamsesV2Config } from './config'; -import { Network } from '../../constants'; -import { DummyDexHelper } from '../../dex-helper/index'; -import { testEventSubscriber } from '../../../tests/utils-events'; -import { PoolState } from './types'; -import { Interface } from '@ethersproject/abi'; -import ERC20ABI from '../../abi/erc20.json'; -import StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; -import { AbiItem } from 'web3-utils'; - -jest.setTimeout(300 * 1000); -const dexKey = 'RamsesV2'; -const network = Network.ARBITRUM; -const config = RamsesV2Config[dexKey][network]; - -async function fetchPoolStateFromContract( - uniswapV3Pool: RamsesV2EventPool, - blockNumber: number, - poolAddress: string, -): Promise { - const message = `UniswapV3: ${poolAddress} blockNumber ${blockNumber}`; - console.log(`Fetching state ${message}`); - // Be careful to not request state prior to contract deployment - // Otherwise need to use manual state sourcing from multicall - // We had that mechanism, but removed it with this commit - // You can restore it, but better just to find block after state multicall - // deployment - const state = uniswapV3Pool.generateState(blockNumber); - console.log(`Done ${message}`); - return state; -} - -describe('UniswapV3 Event', function () { - const poolAddress = '0x1251ef3b87157b86f189bdea80b54673b0b59698'; - const poolFeeCode = 500n; - const token0 = '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1'; - const token1 = '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8'; - - const blockNumbers: { [eventName: string]: number[] } = { - // topic0 - 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67 - ['Swap']: [ - 15846349, 15846351, 15846352, 15846353, 15846355, 15846357, 15846358, - 15846360, 15846360, 15846361, 15846362, 15846364, 15846365, 15846366, - 15846367, 15846368, 15846369, 15846370, 15846372, 15846373, 15846374, - 15846375, 15846376, 15846381, 15846382, 15846383, 15846386, 15846387, - 15846388, 15846390, 15846391, 15846392, 15846393, 15846398, 15846400, - 15846403, 15846405, 15846407, 15846408, 15846411, 15846412, 15846413, - 15846415, - ], - // topic0 - 0x0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c - ['Burn']: [ - 15845483, 15845493, 15845539, 15845573, 15845650, 15845679, 15845680, - 15845758, 15845850, 15845865, 15845874, 15845980, 15846159, 15846217, - 15846263, 15846279, 15846297, 15846309, 15846351, 15846394, 15846398, - ], - // topic0 - 0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde - ['Mint']: [ - 15845479, 15845540, 15845624, 15845650, 15845655, 15845679, 15845680, - 15845758, 15845814, 15845867, 15845939, 15845946, 15845964, 15845980, - 15846000, 15846020, 15846044, 15846138, 15846159, 15846181, 15846217, - 15846229, 15846263, 15846279, 15846336, 15846351, 15846405, - ], - // topic0 - 0x973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b133 - ['SetFeeProtocol']: [], - // topic0 - 0xac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a - // There are some events on blockNumbers: 13125816, 12733621, 12591465 - // But stateMulticall is not deployed at that time. So I just remove that check - // I think it is not important actually - ['IncreaseObservationCardinalityNext']: [], - ['Collect']: [ - 16440688, 16440718, 16440799, 16440818, 16440824, 16440834, 16440840, - 16440931, 16440955, 16441031, 16441106, 16441124, 16441186, 16441187, - 16441202, 16441249, - ], - ['Flash']: [ - 16417763, 16419900, 16422564, 16432928, 16434338, 16434528, 16434610, - 16437224, 16437229, - ], - }; - - describe('UniswapV3EventPool', function () { - Object.keys(blockNumbers).forEach((event: string) => { - blockNumbers[event].forEach((blockNumber: number) => { - it(`${event}:${blockNumber} - should return correct state`, async function () { - const dexHelper = new DummyDexHelper(network); - // await dexHelper.init(); - - const logger = dexHelper.getLogger(dexKey); - - const uniswapV3Pool = new RamsesV2EventPool( - dexHelper, - dexKey, - new dexHelper.web3Provider.eth.Contract( - StateMulticallABI as AbiItem[], - config.stateMulticall, - ), - new Interface(ERC20ABI), - config.factory, - poolFeeCode, - token0, - token1, - logger, - undefined, - config.initHash, - ); - - // It is done in generateState. But here have to make it manually - uniswapV3Pool.poolAddress = poolAddress.toLowerCase(); - uniswapV3Pool.addressesSubscribed[0] = poolAddress; - - await testEventSubscriber( - uniswapV3Pool, - uniswapV3Pool.addressesSubscribed, - (_blockNumber: number) => - fetchPoolStateFromContract( - uniswapV3Pool, - _blockNumber, - poolAddress, - ), - blockNumber, - `${dexKey}_${poolAddress}`, - dexHelper.provider, - ); - }); - }); - }); - }); - - // We had issue with this event. Test to tackle that special case - it('Special event case for Mint', async () => { - const _poolAddress = - '0x64750f4098A7F98352f7CD5797f421cEb8D94f64'.toLowerCase(); - const _feeCode = 100n; - const _token0 = '0x4200000000000000000000000000000000000006'; - const _token1 = '0x94b008aa00579c1307b0ef2c499ad98a8ce58e58'; - const blockNumber = 32203881; - - const dexHelper = new DummyDexHelper(Network.ARBITRUM); - // await dexHelper.init(); - - const logger = dexHelper.getLogger(dexKey); - - const _config = RamsesV2Config[dexKey][Network.ARBITRUM]; - - const uniswapV3Pool = new RamsesV2EventPool( - dexHelper, - dexKey, - new dexHelper.web3Provider.eth.Contract( - StateMulticallABI as AbiItem[], - config.stateMulticall, - ), - new Interface(ERC20ABI), - _config.factory, - _feeCode, - _token0, - _token1, - logger, - undefined, - config.initHash, - ); - - // It is done in generateState. But here have to make it manually - uniswapV3Pool.poolAddress = _poolAddress.toLowerCase(); - uniswapV3Pool.addressesSubscribed[0] = _poolAddress; - - await testEventSubscriber( - uniswapV3Pool, - uniswapV3Pool.addressesSubscribed, - (_blockNumber: number) => - fetchPoolStateFromContract(uniswapV3Pool, _blockNumber, _poolAddress), - blockNumber, - `${dexKey}_${_poolAddress}`, - dexHelper.provider, - ); - }); -}); diff --git a/src/dex/ramses-v2/ramses-v2-integration.test.ts b/src/dex/ramses-v2/ramses-v2-integration.test.ts deleted file mode 100644 index d5d40ff66..000000000 --- a/src/dex/ramses-v2/ramses-v2-integration.test.ts +++ /dev/null @@ -1,462 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); - -import { Interface, Result } from '@ethersproject/abi'; -import { DummyDexHelper } from '../../dex-helper/index'; -import { Network, SwapSide } from '../../constants'; -import { BI_POWS } from '../../bigint-constants'; -import { RamsesV2 } from './ramses-v2'; -import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; -import { Tokens } from '../../../tests/constants-e2e'; -import UniswapV3QuoterABI from '../../abi/uniswap-v3/UniswapV3Quoter.abi.json'; -import { Address } from '@paraswap/core'; - -const network = Network.ARBITRUM; -const TokenASymbol = 'USDC'; -const TokenA = Tokens[network][TokenASymbol]; - -const TokenBSymbol = 'WETH'; -const TokenB = Tokens[network][TokenBSymbol]; - -const amounts = [ - 0n, - 10_000n * BI_POWS[6], - 20_000n * BI_POWS[6], - 30_000n * BI_POWS[6], -]; - -const amountsBuy = [0n, 1n * BI_POWS[18], 2n * BI_POWS[18], 3n * BI_POWS[18]]; - -const dexHelper = new DummyDexHelper(network); -const dexKey = 'RamsesV2'; - -const quoterIface = new Interface(UniswapV3QuoterABI); - -function getReaderCalldata( - exchangeAddress: string, - readerIface: Interface, - amounts: bigint[], - funcName: string, - tokenIn: Address, - tokenOut: Address, - fee: bigint, -) { - return amounts.map(amount => ({ - target: exchangeAddress, - callData: readerIface.encodeFunctionData(funcName, [ - tokenIn, - tokenOut, - fee, - amount, - 0n, - ]), - })); -} - -function decodeReaderResult( - results: Result, - readerIface: Interface, - funcName: string, -) { - return results.map(result => { - const parsed = readerIface.decodeFunctionResult(funcName, result); - return BigInt(parsed[0]._hex); - }); -} - -async function checkOnChainPricing( - uniswapV3: RamsesV2, - funcName: string, - blockNumber: number, - prices: bigint[], - tokenIn: Address, - tokenOut: Address, - fee: bigint, - _amounts: bigint[], -) { - // Quoter address - const exchangeAddress = '0xAA2f0eb52db02650959463F9801442f5dF7D5CBe'; - const readerIface = quoterIface; - - const sum = prices.reduce((acc, curr) => (acc += curr), 0n); - - if (sum === 0n) { - console.log( - `Prices were not calculated for tokenIn=${tokenIn}, tokenOut=${tokenOut}, fee=${fee.toString()}. Most likely price impact is too big for requested amount`, - ); - return false; - } - - const readerCallData = getReaderCalldata( - exchangeAddress, - readerIface, - _amounts.slice(1), - funcName, - tokenIn, - tokenOut, - fee, - ); - - let readerResult; - try { - readerResult = ( - await dexHelper.multiContract.methods - .aggregate(readerCallData) - .call({}, blockNumber) - ).returnData; - } catch (e) { - console.log( - `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, - e, - ); - return false; - } - - const expectedPrices = [0n].concat( - decodeReaderResult(readerResult, readerIface, funcName), - ); - - let firstZeroIndex = prices.slice(1).indexOf(0n); - - // we skipped first, so add +1 on result - firstZeroIndex = firstZeroIndex === -1 ? prices.length : firstZeroIndex; - - // Compare only the ones for which we were able to calculate prices - expect(prices.slice(0, firstZeroIndex)).toEqual( - expectedPrices.slice(0, firstZeroIndex), - ); - return true; -} - -describe('RamsesV2', function () { - let blockNumber: number; - let uniswapV3: RamsesV2; - - beforeEach(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - uniswapV3 = new RamsesV2(network, dexKey, dexHelper); - }); - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - const pools = await uniswapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.SELL, - blockNumber, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await uniswapV3.getPricesVolume( - TokenA, - TokenB, - amounts, - SwapSide.SELL, - blockNumber, - pools, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); - - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - uniswapV3, - 'quoteExactInputSingle', - blockNumber, - price.prices, - TokenA.address, - TokenB.address, - fee, - amounts, - ); - if (res === false) falseChecksCounter++; - }), - ); - - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - const pools = await uniswapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.BUY, - blockNumber, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await uniswapV3.getPricesVolume( - TokenA, - TokenB, - amountsBuy, - SwapSide.BUY, - blockNumber, - pools, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices(poolPrices!, amountsBuy, SwapSide.BUY, dexKey); - - // Check if onchain pricing equals to calculated ones - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - uniswapV3, - 'quoteExactOutputSingle', - blockNumber, - price.prices, - TokenA.address, - TokenB.address, - fee, - amountsBuy, - ); - if (res === false) falseChecksCounter++; - }), - ); - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - it('getPoolIdentifiers and getPricesVolume SELL stable pairs', async function () { - const TokenASymbol = 'USDT'; - const TokenA = Tokens[network][TokenASymbol]; - - const TokenBSymbol = 'USDC'; - const TokenB = Tokens[network][TokenBSymbol]; - - const amounts = [ - 0n, - 6000000n, - 12000000n, - 18000000n, - 24000000n, - 30000000n, - 36000000n, - 42000000n, - 48000000n, - 54000000n, - 60000000n, - 66000000n, - 72000000n, - 78000000n, - 84000000n, - 90000000n, - 96000000n, - 102000000n, - 108000000n, - 114000000n, - 120000000n, - 126000000n, - 132000000n, - 138000000n, - 144000000n, - 150000000n, - 156000000n, - 162000000n, - 168000000n, - 174000000n, - 180000000n, - 186000000n, - 192000000n, - 198000000n, - 204000000n, - 210000000n, - 216000000n, - 222000000n, - 228000000n, - 234000000n, - 240000000n, - 246000000n, - 252000000n, - 258000000n, - 264000000n, - 270000000n, - 276000000n, - 282000000n, - 288000000n, - 294000000n, - 300000000n, - ]; - - const pools = await uniswapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.SELL, - blockNumber, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await uniswapV3.getPricesVolume( - TokenA, - TokenB, - amounts, - SwapSide.SELL, - blockNumber, - pools, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices( - poolPrices!.filter(pp => pp.unit !== 0n), - amounts, - SwapSide.SELL, - dexKey, - ); - - // Check if onchain pricing equals to calculated ones - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - uniswapV3, - 'quoteExactInputSingle', - blockNumber, - price.prices, - TokenA.address, - TokenB.address, - fee, - amounts, - ); - if (res === false) falseChecksCounter++; - }), - ); - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - it('getPoolIdentifiers and getPricesVolume BUY stable pairs', async function () { - const TokenASymbol = 'USDC'; - const TokenA = Tokens[network][TokenASymbol]; - - const TokenBSymbol = 'USDT'; - const TokenB = Tokens[network][TokenBSymbol]; - - const amountsBuy = [ - 0n, - 6000000n, - 12000000n, - 18000000n, - 24000000n, - 30000000n, - 36000000n, - 42000000n, - 48000000n, - 54000000n, - 60000000n, - 66000000n, - 72000000n, - 78000000n, - 84000000n, - 90000000n, - 96000000n, - 102000000n, - 108000000n, - 114000000n, - 120000000n, - 126000000n, - 132000000n, - 138000000n, - 144000000n, - 150000000n, - 156000000n, - 162000000n, - 168000000n, - 174000000n, - 180000000n, - 186000000n, - 192000000n, - 198000000n, - 204000000n, - 210000000n, - 216000000n, - 222000000n, - 228000000n, - 234000000n, - 240000000n, - 246000000n, - 252000000n, - 258000000n, - 264000000n, - 270000000n, - 276000000n, - 282000000n, - 288000000n, - 294000000n, - 300000000n, - ]; - - const pools = await uniswapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.BUY, - blockNumber, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await uniswapV3.getPricesVolume( - TokenA, - TokenB, - amountsBuy, - SwapSide.BUY, - blockNumber, - pools, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices( - poolPrices!.filter(pp => pp.unit !== 0n), - amountsBuy, - SwapSide.BUY, - dexKey, - ); - - // Check if onchain pricing equals to calculated ones - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - uniswapV3, - 'quoteExactOutputSingle', - blockNumber, - price.prices, - TokenA.address, - TokenB.address, - fee, - amountsBuy, - ); - if (res === false) falseChecksCounter++; - }), - ); - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - it('getTopPoolsForToken', async function () { - const poolLiquidity = await uniswapV3.getTopPoolsForToken( - Tokens[Network.ARBITRUM]['USDC'].address, - 10, - ); - console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); - - if (!uniswapV3.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); - } - }); -}); diff --git a/src/dex/ramses-v2/ramses-v2-pool.ts b/src/dex/ramses-v2/ramses-v2-pool.ts deleted file mode 100644 index 7f064a6f1..000000000 --- a/src/dex/ramses-v2/ramses-v2-pool.ts +++ /dev/null @@ -1,513 +0,0 @@ -import _ from 'lodash'; -import { Contract } from 'web3-eth-contract'; -import { Interface } from '@ethersproject/abi'; -import { ethers } from 'ethers'; -import { assert, DeepReadonly } from 'ts-essentials'; -import { Log, Logger, BlockHeader, Address } from '../../types'; -import { - InitializeStateOptions, - StatefulEventSubscriber, -} from '../../stateful-event-subscriber'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { - PoolState, - DecodedStateMultiCallResultWithRelativeBitmaps, - TickInfo, - TickBitMapMappingsWithBigNumber, - TickInfoMappingsWithBigNumber, -} from './types'; -import UniswapV3PoolABI from '../../abi/uniswap-v3/UniswapV3Pool.abi.json'; -import { bigIntify, catchParseLogError, isSampled } from '../../utils'; -import { uniswapV3Math } from './contract-math/uniswap-v3-math'; -import { MultiCallParams } from '../../lib/multi-wrapper'; -import { NumberAsString } from '@paraswap/core'; -import { - DEFAULT_POOL_INIT_CODE_HASH, - OUT_OF_RANGE_ERROR_POSTFIX, - TICK_BITMAP_BUFFER, - TICK_BITMAP_TO_USE, -} from './constants'; -import { TickBitMap } from './contract-math/TickBitMap'; -import { uint256ToBigInt } from '../../lib/decoders'; -import { decodeStateMultiCallResultWithRelativeBitmaps } from './utils'; -import { _reduceTickBitmap, _reduceTicks } from '../uniswap-v3/contract-math/utils'; - -export class RamsesV2EventPool extends StatefulEventSubscriber { - handlers: { - [event: string]: ( - event: any, - pool: PoolState, - log: Log, - blockHeader: Readonly, - ) => PoolState; - } = {}; - - logDecoder: (log: Log) => any; - - readonly token0: Address; - - readonly token1: Address; - - private _poolAddress?: Address; - - private _stateRequestCallData?: MultiCallParams< - bigint | DecodedStateMultiCallResultWithRelativeBitmaps - >[]; - - public readonly poolIface = new Interface(UniswapV3PoolABI); - - public readonly feeCodeAsString; - - constructor( - readonly dexHelper: IDexHelper, - parentName: string, - readonly stateMultiContract: Contract, - readonly erc20Interface: Interface, - protected readonly factoryAddress: Address, - public readonly feeCode: bigint, - token0: Address, - token1: Address, - logger: Logger, - mapKey: string = '', - readonly poolInitCodeHash: string, - ) { - super( - parentName, - `${token0}_${token1}_${feeCode}`, - dexHelper, - logger, - true, - mapKey, - ); - this.feeCodeAsString = feeCode.toString(); - this.token0 = token0.toLowerCase(); - this.token1 = token1.toLowerCase(); - this.logDecoder = (log: Log) => this.poolIface.parseLog(log); - this.addressesSubscribed = new Array
(1); - - // Add handlers - this.handlers['Swap'] = this.handleSwapEvent.bind(this); - this.handlers['Burn'] = this.handleBurnEvent.bind(this); - this.handlers['Mint'] = this.handleMintEvent.bind(this); - this.handlers['SetFeeProtocol'] = this.handleSetFeeProtocolEvent.bind(this); - this.handlers['IncreaseObservationCardinalityNext'] = - this.handleIncreaseObservationCardinalityNextEvent.bind(this); - - // Wen need them to keep balance of the pool up to date - this.handlers['Collect'] = this.handleCollectEvent.bind(this); - // Almost the same as Collect, but for pool owners - this.handlers['CollectProtocol'] = this.handleCollectEvent.bind(this); - this.handlers['Flash'] = this.handleFlashEvent.bind(this); - } - - get poolAddress() { - if (this._poolAddress === undefined) { - this._poolAddress = this._computePoolAddress( - this.token0, - this.token1, - this.feeCode, - ); - } - return this._poolAddress; - } - - set poolAddress(address: Address) { - this._poolAddress = address.toLowerCase(); - } - - async initialize( - blockNumber: number, - options?: InitializeStateOptions, - ) { - await super.initialize(blockNumber, options); - } - - protected async processBlockLogs( - state: DeepReadonly, - logs: Readonly[], - blockHeader: Readonly, - ): Promise | null> { - const newState = await super.processBlockLogs(state, logs, blockHeader); - if (newState && !newState.isValid) { - return await this.generateState(blockHeader.number); - } - return newState; - } - - protected processLog( - state: DeepReadonly, - log: Readonly, - blockHeader: Readonly, - ): DeepReadonly | null { - try { - const event = this.logDecoder(log); - - const uniswapV3EventLoggingSampleRate = - this.dexHelper.config.data.uniswapV3EventLoggingSampleRate; - if ( - !this.dexHelper.config.isSlave && - uniswapV3EventLoggingSampleRate && - isSampled(uniswapV3EventLoggingSampleRate) - ) { - this.logger.info( - `event=${event.name} - block=${ - blockHeader.number - }. Log sampled at rate ${uniswapV3EventLoggingSampleRate * 100}%`, - ); - } - - if (event.name in this.handlers) { - // Because we have observations in array which is mutable by nature, there is a - // ts compile error: https://stackoverflow.com/questions/53412934/disable-allowing-assigning-readonly-types-to-non-readonly-types - // And there is no good workaround, so turn off the type checker for this line - const _state = _.cloneDeep(state) as PoolState; - try { - return this.handlers[event.name](event, _state, log, blockHeader); - } catch (e) { - if ( - e instanceof Error && - e.message.endsWith(OUT_OF_RANGE_ERROR_POSTFIX) - ) { - this.logger.warn( - `${this.parentName}: Pool ${this.poolAddress} on ${ - this.dexHelper.config.data.network - } is out of TickBitmap requested range. Re-query the state. ${JSON.stringify( - event, - )}`, - e, - ); - } else { - this.logger.error( - `${this.parentName}: Pool ${this.poolAddress}, ` + - `network=${this.dexHelper.config.data.network}: Unexpected ` + - `error while handling event on blockNumber=${blockHeader.number}, ` + - `blockHash=${blockHeader.hash} and parentHash=${ - blockHeader.parentHash - } for UniswapV3, ${JSON.stringify(event)}`, - e, - ); - } - _state.isValid = false; - return _state; - } - } - } catch (e) { - catchParseLogError(e, this.logger); - } - return null; // ignore unrecognized event - } - - private _getStateRequestCallData() { - if (!this._stateRequestCallData) { - const callData: MultiCallParams< - bigint | DecodedStateMultiCallResultWithRelativeBitmaps - >[] = [ - { - target: this.token0, - callData: this.erc20Interface.encodeFunctionData('balanceOf', [ - this.poolAddress, - ]), - decodeFunction: uint256ToBigInt, - }, - { - target: this.token1, - callData: this.erc20Interface.encodeFunctionData('balanceOf', [ - this.poolAddress, - ]), - decodeFunction: uint256ToBigInt, - }, - { - target: this.stateMultiContract.options.address, - callData: this.stateMultiContract.methods - .getFullStateWithRelativeBitmaps( - this.factoryAddress, - this.token0, - this.token1, - this.feeCode, - this.getBitmapRangeToRequest(), - this.getBitmapRangeToRequest(), - ) - .encodeABI(), - decodeFunction: decodeStateMultiCallResultWithRelativeBitmaps, - }, - ]; - this._stateRequestCallData = callData; - } - return this._stateRequestCallData; - } - - getBitmapRangeToRequest() { - return TICK_BITMAP_TO_USE + TICK_BITMAP_BUFFER; - } - - async generateState(blockNumber: number): Promise> { - const callData = this._getStateRequestCallData(); - - const [resBalance0, resBalance1, resState] = - await this.dexHelper.multiWrapper.tryAggregate< - bigint | DecodedStateMultiCallResultWithRelativeBitmaps - >( - false, - callData, - blockNumber, - this.dexHelper.multiWrapper.defaultBatchSize, - false, - ); - - // Quite ugly solution, but this is the one that fits to current flow. - // I think UniswapV3 callbacks subscriptions are complexified for no reason. - // Need to be revisited later - assert(resState.success, 'Pool does not exist'); - - const [balance0, balance1, _state] = [ - resBalance0.returnData, - resBalance1.returnData, - resState.returnData, - ] as [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmaps]; - - const tickBitmap = {}; - const ticks = {}; - - _reduceTickBitmap(tickBitmap, _state.tickBitmap); - _reduceTicks(ticks, _state.ticks); - - const observations = { - [_state.slot0.observationIndex]: { - blockTimestamp: bigIntify(_state.observation.blockTimestamp), - tickCumulative: bigIntify(_state.observation.tickCumulative), - secondsPerLiquidityCumulativeX128: bigIntify( - _state.observation.secondsPerLiquidityCumulativeX128, - ), - initialized: _state.observation.initialized, - }, - }; - - const currentTick = bigIntify(_state.slot0.tick); - const tickSpacing = bigIntify(_state.tickSpacing); - - const startTickBitmap = TickBitMap.position(currentTick / tickSpacing)[0]; - const requestedRange = this.getBitmapRangeToRequest(); - - return { - pool: _state.pool, - blockTimestamp: bigIntify(_state.blockTimestamp), - slot0: { - sqrtPriceX96: bigIntify(_state.slot0.sqrtPriceX96), - tick: currentTick, - observationIndex: +_state.slot0.observationIndex, - observationCardinality: +_state.slot0.observationCardinality, - observationCardinalityNext: +_state.slot0.observationCardinalityNext, - feeProtocol: bigIntify(_state.slot0.feeProtocol), - }, - liquidity: bigIntify(_state.liquidity), - fee: this.feeCode, - tickSpacing, - maxLiquidityPerTick: bigIntify(_state.maxLiquidityPerTick), - tickBitmap, - ticks, - observations, - isValid: true, - startTickBitmap, - lowestKnownTick: - (BigInt.asIntN(24, startTickBitmap - requestedRange) << 8n) * - tickSpacing, - highestKnownTick: - ((BigInt.asIntN(24, startTickBitmap + requestedRange) << 8n) + - BigInt.asIntN(24, 255n)) * - tickSpacing, - balance0, - balance1, - }; - } - - handleSwapEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - const newSqrtPriceX96 = bigIntify(event.args.sqrtPriceX96); - const amount0 = bigIntify(event.args.amount0); - const amount1 = bigIntify(event.args.amount1); - const newTick = bigIntify(event.args.tick); - const newLiquidity = bigIntify(event.args.liquidity); - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - - if (amount0 <= 0n && amount1 <= 0n) { - this.logger.error( - `${this.parentName}: amount0 <= 0n && amount1 <= 0n for ` + - `${this.poolAddress} and ${blockHeader.number}. Check why it happened`, - ); - pool.isValid = false; - return pool; - } else { - const zeroForOne = amount0 > 0n; - - uniswapV3Math.swapFromEvent( - pool, - newSqrtPriceX96, - newTick, - newLiquidity, - zeroForOne, - ); - - if (zeroForOne) { - if (amount1 < 0n) { - pool.balance1 -= BigInt.asUintN(256, -amount1); - } else { - this.logger.error( - `In swapEvent for pool ${pool.pool} received incorrect values ${zeroForOne} and ${amount1}`, - ); - pool.isValid = false; - } - // This is not correct fully, because pool may get more tokens then it needs, but - // it is not accounted in internal state, it should be good enough - pool.balance0 += BigInt.asUintN(256, amount0); - } else { - if (amount0 < 0n) { - pool.balance0 -= BigInt.asUintN(256, -amount0); - } else { - this.logger.error( - `In swapEvent for pool ${pool.pool} received incorrect values ${zeroForOne} and ${amount0}`, - ); - pool.isValid = false; - } - pool.balance1 += BigInt.asUintN(256, amount1); - } - - return pool; - } - } - - handleBurnEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - const amount = bigIntify(event.args.amount); - const tickLower = bigIntify(event.args.tickLower); - const tickUpper = bigIntify(event.args.tickUpper); - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - - uniswapV3Math._modifyPosition(pool, { - tickLower, - tickUpper, - liquidityDelta: -BigInt.asIntN(128, BigInt.asIntN(256, amount)), - }); - - // From this transaction I conclude that there is no balance change from - // Burn event: https://dashboard.tenderly.co/tx/mainnet/0xfccf5341147ac3ad0e66452273d12dfc3219e81f8fb369a6cdecfb24b9b9d078/logs - // And it aligns with UniswapV3 doc: - // https://github.com/Uniswap/v3-core/blob/05c10bf6d547d6121622ac51c457f93775e1df09/contracts/interfaces/pool/IUniswapV3PoolActions.sol#L59 - // It just updates positions and tokensOwed which may be requested calling collect - // So, we don't need to update pool.balances0 and pool.balances1 here - - return pool; - } - - handleMintEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - const amount = bigIntify(event.args.amount); - const tickLower = bigIntify(event.args.tickLower); - const tickUpper = bigIntify(event.args.tickUpper); - const amount0 = bigIntify(event.args.amount0); - const amount1 = bigIntify(event.args.amount1); - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - - uniswapV3Math._modifyPosition(pool, { - tickLower, - tickUpper, - liquidityDelta: amount, - }); - - pool.balance0 += amount0; - pool.balance1 += amount1; - - return pool; - } - - handleSetFeeProtocolEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - const feeProtocol0 = bigIntify(event.args.feeProtocol0New); - const feeProtocol1 = bigIntify(event.args.feeProtocol1New); - pool.slot0.feeProtocol = feeProtocol0 + (feeProtocol1 << 4n); - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - - return pool; - } - - handleCollectEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - const amount0 = bigIntify(event.args.amount0); - const amount1 = bigIntify(event.args.amount1); - pool.balance0 -= amount0; - pool.balance1 -= amount1; - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - - return pool; - } - - handleFlashEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - const paid0 = bigIntify(event.args.paid0); - const paid1 = bigIntify(event.args.paid1); - pool.balance0 += paid0; - pool.balance1 += paid1; - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - - return pool; - } - - handleIncreaseObservationCardinalityNextEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - pool.slot0.observationCardinalityNext = parseInt( - event.args.observationCardinalityNextNew, - 10, - ); - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - return pool; - } - - private _computePoolAddress( - token0: Address, - token1: Address, - fee: bigint, - ): Address { - // https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/PoolAddress.sol - if (token0 > token1) [token0, token1] = [token1, token0]; - - const encodedKey = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( - ['address', 'address', 'uint24'], - [token0, token1, BigInt.asUintN(24, fee)], - ), - ); - - return ethers.utils.getCreate2Address( - this.factoryAddress, - encodedKey, - this.poolInitCodeHash, - ); - } -} diff --git a/src/dex/ramses-v2/ramses-v2.ts b/src/dex/ramses-v2/ramses-v2.ts deleted file mode 100644 index cc3ce8852..000000000 --- a/src/dex/ramses-v2/ramses-v2.ts +++ /dev/null @@ -1,1136 +0,0 @@ -import { defaultAbiCoder, Interface } from '@ethersproject/abi'; -import _ from 'lodash'; -import { pack } from '@ethersproject/solidity'; -import { - Token, - Address, - ExchangePrices, - AdapterExchangeParam, - SimpleExchangeParam, - PoolLiquidity, - Logger, - NumberAsString, - PoolPrices, - TxInfo, - PreprocessTransactionOptions, - ExchangeTxInfo, -} from '../../types'; -import { SwapSide, Network, CACHE_PREFIX } from '../../constants'; -import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { - getBigIntPow, - getDexKeysWithNetwork, - interpolate, - isTruthy, - uuidToBytes16, -} from '../../utils'; -import { IDex } from '../../dex/idex'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { - DexParams, - OutputResult, - PoolState, - RamsesV2Data, - RamsesV2Functions, - RamsesV2Param, - RamsesV2SimpleSwapParams, -} from './types'; -import { - getLocalDeadlineAsFriendlyPlaceholder, - SimpleExchange, -} from '../simple-exchange'; -import { RamsesV2Config, Adapters } from './config'; -import { RamsesV2EventPool } from './ramses-v2-pool'; -import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; -import UniswapV3QuoterABI from '../../abi/uniswap-v3/UniswapV3Quoter.abi.json'; -import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; -import DirectSwapABI from '../../abi/DirectSwap.json'; -import RamsesV2StateMulticallABI from '../../abi/RamsesV2StateMulticall.abi.json'; -import { - DirectMethods, - UNISWAPV3_EFFICIENCY_FACTOR, - UNISWAPV3_POOL_SEARCH_OVERHEAD, - UNISWAPV3_TICK_BASE_OVERHEAD, - UNISWAPV3_TICK_GAS_COST, -} from './constants'; -import { assert, DeepReadonly } from 'ts-essentials'; -import { uniswapV3Math } from './contract-math/uniswap-v3-math'; -import { Contract } from 'web3-eth-contract'; -import { AbiItem } from 'web3-utils'; -import { BalanceRequest, getBalances } from '../../lib/tokens/balancer-fetcher'; -import { - AssetType, - DEFAULT_ID_ERC20, - DEFAULT_ID_ERC20_AS_STRING, -} from '../../lib/tokens/types'; -import { OptimalSwapExchange } from '@paraswap/core'; - -type PoolPairsInfo = { - token0: Address; - token1: Address; - fee: string; -}; - -const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 60 * 60 * 24 * 1000; // 24 hours -const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 30 * 60 * 1000; // Once in 30 minutes -const UNISWAPV3_QUOTE_GASLIMIT = 200_000; - -export class RamsesV2 - extends SimpleExchange - implements IDex -{ - readonly isFeeOnTransferSupported: boolean = false; - readonly eventPools: Record = {}; - - readonly hasConstantPriceLargeAmounts = false; - readonly needWrapNative = true; - - readonly directSwapIface = new Interface(DirectSwapABI); - - intervalTask?: NodeJS.Timeout; - - public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(_.pick(RamsesV2Config, ['RamsesV2'])); - - logger: Logger; - - private uniswapMulti: Contract; - private stateMultiContract: Contract; - - private notExistingPoolSetKey: string; - - constructor( - protected network: Network, - dexKey: string, - protected dexHelper: IDexHelper, - protected adapters = Adapters[network] || {}, - readonly routerIface = new Interface(UniswapV3RouterABI), - readonly quoterIface = new Interface(UniswapV3QuoterABI), - protected config = RamsesV2Config[dexKey][network], - ) { - super(dexHelper, dexKey); - this.logger = dexHelper.getLogger(dexKey + '-' + network); - this.uniswapMulti = new this.dexHelper.web3Provider.eth.Contract( - UniswapV3MultiABI as AbiItem[], - this.config.uniswapMulticall, - ); - this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( - RamsesV2StateMulticallABI as AbiItem[], - this.config.stateMulticall, - ); - - // To receive revert reasons - this.dexHelper.web3Provider.eth.handleRevert = false; - - // Normalize once all config addresses and use across all scenarios - this.config = this._toLowerForAllConfigAddresses(); - - this.notExistingPoolSetKey = - `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); - } - - get supportedFees() { - return this.config.supportedFees; - } - - getAdapters(side: SwapSide): { name: string; index: number }[] | null { - return this.adapters[side] ? this.adapters[side] : null; - } - - getPoolIdentifier(srcAddress: Address, destAddress: Address, fee: bigint) { - const tokenAddresses = this._sortTokens(srcAddress, destAddress).join('_'); - return `${this.dexKey}_${tokenAddresses}_${fee}`; - } - - async initializePricing(blockNumber: number) { - if (!this.dexHelper.config.isSlave) { - const cleanExpiredNotExistingPoolsKeys = async () => { - const maxTimestamp = - Date.now() - UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS; - await this.dexHelper.cache.zremrangebyscore( - this.notExistingPoolSetKey, - 0, - maxTimestamp, - ); - }; - - this.intervalTask = setInterval( - cleanExpiredNotExistingPoolsKeys.bind(this), - UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS, - ); - } - } - - async getPool( - srcAddress: Address, - destAddress: Address, - fee: bigint, - blockNumber: number, - ): Promise { - let pool = - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)]; - - - if (pool === undefined) { - const [token0, token1] = this._sortTokens(srcAddress, destAddress); - - const key = `${token0}_${token1}_${fee}`.toLowerCase(); - - const notExistingPoolScore = await this.dexHelper.cache.zscore( - this.notExistingPoolSetKey, - key, - ); - const poolDoesNotExist = notExistingPoolScore !== null; - - if (poolDoesNotExist) { - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - null; - return null; - } - - await this.dexHelper.cache.hset( - this.dexmapKey, - key, - JSON.stringify({ - token0, - token1, - fee: fee.toString(), - }), - ); - - this.logger.trace(`starting to listen to new pool: ${key}`); - pool = new RamsesV2EventPool( - this.dexHelper, - this.dexKey, - this.stateMultiContract, - this.erc20Interface, - this.config.factory, - fee, - token0, - token1, - this.logger, - this.cacheStateKey, - this.config.initHash, - ); - - try { - await pool.initialize(blockNumber, { - initCallback: (state: DeepReadonly) => { - //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber - pool!.addressesSubscribed[0] = state.pool; - pool!.poolAddress = state.pool; - }, - }); - } catch (e) { - if (e instanceof Error && e.message.endsWith('Pool does not exist')) { - // no need to await we want the set to have the pool key but it's not blocking - this.dexHelper.cache.zadd( - this.notExistingPoolSetKey, - [Date.now(), key], - 'NX', - ); - - // Pool does not exist for this feeCode, so we can set it to null - // to prevent more requests for this pool - pool = null; - this.logger.trace( - `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, - e, - ); - } else { - // Unexpected Error. Break execution. Do not save the pool in this.eventPools - this.logger.error( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool`, - e, - ); - throw new Error('Cannot generate pool state'); - } - } - - if (pool !== null) { - const allEventPools = Object.values(this.eventPools); - this.logger.info( - `starting to listen to new non-null pool: ${key}. Already following ${allEventPools - // Not that I like this reduce, but since it is done only on initialization, expect this to be ok - .reduce( - (acc, curr) => (curr !== null ? ++acc : acc), - 0, - )} non-null pools or ${allEventPools.length} total pools`, - ); - } - - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - pool; - } - return pool; - } - - async addMasterPool(poolKey: string, blockNumber: number): Promise { - const _pairs = await this.dexHelper.cache.hget(this.dexmapKey, poolKey); - if (!_pairs) { - this.logger.warn( - `did not find poolConfig in for key ${this.dexmapKey} ${poolKey}`, - ); - return false; - } - - const poolInfo: PoolPairsInfo = JSON.parse(_pairs); - - const pool = await this.getPool( - poolInfo.token0, - poolInfo.token1, - BigInt(poolInfo.fee), - blockNumber, - ); - - if (!pool) { - return false; - } - - return true; - } - - async getPoolIdentifiers( - srcToken: Token, - destToken: Token, - side: SwapSide, - blockNumber: number, - ): Promise { - const _srcToken = this.dexHelper.config.wrapETH(srcToken); - const _destToken = this.dexHelper.config.wrapETH(destToken); - - const [_srcAddress, _destAddress] = this._getLoweredAddresses( - _srcToken, - _destToken, - ); - - if (_srcAddress === _destAddress) return []; - - const pools = ( - await Promise.all( - this.supportedFees.map(async fee => - this.getPool(_srcAddress, _destAddress, fee, blockNumber), - ), - ) - ).filter(pool => pool); - - if (pools.length === 0) return []; - - return pools.map(pool => - this.getPoolIdentifier(_srcAddress, _destAddress, pool!.feeCode), - ); - } - - async getPricingFromRpc( - from: Token, - to: Token, - amounts: bigint[], - side: SwapSide, - pools: RamsesV2EventPool[], - ): Promise | null> { - if (pools.length === 0) { - return null; - } - this.logger.warn(`fallback to rpc for ${pools.length} pool(s)`); - - const requests = pools.map( - pool => ({ - owner: pool.poolAddress, - asset: side == SwapSide.SELL ? from.address : to.address, - assetType: AssetType.ERC20, - ids: [ - { - id: DEFAULT_ID_ERC20, - spenders: [], - }, - ], - }), - [], - ); - - const balances = await getBalances(this.dexHelper.multiWrapper, requests); - - pools = pools.filter((pool, index) => { - const balance = balances[index].amounts[DEFAULT_ID_ERC20_AS_STRING]; - if (balance >= amounts[amounts.length - 1]) { - return true; - } - this.logger.warn( - `[${this.network}][${pool.parentName}] have no balance ${pool.poolAddress} ${from.address} ${to.address}. (Balance: ${balance})`, - ); - return false; - }); - - pools.forEach(pool => { - this.logger.warn( - `[${this.network}][${pool.parentName}] fallback to rpc for ${pool.name}`, - ); - }); - - const unitVolume = getBigIntPow( - (side === SwapSide.SELL ? from : to).decimals, - ); - - const chunks = amounts.length - 1; - - const _width = Math.floor(chunks / this.config.chunksCount); - - const _amounts = [unitVolume].concat( - Array.from(Array(this.config.chunksCount).keys()).map( - i => amounts[(i + 1) * _width], - ), - ); - - const calldata = pools.map(pool => - _amounts.map(_amount => ({ - target: this.config.quoter, - gasLimit: UNISWAPV3_QUOTE_GASLIMIT, - callData: - side === SwapSide.SELL - ? this.quoterIface.encodeFunctionData('quoteExactInputSingle', [ - [ - from.address, - to.address, - _amount.toString(), - pool.feeCodeAsString, - 0, //sqrtPriceLimitX96 - ], - ]) - : this.quoterIface.encodeFunctionData('quoteExactOutputSingle', [ - [ - from.address, - to.address, - _amount.toString(), - pool.feeCodeAsString, - 0, //sqrtPriceLimitX96 - ], - ]), - })), - ); - - const data = await this.uniswapMulti.methods - .multicall(calldata.flat()) - .call(); - - const decode = (j: number): bigint => { - if (!data.returnData[j].success) { - return 0n; - } - const decoded = defaultAbiCoder.decode( - ['uint256'], - data.returnData[j].returnData, - ); - return BigInt(decoded[0].toString()); - }; - - let i = 0; - const result = pools.map(pool => { - const _rates = _amounts.map(() => decode(i++)); - const unit: bigint = _rates[0]; - - const prices = interpolate( - _amounts.slice(1), - _rates.slice(1), - amounts, - side, - ); - - return { - prices, - unit, - data: { - path: [ - { - tokenIn: from.address, - tokenOut: to.address, - fee: pool.feeCodeAsString, - }, - ], - exchange: pool.poolAddress, - }, - poolIdentifier: this.getPoolIdentifier( - pool.token0, - pool.token1, - pool.feeCode, - ), - exchange: this.dexKey, - gasCost: prices.map(p => (p === 0n ? 0 : UNISWAPV3_QUOTE_GASLIMIT)), - poolAddresses: [pool.poolAddress], - }; - }); - - return result; - } - - async getPricesVolume( - srcToken: Token, - destToken: Token, - amounts: bigint[], - side: SwapSide, - blockNumber: number, - limitPools?: string[], - ): Promise> { - try { - const _srcToken = this.dexHelper.config.wrapETH(srcToken); - const _destToken = this.dexHelper.config.wrapETH(destToken); - - const [_srcAddress, _destAddress] = this._getLoweredAddresses( - _srcToken, - _destToken, - ); - - if (_srcAddress === _destAddress) return null; - - let selectedPools: RamsesV2EventPool[] = []; - - if (!limitPools) { - selectedPools = ( - await Promise.all( - this.supportedFees.map(async fee => { - const locallyFoundPool = - this.eventPools[ - this.getPoolIdentifier(_srcAddress, _destAddress, fee) - ]; - if (locallyFoundPool) return locallyFoundPool; - - const newlyFetchedPool = await this.getPool( - _srcAddress, - _destAddress, - fee, - blockNumber, - ); - return newlyFetchedPool; - }), - ) - ).filter(isTruthy); - } else { - const pairIdentifierWithoutFee = this.getPoolIdentifier( - _srcAddress, - _destAddress, - 0n, - // Trim from 0 fee postfix, so it become comparable - ).slice(0, -1); - - const poolIdentifiers = limitPools.filter(identifier => - identifier.startsWith(pairIdentifierWithoutFee), - ); - - selectedPools = ( - await Promise.all( - poolIdentifiers.map(async identifier => { - let locallyFoundPool = this.eventPools[identifier]; - if (locallyFoundPool) return locallyFoundPool; - - const [, srcAddress, destAddress, fee] = identifier.split('_'); - const newlyFetchedPool = await this.getPool( - srcAddress, - destAddress, - BigInt(fee), - blockNumber, - ); - return newlyFetchedPool; - }), - ) - ).filter(isTruthy); - } - - if (selectedPools.length === 0) return null; - - const poolsToUse = selectedPools.reduce( - (acc, pool) => { - let state = pool.getState(blockNumber); - if (state === null) { - this.logger.trace( - `${this.dexKey}: State === null. Fallback to rpc ${pool.name}`, - ); - acc.poolWithoutState.push(pool); - } else { - acc.poolWithState.push(pool); - } - return acc; - }, - { - poolWithState: [] as RamsesV2EventPool[], - poolWithoutState: [] as RamsesV2EventPool[], - }, - ); - - const rpcResultsPromise = this.getPricingFromRpc( - _srcToken, - _destToken, - amounts, - side, - poolsToUse.poolWithoutState, - ); - - const states = poolsToUse.poolWithState.map( - p => p.getState(blockNumber)!, - ); - - const unitAmount = getBigIntPow( - side == SwapSide.SELL ? _srcToken.decimals : _destToken.decimals, - ); - - const _amounts = [...amounts.slice(1)]; - - const [token0] = this._sortTokens(_srcAddress, _destAddress); - - const zeroForOne = token0 === _srcAddress ? true : false; - - const result = await Promise.all( - poolsToUse.poolWithState.map(async (pool, i) => { - const state = states[i]; - - if (state.liquidity <= 0n) { - this.logger.trace(`pool have 0 liquidity`); - return null; - } - - const balanceDestToken = - _destAddress === pool.token0 ? state.balance0 : state.balance1; - - const unitResult = this._getOutputs( - state, - [unitAmount], - zeroForOne, - side, - balanceDestToken, - ); - const pricesResult = this._getOutputs( - state, - _amounts, - zeroForOne, - side, - balanceDestToken, - ); - - if (!unitResult || !pricesResult) { - this.logger.debug('Prices or unit is not calculated'); - return null; - } - - const prices = [0n, ...pricesResult.outputs]; - const gasCost = [ - 0, - ...pricesResult.outputs.map((p, index) => { - if (p == 0n) { - return 0; - } else { - return ( - UNISWAPV3_POOL_SEARCH_OVERHEAD + - UNISWAPV3_TICK_BASE_OVERHEAD + - pricesResult.tickCounts[index] * UNISWAPV3_TICK_GAS_COST - ); - } - }), - ]; - return { - unit: unitResult.outputs[0], - prices, - data: { - path: [ - { - tokenIn: _srcAddress, - tokenOut: _destAddress, - fee: pool.feeCode.toString(), - }, - ], - }, - poolIdentifier: this.getPoolIdentifier( - pool.token0, - pool.token1, - pool.feeCode, - ), - exchange: this.dexKey, - gasCost: gasCost, - poolAddresses: [pool.poolAddress], - }; - }), - ); - const rpcResults = await rpcResultsPromise; - - const notNullResult = result.filter( - res => res !== null, - ) as ExchangePrices; - - if (rpcResults) { - rpcResults.forEach(r => { - if (r) { - notNullResult.push(r); - } - }); - } - - return notNullResult; - } catch (e) { - this.logger.error( - `Error_getPricesVolume ${srcToken.symbol || srcToken.address}, ${ - destToken.symbol || destToken.address - }, ${side}:`, - e, - ); - return null; - } - } - - getAdapterParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, - data: RamsesV2Data, - side: SwapSide, - ): AdapterExchangeParam { - const { path: rawPath } = data; - const path = this._encodePath(rawPath, side); - - const payload = this.abiCoder.encodeParameter( - { - ParentStruct: { - path: 'bytes', - deadline: 'uint256', - }, - }, - { - path, - deadline: getLocalDeadlineAsFriendlyPlaceholder(), // FIXME: more gas efficient to pass block.timestamp in adapter - }, - ); - - return { - targetExchange: this.config.router, - payload, - networkFee: '0', - }; - } - - getCalldataGasCost(poolPrices: PoolPrices): number | number[] { - const gasCost = - CALLDATA_GAS_COST.DEX_OVERHEAD + - CALLDATA_GAS_COST.LENGTH_SMALL + - // ParentStruct header - CALLDATA_GAS_COST.OFFSET_SMALL + - // ParentStruct -> path header - CALLDATA_GAS_COST.OFFSET_SMALL + - // ParentStruct -> deadline - CALLDATA_GAS_COST.TIMESTAMP + - // ParentStruct -> path (20+3+20 = 43 = 32+11 bytes) - CALLDATA_GAS_COST.LENGTH_SMALL + - CALLDATA_GAS_COST.FULL_WORD + - CALLDATA_GAS_COST.wordNonZeroBytes(11); - const arr = new Array(poolPrices.prices.length); - poolPrices.prices.forEach((p, index) => { - if (p == 0n) { - arr[index] = 0; - } else { - arr[index] = gasCost; - } - }); - return arr; - } - - getTokenFromAddress(address: Address): Token { - // In this Dex decimals are not used - return { address, decimals: 0 }; - } - - async preProcessTransaction( - optimalSwapExchange: OptimalSwapExchange, - srcToken: Token, - _0: Token, - _1: SwapSide, - options: PreprocessTransactionOptions, - ): Promise<[OptimalSwapExchange, ExchangeTxInfo]> { - if (!options.isDirectMethod) { - return [ - optimalSwapExchange, - { - deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), - }, - ]; - } - - assert( - optimalSwapExchange.data !== undefined, - `preProcessTransaction: data field is missing`, - ); - - let isApproved: boolean | undefined; - - try { - this.erc20Contract.options.address = - this.dexHelper.config.wrapETH(srcToken).address; - const allowance = await this.erc20Contract.methods - .allowance(this.augustusAddress, this.config.router) - .call(undefined, 'latest'); - isApproved = - BigInt(allowance.toString()) >= BigInt(optimalSwapExchange.srcAmount); - } catch (e) { - this.logger.error( - `preProcessTransaction failed to retrieve allowance info: `, - e, - ); - } - - return [ - { - ...optimalSwapExchange, - data: { - ...optimalSwapExchange.data, - isApproved, - }, - }, - { - deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), - }, - ]; - } - - getDirectParam( - srcToken: Address, - destToken: Address, - srcAmount: NumberAsString, - destAmount: NumberAsString, - expectedAmount: NumberAsString, - data: RamsesV2Data, - side: SwapSide, - permit: string, - uuid: string, - feePercent: NumberAsString, - deadline: NumberAsString, - partner: string, - beneficiary: string, - contractMethod?: string, - ): TxInfo { - if ( - contractMethod !== DirectMethods.directSell && - contractMethod !== DirectMethods.directBuy - ) { - throw new Error(`Invalid contract method ${contractMethod}`); - } - - let isApproved: boolean = !!data.isApproved; - if (data.isApproved === undefined) { - this.logger.warn(`isApproved is undefined, defaulting to false`); - } - - const path = this._encodePath(data.path, side); - - const swapParams: RamsesV2Param = [ - srcToken, - destToken, - this.config.router, - srcAmount, - destAmount, - expectedAmount, - feePercent, - deadline, - partner, - isApproved, - beneficiary, - path, - permit, - uuidToBytes16(uuid), - ]; - - const encoder = (...params: RamsesV2Param) => { - return this.directSwapIface.encodeFunctionData( - side === SwapSide.SELL - ? DirectMethods.directSell - : DirectMethods.directBuy, - [params], - ); - }; - - return { - params: swapParams, - encoder, - networkFee: '0', - }; - } - - static getDirectFunctionName(): string[] { - return [DirectMethods.directSell, DirectMethods.directBuy]; - } - - async getSimpleParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, - data: RamsesV2Data, - side: SwapSide, - ): Promise { - const swapFunction = - side === SwapSide.SELL - ? RamsesV2Functions.exactInput - : RamsesV2Functions.exactOutput; - - const path = this._encodePath(data.path, side); - const swapFunctionParams: RamsesV2SimpleSwapParams = - side === SwapSide.SELL - ? { - recipient: this.augustusAddress, - deadline: getLocalDeadlineAsFriendlyPlaceholder(), - amountIn: srcAmount, - amountOutMinimum: destAmount, - path, - } - : { - recipient: this.augustusAddress, - deadline: getLocalDeadlineAsFriendlyPlaceholder(), - amountOut: destAmount, - amountInMaximum: srcAmount, - path, - }; - const swapData = this.routerIface.encodeFunctionData(swapFunction, [ - swapFunctionParams, - ]); - - return this.buildSimpleParamWithoutWETHConversion( - srcToken, - srcAmount, - destToken, - destAmount, - swapData, - this.config.router, - ); - } - - async getTopPoolsForToken( - tokenAddress: Address, - limit: number, - ): Promise { - const _tokenAddress = tokenAddress.toLowerCase(); - - const res = await this._querySubgraph( - `query ($token: Bytes!, $count: Int) { - pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token}) { - id - token0 { - id - decimals - } - token1 { - id - decimals - } - totalValueLockedUSD - } - pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token}) { - id - token0 { - id - decimals - } - token1 { - id - decimals - } - totalValueLockedUSD - } - }`, - { - token: _tokenAddress, - count: limit, - }, - ); - - if (!(res && res.pools0 && res.pools1)) { - this.logger.error( - `Error_${this.dexKey}_Subgraph: couldn't fetch the pools from the subgraph`, - ); - return []; - } - - const pools0 = _.map(res.pools0, pool => ({ - exchange: this.dexKey, - address: pool.id.toLowerCase(), - connectorTokens: [ - { - address: pool.token1.id.toLowerCase(), - decimals: parseInt(pool.token1.decimals), - }, - ], - liquidityUSD: - parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, - })); - - const pools1 = _.map(res.pools1, pool => ({ - exchange: this.dexKey, - address: pool.id.toLowerCase(), - connectorTokens: [ - { - address: pool.token0.id.toLowerCase(), - decimals: parseInt(pool.token0.decimals), - }, - ], - liquidityUSD: - parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, - })); - - const pools = _.slice( - _.sortBy(_.concat(pools0, pools1), [pool => -1 * pool.liquidityUSD]), - 0, - limit, - ); - return pools; - } - - private async _getPoolsFromIdentifiers( - poolIdentifiers: string[], - blockNumber: number, - ): Promise { - const pools = await Promise.all( - poolIdentifiers.map(async identifier => { - const [, srcAddress, destAddress, fee] = identifier.split('_'); - return this.getPool(srcAddress, destAddress, BigInt(fee), blockNumber); - }), - ); - return pools.filter(pool => pool) as RamsesV2EventPool[]; - } - - private _getLoweredAddresses(srcToken: Token, destToken: Token) { - return [srcToken.address.toLowerCase(), destToken.address.toLowerCase()]; - } - - private _sortTokens(srcAddress: Address, destAddress: Address) { - return [srcAddress, destAddress].sort((a, b) => (a < b ? -1 : 1)); - } - - private _toLowerForAllConfigAddresses() { - // If new config property will be added, the TS will throw compile error - const newConfig: DexParams = { - router: this.config.router.toLowerCase(), - quoter: this.config.quoter.toLowerCase(), - factory: this.config.factory.toLowerCase(), - supportedFees: this.config.supportedFees, - stateMulticall: this.config.stateMulticall.toLowerCase(), - chunksCount: this.config.chunksCount, - uniswapMulticall: this.config.uniswapMulticall, - deployer: this.config.deployer?.toLowerCase(), - initHash: this.config.initHash, - subgraphURL: this.config.subgraphURL, - }; - return newConfig; - } - - private _getOutputs( - state: DeepReadonly, - amounts: bigint[], - zeroForOne: boolean, - side: SwapSide, - destTokenBalance: bigint, - ): OutputResult | null { - try { - const outputsResult = uniswapV3Math.queryOutputs( - state, - amounts, - zeroForOne, - side, - ); - - if (side === SwapSide.SELL) { - if (outputsResult.outputs[0] > destTokenBalance) { - return null; - } - - for (let i = 0; i < outputsResult.outputs.length; i++) { - if (outputsResult.outputs[i] > destTokenBalance) { - outputsResult.outputs[i] = 0n; - outputsResult.tickCounts[i] = 0; - } - } - } else { - if (amounts[0] > destTokenBalance) { - return null; - } - - // This may be improved by first checking outputs and requesting outputs - // only for amounts that makes more sense, but I don't think this is really - // important now - for (let i = 0; i < amounts.length; i++) { - if (amounts[i] > destTokenBalance) { - outputsResult.outputs[i] = 0n; - outputsResult.tickCounts[i] = 0; - } - } - } - - return outputsResult; - } catch (e) { - this.logger.debug( - `${this.dexKey}: received error in _getOutputs while calculating outputs`, - e, - ); - return null; - } - } - - private async _querySubgraph( - query: string, - variables: Object, - timeout = 30000, - ) { - try { - const res = await this.dexHelper.httpRequest.post( - this.config.subgraphURL, - { query, variables }, - undefined, - { timeout: timeout }, - ); - return res.data; - } catch (e) { - this.logger.error(`${this.dexKey}: can not query subgraph: `, e); - return {}; - } - } - - private _encodePath( - path: { - tokenIn: Address; - tokenOut: Address; - fee: NumberAsString; - }[], - side: SwapSide, - ): string { - if (path.length === 0) { - this.logger.error( - `${this.dexKey}: Received invalid path=${path} for side=${side} to encode`, - ); - return '0x'; - } - - const { _path, types } = path.reduce( - ( - { _path, types }: { _path: string[]; types: string[] }, - curr, - index, - ): { _path: string[]; types: string[] } => { - if (index === 0) { - return { - types: ['address', 'uint24', 'address'], - _path: [curr.tokenIn, curr.fee, curr.tokenOut], - }; - } else { - return { - types: [...types, 'uint24', 'address'], - _path: [..._path, curr.fee, curr.tokenOut], - }; - } - }, - { _path: [], types: [] }, - ); - - return side === SwapSide.BUY - ? pack(types.reverse(), _path.reverse()) - : pack(types, _path); - } - - releaseResources() { - if (this.intervalTask !== undefined) { - clearInterval(this.intervalTask); - this.intervalTask = undefined; - } - } -} diff --git a/src/dex/ramses-v2/types.ts b/src/dex/ramses-v2/types.ts deleted file mode 100644 index c2db00297..000000000 --- a/src/dex/ramses-v2/types.ts +++ /dev/null @@ -1,177 +0,0 @@ -import { BigNumber } from 'ethers'; -import { NumberAsString } from '../../types'; -import { Address } from '../../types'; - -export type OracleObservation = { - blockTimestamp: bigint; - tickCumulative: bigint; - secondsPerLiquidityCumulativeX128: bigint; - initialized: boolean; -}; - -export type OracleObservationCandidates = { - beforeOrAt: OracleObservation; - atOrAfter: OracleObservation; -}; - -export type TickInfo = { - liquidityGross: bigint; - liquidityNet: bigint; - tickCumulativeOutside: bigint; - secondsPerLiquidityOutsideX128: bigint; - secondsOutside: bigint; - initialized: boolean; -}; - -export type Slot0 = { - sqrtPriceX96: bigint; - tick: bigint; - observationIndex: number; - observationCardinality: number; - observationCardinalityNext: number; - feeProtocol: bigint; -}; - -export type PoolState = { - pool: string; - blockTimestamp: bigint; - tickSpacing: bigint; - fee: bigint; - slot0: Slot0; - liquidity: bigint; - maxLiquidityPerTick: bigint; - tickBitmap: Record; - ticks: Record; - observations: Record; - isValid: boolean; - startTickBitmap: bigint; - lowestKnownTick: bigint; - highestKnownTick: bigint; - balance0: bigint; - balance1: bigint; -}; - -export type RamsesV2Data = { - path: { - tokenIn: Address; - tokenOut: Address; - fee: NumberAsString; - }[]; - isApproved?: boolean; -}; - -export type DexParams = { - router: Address; - quoter: Address; - factory: Address; - stateMulticall: Address; - uniswapMulticall: Address; - supportedFees: bigint[]; - chunksCount: number; - deployer?: Address; - subgraphURL: string; - initHash: string; -}; - -export type RamsesV2SimpleSwapSellParam = { - path: string; - recipient: Address; - deadline: string; - amountIn: NumberAsString; - amountOutMinimum: NumberAsString; -}; - -export type RamsesV2SimpleSwapBuyParam = { - path: string; - recipient: Address; - deadline: string; - amountOut: NumberAsString; - amountInMaximum: NumberAsString; -}; - -export type RamsesV2SimpleSwapParams = - | RamsesV2SimpleSwapSellParam - | RamsesV2SimpleSwapBuyParam; - -export type RamsesV2Param = [ - fromToken: Address, - toToken: Address, - exchange: Address, - fromAmount: NumberAsString, - toAmount: NumberAsString, - expectedAmount: NumberAsString, - feePercent: NumberAsString, - deadline: NumberAsString, - partner: Address, - isApproved: boolean, - beneficiary: Address, - path: string, - permit: string, - uuid: string, -]; - -export enum RamsesV2Functions { - exactInput = 'exactInput', - exactOutput = 'exactOutput', -} - -export type TickInfoMappings = { - index: number; - value: TickInfo; -}; - -export type TickBitMapMappings = { - index: number; - value: bigint; -}; - -export type OutputResult = { - outputs: bigint[]; - tickCounts: number[]; -}; - -// Just rewrote every type with BigNumber basically - -export type TickBitMapMappingsWithBigNumber = { - index: number; - value: BigNumber; -}; - -export type TickInfoWithBigNumber = { - initialized: boolean; - liquidityGross: BigNumber; - liquidityNet: BigNumber; - secondsOutside: number; - secondsPerLiquidityOutsideX128: BigNumber; - tickCumulativeOutside: BigNumber; -}; - -export type TickInfoMappingsWithBigNumber = { - index: number; - value: TickInfoWithBigNumber; -}; - -export type DecodedStateMultiCallResultWithRelativeBitmaps = { - pool: Address; - blockTimestamp: BigNumber; - slot0: { - feeProtocol: number; - observationCardinality: number; - observationCardinalityNext: number; - observationIndex: number; - sqrtPriceX96: BigNumber; - tick: number; - unlocked: boolean; - }; - liquidity: BigNumber; - tickSpacing: number; - maxLiquidityPerTick: BigNumber; - observation: { - blockTimestamp: number; - initialized: boolean; - secondsPerLiquidityCumulativeX128: BigNumber; - tickCumulative: BigNumber; - }; - tickBitmap: TickBitMapMappingsWithBigNumber[]; - ticks: TickInfoMappingsWithBigNumber[]; -}; diff --git a/src/dex/ramses-v2/utils.ts b/src/dex/ramses-v2/utils.ts deleted file mode 100644 index badfd0956..000000000 --- a/src/dex/ramses-v2/utils.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { BytesLike, ethers } from 'ethers'; -import { assert } from 'ts-essentials'; -import { extractSuccessAndValue } from '../../lib/decoders'; -import { MultiResult } from '../../lib/multi-wrapper'; -import { DexConfigMap } from '../../types'; -import { - DexParams, - DecodedStateMultiCallResultWithRelativeBitmaps, -} from './types'; - -export function getUniswapV3DexKey(UniswapV3Config: DexConfigMap) { - const UniswapV3Keys = Object.keys(UniswapV3Config); - if (UniswapV3Keys.length !== 1) { - throw new Error( - `UniswapV3 key in UniswapV3Config is not unique. Update relevant places (optimizer) or fix config issue. Received: ${JSON.stringify( - UniswapV3Config, - (_0, value) => (typeof value === 'bigint' ? value.toString() : value), - )}`, - ); - } - - return UniswapV3Keys[0].toLowerCase(); -} - -export function decodeStateMultiCallResultWithRelativeBitmaps( - result: MultiResult | BytesLike, -): DecodedStateMultiCallResultWithRelativeBitmaps { - const [isSuccess, toDecode] = extractSuccessAndValue(result); - - assert( - isSuccess && toDecode !== '0x', - `decodeStateMultiCallResultWithRelativeBitmaps failed to get decodable result: ${result}`, - ); - - const decoded = ethers.utils.defaultAbiCoder.decode( - [ - // I don't want to pass here any interface, so I just use it in ethers format - ` - tuple( - address pool, - uint256 blockTimestamp, - tuple( - uint160 sqrtPriceX96, - int24 tick, - uint16 observationIndex, - uint16 observationCardinality, - uint16 observationCardinalityNext, - uint8 feeProtocol, - bool unlocked, - ) slot0, - uint128 liquidity, - int24 tickSpacing, - uint128 maxLiquidityPerTick, - tuple( - uint32 blockTimestamp, - int56 tickCumulative, - uint160 secondsPerLiquidityCumulativeX128, - bool initialized, - uint160 secondsPerBoostedLiquidityPeriodX128, - uint32 boostedInRange, - ) observation, - tuple( - int16 index, - uint256 value - )[] tickBitmap, - tuple( - int24 index, - tuple( - uint128 liquidityGross, - int128 liquidityNet, - uint128 cleanUnusedSlot, - uint128 cleanUnusedSlot2, - uint256 feeGrowthOutside0X128, - uint256 feeGrowthOutside1X128, - int56 tickCumulativeOutside, - uint160 secondsPerLiquidityOutsideX128, - uint32 secondsOutside, - bool initialized, - ) value, - )[] ticks - ) - `, - ], - toDecode, - )[0]; - - // This conversion is not precise, because when we decode, we have more values - // But I typed only the ones that are used later - return decoded as DecodedStateMultiCallResultWithRelativeBitmaps; -} diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index ae4ffceea..18a66c612 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -111,8 +111,7 @@ export const UniswapV3Config: DexConfigMap = { [Network.ARBITRUM]: { factory: '0xAA2cd7477c451E703f3B9Ba5663334914763edF8', deployer: '0xb3e423ab9cE6C03D98326A3A2a0D7D96b0829f22', - quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', - // quoter: '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', + quoter: '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', router: '0xAA23611badAFB62D37E7295A682D21960ac85A90', supportedFees: SUPPORTED_FEES, stateMulticall: '0x50EE4112Cab9c79812F23bE079aB3911395ACc8e', diff --git a/src/dex/uniswap-v3/forks/ramses-v2/utils.ts b/src/dex/uniswap-v3/forks/ramses-v2/utils.ts index c6032107e..9e47f08f2 100644 --- a/src/dex/uniswap-v3/forks/ramses-v2/utils.ts +++ b/src/dex/uniswap-v3/forks/ramses-v2/utils.ts @@ -1,6 +1,6 @@ import { MultiResult } from '../../../../lib/multi-wrapper'; import { BytesLike, ethers } from 'ethers'; -import { DecodedStateMultiCallResultWithRelativeBitmaps } from '../../../ramses-v2/types'; +import { DecodedStateMultiCallResultWithRelativeBitmaps } from '../../types'; import { extractSuccessAndValue } from '../../../../lib/decoders'; import { assert } from 'ts-essentials'; diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index 3afbd8148..bccf2bf69 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -439,50 +439,50 @@ describe('UniswapV3 E2E', () => { SwapSide.SELL, [ ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - // ContractMethod.directUniV3Swap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, ], ], - // [ - // SwapSide.BUY, - // [ - // ContractMethod.simpleBuy, - // ContractMethod.buy, - // ContractMethod.directUniV3Buy, - // ], - // ], ]); sideToContractMethods.forEach((contractMethods, side) => contractMethods.forEach((contractMethod: ContractMethod) => { describe(`${contractMethod}`, () => { - // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - // await testE2E( - // tokens[nativeTokenSymbol], - // tokens[tokenASymbol], - // holders[nativeTokenSymbol], - // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - // await testE2E( - // tokens[tokenASymbol], - // tokens[nativeTokenSymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { await testE2E( tokens[tokenASymbol], diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index 8564dc54b..bd656e368 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -3,13 +3,13 @@ import dotenv from 'dotenv'; dotenv.config(); import { Interface, Result } from '@ethersproject/abi'; -import { DummyDexHelper } from '../../dex-helper/index'; +import { DummyDexHelper, IDexHelper } from '../../dex-helper/index'; import { Network, SwapSide } from '../../constants'; import { BI_POWS } from '../../bigint-constants'; import { UniswapV3 } from './uniswap-v3'; import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; -import UniswapV3QuoterABI from '../../abi/uniswap-v3/UniswapV3Quoter.abi.json'; +import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; import { Address } from '@paraswap/core'; const network = Network.POLYGON; @@ -28,10 +28,8 @@ const amounts = [ const amountsBuy = [0n, 1n * BI_POWS[18], 2n * BI_POWS[18], 3n * BI_POWS[18]]; -const dexHelper = new DummyDexHelper(network); -const dexKey = 'UniswapV3'; -const quoterIface = new Interface(UniswapV3QuoterABI); +const quoterIface = new Interface(UniswapV3QuoterV2ABI); function getReaderCalldata( exchangeAddress: string, @@ -45,11 +43,13 @@ function getReaderCalldata( return amounts.map(amount => ({ target: exchangeAddress, callData: readerIface.encodeFunctionData(funcName, [ - tokenIn, - tokenOut, - fee, - amount, - 0n, + [ + tokenIn, + tokenOut, + amount.toString(), + fee.toString(), + 0, + ] ]), })); } @@ -66,9 +66,11 @@ function decodeReaderResult( } async function checkOnChainPricing( + dexHelper: IDexHelper, uniswapV3: UniswapV3, funcName: string, blockNumber: number, + exchangeAddress: string, prices: bigint[], tokenIn: Address, tokenOut: Address, @@ -99,8 +101,9 @@ async function checkOnChainPricing( // ); const readerCallData = getReaderCalldata( + exchangeAddress, // '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', - '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', + // '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', readerIface, _amounts.slice(1), funcName, @@ -117,7 +120,6 @@ async function checkOnChainPricing( .call({}, blockNumber) ).returnData; } catch (e) { - console.log('E: ', e); console.log( `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, e, @@ -129,6 +131,8 @@ async function checkOnChainPricing( decodeReaderResult(readerResult, readerIface, funcName), ); + console.log('EXPECTED PRICES: ', expectedPrices); + let firstZeroIndex = prices.slice(1).indexOf(0n); // we skipped first, so add +1 on result @@ -142,6 +146,9 @@ async function checkOnChainPricing( } describe('UniswapV3', function () { + const dexHelper = new DummyDexHelper(network); + const dexKey = 'UniswapV3'; + let blockNumber: number; let uniswapV3: UniswapV3; let uniswapV3Mainnet: UniswapV3; @@ -185,9 +192,11 @@ describe('UniswapV3', function () { poolPrices!.map(async price => { const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; const res = await checkOnChainPricing( + dexHelper, uniswapV3, 'quoteExactInputSingle', blockNumber, + '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', price.prices, TokenA.address, TokenB.address, @@ -231,9 +240,11 @@ describe('UniswapV3', function () { poolPrices!.map(async price => { const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; const res = await checkOnChainPricing( + dexHelper, uniswapV3, 'quoteExactOutputSingle', blockNumber, + '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', price.prices, TokenA.address, TokenB.address, @@ -341,9 +352,11 @@ describe('UniswapV3', function () { poolPrices!.map(async price => { const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; const res = await checkOnChainPricing( + dexHelper, uniswapV3, 'quoteExactInputSingle', blockNumber, + '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', price.prices, TokenA.address, TokenB.address, @@ -451,9 +464,11 @@ describe('UniswapV3', function () { poolPrices!.map(async price => { const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; const res = await checkOnChainPricing( + dexHelper, uniswapV3, 'quoteExactOutputSingle', blockNumber, + '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', price.prices, TokenA.address, TokenB.address, @@ -503,7 +518,6 @@ describe('RamsesV2', () => { ); }); - it('getPoolIdentifiers and getPricesVolume SELL', async function () { const amounts = [ @@ -545,9 +559,70 @@ describe('RamsesV2', () => { poolPrices!.map(async price => { const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; const res = await checkOnChainPricing( + dexHelper, uniswapV3, 'quoteExactInputSingle', blockNumber, + '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + + const amounts = [ + 0n, + 6000000n, + 12000000n, + 18000000n, + 24000000n, + 30000000n, + 36000000n, + 42000000n, + ]; + + const pools = await uniswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await uniswapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + uniswapV3, + 'quoteExactOutputSingle', + blockNumber, + '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', price.prices, TokenA.address, TokenB.address, diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 5b2aaa1e2..1e9be24da 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -42,7 +42,6 @@ import { import { UniswapV3Config, Adapters, PoolsToPreload } from './config'; import { UniswapV3EventPool } from './uniswap-v3-pool'; import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; -import UniswapV3QuoterABI from '../../abi/uniswap-v3/UniswapV3Quoter.abi.json'; import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; import DirectSwapABI from '../../abi/DirectSwap.json'; @@ -370,7 +369,6 @@ export class UniswapV3 side: SwapSide, pools: UniswapV3EventPool[], ): Promise | null> { - console.log('POOLS: ', pools); if (pools.length === 0) { return null; } @@ -424,7 +422,6 @@ export class UniswapV3 ), ); - console.log('QUOTER: ', this.config.quoter); const calldata = pools.map(pool => _amounts.map(_amount => ({ target: this.config.quoter, @@ -580,18 +577,17 @@ export class UniswapV3 if (selectedPools.length === 0) return null; - const poolsToUse = selectedPools.reduce( (acc, pool) => { let state = pool.getState(blockNumber); - // if (state === null || pool.poolAddress === '0x6059cf1c818979bccac5d1f015e1b322d154592f') { + if (state === null) { this.logger.trace( `${this.dexKey}: State === null. Fallback to rpc ${pool.name}`, ); acc.poolWithoutState.push(pool); - // } else { - // acc.poolWithState.push(pool); - // } + } else { + acc.poolWithState.push(pool); + } return acc; }, { @@ -600,7 +596,6 @@ export class UniswapV3 }, ); - const rpcResultsPromise = this.getPricingFromRpc( _srcToken, _destToken, @@ -700,9 +695,6 @@ export class UniswapV3 ); const rpcResults = await rpcResultsPromise; - - console.log('RPC RESULTS: ', rpcResults); - const notNullResult = result.filter( res => res !== null, ) as ExchangePrices; From 0df6e5825c87cbdf9c7474d5cb720c60db1eb1c7 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 18 Aug 2023 15:07:52 +0300 Subject: [PATCH 067/833] rollback multiwrapper --- src/lib/multi-wrapper.ts | 8 ++++---- tests/utils-e2e.ts | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/lib/multi-wrapper.ts b/src/lib/multi-wrapper.ts index 4529f81ba..80aff4725 100644 --- a/src/lib/multi-wrapper.ts +++ b/src/lib/multi-wrapper.ts @@ -65,11 +65,11 @@ export class MultiWrapper { } const aggregatedResult = await Promise.all( - allCalls.map(batch => { - return this.multi.methods + allCalls.map(batch => + this.multi.methods .tryAggregate(mandatory, batch) - .call(undefined, blockNumber); - }) + .call(undefined, blockNumber), + ), ); let globalInd = 0; diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index 9aefbaf8f..12143c4dc 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -368,7 +368,6 @@ export async function testE2E( poolIdentifiers, transferFees, ); - console.log('priceRoute: ', priceRoute); expect(parseFloat(priceRoute.destAmount)).toBeGreaterThan(0); // Calculate slippage. Default is 1% From 600b59986c515fbfe2af89ec33508bf29a0920cf Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 18 Aug 2023 15:09:00 +0300 Subject: [PATCH 068/833] remove commented lines from integration tests --- src/dex/uniswap-v3/uniswap-v3-integration.test.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index bd656e368..5dbdb7643 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -90,20 +90,8 @@ async function checkOnChainPricing( return false; } - // const readerCallData = getReaderCalldata( - // exchangeAddress, - // readerIface, - // _amounts.slice(1), - // funcName, - // tokenIn, - // tokenOut, - // fee, - // ); - const readerCallData = getReaderCalldata( exchangeAddress, - // '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', - // '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', readerIface, _amounts.slice(1), funcName, From b24c9bfb6100cef2324bc31e6eddb3a7c6d226b5 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 18 Aug 2023 15:10:55 +0300 Subject: [PATCH 069/833] 2.28.11-ramses-v2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 49e6c222d..9e7ab1986 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.10-ramses-v2", + "version": "2.28.11-ramses-v2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 86c76e117724c29a3621ee08dd06967090e4c4f9 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 18 Aug 2023 15:17:12 +0300 Subject: [PATCH 070/833] remove unused vars --- src/dex/uniswap-v3/uniswap-v3-pool.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/uniswap-v3/uniswap-v3-pool.ts b/src/dex/uniswap-v3/uniswap-v3-pool.ts index 27623c0a2..5eaff129c 100644 --- a/src/dex/uniswap-v3/uniswap-v3-pool.ts +++ b/src/dex/uniswap-v3/uniswap-v3-pool.ts @@ -1,7 +1,7 @@ import _ from 'lodash'; import { Contract } from 'web3-eth-contract'; import { Interface } from '@ethersproject/abi'; -import { BytesLike, ethers } from 'ethers'; +import { ethers } from 'ethers'; import { assert, DeepReadonly } from 'ts-essentials'; import { Log, Logger, BlockHeader, Address } from '../../types'; import { @@ -16,7 +16,7 @@ import { import UniswapV3PoolABI from '../../abi/uniswap-v3/UniswapV3Pool.abi.json'; import { bigIntify, catchParseLogError, isSampled } from '../../utils'; import { uniswapV3Math } from './contract-math/uniswap-v3-math'; -import { MultiCallParams, MultiResult } from '../../lib/multi-wrapper'; +import { MultiCallParams } from '../../lib/multi-wrapper'; import { OUT_OF_RANGE_ERROR_POSTFIX, TICK_BITMAP_BUFFER, From 0a46d6e0bb7b561e1e73fa2ed82557badb348839 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 18 Aug 2023 14:11:51 +0100 Subject: [PATCH 071/833] feat: add new factory crv-usd --- src/dex/curve-v1-factory/config.ts | 26 +- src/dex/curve-v1-factory/curve-v1-factory.ts | 782 ++++++++++-------- .../functions/_calc_withdraw_one_coin.ts | 1 + .../price-handlers/functions/_dynamic_fee.ts | 1 + .../price-handlers/functions/_rates.ts | 1 + .../price-handlers/functions/_xp.ts | 1 + .../price-handlers/functions/_xp_mem.ts | 1 + .../functions/calc_token_amount.ts | 58 ++ .../functions/calc_withdraw_one_coin.ts | 1 + .../price-handlers/functions/constants.ts | 11 + .../price-handlers/functions/get_D.ts | 2 + .../price-handlers/functions/get_D_mem.ts | 1 + .../functions/get_D_precisions.ts | 1 + .../price-handlers/functions/get_dy.ts | 1 + .../functions/get_dy_underlying.ts | 1 + .../price-handlers/functions/get_y.ts | 1 + .../price-handlers/functions/get_y_D.ts | 1 + .../factory-pool-polling.ts | 3 +- src/dex/curve-v1-factory/types.ts | 4 +- 19 files changed, 520 insertions(+), 378 deletions(-) diff --git a/src/dex/curve-v1-factory/config.ts b/src/dex/curve-v1-factory/config.ts index f485b873e..5d5d392bd 100644 --- a/src/dex/curve-v1-factory/config.ts +++ b/src/dex/curve-v1-factory/config.ts @@ -13,7 +13,10 @@ import { normalizeAddress } from '../../utils'; const CurveV1FactoryConfig: DexConfigMap = { CurveV1Factory: { [Network.MAINNET]: { - factoryAddress: '0xB9fC157394Af804a3578134A6585C0dc9cc990d4', + factoryAddresses: [ + '0xB9fC157394Af804a3578134A6585C0dc9cc990d4', + '0x4f8846ae9380b90d2e71d5e3d042dff3e7ebb40d', + ], stateUpdatePeriodMs: 5 * 1000, disabledPools: new Set([ '0x28B0Cf1baFB707F2c6826d10caf6DD901a6540C5', // It is rug pool token @@ -150,6 +153,11 @@ const CurveV1FactoryConfig: DexConfigMap = { name: ImplementationNames.FACTORY_PLAIN_4_OPTIMIZED, address: '0xad4753d045d3aed5c1a6606dfb6a7d7ad67c1ad7', }, + '0xb9f861B7755Ff09cFD65CfE262D19823607b1f24': { + name: ImplementationNames.FACTORY_PLAIN_2_CRV_EMA, + address: '0xb9f861B7755Ff09cFD65CfE262D19823607b1f24', + liquidityApiSlug: '/factory-crvusd', + }, }, customPools: { '0xDcEF968d416a41Cdac0ED8702fAC8128A64241A2': { @@ -200,7 +208,7 @@ const CurveV1FactoryConfig: DexConfigMap = { }, }, [Network.POLYGON]: { - factoryAddress: '0x722272D36ef0Da72FF51c5A65Db7b870E2e8D4ee', + factoryAddresses: ['0x722272D36ef0Da72FF51c5A65Db7b870E2e8D4ee'], stateUpdatePeriodMs: 2 * 1000, disabledPools: new Set([ '0x666Dc3b4baBfd063FaF965BD020024AF0dC51B64', @@ -306,7 +314,7 @@ const CurveV1FactoryConfig: DexConfigMap = { }, }, [Network.FANTOM]: { - factoryAddress: '0x686d67265703D1f124c45E33d47d794c566889Ba', + factoryAddresses: ['0x686d67265703D1f124c45E33d47d794c566889Ba'], stateUpdatePeriodMs: 2 * 1000, disabledPools: new Set([]), disabledImplementations: new Set([]), @@ -421,7 +429,7 @@ const CurveV1FactoryConfig: DexConfigMap = { }, }, [Network.AVALANCHE]: { - factoryAddress: '0xb17b674D9c5CB2e441F8e196a2f048A81355d031', + factoryAddresses: ['0xb17b674D9c5CB2e441F8e196a2f048A81355d031'], stateUpdatePeriodMs: 2 * 1000, // FIX: This must be removed when we go for full CurveV1 event based support disabledPools: new Set(['0x16a7da911a4dd1d83f3ff066fe28f3c792c50d90']), @@ -519,7 +527,7 @@ const CurveV1FactoryConfig: DexConfigMap = { }, }, [Network.ARBITRUM]: { - factoryAddress: '0xb17b674D9c5CB2e441F8e196a2f048A81355d031', + factoryAddresses: ['0xb17b674D9c5CB2e441F8e196a2f048A81355d031'], stateUpdatePeriodMs: 2 * 1000, disabledPools: new Set([]), disabledImplementations: new Set([]), @@ -645,7 +653,7 @@ const CurveV1FactoryConfig: DexConfigMap = { }, }, [Network.OPTIMISM]: { - factoryAddress: '0x2db0E83599a91b508Ac268a6197b8B14F5e72840', + factoryAddresses: ['0x2db0E83599a91b508Ac268a6197b8B14F5e72840'], stateUpdatePeriodMs: 2 * 1000, disabledPools: new Set([]), disabledImplementations: new Set([]), @@ -869,9 +877,9 @@ const configAddressesNormalizer = ( // Unite everything into top level config const normalizedConfig: DexParams = { - factoryAddress: _config.factoryAddress - ? _config.factoryAddress.toLowerCase() - : _config.factoryAddress, + factoryAddresses: _config.factoryAddresses + ? _config.factoryAddresses.map(e => e.toLowerCase()) + : _config.factoryAddresses, stateUpdatePeriodMs: _config.stateUpdatePeriodMs, factoryPoolImplementations, customPools, diff --git a/src/dex/curve-v1-factory/curve-v1-factory.ts b/src/dex/curve-v1-factory/curve-v1-factory.ts index e365c351b..0e88729f8 100644 --- a/src/dex/curve-v1-factory/curve-v1-factory.ts +++ b/src/dex/curve-v1-factory/curve-v1-factory.ts @@ -127,7 +127,7 @@ export class CurveV1Factory private coinsTypeTemplate: AbiItem = DefaultCoinsABI, ) { super(dexHelper, dexKey); - this.logger = dexHelper.getLogger(dexKey); + this.logger = dexHelper.getLogger(`${this.dexKey}-${this.network}`); this.ifaces = { exchangeRouter: new Interface(CurveABI), factory: new Interface(FactoryCurveV1ABI as JsonFragment[]), @@ -185,6 +185,7 @@ export class CurveV1Factory } async initializeCustomPollingPools( + factoryAddresses: string[], blockNumber?: number, // We don't want to initialize state for PoolTracker. It doesn't make any sense initializeInitialState: boolean = true, @@ -193,131 +194,144 @@ export class CurveV1Factory return; } - const { factoryAddress } = this.config; - if (!factoryAddress) { - this.logger.warn( - `${this.dexKey}: No factory address specified for ${this.network}`, - ); - return; - } - await Promise.all( - Object.values(this.config.customPools).map(async customPool => { - const poolIdentifier = this.getPoolIdentifier( - customPool.address, - false, - ); - - const poolContextConstants = ImplementationConstants[customPool.name]; - const { - N_COINS: nCoins, - USE_LENDING: useLending, - isLending, - } = poolContextConstants; - - const coinsAndImplementations = - await this.dexHelper.multiWrapper.aggregate( - _.range(0, nCoins) - .map(i => ({ - target: customPool.address, - callData: this.abiCoder.encodeFunctionCall( - this._getCoinsABI(customPool.coinsInputType), - [i.toString()], - ), - decodeFunction: addressDecode, - })) - .concat([ - { - target: factoryAddress, - callData: this.ifaces.factory.encodeFunctionData( - 'get_implementation_address', - [customPool.address], - ), - decodeFunction: addressDecode, - }, - ]), - ); - const COINS = coinsAndImplementations.slice(0, -1); - const implementationAddress = coinsAndImplementations.slice(-1)[0]; - - const coins_decimals = ( - await this.dexHelper.multiWrapper.tryAggregate( - true, - COINS.map(c => ({ - target: c, - callData: this.ifaces.erc20.encodeFunctionData('decimals', []), - decodeFunction: uint8ToNumber, - })), - ) - ).map(r => r.returnData); - - const poolConstants: PoolConstants = { - COINS, - coins_decimals, - rate_multipliers: this._calcRateMultipliers(coins_decimals), - lpTokenAddress: customPool.lpTokenAddress, - }; - - let newPool: PoolPollingBase; - if ( - Object.values( - CustomImplementationNames, - ).includes(customPool.name) - ) { - // We don't want custom pools to be used for pricing, unless explicitly specified - newPool = new CustomBasePoolForFactory( - this.logger, - this.dexKey, - this.dexHelper.config.data.network, - this.cacheStateKey, - customPool.name, - implementationAddress, - customPool.address, - this.config.stateUpdatePeriodMs, - poolIdentifier, - poolConstants, - poolContextConstants, - customPool.liquidityApiSlug, - customPool.lpTokenAddress, - isLending, - customPool.balancesInputType, - useLending, - customPool.useForPricing, - ); - } else { - // Use for pricing pools from factory - newPool = new CustomBasePoolForFactory( - this.logger, - this.dexKey, - this.dexHelper.config.data.network, - this.cacheStateKey, - customPool.name, - implementationAddress, - customPool.address, - this.config.stateUpdatePeriodMs, - poolIdentifier, - poolConstants, - poolContextConstants, - customPool.liquidityApiSlug, - customPool.lpTokenAddress, - isLending, - customPool.balancesInputType, - useLending, - true, + factoryAddresses.map(async factoryAddress => { + try { + await Promise.all( + Object.values(this.config.customPools).map(async customPool => { + const poolIdentifier = this.getPoolIdentifier( + customPool.address, + false, + ); + + const poolContextConstants = + ImplementationConstants[customPool.name]; + const { + N_COINS: nCoins, + USE_LENDING: useLending, + isLending, + } = poolContextConstants; + + const coinsAndImplementations = + await this.dexHelper.multiWrapper.aggregate( + _.range(0, nCoins) + .map(i => ({ + target: customPool.address, + callData: this.abiCoder.encodeFunctionCall( + this._getCoinsABI(customPool.coinsInputType), + [i.toString()], + ), + decodeFunction: addressDecode, + })) + .concat([ + { + target: factoryAddress, + callData: this.ifaces.factory.encodeFunctionData( + 'get_implementation_address', + [customPool.address], + ), + decodeFunction: addressDecode, + }, + ]), + ); + const COINS = coinsAndImplementations.slice(0, -1); + const implementationAddress = + coinsAndImplementations.slice(-1)[0]; + + const coins_decimals = ( + await this.dexHelper.multiWrapper.tryAggregate( + true, + COINS.map(c => ({ + target: c, + callData: this.ifaces.erc20.encodeFunctionData( + 'decimals', + [], + ), + decodeFunction: uint8ToNumber, + })), + ) + ).map(r => r.returnData); + + const poolConstants: PoolConstants = { + COINS, + coins_decimals, + rate_multipliers: this._calcRateMultipliers(coins_decimals), + lpTokenAddress: customPool.lpTokenAddress, + }; + + let newPool: PoolPollingBase; + if ( + Object.values( + CustomImplementationNames, + ).includes(customPool.name) + ) { + // We don't want custom pools to be used for pricing, unless explicitly specified + newPool = new CustomBasePoolForFactory( + this.logger, + this.dexKey, + this.dexHelper.config.data.network, + this.cacheStateKey, + customPool.name, + implementationAddress, + customPool.address, + this.config.stateUpdatePeriodMs, + poolIdentifier, + poolConstants, + poolContextConstants, + customPool.liquidityApiSlug, + customPool.lpTokenAddress, + isLending, + customPool.balancesInputType, + useLending, + customPool.useForPricing, + ); + } else { + // Use for pricing pools from factory + newPool = new CustomBasePoolForFactory( + this.logger, + this.dexKey, + this.dexHelper.config.data.network, + this.cacheStateKey, + customPool.name, + implementationAddress, + customPool.address, + this.config.stateUpdatePeriodMs, + poolIdentifier, + poolConstants, + poolContextConstants, + customPool.liquidityApiSlug, + customPool.lpTokenAddress, + isLending, + customPool.balancesInputType, + useLending, + true, + ); + } + + this.poolManager.initializeNewPoolForState( + poolIdentifier, + newPool, + ); + + if (initializeInitialState) { + await this.poolManager.initializeIndividualPollingPoolState( + poolIdentifier, + CustomBasePoolForFactory.IS_SRC_FEE_ON_TRANSFER_SUPPORTED, + blockNumber, + ); + } + }), ); - } - - this.poolManager.initializeNewPoolForState(poolIdentifier, newPool); - - if (initializeInitialState) { - await this.poolManager.initializeIndividualPollingPoolState( - poolIdentifier, - CustomBasePoolForFactory.IS_SRC_FEE_ON_TRANSFER_SUPPORTED, - blockNumber, + } catch (e) { + this.logger.error( + `Error initializing custom polling pools for factory ${factoryAddress}: `, + e, ); + throw e; } }), ); + this.areCustomPoolsFetched = true; } @@ -332,277 +346,311 @@ export class CurveV1Factory return; } + if ( + !this.config.factoryAddresses || + this.config.factoryAddresses.length == 0 + ) { + this.logger.warn(`No factory address specified in configs`); + return; + } + // There is no scenario when we need to call initialize custom pools without factory pools // So I put it here to not forget call, because custom pools must be initialised before factory pools // This function may be called multiple times, but will execute only once await this.initializeCustomPollingPools( + this.config.factoryAddresses, blockNumber, initializeInitialState, ); - const { factoryAddress } = this.config; - if (!factoryAddress) { - this.logger.warn( - `${this.dexKey}: No factory address specified for ${this.network}`, - ); - return; - } - - const poolCountResult = await this.dexHelper.multiWrapper!.tryAggregate( - true, - [ - { - target: factoryAddress, - callData: this.ifaces.factory.encodeFunctionData('pool_count'), - decodeFunction: uint256DecodeToNumber, - }, - // This is used later to request all available implementations. In particular meta implementations - { - target: factoryAddress, - callData: this.ifaces.factory.encodeFunctionData('base_pool_count'), - decodeFunction: uint256DecodeToNumber, - }, - ], - ); - - const poolCount = poolCountResult[0].returnData; - const basePoolCount = poolCountResult[1].returnData; - - const calldataGetPoolAddresses = _.range(0, poolCount).map(i => ({ - target: factoryAddress, - callData: this.ifaces.factory.encodeFunctionData('pool_list', [i]), - decodeFunction: addressDecode, - })); - - const calldataGetBasePoolAddresses = _.range(0, basePoolCount).map(i => ({ - target: factoryAddress, - callData: this.ifaces.factory.encodeFunctionData('base_pool_list', [i]), - decodeFunction: addressDecode, - })); - - const allPoolAddresses = ( - await this.dexHelper.multiWrapper.tryAggregate( - true, - calldataGetPoolAddresses.concat(calldataGetBasePoolAddresses), - ) - ).map(e => e.returnData); - - const poolAddresses = allPoolAddresses.slice(0, poolCount); - const basePoolAddresses = allPoolAddresses.slice(poolCount); - - const customPoolAddresses = Object.values(this.config.customPools).map( - customPool => customPool.address, - ); - basePoolAddresses.forEach(basePool => { - if ( - !customPoolAddresses.includes(basePool) && - !this.config.disabledPools.has(basePool) - ) { - this._reportForUnspecifiedCustomPool(basePool); - } - }); - - let callDataFromFactoryPools: MultiCallParams< - string[] | number[] | string - >[] = poolAddresses - .map(p => [ - { - target: factoryAddress, - callData: this.ifaces.factory.encodeFunctionData( - 'get_implementation_address', - [p], - ), - decodeFunction: addressDecode, - }, - { - target: factoryAddress, - callData: this.ifaces.factory.encodeFunctionData('get_coins', [p]), - decodeFunction: ( - result: MultiResult | BytesLike, - ): string[] => - generalDecoder( - result, - ['address[4]'], - new Array(4).fill(NULL_ADDRESS), - parsed => parsed[0].map((p: string) => p.toLowerCase()), - ), - }, - { - target: factoryAddress, - callData: this.ifaces.factory.encodeFunctionData('get_decimals', [p]), - decodeFunction: ( - result: MultiResult | BytesLike, - ): number[] => - generalDecoder( - result, - ['uint256[4]'], - [0, 0, 0, 0], - parsed => parsed[0].map((p: BigNumber) => Number(p.toString())), - ), - }, - ]) - .flat(); - - // This is divider between pools related results and implementations - const factoryResultsDivider = callDataFromFactoryPools.length; - - // Implementations must be requested from factory, but it accepts as arg basePool address - // for metaPools - callDataFromFactoryPools = callDataFromFactoryPools.concat( - ...basePoolAddresses.map(basePoolAddress => ({ - target: factoryAddress, - callData: this.ifaces.factory.encodeFunctionData( - 'metapool_implementations', - [basePoolAddress], - ), - decodeFunction: ( - result: MultiResult | BytesLike, - ): string[] => - generalDecoder( - result, - ['address[10]'], - new Array(10).fill(NULL_ADDRESS), - parsed => parsed[0].map((p: string) => p.toLowerCase()), - ), - })), - // To receive plain pool implementation address, you have to call plain_implementations - // with two variables: N_COINS and implementations_index - // N_COINS is between 2-4. Currently more than 4 coins is not supported - // as for implementation index, there are only 0-9 indexes - ..._.flattenDeep( - _.range(2, FACTORY_MAX_PLAIN_COINS + 1).map(coinNumber => - _.range(FACTORY_MAX_PLAIN_IMPLEMENTATIONS_FOR_COIN).map(implInd => ({ + await Promise.all( + this.config.factoryAddresses.map(async factoryAddress => { + try { + const poolCountResult = + await this.dexHelper.multiWrapper!.tryAggregate(true, [ + { + target: factoryAddress, + callData: this.ifaces.factory.encodeFunctionData('pool_count'), + decodeFunction: uint256DecodeToNumber, + }, + // This is used later to request all available implementations. In particular meta implementations + { + target: factoryAddress, + callData: + this.ifaces.factory.encodeFunctionData('base_pool_count'), + decodeFunction: uint256DecodeToNumber, + }, + ]); + + const poolCount = poolCountResult[0].returnData; + const basePoolCount = poolCountResult[1].returnData; + + const calldataGetPoolAddresses = _.range(0, poolCount).map(i => ({ target: factoryAddress, - callData: this.ifaces.factory.encodeFunctionData( - 'plain_implementations', - [coinNumber, implInd], - ), + callData: this.ifaces.factory.encodeFunctionData('pool_list', [i]), decodeFunction: addressDecode, - })), - ), - ), - ); + })); + + const calldataGetBasePoolAddresses = _.range(0, basePoolCount).map( + i => ({ + target: factoryAddress, + callData: this.ifaces.factory.encodeFunctionData( + 'base_pool_list', + [i], + ), + decodeFunction: addressDecode, + }), + ); - const allResultsFromFactory = ( - await this.dexHelper.multiWrapper.tryAggregate< - string[] | number[] | string - >(true, callDataFromFactoryPools) - ).map(r => r.returnData); + const allPoolAddresses = ( + await this.dexHelper.multiWrapper.tryAggregate( + true, + calldataGetPoolAddresses.concat(calldataGetBasePoolAddresses), + ) + ).map(e => e.returnData); + + const poolAddresses = allPoolAddresses.slice(0, poolCount); + const basePoolAddresses = allPoolAddresses.slice(poolCount); + + const customPoolAddresses = Object.values( + this.config.customPools, + ).map(customPool => customPool.address); + basePoolAddresses.forEach(basePool => { + if ( + !customPoolAddresses.includes(basePool) && + !this.config.disabledPools.has(basePool) + ) { + this._reportForUnspecifiedCustomPool(basePool); + } + }); - const resultsFromFactory = allResultsFromFactory.slice( - 0, - factoryResultsDivider, - ); + let callDataFromFactoryPools: MultiCallParams< + string[] | number[] | string + >[] = poolAddresses + .map(p => [ + { + target: factoryAddress, + callData: this.ifaces.factory.encodeFunctionData( + 'get_implementation_address', + [p], + ), + decodeFunction: addressDecode, + }, + { + target: factoryAddress, + callData: this.ifaces.factory.encodeFunctionData('get_coins', [ + p, + ]), + decodeFunction: ( + result: MultiResult | BytesLike, + ): string[] => + generalDecoder( + result, + ['address[4]'], + new Array(4).fill(NULL_ADDRESS), + parsed => parsed[0].map((p: string) => p.toLowerCase()), + ), + }, + { + target: factoryAddress, + callData: this.ifaces.factory.encodeFunctionData( + 'get_decimals', + [p], + ), + decodeFunction: ( + result: MultiResult | BytesLike, + ): number[] => + generalDecoder( + result, + ['uint256[4]'], + [0, 0, 0, 0], + parsed => + parsed[0].map((p: BigNumber) => Number(p.toString())), + ), + }, + ]) + .flat(); + + // This is divider between pools related results and implementations + const factoryResultsDivider = callDataFromFactoryPools.length; + + // Implementations must be requested from factory, but it accepts as arg basePool address + // for metaPools + callDataFromFactoryPools = callDataFromFactoryPools.concat( + ...basePoolAddresses.map(basePoolAddress => ({ + target: factoryAddress, + callData: this.ifaces.factory.encodeFunctionData( + 'metapool_implementations', + [basePoolAddress], + ), + decodeFunction: ( + result: MultiResult | BytesLike, + ): string[] => + generalDecoder( + result, + ['address[10]'], + new Array(10).fill(NULL_ADDRESS), + parsed => parsed[0].map((p: string) => p.toLowerCase()), + ), + })), + // To receive plain pool implementation address, you have to call plain_implementations + // with two variables: N_COINS and implementations_index + // N_COINS is between 2-4. Currently more than 4 coins is not supported + // as for implementation index, there are only 0-9 indexes + ..._.flattenDeep( + _.range(2, FACTORY_MAX_PLAIN_COINS + 1).map(coinNumber => + _.range(FACTORY_MAX_PLAIN_IMPLEMENTATIONS_FOR_COIN).map( + implInd => ({ + target: factoryAddress, + callData: this.ifaces.factory.encodeFunctionData( + 'plain_implementations', + [coinNumber, implInd], + ), + decodeFunction: addressDecode, + }), + ), + ), + ), + ); - const allAvailableImplementations = _.flattenDeep( - allResultsFromFactory.slice(factoryResultsDivider) as string[], - ).filter( - implementation => - implementation !== NULL_ADDRESS && - !this.config.disabledImplementations.has(implementation), - ); + const allResultsFromFactory = ( + await this.dexHelper.multiWrapper.tryAggregate< + string[] | number[] | string + >(true, callDataFromFactoryPools) + ).map(r => r.returnData); - allAvailableImplementations.forEach(implementation => { - const currentImplementation = - this.config.factoryPoolImplementations[implementation]; - if (currentImplementation === undefined) { - this._reportForUnspecifiedImplementation(implementation); - } - }); + const resultsFromFactory = allResultsFromFactory.slice( + 0, + factoryResultsDivider, + ); - const stateInitializePromises: Promise[] = []; - _.chunk(resultsFromFactory, 3).forEach((result, i) => { - if (this.config.disabledPools.has(poolAddresses[i])) { - this.logger.trace(`Filtering disabled pool ${poolAddresses[i]}`); - return; - } + const allAvailableImplementations = _.flattenDeep( + allResultsFromFactory.slice(factoryResultsDivider) as string[], + ).filter( + implementation => + implementation !== NULL_ADDRESS && + !this.config.disabledImplementations.has(implementation), + ); - let [implementationAddress, coins, coins_decimals] = result as [ - string, - string[], - number[], - ]; + allAvailableImplementations.forEach(implementation => { + const currentImplementation = + this.config.factoryPoolImplementations[implementation]; + if (currentImplementation === undefined) { + this._reportForUnspecifiedImplementation(implementation); + } + }); - implementationAddress = implementationAddress.toLowerCase(); - coins = coins.map(c => c.toLowerCase()).filter(c => c !== NULL_ADDRESS); - coins_decimals = coins_decimals.filter(cd => cd !== 0); + const stateInitializePromises: Promise[] = []; + _.chunk(resultsFromFactory, 3).forEach((result, i) => { + if (this.config.disabledPools.has(poolAddresses[i])) { + this.logger.trace(`Filtering disabled pool ${poolAddresses[i]}`); + return; + } + + let [implementationAddress, coins, coins_decimals] = result as [ + string, + string[], + number[], + ]; + + implementationAddress = implementationAddress.toLowerCase(); + coins = coins + .map(c => c.toLowerCase()) + .filter(c => c !== NULL_ADDRESS); + coins_decimals = coins_decimals.filter(cd => cd !== 0); + + const factoryImplementationFromConfig = + this.config.factoryPoolImplementations[implementationAddress]; + + if ( + factoryImplementationFromConfig === undefined && + !this.config.disabledImplementations.has(implementationAddress) + ) { + this._reportForUnspecifiedImplementation( + implementationAddress, + poolAddresses[i], + ); + return; + } + + const factoryImplementationConstants = + ImplementationConstants[factoryImplementationFromConfig.name]; + + let isMeta: boolean = false; + let basePoolStateFetcher: PoolPollingBase | undefined; + if (factoryImplementationFromConfig.basePoolAddress !== undefined) { + isMeta = true; + const basePoolIdentifier = this.getPoolIdentifier( + factoryImplementationFromConfig.basePoolAddress, + false, + ); + const basePool = this.poolManager.getPool( + basePoolIdentifier, + false, + ); + if (basePool === null) { + this.logger.error( + `${this.dexKey}_${this.dexHelper.config.data.network}: custom base pool ${basePoolIdentifier} was not initialized properly. ` + + `You must call initializeCustomPollingPools before fetching factory`, + ); + return; + } + basePoolStateFetcher = basePool; + } + + const poolConstants: PoolConstants = { + COINS: coins, + coins_decimals, + rate_multipliers: this._calcRateMultipliers(coins_decimals), + }; + + const poolIdentifier = this.getPoolIdentifier( + poolAddresses[i], + isMeta, + ); - const factoryImplementationFromConfig = - this.config.factoryPoolImplementations[implementationAddress]; + const newPool = new FactoryStateHandler( + this.logger, + this.dexKey, + this.dexHelper.config.data.network, + this.cacheStateKey, + factoryImplementationFromConfig.name, + implementationAddress.toLowerCase(), + poolAddresses[i], + this.config.stateUpdatePeriodMs, + factoryAddress, + poolIdentifier, + poolConstants, + factoryImplementationConstants, + factoryImplementationConstants.isFeeOnTransferSupported, + factoryImplementationFromConfig.liquidityApiSlug ?? '/factory', + basePoolStateFetcher, + factoryImplementationFromConfig.customGasCost, + factoryImplementationFromConfig.isStoreRateSupported, + ); - if ( - factoryImplementationFromConfig === undefined && - !this.config.disabledImplementations.has(implementationAddress) - ) { - this._reportForUnspecifiedImplementation( - implementationAddress, - poolAddresses[i], - ); - return; - } + this.poolManager.initializeNewPool(poolIdentifier, newPool); - const factoryImplementationConstants = - ImplementationConstants[factoryImplementationFromConfig.name]; + if (initializeInitialState) { + stateInitializePromises.push( + this.poolManager.initializeIndividualPollingPoolState( + poolIdentifier, + factoryImplementationConstants.isFeeOnTransferSupported, + ), + ); + } + }); - let isMeta: boolean = false; - let basePoolStateFetcher: PoolPollingBase | undefined; - if (factoryImplementationFromConfig.basePoolAddress !== undefined) { - isMeta = true; - const basePoolIdentifier = this.getPoolIdentifier( - factoryImplementationFromConfig.basePoolAddress, - false, - ); - const basePool = this.poolManager.getPool(basePoolIdentifier, false); - if (basePool === null) { + await Promise.all(stateInitializePromises); + } catch (e) { this.logger.error( - `${this.dexKey}_${this.dexHelper.config.data.network}: custom base pool ${basePoolIdentifier} was not initialized properly. ` + - `You must call initializeCustomPollingPools before fetching factory`, + `Error fetching factory pools for ${factoryAddress}: `, + e, ); - return; + throw e; } - basePoolStateFetcher = basePool; - } - - const poolConstants: PoolConstants = { - COINS: coins, - coins_decimals, - rate_multipliers: this._calcRateMultipliers(coins_decimals), - }; - - const poolIdentifier = this.getPoolIdentifier(poolAddresses[i], isMeta); - - const newPool = new FactoryStateHandler( - this.logger, - this.dexKey, - this.dexHelper.config.data.network, - this.cacheStateKey, - factoryImplementationFromConfig.name, - implementationAddress.toLowerCase(), - poolAddresses[i], - this.config.stateUpdatePeriodMs, - factoryAddress, - poolIdentifier, - poolConstants, - factoryImplementationConstants, - factoryImplementationConstants.isFeeOnTransferSupported, - basePoolStateFetcher, - factoryImplementationFromConfig.customGasCost, - factoryImplementationFromConfig.isStoreRateSupported, - ); - - this.poolManager.initializeNewPool(poolIdentifier, newPool); - - if (initializeInitialState) { - stateInitializePromises.push( - this.poolManager.initializeIndividualPollingPoolState( - poolIdentifier, - factoryImplementationConstants.isFeeOnTransferSupported, - ), - ); - } - }); - - await Promise.all(stateInitializePromises); + }), + ); this.areFactoryPoolsFetched = true; } diff --git a/src/dex/curve-v1-factory/price-handlers/functions/_calc_withdraw_one_coin.ts b/src/dex/curve-v1-factory/price-handlers/functions/_calc_withdraw_one_coin.ts index 5c9b0954e..ff85c7bd5 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/_calc_withdraw_one_coin.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/_calc_withdraw_one_coin.ts @@ -284,6 +284,7 @@ const implementations: Record = { [ImplementationNames.FACTORY_PLAIN_2_BASIC_EMA]: customArbitrum2CoinBtc, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA]: customArbitrum2CoinBtc, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: factoryPlain2EthEma2, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: customArbitrum2CoinBtc, }; export default implementations; diff --git a/src/dex/curve-v1-factory/price-handlers/functions/_dynamic_fee.ts b/src/dex/curve-v1-factory/price-handlers/functions/_dynamic_fee.ts index 541a47343..b0ba16915 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/_dynamic_fee.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/_dynamic_fee.ts @@ -93,6 +93,7 @@ const implementations: Record = { [ImplementationNames.FACTORY_PLAIN_2_BASIC_EMA]: notExist, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA]: notExist, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: notExist, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: notExist, }; export default implementations; diff --git a/src/dex/curve-v1-factory/price-handlers/functions/_rates.ts b/src/dex/curve-v1-factory/price-handlers/functions/_rates.ts index b8ab211d1..b742d20da 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/_rates.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/_rates.ts @@ -108,6 +108,7 @@ const implementations: Record = { [ImplementationNames.FACTORY_PLAIN_2_BASIC_EMA]: notExist, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA]: notExist, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: notExist, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: notExist, }; export default implementations; diff --git a/src/dex/curve-v1-factory/price-handlers/functions/_xp.ts b/src/dex/curve-v1-factory/price-handlers/functions/_xp.ts index 2f815afdd..f12737784 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/_xp.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/_xp.ts @@ -106,6 +106,7 @@ const implementations: Record = { [ImplementationNames.FACTORY_PLAIN_2_BASIC_EMA]: notExist, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA]: notExist, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: notExist, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: notExist, }; export default implementations; diff --git a/src/dex/curve-v1-factory/price-handlers/functions/_xp_mem.ts b/src/dex/curve-v1-factory/price-handlers/functions/_xp_mem.ts index c93fe7a3b..94db894b6 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/_xp_mem.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/_xp_mem.ts @@ -95,6 +95,7 @@ const implementations: Record = { [ImplementationNames.FACTORY_PLAIN_2_BASIC_EMA]: factoryPlain2Basic, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA]: factoryPlain2Basic, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: factoryPlain2Basic, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: factoryPlain2Basic, }; export default implementations; diff --git a/src/dex/curve-v1-factory/price-handlers/functions/calc_token_amount.ts b/src/dex/curve-v1-factory/price-handlers/functions/calc_token_amount.ts index cb83a1dfe..573c44b0e 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/calc_token_amount.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/calc_token_amount.ts @@ -96,6 +96,63 @@ const customAvalanche3CoinLending: calc_token_amount = ( return (diff * state.totalSupply) / D0; }; +const customPlain2CoinCrv: calc_token_amount = ( + self: IPoolContext, + state: PoolState, + amounts: bigint[], + is_deposit: boolean, +) => { + const { N_COINS, BI_N_COINS, FEE_DENOMINATOR } = self.constants; + const amp = state.A; + const balances = [...state.balances]; + const D0 = self.get_D_mem(self, state, balances, amp); + for (const i of _.range(N_COINS)) { + if (is_deposit) balances[i] += amounts[i]; + else balances[i] -= amounts[i]; + } + const D1 = self.get_D_mem(self, state, balances, amp); + + if (state.totalSupply === undefined) { + throw new Error( + `${self.IMPLEMENTATION_NAME} customPlain3CoinThree: totalSupply is not provided`, + ); + } + + const total_supply = state.totalSupply; + let D2 = D1; + + if (total_supply > 0n) { + const base_fee = (state.fee * BI_N_COINS) / (4n * (BI_N_COINS - 1n)); + for (const i of _.range(N_COINS)) { + const ideal_balance = (D1 * state.balances[i]) / D0; + let difference = 0n; + const new_balance = balances[i]; + if (ideal_balance > new_balance) { + difference = ideal_balance - new_balance; + } else { + difference = new_balance - ideal_balance; + } + balances[i] -= (base_fee * difference) / FEE_DENOMINATOR; + } + const xp = self._xp_mem( + self, + [...state.constants.rate_multipliers], + balances, + ); + D2 = self.get_D_mem(self, state, xp, amp); + } else { + return D1; + } + + let diff = 0n; + if (is_deposit) { + diff = D2 - D0; + } else { + diff = D0 - D2; + } + return (diff * total_supply) / D0; +}; + const notImplemented: calc_token_amount = ( self: IPoolContext, state: PoolState, @@ -165,6 +222,7 @@ const implementations: Record = { [ImplementationNames.FACTORY_PLAIN_2_BASIC_EMA]: customPlain3CoinThree, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA]: customPlain3CoinThree, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: customPlain3CoinThree, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: customPlain2CoinCrv, }; export default implementations; diff --git a/src/dex/curve-v1-factory/price-handlers/functions/calc_withdraw_one_coin.ts b/src/dex/curve-v1-factory/price-handlers/functions/calc_withdraw_one_coin.ts index c6269ac23..4e6e06d66 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/calc_withdraw_one_coin.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/calc_withdraw_one_coin.ts @@ -82,6 +82,7 @@ export const implementations: Record< [ImplementationNames.FACTORY_PLAIN_2_BASIC_EMA]: customPlain3CoinThree, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA]: customPlain3CoinThree, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: customPlain3CoinThree, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: customPlain3CoinThree, }; export default implementations; diff --git a/src/dex/curve-v1-factory/price-handlers/functions/constants.ts b/src/dex/curve-v1-factory/price-handlers/functions/constants.ts index e808ade22..a85483b84 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/constants.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/constants.ts @@ -573,6 +573,17 @@ const implementationConstants: Record< isFeeOnTransferSupported: true, isLending: false, + N_COINS: 2, + BI_N_COINS: 2n, + PRECISION: BI_POWS[18], + FEE_DENOMINATOR: BI_POWS[10], + A_PRECISION: 100n, + }, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: { + isWrapNative: false, + isFeeOnTransferSupported: false, + isLending: false, + N_COINS: 2, BI_N_COINS: 2n, PRECISION: BI_POWS[18], diff --git a/src/dex/curve-v1-factory/price-handlers/functions/get_D.ts b/src/dex/curve-v1-factory/price-handlers/functions/get_D.ts index c14500c6c..8ff128af1 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/get_D.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/get_D.ts @@ -321,6 +321,8 @@ const implementations: Record = { makeFuncCacheable(factoryPlain2Basic), [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: makeFuncCacheable(factoryPlain2Basic), + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: + makeFuncCacheable(factoryPlain2Basic), }; export default implementations; diff --git a/src/dex/curve-v1-factory/price-handlers/functions/get_D_mem.ts b/src/dex/curve-v1-factory/price-handlers/functions/get_D_mem.ts index 1178e2123..dc4d1d0fd 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/get_D_mem.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/get_D_mem.ts @@ -140,6 +140,7 @@ export const implementations: Record = { [ImplementationNames.FACTORY_PLAIN_2_BASIC_EMA]: factoryPlain2Basic, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA]: factoryPlain2Basic, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: factoryPlain2EthEma2, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: factoryPlain2Basic, }; export default implementations; diff --git a/src/dex/curve-v1-factory/price-handlers/functions/get_D_precisions.ts b/src/dex/curve-v1-factory/price-handlers/functions/get_D_precisions.ts index 178fc3232..b94501510 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/get_D_precisions.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/get_D_precisions.ts @@ -112,6 +112,7 @@ const implementations: Record = { [ImplementationNames.FACTORY_PLAIN_2_BASIC_EMA]: notExist, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA]: notExist, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: notExist, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: notExist, }; export default implementations; diff --git a/src/dex/curve-v1-factory/price-handlers/functions/get_dy.ts b/src/dex/curve-v1-factory/price-handlers/functions/get_dy.ts index bf69105bf..23339da18 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/get_dy.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/get_dy.ts @@ -266,6 +266,7 @@ const implementations: Record = { [ImplementationNames.FACTORY_PLAIN_2_BASIC_EMA]: factoryPlain2Basic, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA]: factoryPlain2Basic, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: factoryPlain2EthEma2, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: factoryPlain2Basic, }; export default implementations; diff --git a/src/dex/curve-v1-factory/price-handlers/functions/get_dy_underlying.ts b/src/dex/curve-v1-factory/price-handlers/functions/get_dy_underlying.ts index bd21d08e3..e4df36f5c 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/get_dy_underlying.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/get_dy_underlying.ts @@ -285,6 +285,7 @@ const implementations: Record = { [ImplementationNames.FACTORY_PLAIN_2_BASIC_EMA]: notExist, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA]: notExist, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: notExist, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: notExist, }; export default implementations; diff --git a/src/dex/curve-v1-factory/price-handlers/functions/get_y.ts b/src/dex/curve-v1-factory/price-handlers/functions/get_y.ts index 4fab6617e..62a323887 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/get_y.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/get_y.ts @@ -189,6 +189,7 @@ const implementations: Record = { [ImplementationNames.FACTORY_PLAIN_2_BASIC_EMA]: customPlain2CoinFrax, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA]: customPlain2CoinFrax, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: customPlain2CoinFrax, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: customPlain2CoinFrax, }; export default implementations; diff --git a/src/dex/curve-v1-factory/price-handlers/functions/get_y_D.ts b/src/dex/curve-v1-factory/price-handlers/functions/get_y_D.ts index 7c713c3d1..65bbe1c8b 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/get_y_D.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/get_y_D.ts @@ -175,6 +175,7 @@ const implementations: Record = { [ImplementationNames.FACTORY_PLAIN_2_BASIC_EMA]: customPlain2CoinFrax, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA]: customPlain2CoinFrax, [ImplementationNames.FACTORY_PLAIN_2_ETH_EMA2]: customPlain2CoinFrax, + [ImplementationNames.FACTORY_PLAIN_2_CRV_EMA]: customPlain2CoinFrax, }; export default implementations; diff --git a/src/dex/curve-v1-factory/state-polling-pools/factory-pool-polling.ts b/src/dex/curve-v1-factory/state-polling-pools/factory-pool-polling.ts index 42f71e2cb..7f3c3811e 100644 --- a/src/dex/curve-v1-factory/state-polling-pools/factory-pool-polling.ts +++ b/src/dex/curve-v1-factory/state-polling-pools/factory-pool-polling.ts @@ -44,6 +44,7 @@ export class FactoryStateHandler extends PoolPollingBase { readonly poolConstants: PoolConstants, readonly poolContextConstants: PoolContextConstants, readonly isSrcFeeOnTransferSupported: boolean, + liquidityApiSlug: string, baseStatePoolPolling?: PoolPollingBase, customGasCost?: number, readonly isStoredRatesSupported: boolean = false, @@ -65,7 +66,7 @@ export class FactoryStateHandler extends PoolPollingBase { poolIdentifier, poolConstants, address, - '/factory', + liquidityApiSlug, false, baseStatePoolPolling, isSrcFeeOnTransferSupported, diff --git a/src/dex/curve-v1-factory/types.ts b/src/dex/curve-v1-factory/types.ts index f5d6832ce..bb2b889f6 100644 --- a/src/dex/curve-v1-factory/types.ts +++ b/src/dex/curve-v1-factory/types.ts @@ -104,6 +104,7 @@ export enum FactoryImplementationNames { FACTORY_PLAIN_2_ETH_EMA = 'factory_plain_2_eth_ema', FACTORY_PLAIN_2_ETH_EMA2 = 'factory_plain_2_eth_ema2', FACTORY_PLAIN_2_OPTIMIZED = 'factory_plain_2_optimized', + FACTORY_PLAIN_2_CRV_EMA = 'factory_plain_2_crv_ema', FACTORY_PLAIN_3_BALANCES = 'factory_plain_3_balances', FACTORY_PLAIN_3_BASIC = 'factory_plain_3_basic', @@ -154,6 +155,7 @@ export type FactoryPoolImplementations = { basePoolAddress?: Address; customGasCost?: number; isStoreRateSupported?: boolean; + liquidityApiSlug?: string; }; export type CustomPoolConfig = { @@ -174,7 +176,7 @@ export type CustomPoolConfig = { }; export type DexParams = { - factoryAddress: string | null; + factoryAddresses: string[] | null; stateUpdatePeriodMs: number; factoryPoolImplementations: Record; customPools: Record; From d91999ba6522bba23ed956b01c43e02f24ca3a8b Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 18 Aug 2023 14:19:33 +0100 Subject: [PATCH 072/833] fix: remove redundant token from constants --- tests/constants-e2e.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 004aa98b0..e93aa284f 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -785,10 +785,6 @@ export const Tokens: { address: '0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f', decimals: 8, }, - USDCe: { - address: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', - decimals: 6, - }, LEX: { address: '0x6bB7A17AcC227fd1F6781D1EEDEAE01B42047eE0', decimals: 18, From 5ffa95d3545b7cb023dd31f4465d66a9c8ced212 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 18 Aug 2023 16:38:09 +0300 Subject: [PATCH 073/833] update --- tests/constants-e2e.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 004aa98b0..e93aa284f 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -785,10 +785,6 @@ export const Tokens: { address: '0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f', decimals: 8, }, - USDCe: { - address: '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', - decimals: 6, - }, LEX: { address: '0x6bB7A17AcC227fd1F6781D1EEDEAE01B42047eE0', decimals: 18, From c6ee53cd9edd9e13c66d7bb8c8d1574c70f24941 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 18 Aug 2023 15:41:06 +0100 Subject: [PATCH 074/833] fix: set right implementation address --- src/dex/curve-v1-factory/config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/curve-v1-factory/config.ts b/src/dex/curve-v1-factory/config.ts index 5d5d392bd..f458836ab 100644 --- a/src/dex/curve-v1-factory/config.ts +++ b/src/dex/curve-v1-factory/config.ts @@ -153,9 +153,9 @@ const CurveV1FactoryConfig: DexConfigMap = { name: ImplementationNames.FACTORY_PLAIN_4_OPTIMIZED, address: '0xad4753d045d3aed5c1a6606dfb6a7d7ad67c1ad7', }, - '0xb9f861B7755Ff09cFD65CfE262D19823607b1f24': { + '0x67fe41A94e779CcFa22cff02cc2957DC9C0e4286': { name: ImplementationNames.FACTORY_PLAIN_2_CRV_EMA, - address: '0xb9f861B7755Ff09cFD65CfE262D19823607b1f24', + address: '0x67fe41A94e779CcFa22cff02cc2957DC9C0e4286', liquidityApiSlug: '/factory-crvusd', }, }, From 86394596e58071b069c39e8a8584d25ed66ab3b7 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 18 Aug 2023 15:42:26 +0100 Subject: [PATCH 075/833] 2.28.11-factory-crvusd.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6449d4439..58464b583 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.10", + "version": "2.28.11-factory-crvusd.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 5e2166ae82870d70c8036b4cc71ea2230f70ad7e Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 18 Aug 2023 17:01:00 +0100 Subject: [PATCH 076/833] feat: added new test for curve pools --- .../curve-v1-factory-integration.test.ts | 153 ++++++++++++------ tests/constants-e2e.ts | 10 ++ 2 files changed, 118 insertions(+), 45 deletions(-) diff --git a/src/dex/curve-v1-factory/curve-v1-factory-integration.test.ts b/src/dex/curve-v1-factory/curve-v1-factory-integration.test.ts index 55b6fcb20..5dc723f42 100644 --- a/src/dex/curve-v1-factory/curve-v1-factory-integration.test.ts +++ b/src/dex/curve-v1-factory/curve-v1-factory-integration.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import dotenv from 'dotenv'; dotenv.config(); @@ -143,23 +144,6 @@ describe('CurveV1Factory', function () { const tokens = Tokens[network]; - const srcTokenSymbol = 'USDD'; - const destTokenSymbol = 'USDT'; - - const amountsForSell = [ - 0n, - 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - 10n * BI_POWS[tokens[srcTokenSymbol].decimals], - ]; - beforeAll(async () => { blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); // @ts-expect-error for testing there is dummy blocknumber, but it is not @@ -178,39 +162,118 @@ describe('CurveV1Factory', function () { if (curveV1Factory) curveV1Factory.releaseResources(); }); - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - await testPricingOnNetwork( - curveV1Factory, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.SELL, - amountsForSell, - ); + describe(`USDD-USDT`, () => { + const srcTokenSymbol = 'USDD'; + const destTokenSymbol = 'USDT'; + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + curveV1Factory, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newCurveV1Factory = new CurveV1Factory( + network, + dexKey, + dexHelper, + ); + if (newCurveV1Factory.updatePoolState) { + await newCurveV1Factory.updatePoolState(); + } + const poolLiquidity = await newCurveV1Factory.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newCurveV1Factory.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); }); - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - const newCurveV1Factory = new CurveV1Factory(network, dexKey, dexHelper); - if (newCurveV1Factory.updatePoolState) { - await newCurveV1Factory.updatePoolState(); - } - const poolLiquidity = await newCurveV1Factory.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, - ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + describe(`crvUSD-GHO`, () => { + const srcTokenSymbol = 'crvUSD'; + const destTokenSymbol = 'GHO'; + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + curveV1Factory, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + ); + }); - if (!newCurveV1Factory.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newCurveV1Factory = new CurveV1Factory( + network, dexKey, + dexHelper, ); - } + if (newCurveV1Factory.updatePoolState) { + await newCurveV1Factory.updatePoolState(); + } + const poolLiquidity = await newCurveV1Factory.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newCurveV1Factory.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); }); }); describe('Polygon', () => { diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index e93aa284f..3d892ae28 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -299,6 +299,14 @@ export const Tokens: { address: '0xc411db5f5eb3f7d552f9b8454b2d74097ccde6e3', decimals: 6, }, + GHO: { + address: '0x40d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f', + decimals: 18, + }, + crvUSD: { + address: '0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E', + decimals: 18, + }, }, [Network.ROPSTEN]: { DAI: { @@ -904,6 +912,8 @@ export const Holders: { aEthWETH: '0x645C4c0c95C1Aa6EF25d12f4a25038cA9b0C6Cc7', dUSDC: '0x2FC2F705110A7F46Ce85F701d7217EF1018f01A3', PSP: '0xE5E5440a1CE69C5cf67BFFA74d185e57c31b43E5', + crvUSD: '0xA920De414eA4Ab66b97dA1bFE9e6EcA7d4219635', + GHO: '0x844Dc85EdD8492A56228D293cfEbb823EF3E10EC', }, [Network.ROPSTEN]: { ETH: '0x43262A12d8610AA70C15DbaeAC321d51613c9071', From f8ee5a4921676af1f78b62db631637f7f82253e0 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 18 Aug 2023 17:05:30 +0100 Subject: [PATCH 077/833] chore: set to latest version pckage number --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1e8668077..6449d4439 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.10-camelot-v3-tick-bugs.2", + "version": "2.28.10", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 4722f0b9286d3a2b8541d18c848544273b7d8dd5 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 18 Aug 2023 17:06:08 +0100 Subject: [PATCH 078/833] 2.28.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6449d4439..d7547d5cd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.10", + "version": "2.28.11", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From fd3252b6ed3f65839d2b8f08e591facc64900cdf Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sun, 20 Aug 2023 13:36:25 +0300 Subject: [PATCH 079/833] fix pricing --- src/dex/solidly/config.ts | 4 +- src/dex/solidly/forks-override/chronos.ts | 4 - src/dex/solidly/forks-override/ramses.ts | 223 +++++++++++++++++++- src/dex/solidly/solidly-integration.test.ts | 12 +- src/dex/solidly/solidly.ts | 2 + 5 files changed, 230 insertions(+), 15 deletions(-) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index 4cc734bca..fb940e66e 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -134,9 +134,7 @@ export const SolidlyConfig: DexConfigMap = { initCode: '0x1565b129f2d1790f12d45301b9b084335626f0c92410bc43130763b69971135d', poolGasCost: 180 * 1000, - feeCode: 1, - stableFee: 1, - volatileFee: 20, + feeCode: 0, }, }, }; diff --git a/src/dex/solidly/forks-override/chronos.ts b/src/dex/solidly/forks-override/chronos.ts index 3eda10d54..fd3f28d45 100644 --- a/src/dex/solidly/forks-override/chronos.ts +++ b/src/dex/solidly/forks-override/chronos.ts @@ -102,7 +102,6 @@ export class Chronos extends Solidly { } }`; - console.log('tokenAddress.toLowerCase(): ', tokenAddress.toLowerCase()); const { data } = await this.dexHelper.httpRequest.post( this.subgraphURL, { @@ -115,8 +114,6 @@ export class Chronos extends Solidly { if (!(data && data.pools0 && data.pools1)) throw new Error("Couldn't fetch the pools from the subgraph"); - console.log('DATA: ', data); - const pools0 = await this.prepareSubgraphPools(data.pools0, (pool,{ address1, decimals1, liquidityUSDToken0, liquidityUSDToken1, }) => ({ @@ -177,7 +174,6 @@ export class Chronos extends Solidly { liquidityUSDToken1: number, }) => PoolLiquidity ): Promise { - console.log('POOLS: ', pools); return Promise.all(pools.map(async ( pool: ChronosSubgraphPool, ) => { diff --git a/src/dex/solidly/forks-override/ramses.ts b/src/dex/solidly/forks-override/ramses.ts index ea4c8e321..9c525218b 100644 --- a/src/dex/solidly/forks-override/ramses.ts +++ b/src/dex/solidly/forks-override/ramses.ts @@ -1,10 +1,26 @@ -import { Network } from '../../../constants'; +import { Network, SUBGRAPH_TIMEOUT } from '../../../constants'; import { getDexKeysWithNetwork } from '../../../utils'; import { SolidlyConfig } from '../config'; import _ from 'lodash'; -import { Chronos, ChronosSubgraphPool } from './chronos'; -import { PoolLiquidity } from '../../../types'; +import { Address, PoolLiquidity } from '../../../types'; import BigNumber from 'bignumber.js'; +import { Solidly } from '../solidly'; +import { IDexHelper } from '../../../dex-helper'; +import { SolidlyPair } from '../types'; +import { Interface } from '@ethersproject/abi'; + + +const RamsesFactoryABI = [ + { + inputs: [{internalType: 'address', name: '', type: 'address'}], + name: 'pairFee', + outputs: [{internalType: 'uint256', 'name': '', type: 'uint256'}], + stateMutability: 'view', + type: 'function', + }, +]; + +const ramsesFactoryIface = new Interface(RamsesFactoryABI); export type RamsesSubgraphPool = { id: string; @@ -15,7 +31,206 @@ export type RamsesSubgraphPool = { token1: string; }; -export class Ramses extends Chronos { +export type RamsesSubgraphToken = { + id: string; + decimals: string; +} + +export class Ramses extends Solidly { + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork(_.pick(SolidlyConfig, ['Ramses'])); + + constructor( + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + ) { + super( + network, + dexKey, + dexHelper, + true, // dynamic fees + ); + } + + // private callDecoder(values: any[]) { + // const fees = parseInt( + // conePairIface + // .decodeFunctionResult(swapFeeFunctionName, values)[0] + // .toString(), + // ); + // if (!fees) return 0; + // + // const feeCode = Math.ceil( this.feeFactor / fees); + // return feeCode; + // } + + protected getFeesMultiCallData(pair: SolidlyPair) { + const callEntry = { + target: this.factoryAddress, + callData: ramsesFactoryIface.encodeFunctionData('pairFee', [pair.exchange]), + }; + const callDecoder = (values: any[]) => + parseInt( + ramsesFactoryIface + .decodeFunctionResult('pairFee', values)[0] + .toString(), + ); + + return { + callEntry, + callDecoder, + }; + } + + async getTopPoolsForToken( + tokenAddress: Address, + count: number, + ): Promise { + if (!this.subgraphURL) return []; + + const query = `query ($token: Bytes!, $count: Int) { + pools0: pairs(first: $count, orderBy: reserve0, orderDirection: desc, where: {token0: $token, reserve0_gt: 1, reserve1_gt: 1}) { + id + isStable + token0 + token1 + reserve0, + reserve1, + } + pools1: pairs(first: $count, orderBy: reserve1, orderDirection: desc, where: {token1: $token, reserve0_gt: 1, reserve1_gt: 1}) { + id + isStable + token0 + token1 + reserve0, + reserve1, + } + }`; + + const { data } = await this.dexHelper.httpRequest.post( + this.subgraphURL, + { + query, + variables: { token: tokenAddress.toLowerCase(), count }, + }, + SUBGRAPH_TIMEOUT, + ); + + if (!(data && data.pools0 && data.pools1)) + throw new Error("Couldn't fetch the pools from the subgraph"); + + const tokenIds = _.uniq([].concat(data.pools0, data.pools1).map( + (pool: RamsesSubgraphPool) => [ pool.token0, pool.token1]).flat(), + ); + + const tokensQuery = ` + query ($tokenIds: [String!]) { + tokens(where: {id_in: $tokenIds}) { + id + decimals + } + }`; + + + const { data: tokensData } = await this.dexHelper.httpRequest.post( + this.subgraphURL, + { + query: tokensQuery, + variables: { tokenIds }, + }, + SUBGRAPH_TIMEOUT, + ); + + const pools0 = await this.prepareSubgraphPools(tokensData.tokens, data.pools0, (pool,{ + address1, decimals1, liquidityUSDToken0, liquidityUSDToken1, + }) => ({ + exchange: this.dexKey, + stable: pool.isStable, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: address1, + decimals: decimals1, + }, + ], + liquidityUSD: liquidityUSDToken0 + liquidityUSDToken1, + })); + + const pools1 = await this.prepareSubgraphPools(tokensData.tokens, data.pools1, (pool,{ + address0, decimals0, liquidityUSDToken0, liquidityUSDToken1, + }) => ({ + exchange: this.dexKey, + stable: pool.isStable, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: address0, + decimals: decimals0, + }, + ], + liquidityUSD: liquidityUSDToken0 + liquidityUSDToken1, + })); + + return _.slice( + _.sortBy(_.concat(pools0, pools1), [pool => -1 * pool.liquidityUSD]), + 0, + count, + ); + } + + protected async prepareSubgraphPools( + tokens: RamsesSubgraphToken[], + pools: RamsesSubgraphPool[], + iterator: ( + pool: RamsesSubgraphPool, { + address0, + address1, + decimals0, + decimals1, + reserve0, + reserve1, + liquidityUSDToken0, + liquidityUSDToken1, + }: { + address0: string, + address1: string, + decimals0: number, + decimals1: number, + reserve0: bigint, + reserve1: bigint, + liquidityUSDToken0: number, + liquidityUSDToken1: number, + }) => PoolLiquidity + ): Promise { + return Promise.all(pools.map(async ( + pool: RamsesSubgraphPool, + ) => { + const address0 = pool.token0.toLowerCase(); + const address1 = pool.token1.toLowerCase(); + + const decimals0 = parseInt(tokens.find((t) => t.id === address0)!.decimals); + const decimals1 = parseInt(tokens.find((t) => t.id === address1)!.decimals); + + const reserve0 = BigInt(new BigNumber(pool.reserve0).multipliedBy(10 ** decimals0).toFixed()); + const reserve1 = BigInt(new BigNumber(pool.reserve1).multipliedBy(10 ** decimals1).toFixed()); + + const liquidityUSDToken0 = await this.dexHelper.getTokenUSDPrice({ + address: address0, + decimals: decimals0, + }, reserve0); + + const liquidityUSDToken1 = await this.dexHelper.getTokenUSDPrice({ + address: address1, + decimals: decimals1, + }, reserve1); + + return iterator( + pool, { + address0, address1, decimals0, decimals1, reserve0, reserve1, liquidityUSDToken0, liquidityUSDToken1, + }, + ); + })); + } } diff --git a/src/dex/solidly/solidly-integration.test.ts b/src/dex/solidly/solidly-integration.test.ts index 5fcb8a9bd..c4d3163e1 100644 --- a/src/dex/solidly/solidly-integration.test.ts +++ b/src/dex/solidly/solidly-integration.test.ts @@ -62,7 +62,7 @@ const constructCheckOnChainPricing = funcName, tokenIn, ); - console.log('readerCallData', readerCallData); + const readerResult = ( await dexHelper.multiContract.methods .aggregate(readerCallData) @@ -72,6 +72,8 @@ const constructCheckOnChainPricing = decodeReaderResult(readerResult, readerIface, funcName), ); + console.log('ON-CHAIN PRICES: ', expectedPrices); + expect(prices.map(p => p.toString())).toEqual( expectedPrices.map(p => p.toString()), ); @@ -776,12 +778,12 @@ describe('Solidly integration tests', () => { const ramses = new Ramses(network, dexKey, dexHelper); describe('UniswapV2 like pool', function () { - const TokenASymbol = 'USDC'; + const TokenASymbol = 'USDCe'; const tokenA = Tokens[network][TokenASymbol]; const TokenBSymbol = 'WETH'; const tokenB = Tokens[network][TokenBSymbol]; - const amounts = amounts6; + const amounts = amounts18; it('getPoolIdentifiers and getPricesVolume', async function () { const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); @@ -798,6 +800,8 @@ describe('Solidly integration tests', () => { expect(pools.length).toBeGreaterThan(0); + console.log('AMOUNTS: ', amounts); + const poolPrices = await ramses.getPricesVolume( tokenA, tokenB, @@ -843,7 +847,7 @@ describe('Solidly integration tests', () => { describe('Curve like stable pool', function () { const TokenASymbol = 'USDT'; const tokenA = Tokens[network][TokenASymbol]; - const TokenBSymbol = 'USDC'; + const TokenBSymbol = 'USDCe'; const tokenB = Tokens[network][TokenBSymbol]; const amounts = amounts6; diff --git a/src/dex/solidly/solidly.ts b/src/dex/solidly/solidly.ts index d5c12ccf2..1d113a1a4 100644 --- a/src/dex/solidly/solidly.ts +++ b/src/dex/solidly/solidly.ts @@ -72,6 +72,7 @@ export class Solidly extends UniswapV2 { 'Thena', 'SoliSnek', 'Chronos', + 'Ramses' ]), ); @@ -520,6 +521,7 @@ export class Solidly extends UniswapV2 { const pair = await this.findSolidlyPair(from, to, stable); if (!(pair && pair.pool && pair.exchange)) return null; const pairState = pair.pool.getState(blockNumber); + if (!pairState) { this.logger.error( `Error_orderPairParams expected reserves, got none (maybe the pool doesn't exist) ${ From c3549ad59ac722f24977432fd32e118c0d3510c9 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sun, 20 Aug 2023 13:36:53 +0300 Subject: [PATCH 080/833] 2.28.11-ramses --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0e4592226..04a077326 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.27.1-ramses", + "version": "2.28.11-ramses", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 37c507d57f9489e093dbf90f480f6933c9b092b8 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sun, 20 Aug 2023 13:50:18 +0300 Subject: [PATCH 081/833] 2.28.12-ramses --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 04a077326..45c73e225 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.11-ramses", + "version": "2.28.12-ramses", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From d8da14fb0fe3ed9045795ceeaecb31610efe5bbf Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 21 Aug 2023 10:02:37 +0300 Subject: [PATCH 082/833] remove commented lines --- src/dex/solidly/forks-override/chronos.ts | 4 ++-- src/dex/solidly/forks-override/ramses.ts | 12 ------------ 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/dex/solidly/forks-override/chronos.ts b/src/dex/solidly/forks-override/chronos.ts index fd3f28d45..845b46e01 100644 --- a/src/dex/solidly/forks-override/chronos.ts +++ b/src/dex/solidly/forks-override/chronos.ts @@ -21,7 +21,7 @@ const ChronosFactoryABI = [ const chronosFactoryIface = new Interface(ChronosFactoryABI); -export type ChronosSubgraphPool = { +type ChronosSubgraphPool = { id: string; isStable: boolean; token0: { id: string; decimals: string }; @@ -151,7 +151,7 @@ export class Chronos extends Solidly { ); } - protected async prepareSubgraphPools( + private async prepareSubgraphPools( pools: ChronosSubgraphPool[], iterator: ( pool: ChronosSubgraphPool, { diff --git a/src/dex/solidly/forks-override/ramses.ts b/src/dex/solidly/forks-override/ramses.ts index 9c525218b..ffc6d6e1f 100644 --- a/src/dex/solidly/forks-override/ramses.ts +++ b/src/dex/solidly/forks-override/ramses.ts @@ -54,18 +54,6 @@ export class Ramses extends Solidly { ); } - // private callDecoder(values: any[]) { - // const fees = parseInt( - // conePairIface - // .decodeFunctionResult(swapFeeFunctionName, values)[0] - // .toString(), - // ); - // if (!fees) return 0; - // - // const feeCode = Math.ceil( this.feeFactor / fees); - // return feeCode; - // } - protected getFeesMultiCallData(pair: SolidlyPair) { const callEntry = { target: this.factoryAddress, From 982b51dfda0abfb7db0473ebf4af18cbf35d4f62 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 21 Aug 2023 10:09:31 +0300 Subject: [PATCH 083/833] update tests --- src/dex/solidly/solidly-e2e.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index eb8586814..893ccfe11 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -1201,7 +1201,7 @@ describe('Solidly E2E', () => { sellAmount: '1000000000000000000', }, { - name: 'USDC', + name: 'USDCe', sellAmount: '100000000', }, ], @@ -1211,7 +1211,7 @@ describe('Solidly E2E', () => { sellAmount: '1000000000000000000', }, { - name: 'USDC', + name: 'USDCe', sellAmount: '100000000', }, ], @@ -1221,13 +1221,13 @@ describe('Solidly E2E', () => { sellAmount: '100000000', }, { - name: 'USDC', + name: 'USDCe', sellAmount: '100000000', }, ], [ { - name: 'USDC', + name: 'USDCe', sellAmount: '100000000', }, { From 4916fc1465c342f36c6370b1ec68d9567b6bc15c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 21 Aug 2023 10:11:09 +0300 Subject: [PATCH 084/833] 2.28.12-ramses.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 45c73e225..0a49a9302 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.12-ramses", + "version": "2.28.12-ramses.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 85b2567be7bb9053b761e187f06da1214ec658d1 Mon Sep 17 00:00:00 2001 From: pbnather <33466053+pbnather@users.noreply.github.com> Date: Mon, 21 Aug 2023 09:32:33 +0200 Subject: [PATCH 085/833] Add Morphex (GMX fork) --- scripts/dex-integration.ts | 2 +- src/dex/index.ts | 2 + src/dex/morphex/config.ts | 31 ++++++ src/dex/morphex/morphex-e2e.test.ts | 91 ++++++++++++++++ src/dex/morphex/morphex-events.test.ts | 92 ++++++++++++++++ src/dex/morphex/morphex-integration.test.ts | 113 ++++++++++++++++++++ src/dex/morphex/morphex.ts | 22 ++++ tests/constants-e2e.ts | 10 ++ 8 files changed, 362 insertions(+), 1 deletion(-) create mode 100644 src/dex/morphex/config.ts create mode 100644 src/dex/morphex/morphex-e2e.test.ts create mode 100644 src/dex/morphex/morphex-events.test.ts create mode 100644 src/dex/morphex/morphex-integration.test.ts create mode 100644 src/dex/morphex/morphex.ts diff --git a/scripts/dex-integration.ts b/scripts/dex-integration.ts index e3487e690..dfe2a31da 100644 --- a/scripts/dex-integration.ts +++ b/scripts/dex-integration.ts @@ -116,7 +116,7 @@ function testIntegration(argv: IOptions) { process.env.NODE_ENV = 'test'; } - require('../node_modules/jest-cli/build/cli').run( + require('../node_modules/jest-cli/build/run').run( `src\/dex\/${dexNameParam}\/.+\.test\.ts`, ); } diff --git a/src/dex/index.ts b/src/dex/index.ts index f32c7d800..3092d5c4c 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -70,6 +70,7 @@ import { SpiritSwapV3 } from './quickswap/spiritswap-v3'; import { TraderJoeV21 } from './trader-joe-v2.1'; import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3'; import { Algebra } from './algebra/algebra'; +import { Morphex } from './morphex/morphex'; const LegacyDexes = [ CurveV2, @@ -137,6 +138,7 @@ const Dexes = [ MaverickV1, Camelot, SwaapV2, + Morphex, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< diff --git a/src/dex/morphex/config.ts b/src/dex/morphex/config.ts new file mode 100644 index 000000000..7d576f158 --- /dev/null +++ b/src/dex/morphex/config.ts @@ -0,0 +1,31 @@ +import { DexParams } from '../gmx/types'; +import { DexConfigMap } from '../../types'; +import { Network, SwapSide } from '../../constants'; + +export const MorphexConfig: DexConfigMap = { + Morphex: { + [Network.FANTOM]: { + vault: '0x245cD6d33578de9aF75a3C0c636c726b1A8cbdAa', + reader: '0xcA47b9b612a152ece991F31d8D3547D73BaF2Ecc', + priceFeed: '0x7a451DE877CbB6551AACa671d0458B6f9dF1e29A', + fastPriceFeed: '0x7f54C35A38D89fcf5Fe516206E6628745ed38CC7', + fastPriceEvents: '0xDc7C389be5da32e326A261dC0126feCa7AE04d79', + usdg: '0xe135c7BFfda932b5B862Da442cF4CbC4d43DC3Ad', + }, + }, +}; + +export const Adapters: { + [chainId: number]: { + [side: string]: { name: string; index: number }[] | null; + }; +} = { + [Network.FANTOM]: { + [SwapSide.SELL]: [ + { + name: 'FantomAdapter01', + index: 6, // TODO: it's for aavev3, but there is no Morphex adapter + }, + ], + }, +}; diff --git a/src/dex/morphex/morphex-e2e.test.ts b/src/dex/morphex/morphex-e2e.test.ts new file mode 100644 index 000000000..47d04c20a --- /dev/null +++ b/src/dex/morphex/morphex-e2e.test.ts @@ -0,0 +1,91 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { testE2E } from '../../../tests/utils-e2e'; +import { + Tokens, + Holders, + NativeTokenSymbols, +} from '../../../tests/constants-e2e'; +import { Network, ContractMethod, SwapSide } from '../../constants'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; + +describe('Morphex E2E', () => { + const dexKey = 'Morphex'; + + describe('Morphex Fantom', () => { + const network = Network.FANTOM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'axlUSDC'; + const tokenBSymbol: string = 'lzUSDC'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '500000000'; // 500 Axelar USDC + const tokenBAmount: string = '500000000'; // 500 Layer Zero USDC + const nativeTokenAmount = '100000000000000000000'; // 100 FTM + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(nativeTokenSymbol + ' -> TOKEN', async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it('TOKEN -> ' + nativeTokenSymbol, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it('TOKEN -> TOKEN', async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); +}); diff --git a/src/dex/morphex/morphex-events.test.ts b/src/dex/morphex/morphex-events.test.ts new file mode 100644 index 000000000..e488738af --- /dev/null +++ b/src/dex/morphex/morphex-events.test.ts @@ -0,0 +1,92 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { GMXEventPool } from '../gmx/pool'; +import { MorphexConfig } from './config'; +import { Network } from '../../constants'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { testEventSubscriber } from '../../../tests/utils-events'; +import { PoolState } from '../gmx/types'; + +jest.setTimeout(50 * 1000); +const dexKey = 'Morphex'; +const network = Network.FANTOM; +const params = MorphexConfig[dexKey][network]; + +async function fetchPoolState( + gmxPool: GMXEventPool, + blockNumber: number, +): Promise { + return gmxPool.generateState(blockNumber); +} + +// timestamp can't be compared exactly as the event released +// doesn't have the timestamp. It is safe to consider the +// timestamp as the blockTime as the max deviation is bounded +// on the contract +const stateWithoutTimestamp = (state: PoolState) => ({ + ...state, + secondaryPrices: { + prices: state.secondaryPrices.prices, + // timestamp (this is removed) + }, +}); + +function compareState(state: PoolState, expectedState: PoolState) { + expect(stateWithoutTimestamp(state)).toEqual( + stateWithoutTimestamp(expectedState), + ); +} + +describe('Morphex Event', function () { + const blockNumbers: { [eventName: string]: number[] } = { + IncreaseUsdgAmount: [ + 67247602, 67247565, 67247561, 67247508, 67247393, 67247305, 67247303, + 67247302, 67247230, 67247220, 67247218, 67247216, 67247215, 67247145, + 67247059, 67247026, 67246788, 67246731, + ], + DecreaseUsdgAmount: [ + 67247778, 67247602, 67247565, 67247561, 67247508, 67247393, 67247305, + 67247303, 67247302, 67247230, 67247220, 67247218, 67247216, 67247215, + 67247145, 67247059, 67247026, 67246788, + ], + Transfer: [ + 67087282, 67087063, 67087039, 67068002, 67052880, 67052806, 67052801, + ], + PriceUpdate: [67248035, 67247977, 67247907, 67247897, 67247893], + }; + + describe('MorphexEventPool', function () { + Object.keys(blockNumbers).forEach((event: string) => { + blockNumbers[event].forEach((blockNumber: number) => { + it(`Should return the correct state after the ${blockNumber}:${event}`, async function () { + const dexHelper = new DummyDexHelper(network); + const logger = dexHelper.getLogger(dexKey); + + const config = await GMXEventPool.getConfig( + params, + blockNumber, + dexHelper.multiContract, + ); + const gmxPool = new GMXEventPool( + dexKey, + network, + dexHelper, + logger, + config, + ); + + await testEventSubscriber( + gmxPool, + gmxPool.addressesSubscribed, + (_blockNumber: number) => fetchPoolState(gmxPool, _blockNumber), + blockNumber, + `${dexKey}_${params.vault}`, + dexHelper.provider, + compareState, + ); + }); + }); + }); + }); +}); diff --git a/src/dex/morphex/morphex-integration.test.ts b/src/dex/morphex/morphex-integration.test.ts new file mode 100644 index 000000000..6300b74f6 --- /dev/null +++ b/src/dex/morphex/morphex-integration.test.ts @@ -0,0 +1,113 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { Interface } from '@ethersproject/abi'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { Network, SwapSide } from '../../constants'; +import { Morphex } from './morphex'; +import { MorphexConfig } from './config'; +import { + checkPoolPrices, + checkPoolsLiquidity, + checkConstantPoolPrices, +} from '../../../tests/utils'; +import { Tokens } from '../../../tests/constants-e2e'; +import ReaderABI from '../../abi/gmx/reader.json'; + +const network = Network.FANTOM; +const TokenASymbol = 'axlUSDC'; +const TokenA = Tokens[network][TokenASymbol]; + +const TokenBSymbol = 'WFTM'; +const TokenB = Tokens[network][TokenBSymbol]; + +const amounts = [ + 0n, + 1000000000n, + 2000000000n, + 3000000000n, + 4000000000n, + 5000000000n, +]; + +const dexKey = 'Morphex'; +const params = MorphexConfig[dexKey][network]; +const readerInterface = new Interface(ReaderABI); +const readerAddress = params.reader; + +describe('Morphex', function () { + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + const dexHelper = new DummyDexHelper(network); + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const gmx = new Morphex(network, dexKey, dexHelper); + + await gmx.initializePricing(blocknumber); + + const pools = await gmx.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blocknumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await gmx.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + if (gmx.hasConstantPriceLargeAmounts) { + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + } else { + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + } + + // Do on chain pricing based on reader to compare + const readerCallData = amounts.map(a => ({ + target: readerAddress, + callData: readerInterface.encodeFunctionData('getAmountOut', [ + params.vault, + TokenA.address, + TokenB.address, + a.toString(), + ]), + })); + + const readerResult = ( + await dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blocknumber) + ).returnData; + const expectedPrices = readerResult.map((p: any) => + BigInt( + readerInterface.decodeFunctionResult('getAmountOut', p)[0].toString(), + ), + ); + + expect(poolPrices![0].prices).toEqual(expectedPrices); + }); + + it('getTopPoolsForToken', async function () { + const dexHelper = new DummyDexHelper(network); + const gmx = new Morphex(network, dexKey, dexHelper); + + await gmx.updatePoolState(); + const poolLiquidity = await gmx.getTopPoolsForToken(TokenA.address, 10); + console.log( + `${TokenASymbol} Top Pools:`, + JSON.stringify(poolLiquidity, null, 2), + ); + + if (!gmx.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); + } + }); +}); diff --git a/src/dex/morphex/morphex.ts b/src/dex/morphex/morphex.ts new file mode 100644 index 000000000..41596a87a --- /dev/null +++ b/src/dex/morphex/morphex.ts @@ -0,0 +1,22 @@ +import { Network } from '../../constants'; +import { IDexHelper } from '../../dex-helper'; +import { DexParams } from '../gmx/types'; +import { Adapters, MorphexConfig } from './config'; +import { GMX } from '../gmx/gmx'; +import { getDexKeysWithNetwork } from '../../utils'; + +export class Morphex extends GMX { + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(MorphexConfig); + + constructor( + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + protected adapters = Adapters[network], + protected params: DexParams = MorphexConfig[dexKey][network], + ) { + super(network, dexKey, dexHelper, adapters, params); + this.logger = dexHelper.getLogger(dexKey); + } +} diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index cf0284848..a161a1f61 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -496,6 +496,14 @@ export const Tokens: { address: '0xe578C856933D8e1082740bf7661e379Aa2A30b26', decimals: 6, }, + axlUSDC: { + address: '0x1B6382DBDEa11d97f24495C9A90b7c88469134a4', + decimals: 6, + }, + lzUSDC: { + address: '0x28a92dde19D9989F39A49905d7C9C2FAc7799bDf', + decimals: 6, + }, }, [Network.BSC]: { POPS: { @@ -964,6 +972,8 @@ export const Holders: { ETH: '0xf48883940b4056801de30f12b934dcea90133ee6', GUSDC: '0x894d774a293f8aa3d23d67815d4cadb5319c1094', GDAI: '0x0e2ed73f9c1409e2b36fe6c46e60d4557b7c2ac0', + axlUSDC: '0xccf932cd565c21d2e516c8ff3a4f244eea27e09a', + lzUSDC: ' 0xd30442beee8269bfb3829c401c62b38d2ea5bdb4', }, [Network.BSC]: { DAI: '0xf68a4b64162906eff0ff6ae34e2bb1cd42fef62d', From 97bd3cc5747ddeea515202eff34e1bc3787e4876 Mon Sep 17 00:00:00 2001 From: pbnather <33466053+pbnather@users.noreply.github.com> Date: Mon, 21 Aug 2023 11:03:08 +0200 Subject: [PATCH 086/833] Restore local changes --- scripts/dex-integration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/dex-integration.ts b/scripts/dex-integration.ts index dfe2a31da..e3487e690 100644 --- a/scripts/dex-integration.ts +++ b/scripts/dex-integration.ts @@ -116,7 +116,7 @@ function testIntegration(argv: IOptions) { process.env.NODE_ENV = 'test'; } - require('../node_modules/jest-cli/build/run').run( + require('../node_modules/jest-cli/build/cli').run( `src\/dex\/${dexNameParam}\/.+\.test\.ts`, ); } From 5b8dd8dde2e1faea2386d608eca0ccc6701e0e07 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 21 Aug 2023 13:41:17 +0300 Subject: [PATCH 087/833] add a fix for liqudityUSD calculations --- src/dex/solidly/forks-override/ramses.ts | 4 ++-- src/dex/solidly/solidly-e2e.test.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dex/solidly/forks-override/ramses.ts b/src/dex/solidly/forks-override/ramses.ts index ffc6d6e1f..d4c5b4629 100644 --- a/src/dex/solidly/forks-override/ramses.ts +++ b/src/dex/solidly/forks-override/ramses.ts @@ -201,8 +201,8 @@ export class Ramses extends Solidly { const decimals0 = parseInt(tokens.find((t) => t.id === address0)!.decimals); const decimals1 = parseInt(tokens.find((t) => t.id === address1)!.decimals); - const reserve0 = BigInt(new BigNumber(pool.reserve0).multipliedBy(10 ** decimals0).toFixed()); - const reserve1 = BigInt(new BigNumber(pool.reserve1).multipliedBy(10 ** decimals1).toFixed()); + const reserve0 = BigInt(new BigNumber(pool.reserve0).toFixed()); + const reserve1 = BigInt(new BigNumber(pool.reserve1).toFixed()); const liquidityUSDToken0 = await this.dexHelper.getTokenUSDPrice({ address: address0, diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index 893ccfe11..86c59fbaa 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -1198,7 +1198,7 @@ describe('Solidly E2E', () => { [ { name: 'ETH', - sellAmount: '1000000000000000000', + sellAmount: '10000000000000', }, { name: 'USDCe', @@ -1208,7 +1208,7 @@ describe('Solidly E2E', () => { [ { name: 'WETH', - sellAmount: '1000000000000000000', + sellAmount: '10000000000000', }, { name: 'USDCe', @@ -1228,11 +1228,11 @@ describe('Solidly E2E', () => { [ { name: 'USDCe', - sellAmount: '100000000', + sellAmount: '500000', }, { name: 'DAI', - sellAmount: '100000000000000000000', + sellAmount: '1000000000000000000', }, ], ]; From b901cc512b87cb4ce2655f304725a2d9d3c5df02 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 21 Aug 2023 13:43:59 +0300 Subject: [PATCH 088/833] 2.28.12-ramses.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0a49a9302..49af51a70 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.12-ramses.2", + "version": "2.28.12-ramses.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 7e974d4e91b40ab706edfd9a4fc97a649aa5af15 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 21 Aug 2023 14:01:46 +0300 Subject: [PATCH 089/833] 2.29.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9e7ab1986..b1ff73aad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.11-ramses-v2", + "version": "2.29.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 992feda24698821006ce4109d0cf0fb57a1eb9ed Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 21 Aug 2023 14:16:27 +0300 Subject: [PATCH 090/833] 2.29.1-ramses --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 49af51a70..da2603301 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.12-ramses.3", + "version": "2.29.1-ramses", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 7e7bd72a1da7ec36904eadd39f7262f4e85f35c4 Mon Sep 17 00:00:00 2001 From: Verisana Date: Mon, 21 Aug 2023 13:14:13 +0100 Subject: [PATCH 091/833] fix: add new liquidity slug to array --- .../curve-v1-factory-e2e.test.ts | 19 +++++++++++++++++++ .../curve-v1-factory/curve-v1-pool-manager.ts | 5 ++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/dex/curve-v1-factory/curve-v1-factory-e2e.test.ts b/src/dex/curve-v1-factory/curve-v1-factory-e2e.test.ts index baf4d5527..2aa034745 100644 --- a/src/dex/curve-v1-factory/curve-v1-factory-e2e.test.ts +++ b/src/dex/curve-v1-factory/curve-v1-factory-e2e.test.ts @@ -111,6 +111,25 @@ describe('CurveV1Factory E2E', () => { tokenBAmount, ); }); + + describe('Mainnet crvUSD', () => { + const network = Network.MAINNET; + + const tokenASymbol: string = 'crvUSD'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '10000000000000000000'; + const tokenBAmount: string = '10000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + ); + }); describe('Mainnet ng pool', () => { const network = Network.MAINNET; diff --git a/src/dex/curve-v1-factory/curve-v1-pool-manager.ts b/src/dex/curve-v1-factory/curve-v1-pool-manager.ts index c240dbb09..42e2c8c20 100644 --- a/src/dex/curve-v1-factory/curve-v1-pool-manager.ts +++ b/src/dex/curve-v1-factory/curve-v1-pool-manager.ts @@ -42,7 +42,10 @@ export class CurveV1FactoryPoolManager { // It should bo considered for optimizing private coinAddressesToPoolIdentifiers: Record = {}; - private allCurveLiquidityApiSlugs: Set = new Set(['/factory']); + private allCurveLiquidityApiSlugs: Set = new Set([ + '/factory', + '/factory-crvusd', + ]); private statePollingManager = StatePollingManager; private taskScheduler: TaskScheduler; From eb21cbf581ccef27b1e0ab9d5fafb90afcedaf74 Mon Sep 17 00:00:00 2001 From: Verisana Date: Mon, 21 Aug 2023 13:15:45 +0100 Subject: [PATCH 092/833] 2.28.11-factory-crvusd.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 58464b583..863106efb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.11-factory-crvusd.0", + "version": "2.28.11-factory-crvusd.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 4fa2903f5976738610885d467d3d4c5265e6b4b9 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 21 Aug 2023 15:18:31 +0300 Subject: [PATCH 093/833] 2.30.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index da2603301..e73eafb06 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.29.1-ramses", + "version": "2.30.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 4b1db9aa3046eecefa6a29b294f256ab6b315747 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 21 Aug 2023 15:56:39 +0200 Subject: [PATCH 094/833] Revert "Merge pull request #466 from paraswap/fix/1222-multihop-buy-balancer" This reverts commit bcda72dd80a7c5a10531bba5a75f8d3ded44cc58, reversing changes made to 3ff94ef0309bead33c9d87653bc9b117ae7001f1. --- src/dex/balancer-v2/balancer-v2.ts | 2 - src/dex/balancer-v2/optimizer.ts | 111 ++++++++---------- src/dex/balancer-v2/types.ts | 4 - .../functions/calc_token_amount.ts | 34 +----- src/dex/uniswap-v3/uniswap-v3.ts | 7 +- 5 files changed, 54 insertions(+), 104 deletions(-) diff --git a/src/dex/balancer-v2/balancer-v2.ts b/src/dex/balancer-v2/balancer-v2.ts index f71274414..ac1c3f443 100644 --- a/src/dex/balancer-v2/balancer-v2.ts +++ b/src/dex/balancer-v2/balancer-v2.ts @@ -826,8 +826,6 @@ export class BalancerV2 prices: resOut.prices, data: { poolId: pool.id, - tokenIn: _from.address.toLowerCase(), - tokenOut: _to.address.toLowerCase(), }, poolAddresses: [poolAddress], exchange: this.dexKey, diff --git a/src/dex/balancer-v2/optimizer.ts b/src/dex/balancer-v2/optimizer.ts index 201b7a19f..818c2f7f8 100644 --- a/src/dex/balancer-v2/optimizer.ts +++ b/src/dex/balancer-v2/optimizer.ts @@ -1,83 +1,70 @@ -import _ from 'lodash'; -import { UnoptimizedRate } from '../../types'; +import { UnoptimizedRate, OptimalSwapExchange } from '../../types'; +import { BalancerSwapV2 } from './types'; import { SwapSide } from '../../constants'; import { BalancerConfig } from './config'; -import { OptimalSwap } from '@paraswap/core'; + +const MAX_UINT256 = + '115792089237316195423570985008687907853269984665640564039457584007913129639935'; + +const AllBalancerV2Forks = Object.keys(BalancerConfig); export function balancerV2Merge(or: UnoptimizedRate): UnoptimizedRate { - const balancerForksList = Object.keys(BalancerConfig).map(b => - b.toLowerCase(), - ); - const fixSwap = (rawRate: OptimalSwap[], side: SwapSide): OptimalSwap[] => { - let lastExchange: false | OptimalSwap = false; - let optimizedRate = new Array(); - rawRate.forEach((s: OptimalSwap) => { - if ( - s.swapExchanges.length !== 1 || - !balancerForksList.includes(s.swapExchanges[0].exchange.toLowerCase()) - ) { - lastExchange = false; - optimizedRate.push(s); - } else if ( - lastExchange && - lastExchange.swapExchanges[0].exchange.toLowerCase() === - s.swapExchanges[0].exchange.toLowerCase() && - _.last( - lastExchange.swapExchanges[0].data.swaps, - )!.tokenOut.toLowerCase() === - s.swapExchanges[0].data.tokenIn.toLowerCase() - ) { - const [lastExchangeSwap] = lastExchange.swapExchanges; - const [currentSwap] = s.swapExchanges; - lastExchangeSwap.srcAmount = ( - BigInt(lastExchangeSwap.srcAmount) + BigInt(currentSwap.srcAmount) + const fixSwap = ( + rawSwap: OptimalSwapExchange[], + side: SwapSide, + ): OptimalSwapExchange[] => { + const newBalancers: { [key: string]: OptimalSwapExchange } = {}; + let optimizedSwap = new Array>(); + rawSwap.forEach((s: OptimalSwapExchange) => { + const exchangeKey = s.exchange.toLowerCase(); + if (AllBalancerV2Forks.some(d => d.toLowerCase() === exchangeKey)) { + if (!(exchangeKey in newBalancers)) { + newBalancers[exchangeKey] = { + exchange: s.exchange, + srcAmount: '0', + destAmount: '0', + percent: 0, + poolAddresses: [], + data: { + swaps: new Array(), + gasUSD: '0', + }, + }; + } + newBalancers[exchangeKey].srcAmount = ( + BigInt(newBalancers[exchangeKey].srcAmount) + BigInt(s.srcAmount) ).toString(); - lastExchangeSwap.destAmount = ( - BigInt(lastExchangeSwap.destAmount) + BigInt(currentSwap.destAmount) + newBalancers[exchangeKey].destAmount = ( + BigInt(newBalancers[exchangeKey].destAmount) + BigInt(s.destAmount) ).toString(); - lastExchangeSwap.percent += currentSwap.percent; - lastExchangeSwap.data.gasUSD = ( - parseFloat(lastExchangeSwap.data.gasUSD) + - parseFloat(currentSwap.data.gasUSD) + newBalancers[exchangeKey].percent += s.percent; + newBalancers[exchangeKey].data.exchangeProxy = s.data.exchangeProxy; + newBalancers[exchangeKey].data.gasUSD = ( + parseFloat(newBalancers[exchangeKey].data.gasUSD) + + parseFloat(s.data.gasUSD) ).toFixed(6); - lastExchangeSwap.data.swaps.push({ - poolId: currentSwap.data.poolId, - amount: - side === SwapSide.SELL - ? currentSwap.srcAmount - : currentSwap.destAmount, - tokenIn: currentSwap.data.tokenIn, - tokenOut: currentSwap.data.tokenOut, + newBalancers[exchangeKey].data.swaps.push({ + poolId: s.data.poolId, + amount: side === SwapSide.SELL ? s.srcAmount : s.destAmount, }); - lastExchangeSwap.poolAddresses!.push(currentSwap.poolAddresses![0]); + newBalancers[exchangeKey].poolAddresses!.push(s.poolAddresses![0]); } else { - lastExchange = _.cloneDeep(s); - lastExchange.swapExchanges[0].data = {}; - lastExchange.swapExchanges[0].data.gasUSD = - s.swapExchanges[0].data.gasUSD; - lastExchange.swapExchanges[0].data.swaps = [ - { - poolId: s.swapExchanges[0].data.poolId, - amount: - side === SwapSide.SELL - ? s.swapExchanges[0].srcAmount - : s.swapExchanges[0].destAmount, - tokenIn: s.swapExchanges[0].data.tokenIn, - tokenOut: s.swapExchanges[0].data.tokenOut, - }, - ]; - optimizedRate.push(lastExchange); + optimizedSwap.push(s); } }); - return optimizedRate; + optimizedSwap = optimizedSwap.concat(Object.values(newBalancers)); + return optimizedSwap; }; or.bestRoute = or.bestRoute.map(r => ({ ...r, - swaps: fixSwap(r.swaps, or.side), + swaps: r.swaps.map(s => ({ + ...s, + swapExchanges: fixSwap(s.swapExchanges, or.side), + })), })); return or; } diff --git a/src/dex/balancer-v2/types.ts b/src/dex/balancer-v2/types.ts index 33dd35bfe..f1ef3194c 100644 --- a/src/dex/balancer-v2/types.ts +++ b/src/dex/balancer-v2/types.ts @@ -82,8 +82,6 @@ export interface SubgraphPoolBase { export type BalancerSwapV2 = { poolId: string; amount: string; - tokenIn: string; - tokenOut: string; }; export type OptimizedBalancerV2Data = { @@ -141,8 +139,6 @@ export type BalancerV2DirectParam = [ export type BalancerV2Data = { poolId: string; - tokenIn: string; - tokenOut: string; }; export type DexParams = { diff --git a/src/dex/curve-v1-factory/price-handlers/functions/calc_token_amount.ts b/src/dex/curve-v1-factory/price-handlers/functions/calc_token_amount.ts index cb83a1dfe..d8c37134c 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/calc_token_amount.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/calc_token_amount.ts @@ -35,38 +35,6 @@ const customPlain3CoinThree: calc_token_amount = ( return (diff * token_amount) / D0; }; -const factoryPlain2Basic: calc_token_amount = ( - self: IPoolContext, - state: PoolState, - amounts: bigint[], - is_deposit: boolean, -) => { - const { N_COINS } = self.constants; - const amp = state.A; - const balances = [...state.balances]; - const D0 = self.get_D(self, balances, amp); - for (const i of _.range(N_COINS)) { - if (is_deposit) balances[i] += amounts[i]; - else balances[i] -= amounts[i]; - } - const D1 = self.get_D(self, balances, amp); - - if (state.totalSupply === undefined) { - throw new Error( - `${self.IMPLEMENTATION_NAME} customPlain3CoinThree: totalSupply is not provided`, - ); - } - - const token_amount = state.totalSupply; - let diff = 0n; - if (is_deposit) { - diff = D1 - D0; - } else { - diff = D0 - D1; - } - return (diff * token_amount) / D0; -}; - const customAvalanche3CoinLending: calc_token_amount = ( self: IPoolContext, state: PoolState, @@ -146,7 +114,7 @@ const implementations: Record = { [ImplementationNames.FACTORY_META_USD_BALANCES_FRAX_USDC]: notImplemented, [ImplementationNames.FACTORY_PLAIN_2_BALANCES]: notImplemented, - [ImplementationNames.FACTORY_PLAIN_2_BASIC]: factoryPlain2Basic, + [ImplementationNames.FACTORY_PLAIN_2_BASIC]: notImplemented, [ImplementationNames.FACTORY_PLAIN_2_ETH]: notImplemented, [ImplementationNames.FACTORY_PLAIN_2_OPTIMIZED]: notImplemented, diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 1e9be24da..8a6ae661c 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -120,7 +120,7 @@ export class UniswapV3 this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( this.config.stateMultiCallAbi !== undefined ? this.config.stateMultiCallAbi - : UniswapV3StateMulticallABI as AbiItem[], + : (UniswapV3StateMulticallABI as AbiItem[]), this.config.stateMulticall, ); @@ -279,7 +279,7 @@ export class UniswapV3 e, ); } else { - // on unknown error mark as failed and increase retryCount for retry init strategy + // on unkown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, @@ -1059,7 +1059,8 @@ export class UniswapV3 initHash: this.config.initHash, subgraphURL: this.config.subgraphURL, stateMultiCallAbi: this.config.stateMultiCallAbi, - decodeStateMultiCallResultWithRelativeBitmaps: this.config.decodeStateMultiCallResultWithRelativeBitmaps, + decodeStateMultiCallResultWithRelativeBitmaps: + this.config.decodeStateMultiCallResultWithRelativeBitmaps, }; return newConfig; } From 882b7b1e1f8c82277115936db263523081474345 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 21 Aug 2023 15:57:41 +0200 Subject: [PATCH 095/833] 2.30.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e73eafb06..44655e19c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.30.0", + "version": "2.30.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From bfd183a5158c46805d127804aaabe400e2b439c0 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 21 Aug 2023 17:54:10 +0300 Subject: [PATCH 096/833] add tests --- src/dex/uniswap-v3/config.ts | 32 ++++----- src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 87 +++++++++++++++++++++++ src/dex/uniswap-v3/uniswap-v3.ts | 2 +- 3 files changed, 104 insertions(+), 17 deletions(-) diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index 507a190c4..895bbca78 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -107,6 +107,22 @@ export const UniswapV3Config: DexConfigMap = { 'https://api.thegraph.com/subgraphs/name/lynnshaoyu/uniswap-v3-avax', }, }, + ChronosV3: { + [Network.ARBITRUM]: { + factory: '0x4Db9D624F67E00dbF8ef7AE0e0e8eE54aF1dee49', + quoter: '0x6E7f0Ca45171a4440c0CDdF3A46A8dC5D4c2d4A0', + router: '0xE0aBdFD837D451640CF43cB1Ec4eE87976eFbb41', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x46b44eb4Cc3bEbB9f04C419f691aB85Ff885A4D6', + uniswapMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', + chunksCount: 10, + initRetryFrequency: 10, + initHash: + '0x09c178be473df44d1de6970978a4fdedce1ce52a23b2b979754547f6b43a19a5', + subgraphURL: + 'https://subgraph.chronos.exchange/subgraphs/name/chronos-v3', + }, + }, RamsesV2: { [Network.ARBITRUM]: { factory: '0xAA2cd7477c451E703f3B9Ba5663334914763edF8', @@ -141,22 +157,6 @@ export const UniswapV3Config: DexConfigMap = { 'https://api.studio.thegraph.com/query/44554/uniswap-v3/version/latest', }, }, - Chronos: { - [Network.ARBITRUM]: { - factory: '0x4Db9D624F67E00dbF8ef7AE0e0e8eE54aF1dee49', - deployer: '0x0fFc5A81f38d5b6Ac15edACdd35A76578f59BbF2', - quoter: '0x6E7f0Ca45171a4440c0CDdF3A46A8dC5D4c2d4A0', - router: '0xE0aBdFD837D451640CF43cB1Ec4eE87976eFbb41', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x46b44eb4Cc3bEbB9f04C419f691aB85Ff885A4D6', - uniswapMulticall: '0xd703C06A1Dcd0A52A2f445Bfd21F7e6C73fB6662', - chunksCount: 10, - initHash: - '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', - subgraphURL: - 'https://subgraph.chronos.exchange/subgraphs/name/chronos-v3', - }, - }, }; export const Adapters: Record = { diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index bccf2bf69..0c87f6d6f 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -501,4 +501,91 @@ describe('UniswapV3 E2E', () => { ); }); }); + + describe('ChronosV3', () => { + const dexKey = 'ChronosV3'; + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'USDCe'; + const tokenBSymbol: string = 'USDT'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '2000000'; + const tokenBAmount: string = '2000000'; + const nativeTokenAmount = '110000000000000000'; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, + ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); + }); }); diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 1e9be24da..98408f74a 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -91,7 +91,7 @@ export class UniswapV3 public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork( - _.pick(UniswapV3Config, ['UniswapV3', 'QuickSwapV3.1', 'RamsesV2']), + _.pick(UniswapV3Config, ['UniswapV3', 'QuickSwapV3.1', 'RamsesV2', 'ChronosV3']), ); logger: Logger; From c04c210c2fdc9fe85a90b9ccd315f9f43a3d2a3c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 21 Aug 2023 18:15:10 +0300 Subject: [PATCH 097/833] add integration tests --- src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 2 +- .../uniswap-v3/uniswap-v3-integration.test.ts | 135 ++++++++++++++++++ 2 files changed, 136 insertions(+), 1 deletion(-) diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index 0c87f6d6f..ccef2b146 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -519,7 +519,7 @@ describe('UniswapV3 E2E', () => { const tokenAAmount: string = '2000000'; const tokenBAmount: string = '2000000'; - const nativeTokenAmount = '110000000000000000'; + const nativeTokenAmount = '100000000000000000'; const sideToContractMethods = new Map([ [ diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index 5dbdb7643..03e53088a 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -624,3 +624,138 @@ describe('RamsesV2', () => { expect(falseChecksCounter).toBeLessThan(poolPrices!.length); }); }); + +describe('ChronosV3', () => { + const dexKey = 'ChronosV3'; + let blockNumber: number; + let uniswapV3: UniswapV3; + let uniswapV3Mainnet: UniswapV3; + + const network = Network.ARBITRUM; + const dexHelper = new DummyDexHelper(network); + const TokenASymbol = 'USDCe'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDT'; + const TokenB = Tokens[network][TokenBSymbol]; + + beforeEach(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + uniswapV3 = new UniswapV3(network, dexKey, dexHelper); + uniswapV3Mainnet = new UniswapV3( + Network.ARBITRUM, + dexKey, + dexHelper, + ); + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + + const amounts = [0n, BI_POWS[6], 2000000n]; + + const pools = await uniswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await uniswapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + uniswapV3, + 'quoteExactInputSingle', + blockNumber, + '0x6E7f0Ca45171a4440c0CDdF3A46A8dC5D4c2d4A0', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + + const amounts = [0n, BI_POWS[6], 2000000n]; + + const pools = await uniswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await uniswapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + uniswapV3, + 'quoteExactOutputSingle', + blockNumber, + '0x6E7f0Ca45171a4440c0CDdF3A46A8dC5D4c2d4A0', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it.skip('getTopPoolsForToken', async function () { + const poolLiquidity = await uniswapV3.getTopPoolsForToken( + TokenB.address, + 10, + ); + console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); + }); +}); From 57cf7c4e2df0da54351d5b19e98f143a30b335d5 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 21 Aug 2023 18:19:16 +0300 Subject: [PATCH 098/833] 2.30.2-chronos-v3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4c0447180..f1adf8b12 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.30.0", + "version": "2.30.2-chronos-v3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 32a8e3a4e664483e3c545933947d4883fecd5bec Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 21 Aug 2023 18:28:04 +0300 Subject: [PATCH 099/833] update --- package.json | 1 - scripts/dex-integration.ts | 2 +- yarn.lock | 635 +------------------------------------ 3 files changed, 2 insertions(+), 636 deletions(-) diff --git a/package.json b/package.json index f1adf8b12..c07fd7d46 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,6 @@ "cross-fetch": "^3.1.5", "es6-promise": "^4.2.8", "ethers": "^5.6.5", - "jest-cli": "^29.5.0", "joi": "^17.7.0", "lens.ts": "^0.5.1", "lodash": "4.17.21", diff --git a/scripts/dex-integration.ts b/scripts/dex-integration.ts index 2604166f3..e3487e690 100644 --- a/scripts/dex-integration.ts +++ b/scripts/dex-integration.ts @@ -116,7 +116,7 @@ function testIntegration(argv: IOptions) { process.env.NODE_ENV = 'test'; } - require('../node_modules/jest-cli/bin/jest.js').run( + require('../node_modules/jest-cli/build/cli').run( `src\/dex\/${dexNameParam}\/.+\.test\.ts`, ); } diff --git a/yarn.lock b/yarn.lock index fcb920fc6..eb77e24a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -886,18 +886,6 @@ jest-util "^29.2.1" slash "^3.0.0" -"@jest/console@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.5.0.tgz#593a6c5c0d3f75689835f1b3b4688c4f8544cb57" - integrity sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ== - dependencies: - "@jest/types" "^29.5.0" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.5.0" - jest-util "^29.5.0" - slash "^3.0.0" - "@jest/core@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.2.1.tgz#30af794ebd73bfb87cd8ba36718738dfe38b772e" @@ -932,40 +920,6 @@ slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/core@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.5.0.tgz#76674b96904484e8214614d17261cc491e5f1f03" - integrity sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ== - dependencies: - "@jest/console" "^29.5.0" - "@jest/reporters" "^29.5.0" - "@jest/test-result" "^29.5.0" - "@jest/transform" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.5.0" - jest-config "^29.5.0" - jest-haste-map "^29.5.0" - jest-message-util "^29.5.0" - jest-regex-util "^29.4.3" - jest-resolve "^29.5.0" - jest-resolve-dependencies "^29.5.0" - jest-runner "^29.5.0" - jest-runtime "^29.5.0" - jest-snapshot "^29.5.0" - jest-util "^29.5.0" - jest-validate "^29.5.0" - jest-watcher "^29.5.0" - micromatch "^4.0.4" - pretty-format "^29.5.0" - slash "^3.0.0" - strip-ansi "^6.0.0" - "@jest/environment@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.2.1.tgz#acb1994fbd5ad02819a1a34a923c531e6923b665" @@ -976,16 +930,6 @@ "@types/node" "*" jest-mock "^29.2.1" -"@jest/environment@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.5.0.tgz#9152d56317c1fdb1af389c46640ba74ef0bb4c65" - integrity sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ== - dependencies: - "@jest/fake-timers" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - jest-mock "^29.5.0" - "@jest/expect-utils@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.2.1.tgz#eae61c90f2066540f60d23b8f254f03b7869b22f" @@ -993,13 +937,6 @@ dependencies: jest-get-type "^29.2.0" -"@jest/expect-utils@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.5.0.tgz#f74fad6b6e20f924582dc8ecbf2cb800fe43a036" - integrity sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg== - dependencies: - jest-get-type "^29.4.3" - "@jest/expect@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.2.1.tgz#8d99be3886ebfcffd6cabb2b46602a301b976ffe" @@ -1008,14 +945,6 @@ expect "^29.2.1" jest-snapshot "^29.2.1" -"@jest/expect@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.5.0.tgz#80952f5316b23c483fbca4363ce822af79c38fba" - integrity sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g== - dependencies: - expect "^29.5.0" - jest-snapshot "^29.5.0" - "@jest/fake-timers@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.2.1.tgz#786d60e8cb60ca70c9f913cb49fcc77610c072bb" @@ -1028,18 +957,6 @@ jest-mock "^29.2.1" jest-util "^29.2.1" -"@jest/fake-timers@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.5.0.tgz#d4d09ec3286b3d90c60bdcd66ed28d35f1b4dc2c" - integrity sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg== - dependencies: - "@jest/types" "^29.5.0" - "@sinonjs/fake-timers" "^10.0.2" - "@types/node" "*" - jest-message-util "^29.5.0" - jest-mock "^29.5.0" - jest-util "^29.5.0" - "@jest/globals@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.2.1.tgz#6933beb8b4e43b990409a19c462fde7b71210e63" @@ -1050,16 +967,6 @@ "@jest/types" "^29.2.1" jest-mock "^29.2.1" -"@jest/globals@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.5.0.tgz#6166c0bfc374c58268677539d0c181f9c1833298" - integrity sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ== - dependencies: - "@jest/environment" "^29.5.0" - "@jest/expect" "^29.5.0" - "@jest/types" "^29.5.0" - jest-mock "^29.5.0" - "@jest/reporters@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.2.1.tgz#599e4376823751fdda50f2ca97243e013da10c4d" @@ -1090,36 +997,6 @@ strip-ansi "^6.0.0" v8-to-istanbul "^9.0.1" -"@jest/reporters@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.5.0.tgz#985dfd91290cd78ddae4914ba7921bcbabe8ac9b" - integrity sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.5.0" - "@jest/test-result" "^29.5.0" - "@jest/transform" "^29.5.0" - "@jest/types" "^29.5.0" - "@jridgewell/trace-mapping" "^0.3.15" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^5.1.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.5.0" - jest-util "^29.5.0" - jest-worker "^29.5.0" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" - "@jest/schemas@^29.0.0": version "29.0.0" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a" @@ -1127,13 +1004,6 @@ dependencies: "@sinclair/typebox" "^0.24.1" -"@jest/schemas@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.3.tgz#39cf1b8469afc40b6f5a2baaa146e332c4151788" - integrity sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg== - dependencies: - "@sinclair/typebox" "^0.25.16" - "@jest/source-map@^29.2.0": version "29.2.0" resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.2.0.tgz#ab3420c46d42508dcc3dc1c6deee0b613c235744" @@ -1143,15 +1013,6 @@ callsites "^3.0.0" graceful-fs "^4.2.9" -"@jest/source-map@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.4.3.tgz#ff8d05cbfff875d4a791ab679b4333df47951d20" - integrity sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w== - dependencies: - "@jridgewell/trace-mapping" "^0.3.15" - callsites "^3.0.0" - graceful-fs "^4.2.9" - "@jest/test-result@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.2.1.tgz#f42dbf7b9ae465d0a93eee6131473b8bb3bd2edb" @@ -1162,16 +1023,6 @@ "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-result@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.5.0.tgz#7c856a6ca84f45cc36926a4e9c6b57f1973f1408" - integrity sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ== - dependencies: - "@jest/console" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - "@jest/test-sequencer@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.2.1.tgz#cafd2c5f3528c70bd4cc243800459ac366e480cc" @@ -1182,16 +1033,6 @@ jest-haste-map "^29.2.1" slash "^3.0.0" -"@jest/test-sequencer@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz#34d7d82d3081abd523dbddc038a3ddcb9f6d3cc4" - integrity sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ== - dependencies: - "@jest/test-result" "^29.5.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.5.0" - slash "^3.0.0" - "@jest/transform@^29.2.1": version "29.2.1" resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.2.1.tgz#f3d8154edd19cdbcaf1d6646bd8f4ff7812318a2" @@ -1213,27 +1054,6 @@ slash "^3.0.0" write-file-atomic "^4.0.1" -"@jest/transform@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.5.0.tgz#cf9c872d0965f0cbd32f1458aa44a2b1988b00f9" - integrity sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.5.0" - "@jridgewell/trace-mapping" "^0.3.15" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.5.0" - jest-regex-util "^29.4.3" - jest-util "^29.5.0" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.2" - "@jest/types@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" @@ -1257,18 +1077,6 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jest/types@^29.5.0": - version "29.5.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.5.0.tgz#f59ef9b031ced83047c67032700d8c807d6e1593" - integrity sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog== - dependencies: - "@jest/schemas" "^29.4.3" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" @@ -1708,11 +1516,6 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.47.tgz#530b67163714356f93e82bdb871e7db4b7bc564e" integrity sha512-J4Xw0xYK4h7eC34MNOPQi6IkNxGRck6n4VJpWDzXIFVTW8I/D43Gf+NfWz/v/7NHlzWOPd3+T4PJ4OqklQ2u7A== -"@sinclair/typebox@^0.25.16": - version "0.25.24" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718" - integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ== - "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -1730,20 +1533,6 @@ dependencies: type-detect "4.0.8" -"@sinonjs/commons@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" - integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^10.0.2": - version "10.2.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz#b3e322a34c5f26e3184e7f6115695f299c1b1194" - integrity sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg== - dependencies: - "@sinonjs/commons" "^3.0.0" - "@sinonjs/fake-timers@^9.1.2": version "9.1.2" resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz#4eaab737fab77332ab132d396a3c0d364bd0ea8c" @@ -2475,19 +2264,6 @@ babel-jest@^29.2.1: graceful-fs "^4.2.9" slash "^3.0.0" -babel-jest@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.5.0.tgz#3fe3ddb109198e78b1c88f9ebdecd5e4fc2f50a5" - integrity sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q== - dependencies: - "@jest/transform" "^29.5.0" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.5.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - babel-plugin-istanbul@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" @@ -2509,16 +2285,6 @@ babel-plugin-jest-hoist@^29.2.0: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" -babel-plugin-jest-hoist@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz#a97db437936f441ec196990c9738d4b88538618a" - integrity sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" - babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -2545,14 +2311,6 @@ babel-preset-jest@^29.2.0: babel-plugin-jest-hoist "^29.2.0" babel-preset-current-node-syntax "^1.0.0" -babel-preset-jest@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz#57bc8cc88097af7ff6a5ab59d1cd29d52a5916e2" - integrity sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg== - dependencies: - babel-plugin-jest-hoist "^29.5.0" - babel-preset-current-node-syntax "^1.0.0" - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -3206,11 +2964,6 @@ convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -3476,11 +3229,6 @@ diff-sequences@^29.2.0: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.2.0.tgz#4c55b5b40706c7b5d2c5c75999a50c56d214e8f6" integrity sha512-413SY5JpYeSBZxmenGEmCVQ8mCgtFJF0w9PROdaS6z987XC2Pd2GOKqOITLtMftmyFZqgtCOb/QA7/Z3ZXfzIw== -diff-sequences@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2" - integrity sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA== - diff@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" @@ -3580,11 +3328,6 @@ emittery@^0.10.2: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933" integrity sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw== -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -4187,17 +3930,6 @@ expect@^29.2.1: jest-message-util "^29.2.1" jest-util "^29.2.1" -expect@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.5.0.tgz#68c0509156cb2a0adb8865d413b137eeaae682f7" - integrity sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg== - dependencies: - "@jest/expect-utils" "^29.5.0" - jest-get-type "^29.4.3" - jest-matcher-utils "^29.5.0" - jest-message-util "^29.5.0" - jest-util "^29.5.0" - express@^4.14.0, express@^4.18.2: version "4.18.2" resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" @@ -5268,14 +5000,6 @@ jest-changed-files@^29.2.0: execa "^5.0.0" p-limit "^3.1.0" -jest-changed-files@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.5.0.tgz#e88786dca8bf2aa899ec4af7644e16d9dcf9b23e" - integrity sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag== - dependencies: - execa "^5.0.0" - p-limit "^3.1.0" - jest-circus@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.2.1.tgz#1385353d9bca6acf58f916068bbeffcfc95bef02" @@ -5301,32 +5025,6 @@ jest-circus@^29.2.1: slash "^3.0.0" stack-utils "^2.0.3" -jest-circus@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.5.0.tgz#b5926989449e75bff0d59944bae083c9d7fb7317" - integrity sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA== - dependencies: - "@jest/environment" "^29.5.0" - "@jest/expect" "^29.5.0" - "@jest/test-result" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^0.7.0" - is-generator-fn "^2.0.0" - jest-each "^29.5.0" - jest-matcher-utils "^29.5.0" - jest-message-util "^29.5.0" - jest-runtime "^29.5.0" - jest-snapshot "^29.5.0" - jest-util "^29.5.0" - p-limit "^3.1.0" - pretty-format "^29.5.0" - pure-rand "^6.0.0" - slash "^3.0.0" - stack-utils "^2.0.3" - jest-cli@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.2.1.tgz#fbfa90b87b27a04e1041cc9d33ee80f32e2f2528" @@ -5345,24 +5043,6 @@ jest-cli@^29.2.1: prompts "^2.0.1" yargs "^17.3.1" -jest-cli@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.5.0.tgz#b34c20a6d35968f3ee47a7437ff8e53e086b4a67" - integrity sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw== - dependencies: - "@jest/core" "^29.5.0" - "@jest/test-result" "^29.5.0" - "@jest/types" "^29.5.0" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - import-local "^3.0.2" - jest-config "^29.5.0" - jest-util "^29.5.0" - jest-validate "^29.5.0" - prompts "^2.0.1" - yargs "^17.3.1" - jest-config@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.2.1.tgz#2182af014d6c73978208626335db5134803dd183" @@ -5391,34 +5071,6 @@ jest-config@^29.2.1: slash "^3.0.0" strip-json-comments "^3.1.1" -jest-config@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.5.0.tgz#3cc972faec8c8aaea9ae158c694541b79f3748da" - integrity sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.5.0" - "@jest/types" "^29.5.0" - babel-jest "^29.5.0" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.5.0" - jest-environment-node "^29.5.0" - jest-get-type "^29.4.3" - jest-regex-util "^29.4.3" - jest-resolve "^29.5.0" - jest-runner "^29.5.0" - jest-util "^29.5.0" - jest-validate "^29.5.0" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.5.0" - slash "^3.0.0" - strip-json-comments "^3.1.1" - jest-diff@^26.0.0: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" @@ -5439,16 +5091,6 @@ jest-diff@^29.2.1: jest-get-type "^29.2.0" pretty-format "^29.2.1" -jest-diff@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.5.0.tgz#e0d83a58eb5451dcc1fa61b1c3ee4e8f5a290d63" - integrity sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.4.3" - jest-get-type "^29.4.3" - pretty-format "^29.5.0" - jest-docblock@^29.2.0: version "29.2.0" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.2.0.tgz#307203e20b637d97cee04809efc1d43afc641e82" @@ -5456,13 +5098,6 @@ jest-docblock@^29.2.0: dependencies: detect-newline "^3.0.0" -jest-docblock@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.4.3.tgz#90505aa89514a1c7dceeac1123df79e414636ea8" - integrity sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg== - dependencies: - detect-newline "^3.0.0" - jest-each@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.2.1.tgz#6b0a88ee85c2ba27b571a6010c2e0c674f5c9b29" @@ -5474,17 +5109,6 @@ jest-each@^29.2.1: jest-util "^29.2.1" pretty-format "^29.2.1" -jest-each@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.5.0.tgz#fc6e7014f83eac68e22b7195598de8554c2e5c06" - integrity sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA== - dependencies: - "@jest/types" "^29.5.0" - chalk "^4.0.0" - jest-get-type "^29.4.3" - jest-util "^29.5.0" - pretty-format "^29.5.0" - jest-environment-node@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.2.1.tgz#f90311d0f0e8ef720349f83c97a076e403f90665" @@ -5497,18 +5121,6 @@ jest-environment-node@^29.2.1: jest-mock "^29.2.1" jest-util "^29.2.1" -jest-environment-node@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.5.0.tgz#f17219d0f0cc0e68e0727c58b792c040e332c967" - integrity sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw== - dependencies: - "@jest/environment" "^29.5.0" - "@jest/fake-timers" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - jest-mock "^29.5.0" - jest-util "^29.5.0" - jest-get-type@^26.3.0: version "26.3.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" @@ -5519,11 +5131,6 @@ jest-get-type@^29.2.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.2.0.tgz#726646f927ef61d583a3b3adb1ab13f3a5036408" integrity sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA== -jest-get-type@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.4.3.tgz#1ab7a5207c995161100b5187159ca82dd48b3dd5" - integrity sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg== - jest-haste-map@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.2.1.tgz#f803fec57f8075e6c55fb5cd551f99a72471c699" @@ -5543,25 +5150,6 @@ jest-haste-map@^29.2.1: optionalDependencies: fsevents "^2.3.2" -jest-haste-map@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.5.0.tgz#69bd67dc9012d6e2723f20a945099e972b2e94de" - integrity sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA== - dependencies: - "@jest/types" "^29.5.0" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.4.3" - jest-util "^29.5.0" - jest-worker "^29.5.0" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - jest-leak-detector@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.2.1.tgz#ec551686b7d512ec875616c2c3534298b1ffe2fc" @@ -5570,14 +5158,6 @@ jest-leak-detector@^29.2.1: jest-get-type "^29.2.0" pretty-format "^29.2.1" -jest-leak-detector@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz#cf4bdea9615c72bac4a3a7ba7e7930f9c0610c8c" - integrity sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow== - dependencies: - jest-get-type "^29.4.3" - pretty-format "^29.5.0" - jest-matcher-utils@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.2.1.tgz#2bf876c5f891b33786aadf5d65d5da5970744122" @@ -5588,16 +5168,6 @@ jest-matcher-utils@^29.2.1: jest-get-type "^29.2.0" pretty-format "^29.2.1" -jest-matcher-utils@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz#d957af7f8c0692c5453666705621ad4abc2c59c5" - integrity sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw== - dependencies: - chalk "^4.0.0" - jest-diff "^29.5.0" - jest-get-type "^29.4.3" - pretty-format "^29.5.0" - jest-message-util@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.2.1.tgz#3a51357fbbe0cc34236f17a90d772746cf8d9193" @@ -5613,21 +5183,6 @@ jest-message-util@^29.2.1: slash "^3.0.0" stack-utils "^2.0.3" -jest-message-util@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.5.0.tgz#1f776cac3aca332ab8dd2e3b41625435085c900e" - integrity sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.5.0" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.5.0" - slash "^3.0.0" - stack-utils "^2.0.3" - jest-mock@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.2.1.tgz#a0d361cffcb28184fa9c5443adbf591fa5759775" @@ -5637,15 +5192,6 @@ jest-mock@^29.2.1: "@types/node" "*" jest-util "^29.2.1" -jest-mock@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.5.0.tgz#26e2172bcc71d8b0195081ff1f146ac7e1518aed" - integrity sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw== - dependencies: - "@jest/types" "^29.5.0" - "@types/node" "*" - jest-util "^29.5.0" - jest-pnp-resolver@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" @@ -5656,11 +5202,6 @@ jest-regex-util@^29.2.0: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.2.0.tgz#82ef3b587e8c303357728d0322d48bbfd2971f7b" integrity sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA== -jest-regex-util@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.4.3.tgz#a42616141e0cae052cfa32c169945d00c0aa0bb8" - integrity sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg== - jest-resolve-dependencies@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.2.1.tgz#8d717dd41dc615fef1d412d395ea3deccfb1b9fa" @@ -5669,14 +5210,6 @@ jest-resolve-dependencies@^29.2.1: jest-regex-util "^29.2.0" jest-snapshot "^29.2.1" -jest-resolve-dependencies@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz#f0ea29955996f49788bf70996052aa98e7befee4" - integrity sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg== - dependencies: - jest-regex-util "^29.4.3" - jest-snapshot "^29.5.0" - jest-resolve@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.2.1.tgz#a4d2f76db88aeb6ec5f5453c9a40b52483d17799" @@ -5692,21 +5225,6 @@ jest-resolve@^29.2.1: resolve.exports "^1.1.0" slash "^3.0.0" -jest-resolve@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.5.0.tgz#b053cc95ad1d5f6327f0ac8aae9f98795475ecdc" - integrity sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.5.0" - jest-pnp-resolver "^1.2.2" - jest-util "^29.5.0" - jest-validate "^29.5.0" - resolve "^1.20.0" - resolve.exports "^2.0.0" - slash "^3.0.0" - jest-runner@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.2.1.tgz#885afe64661cb2f51f84c1b97afb713d1093c124" @@ -5734,33 +5252,6 @@ jest-runner@^29.2.1: p-limit "^3.1.0" source-map-support "0.5.13" -jest-runner@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.5.0.tgz#6a57c282eb0ef749778d444c1d758c6a7693b6f8" - integrity sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ== - dependencies: - "@jest/console" "^29.5.0" - "@jest/environment" "^29.5.0" - "@jest/test-result" "^29.5.0" - "@jest/transform" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.4.3" - jest-environment-node "^29.5.0" - jest-haste-map "^29.5.0" - jest-leak-detector "^29.5.0" - jest-message-util "^29.5.0" - jest-resolve "^29.5.0" - jest-runtime "^29.5.0" - jest-util "^29.5.0" - jest-watcher "^29.5.0" - jest-worker "^29.5.0" - p-limit "^3.1.0" - source-map-support "0.5.13" - jest-runtime@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.2.1.tgz#62e3a23c33710ae4d9c3304dda851a5fb225b574" @@ -5789,34 +5280,6 @@ jest-runtime@^29.2.1: slash "^3.0.0" strip-bom "^4.0.0" -jest-runtime@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.5.0.tgz#c83f943ee0c1da7eb91fa181b0811ebd59b03420" - integrity sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw== - dependencies: - "@jest/environment" "^29.5.0" - "@jest/fake-timers" "^29.5.0" - "@jest/globals" "^29.5.0" - "@jest/source-map" "^29.4.3" - "@jest/test-result" "^29.5.0" - "@jest/transform" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.5.0" - jest-message-util "^29.5.0" - jest-mock "^29.5.0" - jest-regex-util "^29.4.3" - jest-resolve "^29.5.0" - jest-snapshot "^29.5.0" - jest-util "^29.5.0" - slash "^3.0.0" - strip-bom "^4.0.0" - jest-snapshot@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.2.1.tgz#f3843b3099c8fec7e6218dea18cc506f10ea5d30" @@ -5847,35 +5310,6 @@ jest-snapshot@^29.2.1: pretty-format "^29.2.1" semver "^7.3.5" -jest-snapshot@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.5.0.tgz#c9c1ce0331e5b63cd444e2f95a55a73b84b1e8ce" - integrity sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/traverse" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.5.0" - "@jest/transform" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/babel__traverse" "^7.0.6" - "@types/prettier" "^2.1.5" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.5.0" - graceful-fs "^4.2.9" - jest-diff "^29.5.0" - jest-get-type "^29.4.3" - jest-matcher-utils "^29.5.0" - jest-message-util "^29.5.0" - jest-util "^29.5.0" - natural-compare "^1.4.0" - pretty-format "^29.5.0" - semver "^7.3.5" - jest-util@^29.0.0, jest-util@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.2.1.tgz#f26872ba0dc8cbefaba32c34f98935f6cf5fc747" @@ -5888,18 +5322,6 @@ jest-util@^29.0.0, jest-util@^29.2.1: graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-util@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.5.0.tgz#24a4d3d92fc39ce90425311b23c27a6e0ef16b8f" - integrity sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ== - dependencies: - "@jest/types" "^29.5.0" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - jest-validate@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.2.1.tgz#db814ce12c4c7e4746044922762e56eb177d066c" @@ -5912,18 +5334,6 @@ jest-validate@^29.2.1: leven "^3.1.0" pretty-format "^29.2.1" -jest-validate@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.5.0.tgz#8e5a8f36178d40e47138dc00866a5f3bd9916ffc" - integrity sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ== - dependencies: - "@jest/types" "^29.5.0" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.4.3" - leven "^3.1.0" - pretty-format "^29.5.0" - jest-watcher@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.2.1.tgz#1cb91f8aa9e77b1332af139944ad65e51430d7c3" @@ -5938,20 +5348,6 @@ jest-watcher@^29.2.1: jest-util "^29.2.1" string-length "^4.0.1" -jest-watcher@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.5.0.tgz#cf7f0f949828ba65ddbbb45c743a382a4d911363" - integrity sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA== - dependencies: - "@jest/test-result" "^29.5.0" - "@jest/types" "^29.5.0" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.5.0" - string-length "^4.0.1" - jest-worker@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.2.1.tgz#8ba68255438252e1674f990f0180c54dfa26a3b1" @@ -5962,16 +5358,6 @@ jest-worker@^29.2.1: merge-stream "^2.0.0" supports-color "^8.0.0" -jest-worker@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.5.0.tgz#bdaefb06811bd3384d93f009755014d8acb4615d" - integrity sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA== - dependencies: - "@types/node" "*" - jest-util "^29.5.0" - merge-stream "^2.0.0" - supports-color "^8.0.0" - jest@^29.0.3: version "29.2.1" resolved "https://registry.yarnpkg.com/jest/-/jest-29.2.1.tgz#352ec0b81a0e436691d546d984cd7d8f72ffd26a" @@ -7078,15 +6464,6 @@ pretty-format@^29.2.1: ansi-styles "^5.0.0" react-is "^18.0.0" -pretty-format@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.5.0.tgz#283134e74f70e2e3e7229336de0e4fce94ccde5a" - integrity sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw== - dependencies: - "@jest/schemas" "^29.4.3" - ansi-styles "^5.0.0" - react-is "^18.0.0" - pretty-quick@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-3.1.3.tgz#15281108c0ddf446675157ca40240099157b638e" @@ -7160,11 +6537,6 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -pure-rand@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.2.tgz#a9c2ddcae9b68d736a8163036f088a2781c8b306" - integrity sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ== - qs@6.11.0, qs@^6.7.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" @@ -7329,11 +6701,6 @@ resolve.exports@^1.1.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== -resolve.exports@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" - integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== - resolve@1.17.0: version "1.17.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" @@ -8613,7 +7980,7 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write-file-atomic@^4.0.1, write-file-atomic@^4.0.2: +write-file-atomic@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== From dd0fb03844d937383bb85900ee81b71b15ae5b0a Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 22 Aug 2023 10:19:58 +0100 Subject: [PATCH 100/833] feat: re add cal token amount removed when revert --- .../functions/calc_token_amount.ts | 34 ++++++++++++++++++- src/dex/uniswap-v3/uniswap-v3.ts | 2 +- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/dex/curve-v1-factory/price-handlers/functions/calc_token_amount.ts b/src/dex/curve-v1-factory/price-handlers/functions/calc_token_amount.ts index 4121d1224..7f5708faa 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/calc_token_amount.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/calc_token_amount.ts @@ -64,6 +64,38 @@ const customAvalanche3CoinLending: calc_token_amount = ( return (diff * state.totalSupply) / D0; }; +const factoryPlain2Basic: calc_token_amount = ( + self: IPoolContext, + state: PoolState, + amounts: bigint[], + is_deposit: boolean, +) => { + const { N_COINS } = self.constants; + const amp = state.A; + const balances = [...state.balances]; + const D0 = self.get_D(self, balances, amp); + for (const i of _.range(N_COINS)) { + if (is_deposit) balances[i] += amounts[i]; + else balances[i] -= amounts[i]; + } + const D1 = self.get_D(self, balances, amp); + + if (state.totalSupply === undefined) { + throw new Error( + `${self.IMPLEMENTATION_NAME} customPlain3CoinThree: totalSupply is not provided`, + ); + } + + const token_amount = state.totalSupply; + let diff = 0n; + if (is_deposit) { + diff = D1 - D0; + } else { + diff = D0 - D1; + } + return (diff * token_amount) / D0; +}; + const customPlain2CoinCrv: calc_token_amount = ( self: IPoolContext, state: PoolState, @@ -171,7 +203,7 @@ const implementations: Record = { [ImplementationNames.FACTORY_META_USD_BALANCES_FRAX_USDC]: notImplemented, [ImplementationNames.FACTORY_PLAIN_2_BALANCES]: notImplemented, - [ImplementationNames.FACTORY_PLAIN_2_BASIC]: notImplemented, + [ImplementationNames.FACTORY_PLAIN_2_BASIC]: factoryPlain2Basic, [ImplementationNames.FACTORY_PLAIN_2_ETH]: notImplemented, [ImplementationNames.FACTORY_PLAIN_2_OPTIMIZED]: notImplemented, diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 8a6ae661c..b31280a11 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -279,7 +279,7 @@ export class UniswapV3 e, ); } else { - // on unkown error mark as failed and increase retryCount for retry init strategy + // on unknown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, From 750de3f06a69eb494f477c0c738bb70beeb62793 Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 22 Aug 2023 10:21:47 +0100 Subject: [PATCH 101/833] 2.28.11-factory-crvusd.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 863106efb..4e1770966 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.11-factory-crvusd.1", + "version": "2.28.11-factory-crvusd.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 269d68374282728227039e59b49b4ad981b1717d Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 22 Aug 2023 11:47:52 +0100 Subject: [PATCH 102/833] chore: set latest dex-lib version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4e1770966..44655e19c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.11-factory-crvusd.2", + "version": "2.30.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 3e438548b267e131b59065dffb0188852378765c Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 22 Aug 2023 11:48:52 +0100 Subject: [PATCH 103/833] 2.30.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 44655e19c..3dbf23b1f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.30.1", + "version": "2.30.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From ae5a33a197166a5c05994d37f66fbfcba4214f5b Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 22 Aug 2023 13:16:53 +0100 Subject: [PATCH 104/833] fix: set proper handling of exchange rate request --- .../price-handlers/functions/_rates.ts | 2 +- .../state-polling-pools/custom-pool-polling.ts | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/dex/curve-v1-factory/price-handlers/functions/_rates.ts b/src/dex/curve-v1-factory/price-handlers/functions/_rates.ts index b742d20da..f16d6b114 100644 --- a/src/dex/curve-v1-factory/price-handlers/functions/_rates.ts +++ b/src/dex/curve-v1-factory/price-handlers/functions/_rates.ts @@ -36,7 +36,7 @@ const customPlain3CoinSbtc: _rates = ( let rate = LENDING_PRECISION; // Used with no lending if (use_lending[i]) { const currentRate = state.exchangeRateCurrent[i]; - if (currentRate === undefined) { + if (!currentRate) { throw new Error( `${self.IMPLEMENTATION_NAME}: exchangeRateCurrent contains undefined value that supposed to be used: ${state.exchangeRateCurrent}`, ); diff --git a/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts b/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts index 7a83192de..99e837ac4 100644 --- a/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts +++ b/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts @@ -13,6 +13,7 @@ import { _require } from '../../../utils'; import { Address } from '@paraswap/core'; import { AbiItem } from 'web3-utils'; import { NULL_ADDRESS } from '../../../constants'; +import { assert } from 'ts-essentials'; type FunctionToCall = | 'A' @@ -255,9 +256,15 @@ export class CustomBasePoolForFactory extends PoolPollingBase { }, 'indicesToFill.length === exchangeRateResults.length', ); - indicesToFill.forEach((indexToFill, currentIndex) => { - exchangeRateResults[indexToFill] = exchangeRateResults[currentIndex]; + if (exchangeRateCurrent === undefined) { + throw new Error( + `${this.poolIdentifier}: exchangeRateCurrent is undefined`, + ); + } + const resultRate = exchangeRateCurrent[indexToFill]; + assert(resultRate, "resultRate can't be undefined"); + exchangeRateCurrent[indexToFill] = exchangeRateResults[currentIndex]; }); } From cd6064efe45b3239a835e5b3ffdac8fd5a07b426 Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 22 Aug 2023 13:19:26 +0100 Subject: [PATCH 105/833] 2.30.3-curve-bigint-mix.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3dbf23b1f..2eede945d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.30.2", + "version": "2.30.3-curve-bigint-mix.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 144d3266bfd5eee26a810877b652d2eb1b6ccbd1 Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 22 Aug 2023 13:28:45 +0100 Subject: [PATCH 106/833] fix: wrong values --- .../state-polling-pools/custom-pool-polling.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts b/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts index 99e837ac4..3edf72510 100644 --- a/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts +++ b/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts @@ -262,9 +262,9 @@ export class CustomBasePoolForFactory extends PoolPollingBase { `${this.poolIdentifier}: exchangeRateCurrent is undefined`, ); } - const resultRate = exchangeRateCurrent[indexToFill]; + const resultRate = exchangeRateResults[indexToFill]; assert(resultRate, "resultRate can't be undefined"); - exchangeRateCurrent[indexToFill] = exchangeRateResults[currentIndex]; + exchangeRateCurrent[indexToFill] = resultRate; }); } From 4b0ab18c69f5c6e0020fe1991b7fde366af4b195 Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 22 Aug 2023 13:29:22 +0100 Subject: [PATCH 107/833] 2.30.3-curve-bigint-mix.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2eede945d..675c36e1e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.30.3-curve-bigint-mix.0", + "version": "2.30.3-curve-bigint-mix.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From fa4ea4e0dffc1aa13d80b857af45b7f5a0c8e075 Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 22 Aug 2023 13:52:55 +0100 Subject: [PATCH 108/833] fix: use proper index --- .../curve-v1-factory/state-polling-pools/custom-pool-polling.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts b/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts index 3edf72510..a0826a822 100644 --- a/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts +++ b/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts @@ -262,7 +262,7 @@ export class CustomBasePoolForFactory extends PoolPollingBase { `${this.poolIdentifier}: exchangeRateCurrent is undefined`, ); } - const resultRate = exchangeRateResults[indexToFill]; + const resultRate = exchangeRateResults[currentIndex]; assert(resultRate, "resultRate can't be undefined"); exchangeRateCurrent[indexToFill] = resultRate; }); From 86619906dda10b2bf217876dadf0c7251b88437c Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 22 Aug 2023 13:53:31 +0100 Subject: [PATCH 109/833] 2.30.3-curve-bigint-mix.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 675c36e1e..bc367b5cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.30.3-curve-bigint-mix.1", + "version": "2.30.3-curve-bigint-mix.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 3ed66b4598ac15f60b583d7aa181536f6e7e68fc Mon Sep 17 00:00:00 2001 From: Tudor Anastasiu Date: Tue, 22 Aug 2023 18:56:04 +0300 Subject: [PATCH 110/833] Add check for `limitPools` for generic-rfq. --- src/dex/generic-rfq/generic-rfq.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/dex/generic-rfq/generic-rfq.ts b/src/dex/generic-rfq/generic-rfq.ts index 389a9a4a3..1a4fb9b57 100644 --- a/src/dex/generic-rfq/generic-rfq.ts +++ b/src/dex/generic-rfq/generic-rfq.ts @@ -140,6 +140,10 @@ export class GenericRFQ extends ParaSwapLimitOrders { _destToken.address, ); + if (!limitPools?.includes(expectedIdentifier)) { + return null; + } + const rates = await this.rateFetcher.getOrderPrice( _srcToken, _destToken, From ac97f999dca9c6b052bdac4a9bbabdb3699e4b26 Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 22 Aug 2023 17:08:52 +0100 Subject: [PATCH 111/833] fix: fix issue with exchange rate requester --- .../curve-v1-factory-integration.test.ts | 57 ++++++++++ src/dex/curve-v1-factory/curve-v1-factory.ts | 102 ++++++++++-------- .../curve-v1-factory/curve-v1-pool-manager.ts | 12 ++- .../custom-pool-polling.ts | 7 +- tests/constants-e2e.ts | 5 + 5 files changed, 135 insertions(+), 48 deletions(-) diff --git a/src/dex/curve-v1-factory/curve-v1-factory-integration.test.ts b/src/dex/curve-v1-factory/curve-v1-factory-integration.test.ts index 5dc723f42..23f81a439 100644 --- a/src/dex/curve-v1-factory/curve-v1-factory-integration.test.ts +++ b/src/dex/curve-v1-factory/curve-v1-factory-integration.test.ts @@ -275,6 +275,63 @@ describe('CurveV1Factory', function () { } }); }); + + describe(`renBTC-wibBTC`, () => { + const srcTokenSymbol = 'renBTC'; + const destTokenSymbol = 'wibBTC'; + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals - 1], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals - 1], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals - 1], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals - 1], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals - 1], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals - 1], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals - 1], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals - 1], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals - 1], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals - 1], + ]; + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + curveV1Factory, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newCurveV1Factory = new CurveV1Factory( + network, + dexKey, + dexHelper, + ); + if (newCurveV1Factory.updatePoolState) { + await newCurveV1Factory.updatePoolState(); + } + const poolLiquidity = await newCurveV1Factory.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newCurveV1Factory.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); + }); }); describe('Polygon', () => { const network = Network.POLYGON; diff --git a/src/dex/curve-v1-factory/curve-v1-factory.ts b/src/dex/curve-v1-factory/curve-v1-factory.ts index 0e88729f8..8606bdce6 100644 --- a/src/dex/curve-v1-factory/curve-v1-factory.ts +++ b/src/dex/curve-v1-factory/curve-v1-factory.ts @@ -181,6 +181,8 @@ export class CurveV1Factory // This is only to start timer, each pool is initialized with updated state this.poolManager.initializePollingPools(); await this.fetchFactoryPools(blockNumber); + await this.poolManager.fetchLiquiditiesFromApi(); + await this.poolManager.updatePollingPoolsInBatch(); this.logger.info(`${this.dexKey}: successfully initialized`); } @@ -340,7 +342,7 @@ export class CurveV1Factory // Variable initializeInitialState is only for poolTracker. We don't want to keep state updated with scheduler // We just want to initialize factory pools and send request to CurveAPI // Other values are not used - initializeInitialState: boolean = true, + initializeInitialState: boolean = false, ) { if (this.areFactoryPoolsFetched) { return; @@ -770,57 +772,69 @@ export class CurveV1Factory ) : amountsWithUnit; - const results = pools.map( - (pool): PoolPrices | null => { - const state = pool.getState(); + const results = await Promise.all( + pools.map( + async (pool): Promise | null> => { + let state = pool.getState(); + if (!state) { + await this.poolManager.updateManuallyPollingPools( + pool.baseStatePoolPolling + ? [pool.baseStatePoolPolling, pool] + : [pool], + ); + state = pool.getState(); + if (!state) { + return null; + } + } - if (!state) { - return null; - } + if (state.balances.every(b => b === 0n)) { + this.logger.trace( + `${this.dexKey} on ${this.dexHelper.config.data.network}: State balances equal to 0 in pool ${pool.address}`, + ); + return null; + } - if (state.balances.every(b => b === 0n)) { - this.logger.trace( - `${this.dexKey} on ${this.dexHelper.config.data.network}: State balances equal to 0 in pool ${pool.address}`, + const poolData = pool.getPoolData( + srcTokenAddress, + destTokenAddress, ); - return null; - } - const poolData = pool.getPoolData(srcTokenAddress, destTokenAddress); + if (poolData === null) { + this.logger.error( + `${pool.fullName}: one or both tokens can not be exchanged in pool ${pool.address}: ${srcTokenAddress} -> ${destTokenAddress}`, + ); + return null; + } - if (poolData === null) { - this.logger.error( - `${pool.fullName}: one or both tokens can not be exchanged in pool ${pool.address}: ${srcTokenAddress} -> ${destTokenAddress}`, - ); - return null; - } + let outputs: bigint[] = this.poolManager + .getPriceHandler(pool.implementationAddress) + .getOutputs( + state, + amountsWithUnitAndFee, + poolData.i, + poolData.j, + poolData.underlyingSwap, + ); - let outputs: bigint[] = this.poolManager - .getPriceHandler(pool.implementationAddress) - .getOutputs( - state, - amountsWithUnitAndFee, - poolData.i, - poolData.j, - poolData.underlyingSwap, + outputs = applyTransferFee( + outputs, + side, + transferFees.destDexFee, + this.DEST_TOKEN_DEX_TRANSFERS, ); - outputs = applyTransferFee( - outputs, - side, - transferFees.destDexFee, - this.DEST_TOKEN_DEX_TRANSFERS, - ); - - return { - prices: [0n, ...outputs.slice(1)], - unit: outputs[0], - data: poolData, - exchange: this.dexKey, - poolIdentifier: pool.poolIdentifier, - gasCost: POOL_EXCHANGE_GAS_COST, - poolAddresses: [pool.address], - }; - }, + return { + prices: [0n, ...outputs.slice(1)], + unit: outputs[0], + data: poolData, + exchange: this.dexKey, + poolIdentifier: pool.poolIdentifier, + gasCost: POOL_EXCHANGE_GAS_COST, + poolAddresses: [pool.address], + }; + }, + ), ); return results.filter( diff --git a/src/dex/curve-v1-factory/curve-v1-pool-manager.ts b/src/dex/curve-v1-factory/curve-v1-pool-manager.ts index 42e2c8c20..45141def5 100644 --- a/src/dex/curve-v1-factory/curve-v1-pool-manager.ts +++ b/src/dex/curve-v1-factory/curve-v1-pool-manager.ts @@ -94,7 +94,7 @@ export class CurveV1FactoryPoolManager { filteredPoolsByLiquidity.sort((a, b) => +a.isMetaPool - +b.isMetaPool), ); - this.statePollingManager.updatePoolsInBatch( + return this.statePollingManager.updatePoolsInBatch( this.logger, this.dexHelper, pools, @@ -105,6 +105,16 @@ export class CurveV1FactoryPoolManager { ); } + async updateManuallyPollingPools(pools: PoolPollingBase[]) { + return this.statePollingManager.updatePoolsInBatch( + this.logger, + this.dexHelper, + pools, + undefined, + undefined, + ); + } + async initializeIndividualPollingPoolState( identifier: string, isSrcFeeOnTransferTokenToBeExchanged: boolean, diff --git a/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts b/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts index a0826a822..f2c3ea087 100644 --- a/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts +++ b/src/dex/curve-v1-factory/state-polling-pools/custom-pool-polling.ts @@ -228,16 +228,17 @@ export class CustomBasePoolForFactory extends PoolPollingBase { let exchangeRateCurrent: (bigint | undefined)[] | undefined; - let lastEndIndex = lastIndex + 1; + let lastEndIndex = lastIndex + this.poolConstants.COINS.length; if (this.useLending) { exchangeRateCurrent = new Array(this.useLending.length).fill(undefined); + let trueUseLendingCount = this.useLending.filter(el => el).length; const exchangeRateResults = multiOutputs.slice( lastEndIndex, // Filter false elements before checking length - lastEndIndex + this.useLending.filter(el => el).length, + lastEndIndex + trueUseLendingCount, ) as bigint[]; - lastEndIndex += this.useLending.length; + lastEndIndex += trueUseLendingCount; // We had array with booleans and I filtered of `false` and sent request. // So, now I must map that results to original indices. That is the reason of this complication const indicesToFill = this.useLending.reduce((acc, curr, i) => { diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 7e91808ca..85df1682c 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -307,6 +307,10 @@ export const Tokens: { address: '0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E', decimals: 18, }, + wibBTC: { + address: '0x8751d4196027d4e6da63716fa7786b5174f04c15', + decimals: 18, + }, }, [Network.ROPSTEN]: { DAI: { @@ -918,6 +922,7 @@ export const Holders: { PSP: '0xE5E5440a1CE69C5cf67BFFA74d185e57c31b43E5', crvUSD: '0xA920De414eA4Ab66b97dA1bFE9e6EcA7d4219635', GHO: '0x844Dc85EdD8492A56228D293cfEbb823EF3E10EC', + wibBTC: '0xFbdCA68601f835b27790D98bbb8eC7f05FDEaA9B', }, [Network.ROPSTEN]: { ETH: '0x43262A12d8610AA70C15DbaeAC321d51613c9071', From 9fcbd1880ce2e14e6ccf88f26783797643b2f916 Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 22 Aug 2023 17:10:50 +0100 Subject: [PATCH 112/833] 2.30.3-curve-bigint-mix.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bc367b5cf..e54b89f10 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.30.3-curve-bigint-mix.2", + "version": "2.30.3-curve-bigint-mix.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 9d05f1d55a4c8fc6dfdc9699252f9b5e5be619ef Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 22 Aug 2023 20:18:47 +0300 Subject: [PATCH 113/833] debug --- src/dex/index.ts | 1 + src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts | 4 +- src/dex/uniswap-v3/config.ts | 98 +++++ src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 337 +++++++++++++++++- src/dex/uniswap-v3/uniswap-v3.ts | 2 +- yarn.lock | 1 + 6 files changed, 434 insertions(+), 9 deletions(-) diff --git a/src/dex/index.ts b/src/dex/index.ts index 31be4947d..11302d4c3 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -70,6 +70,7 @@ import { SwaapV2 } from './swaap-v2/swaap-v2'; import { SpiritSwapV3 } from './quickswap/spiritswap-v3'; import { TraderJoeV21 } from './trader-joe-v2.1'; import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3'; +import { Algebra } from './algebra/algebra'; const LegacyDexes = [ CurveV2, diff --git a/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts b/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts index 2c7c52b85..db0466237 100644 --- a/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts +++ b/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts @@ -106,13 +106,13 @@ function testForNetwork( } describe('SushiswapV3 E2E', () => { - const dexKey = 'SushiswapV3'; + const dexKey = 'SushiSwapV3'; describe('MAINNET', () => { const network = Network.MAINNET; const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'WETH'; + const tokenBSymbol: string = 'USDT'; const tokenAAmount: string = '111110000'; const tokenBAmount: string = '110000000000000000'; diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index 18a66c612..3ee8e588c 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -107,6 +107,104 @@ export const UniswapV3Config: DexConfigMap = { 'https://api.thegraph.com/subgraphs/name/lynnshaoyu/uniswap-v3-avax', }, }, + SushiSwapV3: { + [Network.MAINNET]: { + factory: '0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F', + quoter: '0x64e8802FE490fa7cc61d3463958199161Bb608A7', + router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', + // router: '0x827179dD56d07A7eeA32e3873493835da2866976', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-ethereum', + }, + [Network.POLYGON]: { + factory: '0x917933899c6a5f8e37f31e19f92cdbff7e8ff0e2', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', + // router: '0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-polygon', + }, + [Network.BSC]: { + factory: '0x126555dd55a39328F69400d6aE4F782Bd4C34ABb', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x83c346ba3d4bf36b308705e24fad80999401854b', + // router: '0x400d75dAb26bBc18D163AEA3e83D9Ea68F6c1804', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x593F39A4Ba26A9c8ed2128ac95D109E8e403C485', + uniswapMulticall: '0x963Df249eD09c358A4819E39d9Cd5736c3087184', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-bsc', + }, + [Network.AVALANCHE]: { + factory: '0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x33895c09a0ec0718ce66ab35dfd0b656d77cd053', + // router: '0x717b7948AA264DeCf4D780aa6914482e5F46Da3e', + supportedFees: SUPPORTED_FEES, + stateMulticall: '', + uniswapMulticall: '0x8C0F842791F03C095b6c633759224FcC9ACe68ea', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-avalanche', + }, + [Network.FANTOM]: { + factory: '0x7770978eED668a3ba661d51a773d3a992Fc9DDCB', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x940438cEd3062E3F7aE311c789FA9dDd3a5eA951', + // router: '0x2214A42d8e2A1d20635c2cb0664422c528B6A432', + supportedFees: SUPPORTED_FEES, + stateMulticall: '', + uniswapMulticall: '0xB1395e098c0a847CC719Bcf1Fc8114421a9F8232', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-fantom', + }, + [Network.ARBITRUM]: { + factory: '0x1af415a1eba07a4986a52b6f2e7de7003d82231e', + quoter: '0x0524E833cCD057e4d7A296e3aaAb9f7675964Ce1', + router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', + // router: '0xfc506AaA1340b4dedFfd88bE278bEe058952D674', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-arbitrum', + }, + [Network.OPTIMISM]: { + factory: '0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', + // router: '0x4C5D5234f232BD2D76B96aA33F5AE4FCF0E4BFAb', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x4FF0dEC5f9a763Aa1E5C2a962aa6f4eDFeE4f9eA', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-optimism', + }, + }, RamsesV2: { [Network.ARBITRUM]: { factory: '0xAA2cd7477c451E703f3B9Ba5663334914763edF8', diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index bccf2bf69..68d0ea971 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -2,15 +2,105 @@ import dotenv from 'dotenv'; dotenv.config(); import { testE2E } from '../../../tests/utils-e2e'; -import { - Tokens, - Holders, - NativeTokenSymbols, -} from '../../../tests/constants-e2e'; -import { Network, ContractMethod, SwapSide } from '../../constants'; +import { Holders, NativeTokenSymbols, Tokens, } from '../../../tests/constants-e2e'; +import { ContractMethod, Network, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, + slippage?: number | undefined, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy, ContractMethod.directUniV3Buy]], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + 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, + 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, + network, + provider, + undefined, + undefined, + undefined, + slippage, + ); + }); + }); + }); + }), + ); + }); +} + describe('UniswapV3 E2E', () => { describe('UniswapV3', () => { @@ -501,4 +591,239 @@ describe('UniswapV3 E2E', () => { ); }); }); + + describe('SushiswapV3', () => { + const dexKey = 'SushiSwapV3'; + + describe('MAINNET', () => { + const network = Network.MAINNET; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '1100000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + 500, // 5% + ); + }); + + describe('ARBITRUM', () => { + const network = Network.ARBITRUM; + + const tokenASymbol: string = 'USDCe'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '10000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + 500, // 5% + ); + }); + + describe('POLYGON', () => { + const network = Network.POLYGON; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '21111000'; + const tokenBAmount: string = '200000000'; + const nativeTokenAmount = '110000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + 500, // 5% + ); + }); + + describe('BSC', () => { + const network = Network.BSC; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Buy, + ], + ], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy, ContractMethod.directUniV3Buy]], + ]); + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ + [ + { + name: 'USDT', + sellAmount: '10000000000', + buyAmount: '10000000000000', + }, + { + name: 'BNB', + sellAmount: '10000000000000', + buyAmount: '10000000', + }, + ], + [ + { + name: 'USDC', + sellAmount: '111110000', + buyAmount: '111110000', + }, + { + name: 'USDT', + sellAmount: '111110000', + buyAmount: '111110000', + }, + ], + [ + { + name: 'ETH', + sellAmount: '1000000000000000000', + buyAmount: '500000', + }, + { name: 'USDT', sellAmount: '1000000', buyAmount: '20000000000000000' }, + ], + ]; + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }); + }), + ); + }); + + describe('AVALANCHE', () => { + const network = Network.AVALANCHE; + + const tokenASymbol: string = 'USDCe'; + const tokenBSymbol: string = 'USDC'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '100000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + 500, // 5% + ); + }); + + describe('FANTOM', () => { + const network = Network.FANTOM; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'DAI'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '10000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + 500, // 5% + ); + }); + + describe('OPTIMISM', () => { + const network = Network.OPTIMISM; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '10000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + 500, // 5% + ); + }); + }); }); diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 8a6ae661c..eeeeaea54 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -91,7 +91,7 @@ export class UniswapV3 public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork( - _.pick(UniswapV3Config, ['UniswapV3', 'QuickSwapV3.1', 'RamsesV2']), + _.pick(UniswapV3Config, ['UniswapV3', 'QuickSwapV3.1', 'RamsesV2', 'SushiSwapV3']), ); logger: Logger; diff --git a/yarn.lock b/yarn.lock index ae78a3df3..3c30397f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1687,6 +1687,7 @@ integrity sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg== "@nomiclabs/hardhat-ethers@npm:hardhat-deploy-ethers@0.3.0-beta.13", hardhat-deploy-ethers@0.3.0-beta.13: + name "@nomiclabs/hardhat-ethers" version "0.3.0-beta.13" resolved "https://registry.yarnpkg.com/hardhat-deploy-ethers/-/hardhat-deploy-ethers-0.3.0-beta.13.tgz#b96086ff768ddf69928984d5eb0a8d78cfca9366" integrity sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw== From 5390aad651cd6e11dc49e8ceb1b99ee3e28b3269 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 22 Aug 2023 20:23:32 +0300 Subject: [PATCH 114/833] 2.30.3-chronos-v3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c07fd7d46..8ae4b788b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.30.2-chronos-v3", + "version": "2.30.3-chronos-v3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From b9c6330ac1c81e12fc539ebfded48106afa74426 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 23 Aug 2023 09:59:02 +0100 Subject: [PATCH 115/833] 2.30.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e54b89f10..36fbd9809 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.30.3-curve-bigint-mix.3", + "version": "2.30.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 7a0ca219e2990d7a8bd471f5a3d12c4967194c74 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 23 Aug 2023 12:08:53 +0300 Subject: [PATCH 116/833] 2.30.4-chronos-v3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8ae4b788b..f1eacb27c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.30.3-chronos-v3", + "version": "2.30.4-chronos-v3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From dbace536cb51a10c26b96180922a46feee981261 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 23 Aug 2023 12:51:30 +0300 Subject: [PATCH 117/833] 2.31.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f1eacb27c..8609a6a0e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.30.4-chronos-v3", + "version": "2.31.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 33844618d83988cf0dfc5cf526ef91fbabd90b7b Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 23 Aug 2023 14:54:03 +0300 Subject: [PATCH 118/833] remove separate integration for sushi v3 --- package.json | 1 - src/abi/sushiswap-v3/QuoterV2.json | 267 - src/abi/sushiswap-v3/RouterProcessor3.json | 289 - src/dex/sushiswap-v3/config.ts | 119 - src/dex/sushiswap-v3/constants.ts | 25 - src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts | 154 - .../sushiswap-v3/sushiswap-v3-events.test.ts | 119 - .../sushiswap-v3-integration.test.ts | 378 -- src/dex/sushiswap-v3/sushiswap-v3-pool.ts | 1 - src/dex/sushiswap-v3/sushiswap-v3.ts | 1017 --- src/dex/sushiswap-v3/token.ts | 25 - src/dex/sushiswap-v3/types.ts | 17 - .../uniswap-v3/uniswap-v3-integration.test.ts | 135 + yarn.lock | 5807 +---------------- 14 files changed, 281 insertions(+), 8073 deletions(-) delete mode 100644 src/abi/sushiswap-v3/QuoterV2.json delete mode 100644 src/abi/sushiswap-v3/RouterProcessor3.json delete mode 100644 src/dex/sushiswap-v3/config.ts delete mode 100644 src/dex/sushiswap-v3/constants.ts delete mode 100644 src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts delete mode 100644 src/dex/sushiswap-v3/sushiswap-v3-events.test.ts delete mode 100644 src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts delete mode 100644 src/dex/sushiswap-v3/sushiswap-v3-pool.ts delete mode 100644 src/dex/sushiswap-v3/sushiswap-v3.ts delete mode 100644 src/dex/sushiswap-v3/token.ts delete mode 100644 src/dex/sushiswap-v3/types.ts diff --git a/package.json b/package.json index 28c896974..8609a6a0e 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "@hashflow/sdk": "1.2.4", "@hashflow/taker-js": "0.0.2", "@paraswap/core": "1.1.0", - "@sushiswap/router": "^0.0.12", "async": "^3.2.4", "axios": "0.26.0", "bignumber.js": "9.1.0", diff --git a/src/abi/sushiswap-v3/QuoterV2.json b/src/abi/sushiswap-v3/QuoterV2.json deleted file mode 100644 index ce1374e69..000000000 --- a/src/abi/sushiswap-v3/QuoterV2.json +++ /dev/null @@ -1,267 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_factory", - "type": "address" - }, - { - "internalType": "address", - "name": "_WETH9", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "WETH9", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "factory", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "path", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - } - ], - "name": "quoteExactInput", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint160[]", - "name": "sqrtPriceX96AfterList", - "type": "uint160[]" - }, - { - "internalType": "uint32[]", - "name": "initializedTicksCrossedList", - "type": "uint32[]" - }, - { - "internalType": "uint256", - "name": "gasEstimate", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint24", - "name": "fee", - "type": "uint24" - }, - { - "internalType": "uint160", - "name": "sqrtPriceLimitX96", - "type": "uint160" - } - ], - "internalType": "struct IQuoterV2.QuoteExactInputSingleParams", - "name": "params", - "type": "tuple" - } - ], - "name": "quoteExactInputSingle", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint160", - "name": "sqrtPriceX96After", - "type": "uint160" - }, - { - "internalType": "uint32", - "name": "initializedTicksCrossed", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "gasEstimate", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "path", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "name": "quoteExactOutput", - "outputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint160[]", - "name": "sqrtPriceX96AfterList", - "type": "uint160[]" - }, - { - "internalType": "uint32[]", - "name": "initializedTicksCrossedList", - "type": "uint32[]" - }, - { - "internalType": "uint256", - "name": "gasEstimate", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint24", - "name": "fee", - "type": "uint24" - }, - { - "internalType": "uint160", - "name": "sqrtPriceLimitX96", - "type": "uint160" - } - ], - "internalType": "struct IQuoterV2.QuoteExactOutputSingleParams", - "name": "params", - "type": "tuple" - } - ], - "name": "quoteExactOutputSingle", - "outputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint160", - "name": "sqrtPriceX96After", - "type": "uint160" - }, - { - "internalType": "uint32", - "name": "initializedTicksCrossed", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "gasEstimate", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "amount0Delta", - "type": "int256" - }, - { - "internalType": "int256", - "name": "amount1Delta", - "type": "int256" - }, - { - "internalType": "bytes", - "name": "path", - "type": "bytes" - } - ], - "name": "uniswapV3SwapCallback", - "outputs": [], - "stateMutability": "view", - "type": "function" - } -] diff --git a/src/abi/sushiswap-v3/RouterProcessor3.json b/src/abi/sushiswap-v3/RouterProcessor3.json deleted file mode 100644 index d8959084f..000000000 --- a/src/abi/sushiswap-v3/RouterProcessor3.json +++ /dev/null @@ -1,289 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_bentoBox", - "type": "address" - }, - { - "internalType": "address[]", - "name": "priviledgedUserList", - "type": "address[]" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "name": "Route", - "type": "event" - }, - { - "inputs": [], - "name": "bentoBox", - "outputs": [ - { - "internalType": "contract IBentoBoxMinimal", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "route", - "type": "bytes" - } - ], - "name": "processRoute", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "resume", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "bool", - "name": "priviledge", - "type": "bool" - } - ], - "name": "setPriviledge", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "transferValueTo", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountValueTransfer", - "type": "uint256" - }, - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "route", - "type": "bytes" - } - ], - "name": "transferValueAndprocessRoute", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "amount0Delta", - "type": "int256" - }, - { - "internalType": "int256", - "name": "amount1Delta", - "type": "int256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "uniswapV3SwapCallback", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/src/dex/sushiswap-v3/config.ts b/src/dex/sushiswap-v3/config.ts deleted file mode 100644 index 4ee0b9f03..000000000 --- a/src/dex/sushiswap-v3/config.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { DexParams } from './types'; -import { DexConfigMap, AdapterMappings } from '../../types'; -import { Network, SwapSide } from '../../constants'; - -const SUPPORTED_FEES = [10000n, 3000n, 500n, 100n]; - -export const SushiswapV3Config: DexConfigMap = { - SushiswapV3: { - [Network.MAINNET]: { - factory: '0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F', - quoter: '0x64e8802FE490fa7cc61d3463958199161Bb608A7', - router: '0x827179dD56d07A7eeA32e3873493835da2866976', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-ethereum', - }, - [Network.POLYGON]: { - factory: '0x917933899c6a5f8e37f31e19f92cdbff7e8ff0e2', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-polygon', - }, - [Network.BSC]: { - factory: '0x126555dd55a39328F69400d6aE4F782Bd4C34ABb', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x400d75dAb26bBc18D163AEA3e83D9Ea68F6c1804', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x593F39A4Ba26A9c8ed2128ac95D109E8e403C485', - uniswapMulticall: '0x963Df249eD09c358A4819E39d9Cd5736c3087184', - chunksCount: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-bsc', - }, - [Network.AVALANCHE]: { - factory: '0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x717b7948AA264DeCf4D780aa6914482e5F46Da3e', - supportedFees: SUPPORTED_FEES, - stateMulticall: '', - uniswapMulticall: '0x8C0F842791F03C095b6c633759224FcC9ACe68ea', - chunksCount: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-avalanche', - }, - [Network.FANTOM]: { - factory: '0x7770978eED668a3ba661d51a773d3a992Fc9DDCB', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x2214A42d8e2A1d20635c2cb0664422c528B6A432', - supportedFees: SUPPORTED_FEES, - stateMulticall: '', - uniswapMulticall: '0xB1395e098c0a847CC719Bcf1Fc8114421a9F8232', - chunksCount: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-fantom', - }, - [Network.ARBITRUM]: { - factory: '0x1af415a1eba07a4986a52b6f2e7de7003d82231e', - quoter: '0x0524E833cCD057e4d7A296e3aaAb9f7675964Ce1', - router: '0xfc506AaA1340b4dedFfd88bE278bEe058952D674', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-arbitrum', - }, - [Network.OPTIMISM]: { - factory: '0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x4C5D5234f232BD2D76B96aA33F5AE4FCF0E4BFAb', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x4FF0dEC5f9a763Aa1E5C2a962aa6f4eDFeE4f9eA', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-optimism', - }, - }, -}; - -export const Adapters: Record = { - [Network.MAINNET]: { - [SwapSide.SELL]: [{ name: 'Adapter01', index: 6 }], - [SwapSide.BUY]: [{ name: 'BuyAdapter', index: 2 }], - }, - [Network.BSC]: { - [SwapSide.SELL]: [{ name: 'BscAdapter02', index: 4 }], - [SwapSide.BUY]: [{ name: 'BscBuyAdapter', index: 5 }], - }, - [Network.POLYGON]: { - [SwapSide.SELL]: [{ name: 'PolygonAdapter01', index: 13 }], - [SwapSide.BUY]: [{ name: 'PolygonBuyAdapter', index: 2 }], - }, - [Network.ARBITRUM]: { - [SwapSide.SELL]: [{ name: 'ArbitrumAdapter01', index: 3 }], - [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 2 }], - }, - [Network.OPTIMISM]: { - [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 3 }], - [SwapSide.BUY]: [{ name: 'OptimismBuyAdapter', index: 2 }], - }, - [Network.FANTOM]: { - [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 11 }], - [SwapSide.BUY]: [{ name: 'FantomBuyAdapter', index: 3 }], - }, -}; diff --git a/src/dex/sushiswap-v3/constants.ts b/src/dex/sushiswap-v3/constants.ts deleted file mode 100644 index a722e8088..000000000 --- a/src/dex/sushiswap-v3/constants.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Chain } from 'viem'; -import { - arbitrum, - avalanche, - bsc, - fantom, - mainnet, - optimism, - polygon, -} from '@sushiswap/viem-config'; -import { Network } from '../../constants'; - -export * from '../uniswap-v3/constants'; - -export const ViemChain: Record = { - [Network.ARBITRUM]: arbitrum, - [Network.AVALANCHE]: avalanche, - [Network.BSC]: bsc, - [Network.FANTOM]: fantom, - [Network.MAINNET]: mainnet, - [Network.OPTIMISM]: optimism, - [Network.POLYGON]: polygon, - [Network.RINKEBY]: undefined, - [Network.ROPSTEN]: undefined, -}; diff --git a/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts b/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts deleted file mode 100644 index db0466237..000000000 --- a/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts +++ /dev/null @@ -1,154 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); - -import { testE2E } from '../../../tests/utils-e2e'; -import { - Tokens, - Holders, - NativeTokenSymbols, -} from '../../../tests/constants-e2e'; -import { Network, ContractMethod, SwapSide } from '../../constants'; -import { StaticJsonRpcProvider } from '@ethersproject/providers'; -import { generateConfig } from '../../config'; - -function testForNetwork( - network: Network, - dexKey: string, - tokenASymbol: string, - tokenBSymbol: string, - tokenAAmount: string, - tokenBAmount: string, - nativeTokenAmount: string, - slippage?: number | undefined, -) { - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - const tokens = Tokens[network]; - const holders = Holders[network]; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ], - ], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - ]); - - describe(`${network}`, () => { - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - 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, - 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, - 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, - network, - provider, - undefined, - undefined, - undefined, - slippage, - ); - }); - }); - }); - }), - ); - }); -} - -describe('SushiswapV3 E2E', () => { - const dexKey = 'SushiSwapV3'; - - describe('MAINNET', () => { - const network = Network.MAINNET; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; - - const tokenAAmount: string = '111110000'; - const tokenBAmount: string = '110000000000000000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - 500, // 5% - ); - }); - - describe('ARBITRUM', () => { - const network = Network.ARBITRUM; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'WETH'; - - const tokenAAmount: string = '111110000'; - const tokenBAmount: string = '110000000000000000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - 500, // 5% - ); - }); -}); diff --git a/src/dex/sushiswap-v3/sushiswap-v3-events.test.ts b/src/dex/sushiswap-v3/sushiswap-v3-events.test.ts deleted file mode 100644 index 687386915..000000000 --- a/src/dex/sushiswap-v3/sushiswap-v3-events.test.ts +++ /dev/null @@ -1,119 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); - -import { SushiswapV3EventPool } from './sushiswap-v3-pool'; -import { Network } from '../../constants'; -import { Address } from '../../types'; -import { DummyDexHelper } from '../../dex-helper/index'; -import { testEventSubscriber } from '../../../tests/utils-events'; -import { PoolState } from './types'; -import ERC20ABI from '../../abi/erc20.json'; -import StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; -import { AbiItem } from 'web3-utils'; -import { Interface } from 'ethers/lib/utils'; - -jest.setTimeout(50 * 1000); - -async function fetchPoolState( - sushiswapV3Pool: SushiswapV3EventPool, - blockNumber: number, - poolAddress: string, -): Promise { - const message = `UniswapV3: ${poolAddress} blockNumber ${blockNumber}`; - console.log(`Fetching state ${message}`); - // Be careful to not request state prior to contract deployment - // Otherwise need to use manual state sourcing from multicall - // We had that mechanism, but removed it with this commit - // You can restore it, but better just to find block after state multicall - // deployment - const state = sushiswapV3Pool.generateState(blockNumber); - console.log(`Done ${message}`); - return state; -} - -// eventName -> blockNumbers -type EventMappings = Record; - -describe('SushiswapV3 EventPool Mainnet', function () { - const dexKey = 'SushiswapV3'; - const network = Network.MAINNET; - const dexHelper = new DummyDexHelper(network); - const logger = dexHelper.getLogger(dexKey); - let sushiswapV3Pool: SushiswapV3EventPool; - - const factory = '0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F'; - const poolFeeCode = 500n; - const token0 = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'; - const token1 = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'; - const stateMulticall = '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63'; - const initCodeHash = - '0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54'; - - // poolAddress -> EventMappings - const eventsToTest: Record = { - ['0x35644fb61afbc458bf92b15add6abc1996be5014']: { - // topic0 - 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67 - ['Swap']: [ - 17293592, 17293446, 17293111, 17289023, 17280383, 17280375, 17279057, - ], - // // topic0 - 0x0c396cd989a39f4459b5fa1aed6a9a8dcdbc45908acfd67e028cd568da98982c - ['Burn']: [17259974], - // // topic0 - 0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde - ['Mint']: [17215311], - // // topic0 - 0x973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b133 - ['SetFeeProtocol']: [16988973], - // // topic0 - 0x70935338e69775456a85ddef226c395fb668b63fa0115f5f20610b388e6ca9c0 - ['Collect']: [17259974], - }, - }; - - beforeEach(async () => { - sushiswapV3Pool = new SushiswapV3EventPool( - dexHelper, - dexKey, - new dexHelper.web3Provider.eth.Contract( - StateMulticallABI as AbiItem[], - stateMulticall, - ), - new Interface(ERC20ABI), - factory, - poolFeeCode, - token0, - token1, - logger, - undefined, - initCodeHash, - ); - }); - - Object.entries(eventsToTest).forEach( - ([poolAddress, events]: [string, EventMappings]) => { - describe(`Events for ${poolAddress}`, () => { - Object.entries(events).forEach( - ([eventName, blockNumbers]: [string, number[]]) => { - describe(`${eventName}`, () => { - blockNumbers.forEach((blockNumber: number) => { - it(`State after ${blockNumber}`, async function () { - await testEventSubscriber( - sushiswapV3Pool, - [poolAddress], - (_blockNumber: number) => - fetchPoolState( - sushiswapV3Pool, - _blockNumber, - poolAddress, - ), - blockNumber, - `${dexKey}_${poolAddress}`, - dexHelper.provider, - ); - }); - }); - }); - }, - ); - }); - }, - ); -}); diff --git a/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts b/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts deleted file mode 100644 index 7be6e3cf0..000000000 --- a/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts +++ /dev/null @@ -1,378 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); - -import { Interface, Result } from '@ethersproject/abi'; -import { DummyDexHelper } from '../../dex-helper/index'; -import { Network, SwapSide } from '../../constants'; -import { BI_POWS } from '../../bigint-constants'; -import { SushiswapV3 } from './sushiswap-v3'; -import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; -import { Tokens } from '../../../tests/constants-e2e'; -import { Address } from '../../types'; -import { - QuoteExactInputSingleParams, - QuoteExactOutputSingleParams, -} from './types'; - -function getQuoterV2Params( - funcName: string, - tokenIn: Address, - tokenOut: Address, - amount: bigint, - fee: bigint, -): QuoteExactInputSingleParams | QuoteExactOutputSingleParams { - return funcName === 'quoteExactInputSingle' - ? { tokenIn, tokenOut, fee, sqrtPriceLimitX96: 0n, amountIn: amount } - : { tokenIn, tokenOut, fee, sqrtPriceLimitX96: 0n, amount }; -} - -function getReaderCalldata( - exchangeAddress: string, - readerIface: Interface, - amounts: bigint[], - funcName: string, - tokenIn: Address, - tokenOut: Address, - fee: bigint, -) { - return amounts.map(amount => ({ - target: exchangeAddress, - callData: readerIface.encodeFunctionData(funcName, [ - getQuoterV2Params(funcName, tokenIn, tokenOut, amount, fee), - ]), - })); -} - -function decodeReaderResult( - results: Result, - readerIface: Interface, - funcName: string, -) { - return results.map(result => { - const parsed = readerIface.decodeFunctionResult(funcName, result); - return BigInt(parsed[0]._hex); - }); -} - -async function checkOnChainPricing( - sushiswapV3: SushiswapV3, - funcName: string, - blockNumber: number, - prices: bigint[], - tokenIn: Address, - tokenOut: Address, - fee: bigint, - amounts: bigint[], -) { - const quoterAddress = sushiswapV3.config.quoter; - const readerIface = sushiswapV3.quoterIface; - - const sum = prices.reduce((acc, curr) => (acc += curr), 0n); - - if (sum === 0n) { - console.log( - `Prices were not calculated for tokenIn=${tokenIn}, tokenOut=${tokenOut}, fee=${fee.toString()}. Most likely price impact is too big for requested amount`, - ); - return false; - } - - const readerCallData = getReaderCalldata( - quoterAddress, - readerIface, - amounts.slice(1), - funcName, - tokenIn, - tokenOut, - fee, - ); - - let readerResult; - try { - readerResult = ( - await sushiswapV3.dexHelper.multiContract.methods - .aggregate(readerCallData) - .call({}, blockNumber) - ).returnData; - } catch (e) { - console.log( - `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, - e, - ); - return false; - } - - const expectedPrices = [0n].concat( - decodeReaderResult(readerResult, readerIface, funcName), - ); - - let firstZeroIndex = prices.slice(1).indexOf(0n); - - // we skipped first, so add +1 on result - firstZeroIndex = firstZeroIndex === -1 ? prices.length : firstZeroIndex; - - // Compare only the ones for which we were able to calculate prices - expect(prices.slice(0, firstZeroIndex)).toEqual( - expectedPrices.slice(0, firstZeroIndex), - ); - return true; -} - -async function testPricingOnNetwork( - sushiswapV3: SushiswapV3, - network: Network, - dexKey: string, - blockNumber: number, - srcTokenSymbol: string, - destTokenSymbol: string, - side: SwapSide, - amounts: bigint[], -) { - const networkTokens = Tokens[network]; - - const pools = await sushiswapV3.getPoolIdentifiers( - networkTokens[srcTokenSymbol], - networkTokens[destTokenSymbol], - side, - blockNumber, - ); - console.log( - `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `, - pools, - ); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await sushiswapV3.getPricesVolume( - networkTokens[srcTokenSymbol], - networkTokens[destTokenSymbol], - amounts, - side, - blockNumber, - pools, - ); - console.log( - `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `, - poolPrices, - ); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices( - poolPrices!.filter(poolPrice => - poolPrice.prices.slice(1).every(price => price > 0), - ), - amounts, - side, - dexKey, - ); - - // Check if onchain pricing equals to calculated ones - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = sushiswapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - sushiswapV3, - side === SwapSide.SELL - ? 'quoteExactInputSingle' - : 'quoteExactOutputSingle', - blockNumber, - price.prices, - networkTokens[srcTokenSymbol].address, - networkTokens[destTokenSymbol].address, - fee, - amounts, - ); - if (res === false) falseChecksCounter++; - }), - ); - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); -} - -describe('SushiswapV3', function () { - const dexKey = 'SushiswapV3'; - let blockNumber: number; - let sushiswapV3: SushiswapV3; - - describe('Mainnet', () => { - const network = Network.MAINNET; - const dexHelper = new DummyDexHelper(network); - - const tokens = Tokens[network]; - - const srcTokenSymbol = 'USDC'; - const destTokenSymbol = 'WETH'; - - const amountsForSell = [ - 0n, - 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - 10n * BI_POWS[tokens[srcTokenSymbol].decimals], - ]; - - const amountsForBuy = [ - 0n, - 1n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 2n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 3n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 4n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 5n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 6n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 7n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 8n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 9n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 10n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - ]; - - beforeAll(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - sushiswapV3 = new SushiswapV3(network, dexKey, dexHelper); - if (sushiswapV3.initializePricing) { - await sushiswapV3.initializePricing(blockNumber); - } - }); - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - await testPricingOnNetwork( - sushiswapV3, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.SELL, - amountsForSell, - ); - }); - - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - await testPricingOnNetwork( - sushiswapV3, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.BUY, - amountsForBuy, - ); - }); - - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - const newSushiswapV3 = new SushiswapV3(network, dexKey, dexHelper); - const poolLiquidity = await newSushiswapV3.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, - ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - - if (!newSushiswapV3.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, - dexKey, - ); - } - }); - }); - - describe('Arbitrum', () => { - const network = Network.ARBITRUM; - const dexHelper = new DummyDexHelper(network); - - const tokens = Tokens[network]; - - const srcTokenSymbol = 'USDC'; - const destTokenSymbol = 'WETH'; - - const amountsForSell = [ - 0n, - 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - 10n * BI_POWS[tokens[srcTokenSymbol].decimals], - ]; - - const amountsForBuy = [ - 0n, - 1n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 2n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 3n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 4n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 5n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 6n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 7n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 8n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 9n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - 10n * BI_POWS[tokens[destTokenSymbol].decimals - 2], - ]; - - beforeAll(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - sushiswapV3 = new SushiswapV3(network, dexKey, dexHelper); - if (sushiswapV3.initializePricing) { - await sushiswapV3.initializePricing(blockNumber); - } - }); - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - await testPricingOnNetwork( - sushiswapV3, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.SELL, - amountsForSell, - ); - }); - - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - await testPricingOnNetwork( - sushiswapV3, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.BUY, - amountsForBuy, - ); - }); - - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - const newSushiswapV3 = new SushiswapV3(network, dexKey, dexHelper); - const poolLiquidity = await newSushiswapV3.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, - ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - - if (!newSushiswapV3.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, - dexKey, - ); - } - }); - }); -}); diff --git a/src/dex/sushiswap-v3/sushiswap-v3-pool.ts b/src/dex/sushiswap-v3/sushiswap-v3-pool.ts deleted file mode 100644 index d3e853d6e..000000000 --- a/src/dex/sushiswap-v3/sushiswap-v3-pool.ts +++ /dev/null @@ -1 +0,0 @@ -export { UniswapV3EventPool as SushiswapV3EventPool } from '../uniswap-v3/uniswap-v3-pool'; diff --git a/src/dex/sushiswap-v3/sushiswap-v3.ts b/src/dex/sushiswap-v3/sushiswap-v3.ts deleted file mode 100644 index 19ef285d4..000000000 --- a/src/dex/sushiswap-v3/sushiswap-v3.ts +++ /dev/null @@ -1,1017 +0,0 @@ -import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; -import { - Token, - Address, - ExchangePrices, - PoolPrices, - AdapterExchangeParam, - SimpleExchangeParam, - PoolLiquidity, - Logger, - NumberAsString, -} from '../../types'; -import { SwapSide, Network, CACHE_PREFIX } from '../../constants'; -import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { - getBigIntPow, - getDexKeysWithNetwork, - interpolate, - isTruthy, -} from '../../utils'; -import { IDex } from '../../dex/idex'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { - DexParams, - OutputResult, - PoolState, - QuoteExactInputSingleParams, - QuoteExactOutputSingleParams, - UniswapV3Data as SushiswapV3Data, -} from './types'; -import { - SimpleExchange, - getLocalDeadlineAsFriendlyPlaceholder, -} from '../simple-exchange'; -import { SushiswapV3Config, Adapters } from './config'; -import { SushiswapV3EventPool } from './sushiswap-v3-pool'; -import { Interface, defaultAbiCoder } from 'ethers/lib/utils'; -import { AbiItem } from 'web3-utils'; -import { Contract } from 'web3-eth-contract'; -import { pack } from '@ethersproject/solidity'; -import { - UNISWAPV3_EFFICIENCY_FACTOR, - UNISWAPV3_POOL_SEARCH_OVERHEAD, - UNISWAPV3_TICK_BASE_OVERHEAD, - UNISWAPV3_TICK_GAS_COST, - ViemChain, -} from './constants'; -import { uniswapV3Math } from '../uniswap-v3/contract-math/uniswap-v3-math'; -import { BalanceRequest, getBalances } from '../../lib/tokens/balancer-fetcher'; -import { - AssetType, - DEFAULT_ID_ERC20, - DEFAULT_ID_ERC20_AS_STRING, -} from '../../lib/tokens/types'; -import { DataFetcher, LiquidityProviders, Router } from '@sushiswap/router'; -import { ChainId } from '@sushiswap/chain'; -import { createPublicClient, http } from 'viem'; - -import SushiswapV3RouterABI from '../../abi/sushiswap-v3/RouterProcessor3.json'; -import SushiswapV3QuoterV2ABI from '../../abi/sushiswap-v3/QuoterV2.json'; -import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; -import UniswapV3StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; -import { generateConfig } from '../../config'; -import { BigNumber } from 'ethers'; -import { getToken } from './token'; -import _ from 'lodash'; -import { UniswapV3Config } from '../uniswap-v3/config'; - -const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 60 * 60 * 24 * 1000; // 24 hours -const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 30 * 60 * 1000; // Once in 30 minutes -const UNISWAPV3_QUOTE_GASLIMIT = 200_000; - -export class SushiswapV3 - extends SimpleExchange - implements IDex -{ - readonly eventPools: Record = {}; - - readonly hasConstantPriceLargeAmounts = false; - readonly needWrapNative = true; - - intervalTask?: NodeJS.Timeout; - - readonly isFeeOnTransferSupported = false; - - public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(SushiswapV3Config); - - logger: Logger; - - private uniswapMulti: Contract; - private stateMultiContract: Contract; - - private notExistingPoolSetKey: string; - - constructor( - readonly network: Network, - readonly dexKey: string, - readonly dexHelper: IDexHelper, - protected adapters = Adapters[network] || {}, - readonly routerIface = new Interface(SushiswapV3RouterABI), - readonly quoterIface = new Interface(SushiswapV3QuoterV2ABI), - readonly config = SushiswapV3Config[dexKey][network], - ) { - super(dexHelper, dexKey); - this.logger = dexHelper.getLogger(dexKey + '-' + network); - - this.uniswapMulti = new this.dexHelper.web3Provider.eth.Contract( - UniswapV3MultiABI as AbiItem[], - this.config.uniswapMulticall, - ); - this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( - UniswapV3StateMulticallABI as AbiItem[], - this.config.stateMulticall, - ); - - // To receive revert reasons - this.dexHelper.web3Provider.eth.handleRevert = false; - - // Normalise once all config addresses and use across all scenarios - this.config = this._toLowerForAllConfigAddresses(); - - this.notExistingPoolSetKey = - `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); - } - - // Initialize pricing is called once in the start of - // pricing service. It is intended to setup the integration - // for pricing requests. It is optional for a DEX to - // implement this function - async initializePricing(blockNumber: number) { - if (!this.dexHelper.config.isSlave) { - const cleanExpiredNotExistingPoolsKeys = async () => { - const maxTimestamp = - Date.now() - UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS; - await this.dexHelper.cache.zremrangebyscore( - this.notExistingPoolSetKey, - 0, - maxTimestamp, - ); - }; - - this.intervalTask = setInterval( - cleanExpiredNotExistingPoolsKeys.bind(this), - UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS, - ); - } - } - - get supportedFees() { - return this.config.supportedFees; - } - - // Returns the list of contract adapters (name and index) - // for a buy/sell. Return null if there are no adapters. - getAdapters(side: SwapSide): { name: string; index: number }[] | null { - return this.adapters[side] ? this.adapters[side] : null; - } - - getPoolIdentifier(srcAddress: Address, destAddress: Address, fee: bigint) { - const tokenAddresses = this._sortTokens(srcAddress, destAddress).join('_'); - return `${this.dexKey}_${tokenAddresses}_${fee}`; - } - - // Returns pool prices for amounts. - // If limitPools is defined only pools in limitPools - // should be used. If limitPools is undefined then - // any pools can be used. - async getPricesVolume( - srcToken: Token, - destToken: Token, - amounts: bigint[], - side: SwapSide, - blockNumber: number, - limitPools?: string[], - ): Promise> { - try { - const _srcToken = this.dexHelper.config.wrapETH(srcToken); - const _destToken = this.dexHelper.config.wrapETH(destToken); - - const [_srcAddress, _destAddress] = this._getLoweredAddresses( - _srcToken, - _destToken, - ); - - if (_srcAddress === _destAddress) return null; - - let selectedPools: SushiswapV3EventPool[] = []; - - if (!limitPools) { - selectedPools = ( - await Promise.all( - this.supportedFees.map(async fee => { - const locallyFoundPool = - this.eventPools[ - this.getPoolIdentifier(_srcAddress, _destAddress, fee) - ]; - if (locallyFoundPool) return locallyFoundPool; - - const newlyFetchedPool = await this.getPool( - _srcAddress, - _destAddress, - fee, - blockNumber, - ); - return newlyFetchedPool; - }), - ) - ).filter(isTruthy); - } else { - const pairIdentifierWithoutFee = this.getPoolIdentifier( - _srcAddress, - _destAddress, - 0n, - // Trim from 0 fee postfix, so it become comparable - ).slice(0, -1); - - const poolIdentifiers = limitPools.filter(identifier => - identifier.startsWith(pairIdentifierWithoutFee), - ); - - selectedPools = ( - await Promise.all( - poolIdentifiers.map(async identifier => { - let locallyFoundPool = this.eventPools[identifier]; - if (locallyFoundPool) return locallyFoundPool; - - const [, srcAddress, destAddress, fee] = identifier.split('_'); - const newlyFetchedPool = await this.getPool( - srcAddress, - destAddress, - BigInt(fee), - blockNumber, - ); - return newlyFetchedPool; - }), - ) - ).filter(isTruthy); - } - - if (selectedPools.length === 0) return null; - - const poolsToUse = selectedPools.reduce( - (acc, pool) => { - let state = pool.getState(blockNumber); - if (state === null) { - this.logger.trace( - `${this.dexKey}: State === null. Fallback to rpc ${pool.name}`, - ); - acc.poolWithoutState.push(pool); - } else { - acc.poolWithState.push(pool); - } - return acc; - }, - { - poolWithState: [] as SushiswapV3EventPool[], - poolWithoutState: [] as SushiswapV3EventPool[], - }, - ); - - const rpcResultsPromise = this.getPricingFromRpc( - _srcToken, - _destToken, - amounts, - side, - poolsToUse.poolWithoutState, - ); - - const states = poolsToUse.poolWithState.map( - p => p.getState(blockNumber)!, - ); - - const unitAmount = getBigIntPow( - side == SwapSide.SELL ? _srcToken.decimals : _destToken.decimals, - ); - - const _amounts = [...amounts.slice(1)]; - - const [token0] = this._sortTokens(_srcAddress, _destAddress); - - const zeroForOne = token0 === _srcAddress ? true : false; - - const result = await Promise.all( - poolsToUse.poolWithState.map(async (pool, i) => { - const state = states[i]; - - if (state.liquidity <= 0n) { - this.logger.trace(`pool have 0 liquidity`); - return null; - } - - const balanceDestToken = - _destAddress === pool.token0 ? state.balance0 : state.balance1; - - const unitResult = this._getOutputs( - state, - [unitAmount], - zeroForOne, - side, - balanceDestToken, - ); - const pricesResult = this._getOutputs( - state, - _amounts, - zeroForOne, - side, - balanceDestToken, - ); - - if (!unitResult || !pricesResult) { - this.logger.debug('Prices or unit is not calculated'); - return null; - } - - const prices = [0n, ...pricesResult.outputs]; - const gasCost = [ - 0, - ...pricesResult.outputs.map((p, index) => { - if (p == 0n) { - return 0; - } else { - return ( - UNISWAPV3_POOL_SEARCH_OVERHEAD + - UNISWAPV3_TICK_BASE_OVERHEAD + - pricesResult.tickCounts[index] * UNISWAPV3_TICK_GAS_COST - ); - } - }), - ]; - return { - unit: unitResult.outputs[0], - prices, - data: { - path: [ - { - tokenIn: _srcAddress, - tokenOut: _destAddress, - fee: pool.feeCode.toString(), - }, - ], - }, - poolIdentifier: this.getPoolIdentifier( - pool.token0, - pool.token1, - pool.feeCode, - ), - exchange: this.dexKey, - gasCost: gasCost, - poolAddresses: [pool.poolAddress], - }; - }), - ); - const rpcResults = await rpcResultsPromise; - - const notNullResult = result.filter( - res => res !== null, - ) as ExchangePrices; - - if (rpcResults) { - rpcResults.forEach(r => { - if (r) { - notNullResult.push(r); - } - }); - } - - return notNullResult; - } catch (e) { - this.logger.error( - `Error_getPricesVolume ${srcToken.symbol || srcToken.address}, ${ - destToken.symbol || destToken.address - }, ${side}:`, - e, - ); - return null; - } - } - - private getQuoterV2CallData( - funcName: string, - tokenIn: Address, - tokenOut: Address, - amount: bigint, - fee: bigint, - ): QuoteExactInputSingleParams | QuoteExactOutputSingleParams { - return funcName === 'quoteExactInputSingle' - ? { tokenIn, tokenOut, fee, sqrtPriceLimitX96: 0n, amountIn: amount } - : { tokenIn, tokenOut, fee, sqrtPriceLimitX96: 0n, amount }; - } - - async getPricingFromRpc( - from: Token, - to: Token, - amounts: bigint[], - side: SwapSide, - pools: SushiswapV3EventPool[], - ): Promise | null> { - if (pools.length === 0) { - return null; - } - this.logger.warn(`fallback to rpc for ${pools.length} pool(s)`); - - const requests = pools.map( - pool => ({ - owner: pool.poolAddress, - asset: side == SwapSide.SELL ? from.address : to.address, - assetType: AssetType.ERC20, - ids: [ - { - id: DEFAULT_ID_ERC20, - spenders: [], - }, - ], - }), - [], - ); - - const balances = await getBalances(this.dexHelper.multiWrapper, requests); - - pools = pools.filter((pool, index) => { - const balance = balances[index].amounts[DEFAULT_ID_ERC20_AS_STRING]; - if (balance >= amounts[amounts.length - 1]) { - return true; - } - this.logger.warn( - `[${this.network}][${pool.parentName}] have no balance ${pool.poolAddress} ${from.address} ${to.address}. (Balance: ${balance})`, - ); - return false; - }); - - pools.forEach(pool => { - this.logger.warn( - `[${this.network}][${pool.parentName}] fallback to rpc for ${pool.name}`, - ); - }); - - const unitVolume = getBigIntPow( - (side === SwapSide.SELL ? from : to).decimals, - ); - - const chunks = amounts.length - 1; - - const _width = Math.floor(chunks / this.config.chunksCount); - - const _amounts = [unitVolume].concat( - Array.from(Array(this.config.chunksCount).keys()).map( - i => amounts[(i + 1) * _width], - ), - ); - - const funcName = - side === SwapSide.SELL - ? 'quoteExactInputSingle' - : 'quoteExactOutputSingle'; - - const calldata = pools.map(pool => - _amounts.map(_amount => ({ - target: this.config.quoter, - gasLimit: UNISWAPV3_QUOTE_GASLIMIT, - callData: this.quoterIface.encodeFunctionData(funcName, [ - this.getQuoterV2CallData( - funcName, - from.address, - to.address, - _amount, - pool.feeCode, - ), - ]), - })), - ); - - const data = await new this.dexHelper.web3Provider.eth.Contract( - UniswapV3MultiABI as AbiItem[], - this.config.uniswapMulticall, - ).methods - .multicall(calldata.flat()) - .call(); - - const decode = (j: number): bigint => { - if (!data.returnData[j].success) { - return 0n; - } - const decoded = defaultAbiCoder.decode( - ['uint256'], - data.returnData[j].returnData, - ); - return BigInt(decoded[0].toString()); - }; - - let i = 0; - const result = pools.map(pool => { - const _rates = _amounts.map(() => decode(i++)); - const unit: bigint = _rates[0]; - - const prices = interpolate( - _amounts.slice(1), - _rates.slice(1), - amounts, - side, - ); - - return { - prices, - unit, - data: { - path: [ - { - tokenIn: from.address, - tokenOut: to.address, - fee: pool.feeCodeAsString, - }, - ], - }, - poolIdentifier: this.getPoolIdentifier( - pool.token0, - pool.token1, - pool.feeCode, - ), - exchange: this.dexKey, - gasCost: prices.map(p => (p === 0n ? 0 : UNISWAPV3_QUOTE_GASLIMIT)), - poolAddresses: [pool.poolAddress], - }; - }); - - return result; - } - - // Returns estimated gas cost of calldata for this DEX in multiSwap - getCalldataGasCost( - poolPrices: PoolPrices, - ): number | number[] { - const gasCost = - CALLDATA_GAS_COST.DEX_OVERHEAD + - CALLDATA_GAS_COST.LENGTH_SMALL + - // ParentStruct header - CALLDATA_GAS_COST.OFFSET_SMALL + - // ParentStruct -> path header - CALLDATA_GAS_COST.OFFSET_SMALL + - // ParentStruct -> deadline - CALLDATA_GAS_COST.TIMESTAMP + - // ParentStruct -> path (20+3+20 = 43 = 32+11 bytes) - CALLDATA_GAS_COST.LENGTH_SMALL + - CALLDATA_GAS_COST.FULL_WORD + - CALLDATA_GAS_COST.wordNonZeroBytes(11); - const arr = new Array(poolPrices.prices.length); - poolPrices.prices.forEach((p, index) => { - if (p == 0n) { - arr[index] = 0; - } else { - arr[index] = gasCost; - } - }); - return arr; - } - - // Encode params required by the exchange adapter - // Used for multiSwap, buy & megaSwap - getAdapterParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, - data: SushiswapV3Data, - side: SwapSide, - ): AdapterExchangeParam { - const { path: rawPath } = data; - const path = this._encodePath(rawPath, side); - - const payload = this.abiCoder.encodeParameter( - { - ParentStruct: { - path: 'bytes', - deadline: 'uint256', - }, - }, - { - path, - deadline: getLocalDeadlineAsFriendlyPlaceholder(), // FIXME: more gas efficient to pass block.timestamp in adapter - }, - ); - - return { - targetExchange: UniswapV3Config['UniswapV3'][this.network].router, - payload, - networkFee: '0', - }; - } - - // Encode call data used by simpleSwap like routers - // Used for simpleSwap & simpleBuy - async getSimpleParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, - data: SushiswapV3Data, - ): Promise { - const web3Client = createPublicClient({ - chain: ViemChain[this.network], - transport: http(generateConfig(this.network).privateHttpProvider), - }); - - const dataFetcher = new DataFetcher( - web3Client.chain.id as ChainId, - web3Client, - ); - - dataFetcher.startDataFetching([LiquidityProviders.SushiSwapV3]); - - const fromToken = await getToken({ web3Client, address: srcToken }); - - const toToken = await getToken({ web3Client, address: destToken }); - - await dataFetcher.fetchPoolsForToken(fromToken, toToken); - - const pcMap = dataFetcher.getCurrentPoolCodeMap(fromToken, toToken); - - const route = Router.findBestRoute( - pcMap, - this.network as unknown as ChainId, - fromToken, - BigNumber.from(srcAmount), - toToken, - 50e9, - [LiquidityProviders.SushiSwapV3], - ); - - const rpParams = Router.routeProcessor2Params( - pcMap, - route, - fromToken, - toToken, - this.augustusAddress, - this.config.router, - ); - - const swapData = this.routerIface.encodeFunctionData('processRoute', [ - rpParams.tokenIn, - rpParams.amountIn, - rpParams.tokenOut, - rpParams.amountOutMin, - rpParams.to, - rpParams.routeCode, - ]); - - dataFetcher.stopDataFetching(); - - return this.buildSimpleParamWithoutWETHConversion( - srcToken, - srcAmount, - destToken, - destAmount, - swapData, - this.config.router, - ); - } - - async getTopPoolsForToken( - tokenAddress: Address, - limit: number, - ): Promise { - const _tokenAddress = tokenAddress.toLowerCase(); - - const res = await this._querySubgraph( - `query ($token: Bytes!, $count: Int) { - pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token}) { - id - token0 { - id - decimals - } - token1 { - id - decimals - } - totalValueLockedUSD - } - pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token}) { - id - token0 { - id - decimals - } - token1 { - id - decimals - } - totalValueLockedUSD - } - }`, - { - token: _tokenAddress, - count: limit, - }, - ); - - if (!(res && res.pools0 && res.pools1)) { - this.logger.error( - `Error_${this.dexKey}_Subgraph: couldn't fetch the pools from the subgraph`, - ); - return []; - } - - const pools0 = _.map(res.pools0, pool => ({ - exchange: this.dexKey, - address: pool.id.toLowerCase(), - connectorTokens: [ - { - address: pool.token1.id.toLowerCase(), - decimals: parseInt(pool.token1.decimals), - }, - ], - liquidityUSD: - parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, - })); - - const pools1 = _.map(res.pools1, pool => ({ - exchange: this.dexKey, - address: pool.id.toLowerCase(), - connectorTokens: [ - { - address: pool.token0.id.toLowerCase(), - decimals: parseInt(pool.token0.decimals), - }, - ], - liquidityUSD: - parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, - })); - - const pools = _.slice( - _.sortBy(_.concat(pools0, pools1), [pool => -1 * pool.liquidityUSD]), - 0, - limit, - ); - return pools; - } - - private _encodePath( - path: { - tokenIn: Address; - tokenOut: Address; - fee: NumberAsString; - }[], - side: SwapSide, - ): string { - if (path.length === 0) { - this.logger.error( - `${this.dexKey}: Received invalid path=${path} for side=${side} to encode`, - ); - return '0x'; - } - - const { _path, types } = path.reduce( - ( - { _path, types }: { _path: string[]; types: string[] }, - curr, - index, - ): { _path: string[]; types: string[] } => { - if (index === 0) { - return { - types: ['address', 'uint24', 'address'], - _path: [curr.tokenIn, curr.fee, curr.tokenOut], - }; - } else { - return { - types: [...types, 'uint24', 'address'], - _path: [..._path, curr.fee, curr.tokenOut], - }; - } - }, - { _path: [], types: [] }, - ); - - return side === SwapSide.BUY - ? pack(types.reverse(), _path.reverse()) - : pack(types, _path); - } - - async getPoolIdentifiers( - srcToken: Token, - destToken: Token, - side: SwapSide, - blockNumber: number, - ): Promise { - const _srcToken = this.dexHelper.config.wrapETH(srcToken); - const _destToken = this.dexHelper.config.wrapETH(destToken); - - const [_srcAddress, _destAddress] = this._getLoweredAddresses( - _srcToken, - _destToken, - ); - - if (_srcAddress === _destAddress) return []; - - const pools = ( - await Promise.all( - this.supportedFees.map(async fee => - this.getPool(_srcAddress, _destAddress, fee, blockNumber), - ), - ) - ).filter(pool => pool); - - if (pools.length === 0) return []; - - return pools.map(pool => - this.getPoolIdentifier(_srcAddress, _destAddress, pool!.feeCode), - ); - } - - async getPool( - srcAddress: Address, - destAddress: Address, - fee: bigint, - blockNumber: number, - ): Promise { - let pool = - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)]; - - if (pool === undefined) { - const [token0, token1] = this._sortTokens(srcAddress, destAddress); - - const key = `${token0}_${token1}_${fee}`.toLowerCase(); - - const notExistingPoolScore = await this.dexHelper.cache.zscore( - this.notExistingPoolSetKey, - key, - ); - - const poolDoesNotExist = notExistingPoolScore !== null; - - if (poolDoesNotExist) { - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - null; - return null; - } - - await this.dexHelper.cache.hset( - this.dexmapKey, - key, - JSON.stringify({ - token0, - token1, - fee: fee.toString(), - }), - ); - - this.logger.trace(`starting to listen to new pool: ${key}`); - pool = new SushiswapV3EventPool( - this.dexHelper, - this.dexKey, - this.stateMultiContract, - this.erc20Interface, - this.config.factory, - fee, - token0, - token1, - this.logger, - this.cacheStateKey, - this.config.initHash, - ); - - try { - await pool.initialize(blockNumber, { - initCallback: (state: DeepReadonly) => { - //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber - pool!.addressesSubscribed[0] = state.pool; - pool!.poolAddress = state.pool; - }, - }); - } catch (e) { - if (e instanceof Error && e.message.endsWith('Pool does not exist')) { - // no need to await we want the set to have the pool key but it's not blocking - this.dexHelper.cache.zadd( - this.notExistingPoolSetKey, - [Date.now(), key], - 'NX', - ); - - // Pool does not exist for this feeCode, so we can set it to null - // to prevent more requests for this pool - pool = null; - this.logger.trace( - `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, - e, - ); - } else { - // Unexpected Error. Break execution. Do not save the pool in this.eventPools - this.logger.error( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool`, - e, - ); - throw new Error('Cannot generate pool state'); - } - } - - if (pool !== null) { - const allEventPools = Object.values(this.eventPools); - this.logger.info( - `starting to listen to new non-null pool: ${key}. Already following ${allEventPools - // Not that I like this reduce, but since it is done only on initialization, expect this to be ok - .reduce( - (acc, curr) => (curr !== null ? ++acc : acc), - 0, - )} non-null pools or ${allEventPools.length} total pools`, - ); - } - - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - pool; - } - return pool; - } - - private _getLoweredAddresses(srcToken: Token, destToken: Token) { - return [srcToken.address.toLowerCase(), destToken.address.toLowerCase()]; - } - - private _sortTokens(srcAddress: Address, destAddress: Address) { - return [srcAddress, destAddress].sort((a, b) => (a < b ? -1 : 1)); - } - - private _toLowerForAllConfigAddresses() { - // If new config property will be added, the TS will throw compile error - const newConfig: DexParams = { - router: this.config.router.toLowerCase(), - quoter: this.config.quoter.toLowerCase(), - factory: this.config.factory.toLowerCase(), - supportedFees: this.config.supportedFees, - stateMulticall: this.config.stateMulticall.toLowerCase(), - chunksCount: this.config.chunksCount, - uniswapMulticall: this.config.uniswapMulticall, - deployer: this.config.deployer?.toLowerCase(), - initHash: this.config.initHash, - subgraphURL: this.config.subgraphURL, - }; - return newConfig; - } - - private async _querySubgraph( - query: string, - variables: Object, - timeout = 30000, - ) { - try { - const res = await this.dexHelper.httpRequest.post( - this.config.subgraphURL, - { query, variables }, - undefined, - { timeout: timeout }, - ); - return res.data; - } catch (e) { - this.logger.error(`${this.dexKey}: can not query subgraph: `, e); - return {}; - } - } - - private _getOutputs( - state: DeepReadonly, - amounts: bigint[], - zeroForOne: boolean, - side: SwapSide, - destTokenBalance: bigint, - ): OutputResult | null { - try { - const outputsResult = uniswapV3Math.queryOutputs( - state, - amounts, - zeroForOne, - side, - ); - - if (side === SwapSide.SELL) { - if (outputsResult.outputs[0] > destTokenBalance) { - return null; - } - - for (let i = 0; i < outputsResult.outputs.length; i++) { - if (outputsResult.outputs[i] > destTokenBalance) { - outputsResult.outputs[i] = 0n; - outputsResult.tickCounts[i] = 0; - } - } - } else { - if (amounts[0] > destTokenBalance) { - return null; - } - - // This may be improved by first checking outputs and requesting outputs - // only for amounts that makes more sense, but I don't think this is really - // important now - for (let i = 0; i < amounts.length; i++) { - if (amounts[i] > destTokenBalance) { - outputsResult.outputs[i] = 0n; - outputsResult.tickCounts[i] = 0; - } - } - } - - return outputsResult; - } catch (e) { - this.logger.debug( - `${this.dexKey}: received error in _getOutputs while calculating outputs`, - e, - ); - return null; - } - } - - releaseResources(): AsyncOrSync { - if (this.intervalTask !== undefined) { - clearInterval(this.intervalTask); - this.intervalTask = undefined; - } - } -} diff --git a/src/dex/sushiswap-v3/token.ts b/src/dex/sushiswap-v3/token.ts deleted file mode 100644 index 2e22b7176..000000000 --- a/src/dex/sushiswap-v3/token.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { PublicClient, Address, Transport, Chain } from 'viem'; -import { Token } from '@sushiswap/currency'; - -import ERC20Abi from '../../abi/erc20.json'; - -export async function getToken({ - web3Client, - address, -}: { - web3Client: PublicClient; - address: string; -}) { - const decimals: number = (await web3Client.readContract({ - address: address as Address, - abi: ERC20Abi, - functionName: 'decimals', - args: [], - })) as unknown as number; - - return new Token({ - address, - chainId: web3Client.chain.id, - decimals, - }); -} diff --git a/src/dex/sushiswap-v3/types.ts b/src/dex/sushiswap-v3/types.ts deleted file mode 100644 index e61e91b34..000000000 --- a/src/dex/sushiswap-v3/types.ts +++ /dev/null @@ -1,17 +0,0 @@ -export * from '../uniswap-v3/types'; - -export type QuoteExactInputSingleParams = { - tokenIn: string; - tokenOut: string; - amountIn: bigint; - fee: bigint; - sqrtPriceLimitX96: bigint; -}; - -export type QuoteExactOutputSingleParams = { - tokenIn: string; - tokenOut: string; - amount: bigint; - fee: bigint; - sqrtPriceLimitX96: bigint; -}; diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index 6df249331..4583a2bbf 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -746,3 +746,138 @@ describe('ChronosV3', () => { checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); }); }); + +describe('SushiSwapV3', () => { + const dexKey = 'SushiSwapV3'; + let blockNumber: number; + let uniswapV3: UniswapV3; + let uniswapV3Mainnet: UniswapV3; + + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + const TokenASymbol = 'USDC'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDT'; + const TokenB = Tokens[network][TokenBSymbol]; + + beforeEach(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + uniswapV3 = new UniswapV3(network, dexKey, dexHelper); + uniswapV3Mainnet = new UniswapV3( + Network.ARBITRUM, + dexKey, + dexHelper, + ); + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + + const amounts = [0n, BI_POWS[6], 2000000n]; + + const pools = await uniswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await uniswapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + uniswapV3, + 'quoteExactInputSingle', + blockNumber, + '0x64e8802FE490fa7cc61d3463958199161Bb608A7', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + + const amounts = [0n, BI_POWS[6], 2000000n]; + + const pools = await uniswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await uniswapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + uniswapV3, + 'quoteExactOutputSingle', + blockNumber, + '0x64e8802FE490fa7cc61d3463958199161Bb608A7', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getTopPoolsForToken', async function () { + const poolLiquidity = await uniswapV3.getTopPoolsForToken( + TokenB.address, + 10, + ); + console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); + }); +}); diff --git a/yarn.lock b/yarn.lock index 3c30397f0..eb77e24a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -41,11 +41,6 @@ js-sha3 "^0.7.0" lodash "^4.17.11" -"@adraffy/ens-normalize@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.9.0.tgz#223572538f6bea336750039bb43a4016dcc8182d" - integrity sha512-iowxq3U30sghZotgl4s/oJRci6WPBfNO5YYgk2cIOMCHr3LeGPcsZjCEr+33Q4N+oV3OABDAtA+pyvWjbvBifQ== - "@ampproject/remapping@^2.1.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" @@ -336,57 +331,11 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" -"@balena/dockerignore@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" - integrity sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q== - "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@chainsafe/as-sha256@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz#3639df0e1435cab03f4d9870cc3ac079e57a6fc9" - integrity sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg== - -"@chainsafe/persistent-merkle-tree@^0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz#4c9ee80cc57cd3be7208d98c40014ad38f36f7ff" - integrity sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - -"@chainsafe/persistent-merkle-tree@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz#2b4a62c9489a5739dedd197250d8d2f5427e9f63" - integrity sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - -"@chainsafe/ssz@^0.10.0": - version "0.10.2" - resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.10.2.tgz#c782929e1bb25fec66ba72e75934b31fd087579e" - integrity sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - "@chainsafe/persistent-merkle-tree" "^0.5.0" - -"@chainsafe/ssz@^0.9.2": - version "0.9.4" - resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.9.4.tgz#696a8db46d6975b600f8309ad3a12f7c0e310497" - integrity sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - "@chainsafe/persistent-merkle-tree" "^0.4.2" - case "^1.6.3" - -"@colors/colors@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" - integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== - "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -394,22 +343,6 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@ensdomains/ens@^0.4.4": - version "0.4.5" - resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" - integrity sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw== - dependencies: - bluebird "^3.5.2" - eth-ens-namehash "^2.0.8" - solc "^0.4.20" - testrpc "0.0.1" - web3-utils "^1.0.0-beta.31" - -"@ensdomains/resolver@^0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" - integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== - "@eslint/eslintrc@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.0.tgz#8ec64e0df3e7a1971ee1ff5158da87389f167a63" @@ -479,59 +412,6 @@ merkletreejs "^0.2.27" rlp "^2.2.7" -"@ethereum-waffle/chai@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.4.tgz#16c4cc877df31b035d6d92486dfdf983df9138ff" - integrity sha512-/K8czydBtXXkcM9X6q29EqEkc5dN3oYenyH2a9hF7rGAApAJUpH8QBtojxOY/xQ2up5W332jqgxwp0yPiYug1g== - dependencies: - "@ethereum-waffle/provider" "^3.4.4" - ethers "^5.5.2" - -"@ethereum-waffle/compiler@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.4.tgz#d568ee0f6029e68b5c645506079fbf67d0dfcf19" - integrity sha512-RUK3axJ8IkD5xpWjWoJgyHclOeEzDLQFga6gKpeGxiS/zBu+HB0W2FvsrrLalTFIaPw/CGYACRBSIxqiCqwqTQ== - dependencies: - "@resolver-engine/imports" "^0.3.3" - "@resolver-engine/imports-fs" "^0.3.3" - "@typechain/ethers-v5" "^2.0.0" - "@types/mkdirp" "^0.5.2" - "@types/node-fetch" "^2.5.5" - ethers "^5.0.1" - mkdirp "^0.5.1" - node-fetch "^2.6.1" - solc "^0.6.3" - ts-generator "^0.1.1" - typechain "^3.0.0" - -"@ethereum-waffle/ens@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.4.4.tgz#db97ea2c9decbb70b9205d53de2ccbd6f3182ba1" - integrity sha512-0m4NdwWxliy3heBYva1Wr4WbJKLnwXizmy5FfSSr5PMbjI7SIGCdCB59U7/ZzY773/hY3bLnzLwvG5mggVjJWg== - dependencies: - "@ensdomains/ens" "^0.4.4" - "@ensdomains/resolver" "^0.2.4" - ethers "^5.5.2" - -"@ethereum-waffle/mock-contract@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.4.4.tgz#fc6ffa18813546f4950a69f5892d4dd54b2c685a" - integrity sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA== - dependencies: - "@ethersproject/abi" "^5.5.0" - ethers "^5.5.2" - -"@ethereum-waffle/provider@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.4.tgz#398fc1f7eb91cc2df7d011272eacba8af0c7fffb" - integrity sha512-GK8oKJAM8+PKy2nK08yDgl4A80mFuI8zBkE0C9GqTRYQqvuxIyXoLmJ5NZU9lIwyWVv5/KsoA11BgAv2jXE82g== - dependencies: - "@ethereum-waffle/ens" "^3.4.4" - ethers "^5.5.2" - ganache-core "^2.13.2" - patch-package "^6.2.2" - postinstall-postinstall "^2.1.0" - "@ethereumjs/common@^2.3.0", "@ethereumjs/common@^2.4.0", "@ethereumjs/common@^2.6.4": version "2.6.5" resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30" @@ -548,21 +428,6 @@ "@ethereumjs/common" "^2.6.4" ethereumjs-util "^7.1.5" -"@ethersproject/abi@5.0.0-beta.153": - version "5.0.0-beta.153" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" - integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg== - dependencies: - "@ethersproject/address" ">=5.0.0-beta.128" - "@ethersproject/bignumber" ">=5.0.0-beta.130" - "@ethersproject/bytes" ">=5.0.0-beta.129" - "@ethersproject/constants" ">=5.0.0-beta.128" - "@ethersproject/hash" ">=5.0.0-beta.128" - "@ethersproject/keccak256" ">=5.0.0-beta.127" - "@ethersproject/logger" ">=5.0.0-beta.129" - "@ethersproject/properties" ">=5.0.0-beta.131" - "@ethersproject/strings" ">=5.0.0-beta.130" - "@ethersproject/abi@5.0.7": version "5.0.7" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" @@ -578,7 +443,7 @@ "@ethersproject/properties" "^5.0.3" "@ethersproject/strings" "^5.0.4" -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.7.0": +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== @@ -617,7 +482,7 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/address@5.7.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.7.0": +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== @@ -643,7 +508,7 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.7.0": +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== @@ -652,14 +517,14 @@ "@ethersproject/logger" "^5.7.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.7.0": +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/constants@5.7.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.7.0": +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== @@ -682,7 +547,7 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/transactions" "^5.7.0" -"@ethersproject/hash@5.7.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.7.0": +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== @@ -734,7 +599,7 @@ aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.7.0": +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== @@ -742,7 +607,7 @@ "@ethersproject/bytes" "^5.7.0" js-sha3 "0.8.0" -"@ethersproject/logger@5.7.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.7.0": +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== @@ -762,14 +627,14 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/sha2" "^5.7.0" -"@ethersproject/properties@5.7.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.7.0": +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.0", "@ethersproject/providers@^5.7.1", "@ethersproject/providers@^5.7.2": +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.0": version "5.7.2" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== @@ -832,7 +697,7 @@ elliptic "6.5.4" hash.js "1.1.7" -"@ethersproject/solidity@5.7.0", "@ethersproject/solidity@^5.7.0": +"@ethersproject/solidity@5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== @@ -844,7 +709,7 @@ "@ethersproject/sha2" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@ethersproject/strings@5.7.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.7.0": +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== @@ -868,7 +733,7 @@ "@ethersproject/rlp" "^5.7.0" "@ethersproject/signing-key" "^5.7.0" -"@ethersproject/units@5.7.0", "@ethersproject/units@^5.7.0": +"@ethersproject/units@5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== @@ -877,7 +742,7 @@ "@ethersproject/constants" "^5.7.0" "@ethersproject/logger" "^5.7.0" -"@ethersproject/wallet@5.7.0", "@ethersproject/wallet@^5.7.0": +"@ethersproject/wallet@5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== @@ -1260,22 +1125,6 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@matterlabs/hardhat-zksync-deploy@0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-deploy/-/hardhat-zksync-deploy-0.6.2.tgz#077beeaadc28af5afc469c0a94f394bbc9d96ad4" - integrity sha512-TRGbYXqFdLspaGRjNRWFcej0i8+OgYodDPFVRMg/3KJvC0QLViEEcBZ2cpBqC/R5fydsIql5KXe8ZVMz22AeqA== - dependencies: - chalk "4.1.2" - -"@matterlabs/hardhat-zksync-solc@0.3.14": - version "0.3.14" - resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-solc/-/hardhat-zksync-solc-0.3.14.tgz#0a32f01b4cd8631ecd8dfe0547e3ac49ab8290d5" - integrity sha512-iKuQ+vvnpv3K2lkFO41xpJcNWH0KHJ/5JbOboTlPZATVR7F3GJeHfJL+GG4wkxKXnxZczpxyQqC4rAfMKvRaDg== - dependencies: - "@nomiclabs/hardhat-docker" "^2.0.0" - chalk "4.1.2" - dockerode "^3.3.4" - "@metamask/eth-sig-util@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" @@ -1287,33 +1136,16 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" -"@noble/curves@1.0.0", "@noble/curves@~1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.0.0.tgz#e40be8c7daf088aaf291887cbc73f43464a92932" - integrity sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw== - dependencies: - "@noble/hashes" "1.3.0" - "@noble/hashes@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== -"@noble/hashes@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" - integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== - "@noble/hashes@~1.1.1": version "1.1.5" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.5.tgz#1a0377f3b9020efe2fae03290bd2a12140c95c11" integrity sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ== -"@noble/hashes@~1.3.0": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" - integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== - "@noble/secp256k1@1.6.3", "@noble/secp256k1@~1.6.0": version "1.6.3" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.6.3.tgz#7eed12d9f4404b416999d0c87686836c4c5c9b94" @@ -1340,19 +1172,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@nomicfoundation/ethereumjs-block@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.1.tgz#6f89664f55febbd723195b6d0974773d29ee133d" - integrity sha512-u1Yioemi6Ckj3xspygu/SfFvm8vZEO8/Yx5a1QLzi6nVU0jz3Pg2OmHKJ5w+D9Ogk1vhwRiqEBAqcb0GVhCyHw== - dependencies: - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - ethereum-cryptography "0.1.3" - ethers "^5.7.1" - "@nomicfoundation/ethereumjs-block@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.0.0.tgz#fdd5c045e7baa5169abeed0e1202bf94e4481c49" @@ -1365,25 +1184,6 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-blockchain@7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.1.tgz#80e0bd3535bfeb9baa29836b6f25123dab06a726" - integrity sha512-NhzndlGg829XXbqJEYrF1VeZhAwSPgsK/OB7TVrdzft3y918hW5KNd7gIZ85sn6peDZOdjBsAXIpXZ38oBYE5A== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-ethash" "3.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - abstract-level "^1.0.3" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - level "^8.0.0" - lru-cache "^5.1.1" - memory-level "^1.0.0" - "@nomicfoundation/ethereumjs-blockchain@^6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.0.0.tgz#1a8c243a46d4d3691631f139bfb3a4a157187b0c" @@ -1402,14 +1202,6 @@ lru-cache "^5.1.1" memory-level "^1.0.0" -"@nomicfoundation/ethereumjs-common@4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.1.tgz#4702d82df35b07b5407583b54a45bf728e46a2f0" - integrity sha512-OBErlkfp54GpeiE06brBW/TTbtbuBJV5YI5Nz/aB2evTDo+KawyEzPjBlSr84z/8MFfj8wS2wxzQX1o32cev5g== - dependencies: - "@nomicfoundation/ethereumjs-util" "9.0.1" - crc-32 "^1.2.0" - "@nomicfoundation/ethereumjs-common@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.0.0.tgz#f6bcc7753994555e49ab3aa517fc8bcf89c280b9" @@ -1418,18 +1210,6 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" crc-32 "^1.2.0" -"@nomicfoundation/ethereumjs-ethash@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.1.tgz#65ca494d53e71e8415c9a49ef48bc921c538fc41" - integrity sha512-KDjGIB5igzWOp8Ik5I6QiRH5DH+XgILlplsHR7TEuWANZA759G6krQ6o8bvj+tRUz08YygMQu/sGd9mJ1DYT8w== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - abstract-level "^1.0.3" - bigint-crypto-utils "^3.0.23" - ethereum-cryptography "0.1.3" - "@nomicfoundation/ethereumjs-ethash@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.0.tgz#11539c32fe0990e1122ff987d1b84cfa34774e81" @@ -1442,20 +1222,6 @@ bigint-crypto-utils "^3.0.23" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-evm@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.1.tgz#f35681e203363f69ce2b3d3bf9f44d4e883ca1f1" - integrity sha512-oL8vJcnk0Bx/onl+TgQOQ1t/534GKFaEG17fZmwtPFeH8S5soiBYPCLUrvANOl4sCp9elYxIMzIiTtMtNNN8EQ== - dependencies: - "@ethersproject/providers" "^5.7.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - "@nomicfoundation/ethereumjs-evm@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.0.0.tgz#99cd173c03b59107c156a69c5e215409098a370b" @@ -1470,28 +1236,11 @@ mcl-wasm "^0.7.1" rustbn.js "~0.2.0" -"@nomicfoundation/ethereumjs-rlp@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.1.tgz#0b30c1cf77d125d390408e391c4bb5291ef43c28" - integrity sha512-xtxrMGa8kP4zF5ApBQBtjlSbN5E2HI8m8FYgVSYAnO6ssUoY5pVPGy2H8+xdf/bmMa22Ce8nWMH3aEW8CcqMeQ== - "@nomicfoundation/ethereumjs-rlp@^4.0.0", "@nomicfoundation/ethereumjs-rlp@^4.0.0-beta.2": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.0.tgz#d9a9c5f0f10310c8849b6525101de455a53e771d" integrity sha512-GaSOGk5QbUk4eBP5qFbpXoZoZUj/NrW7MRa0tKY4Ew4c2HAS0GXArEMAamtFrkazp0BO4K5p2ZCG3b2FmbShmw== -"@nomicfoundation/ethereumjs-statemanager@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.1.tgz#8824a97938db4471911e2d2f140f79195def5935" - integrity sha512-B5ApMOnlruVOR7gisBaYwFX+L/AP7i/2oAahatssjPIBVDF6wTX1K7Qpa39E/nzsH8iYuL3krkYeUFIdO3EMUQ== - dependencies: - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - ethers "^5.7.1" - js-sdsl "^4.1.4" - "@nomicfoundation/ethereumjs-statemanager@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.0.tgz#14a9d4e1c828230368f7ab520c144c34d8721e4b" @@ -1505,17 +1254,6 @@ ethereum-cryptography "0.1.3" functional-red-black-tree "^1.0.1" -"@nomicfoundation/ethereumjs-trie@6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.1.tgz#662c55f6b50659fd4b22ea9f806a7401cafb7717" - integrity sha512-A64It/IMpDVODzCgxDgAAla8jNjNtsoQZIzZUfIV5AY6Coi4nvn7+VReBn5itlxMiL2yaTlQr9TRWp3CSI6VoA== - dependencies: - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - "@types/readable-stream" "^2.3.13" - ethereum-cryptography "0.1.3" - readable-stream "^3.6.0" - "@nomicfoundation/ethereumjs-trie@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.0.tgz#dcfbe3be53a94bc061c9767a396c16702bc2f5b7" @@ -1526,18 +1264,6 @@ ethereum-cryptography "0.1.3" readable-stream "^3.6.0" -"@nomicfoundation/ethereumjs-tx@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.1.tgz#7629dc2036b4a33c34e9f0a592b43227ef4f0c7d" - integrity sha512-0HwxUF2u2hrsIM1fsasjXvlbDOq1ZHFV2dd1yGq8CA+MEYhaxZr8OTScpVkkxqMwBcc5y83FyPl0J9MZn3kY0w== - dependencies: - "@chainsafe/ssz" "^0.9.2" - "@ethersproject/providers" "^5.7.2" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - ethereum-cryptography "0.1.3" - "@nomicfoundation/ethereumjs-tx@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.0.0.tgz#59dc7452b0862b30342966f7052ab9a1f7802f52" @@ -1548,15 +1274,6 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-util@9.0.1": - version "9.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.1.tgz#530cda8bae33f8b5020a8f199ed1d0a2ce48ec89" - integrity sha512-TwbhOWQ8QoSCFhV/DDfSmyfFIHjPjFBj957219+V3jTZYZ2rf9PmDtNOeZWAE3p3vlp8xb02XGpd0v6nTUPbsA== - dependencies: - "@chainsafe/ssz" "^0.10.0" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - ethereum-cryptography "0.1.3" - "@nomicfoundation/ethereumjs-util@^8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.0.tgz#deb2b15d2c308a731e82977aefc4e61ca0ece6c5" @@ -1565,25 +1282,6 @@ "@nomicfoundation/ethereumjs-rlp" "^4.0.0-beta.2" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-vm@7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.1.tgz#7d035e0993bcad10716c8b36e61dfb87fa3ca05f" - integrity sha512-rArhyn0jPsS/D+ApFsz3yVJMQ29+pVzNZ0VJgkzAZ+7FqXSRtThl1C1prhmlVr3YNUlfpZ69Ak+RUT4g7VoOuQ== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-blockchain" "7.0.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-evm" "2.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-statemanager" "2.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - "@nomicfoundation/ethereumjs-vm@^6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.0.0.tgz#2bb50d332bf41790b01a3767ffec3987585d1de6" @@ -1672,57 +1370,6 @@ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.0" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.0" -"@nomiclabs/hardhat-docker@^2.0.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-docker/-/hardhat-docker-2.0.2.tgz#ae964be17951275a55859ff7358e9e7c77448846" - integrity sha512-XgGEpRT3wlA1VslyB57zyAHV+oll8KnV1TjwnxxC1tpAL04/lbdwpdO5KxInVN8irMSepqFpsiSkqlcnvbE7Ng== - dependencies: - dockerode "^2.5.8" - fs-extra "^7.0.1" - node-fetch "^2.6.0" - -"@nomiclabs/hardhat-ethers@^2.1.1": - version "2.2.3" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz#b41053e360c31a32c2640c9a45ee981a7e603fe0" - integrity sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg== - -"@nomiclabs/hardhat-ethers@npm:hardhat-deploy-ethers@0.3.0-beta.13", hardhat-deploy-ethers@0.3.0-beta.13: - name "@nomiclabs/hardhat-ethers" - version "0.3.0-beta.13" - resolved "https://registry.yarnpkg.com/hardhat-deploy-ethers/-/hardhat-deploy-ethers-0.3.0-beta.13.tgz#b96086ff768ddf69928984d5eb0a8d78cfca9366" - integrity sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw== - -"@nomiclabs/hardhat-etherscan@3.1.3": - version "3.1.3" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.3.tgz#c9dbaa4174edfa075a464a0e9142bc8710a2c4e2" - integrity sha512-UeNO97j0lwOHqX7mrH6SfQQBdXq1Ng6eFr7uJKuQOrq2UVTWGD70lE5QO4fAFVPz9ao+xlNpMyIqSR7+OaDR+Q== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@ethersproject/address" "^5.0.2" - cbor "^8.1.0" - chalk "^2.4.2" - debug "^4.1.1" - fs-extra "^7.0.1" - lodash "^4.17.11" - semver "^6.3.0" - table "^6.8.0" - undici "^5.4.0" - -"@nomiclabs/hardhat-solhint@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-solhint/-/hardhat-solhint-2.0.1.tgz#62896569d10c95a17cefab0229701cfffd19246f" - integrity sha512-SrTLufY21t78KLpJL5fS6gHIsCwVv0yWsHp1aQOPL1qwRWpe0Mnh5wb2YzBHd3Dbr/KzUYys+j2ui0PsSVU9pg== - dependencies: - solhint "^2.0.0" - -"@nomiclabs/hardhat-waffle@2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.3.tgz#9c538a09c5ed89f68f5fd2dc3f78f16ed1d6e0b1" - integrity sha512-049PHSnI1CZq6+XTbrMbMv5NaL7cednTfPenx02k3cEh8wBMLa6ys++dBETJa6JjfwgA9nBhhHQ173LJv6k2Pg== - dependencies: - "@types/sinon-chai" "^3.2.3" - "@types/web3" "1.0.19" - "@openzeppelin/contracts-upgradeable@4.7.3": version "4.7.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.7.3.tgz#f1d606e2827d409053f3e908ba4eb8adb1dd6995" @@ -1733,16 +1380,6 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.1.tgz#363f7dd08f25f8f77e16d374350c3d6b43340a7a" integrity sha512-1wTv+20lNiC0R07jyIAbHU7TNHKRwGiTGRfiNnA8jOWjKT98g5OgLpYWOi40Vgpk8SPLA9EvfJAbAeIyVn+7Bw== -"@openzeppelin/contracts@3.4.1-solc-0.7-2": - version "3.4.1-solc-0.7-2" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.1-solc-0.7-2.tgz#371c67ebffe50f551c3146a9eec5fe6ffe862e92" - integrity sha512-tAG9LWg8+M2CMu7hIsqHPaTyG4uDzjr6mhvH96LvOpLZZj6tgzTluBt+LsCf1/QaYrlis6pITvpIaIhE+iZB+Q== - -"@openzeppelin/contracts@3.4.2-solc-0.7": - version "3.4.2-solc-0.7" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.2-solc-0.7.tgz#38f4dbab672631034076ccdf2f3201fab1726635" - integrity sha512-W6QmqgkADuFcTLzHL8vVoNBtkwjvQRpYIAom7KiUNoLKghyx3FgH0GBjt8NRvigV1ZmMOBllvE1By1C+bi8WpA== - "@openzeppelin/contracts@4.7.3": version "4.7.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.3.tgz#939534757a81f8d69cc854c7692805684ff3111e" @@ -1767,48 +1404,6 @@ bignumber.js "^9.0.2" ts-essentials "^9.1.2" -"@rari-capital/solmate@6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@rari-capital/solmate/-/solmate-6.2.0.tgz#4f70dc236606c27ec2cb1b4261dd830235d01fe4" - integrity sha512-g94F+Ra9ixyJyNgvnOIufNjUz488uEG0nxIEEtJ7+g+tA1XGUupRB2kB5b+VO7WYO26RNOVD2fW6xE4e14iWpg== - -"@resolver-engine/core@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" - integrity sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ== - dependencies: - debug "^3.1.0" - is-url "^1.2.4" - request "^2.85.0" - -"@resolver-engine/fs@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.3.3.tgz#fbf83fa0c4f60154a82c817d2fe3f3b0c049a973" - integrity sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ== - dependencies: - "@resolver-engine/core" "^0.3.3" - debug "^3.1.0" - -"@resolver-engine/imports-fs@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz#4085db4b8d3c03feb7a425fbfcf5325c0d1e6c1b" - integrity sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA== - dependencies: - "@resolver-engine/fs" "^0.3.3" - "@resolver-engine/imports" "^0.3.3" - debug "^3.1.0" - -"@resolver-engine/imports@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.3.3.tgz#badfb513bb3ff3c1ee9fd56073e3144245588bcc" - integrity sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q== - dependencies: - "@resolver-engine/core" "^0.3.3" - debug "^3.1.0" - hosted-git-info "^2.6.0" - path-browserify "^1.0.0" - url "^0.11.0" - "@scure/base@~1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" @@ -1823,15 +1418,6 @@ "@noble/secp256k1" "~1.6.0" "@scure/base" "~1.1.0" -"@scure/bip32@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.0.tgz#6c8d980ef3f290987736acd0ee2e0f0d50068d87" - integrity sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q== - dependencies: - "@noble/curves" "~1.0.0" - "@noble/hashes" "~1.3.0" - "@scure/base" "~1.1.0" - "@scure/bip39@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.0.tgz#92f11d095bae025f166bef3defcc5bf4945d419a" @@ -1840,14 +1426,6 @@ "@noble/hashes" "~1.1.1" "@scure/base" "~1.1.0" -"@scure/bip39@1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.0.tgz#a207e2ef96de354de7d0002292ba1503538fc77b" - integrity sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg== - dependencies: - "@noble/hashes" "~1.3.0" - "@scure/base" "~1.1.0" - "@sentry/core@5.30.0": version "5.30.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" @@ -1962,191 +1540,6 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@sushiswap/abi@0.0.1": - version "0.0.1" - resolved "https://registry.yarnpkg.com/@sushiswap/abi/-/abi-0.0.1.tgz#2bb8ab632e4a95ec2152603c489f88fcc8ffdf7d" - integrity sha512-J4zWyfZdFiDIBa28MV/yYmr9nmWDqX8CXVfUoLfg48RVUyqPsu57dKtEKiBqAO/xpl7d9ZciNcya0d09NXvm8w== - -"@sushiswap/amm@0.1.12": - version "0.1.12" - resolved "https://registry.yarnpkg.com/@sushiswap/amm/-/amm-0.1.12.tgz#e4ddd4e8dfc6eccb3b6dbd203557333db1d3d655" - integrity sha512-SvgRfKZnNxSUwocuUbQFfHi2VYysrgPVxGnDC7iOTVU+4mS27XcNUmWXeJ/qciQe/f6x7z/GNbbeXjM2ZdehVg== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@sushiswap/chain" "0.1.2" - "@sushiswap/currency" "0.1.1" - "@sushiswap/math" "0.1.0" - "@sushiswap/tines" "1.0.8" - "@sushiswap/trident-core" "1.0.7" - "@sushiswap/types" "0.0.2" - "@sushiswap/v2-sdk" "0.0.8" - tiny-invariant "1.3.1" - tiny-warning "1.0.3" - zod "3.21.4" - -"@sushiswap/bentobox@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@sushiswap/bentobox/-/bentobox-1.0.1.tgz#a3fb265d66b28e4ddba290182ccf2f3e565a7da7" - integrity sha512-Wg3QVWie0YIVHch0oE0y6Dy+qpX/e5fsiF0MSaXgYNhTki1Uc5IPTcJ2wCISbkMjDpEP+HiLWivftNdc7gc+aw== - -"@sushiswap/chain@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@sushiswap/chain/-/chain-0.1.2.tgz#dc164887ace62edd781a8d9afac1054cbdefd582" - integrity sha512-A0S5fYxYxUZu3UQj3AwekCRgjDQ8hzLRjc1p9XwV9i+0r9ZxAdXafWFrpQufDoXS0lfKd/4XiFh50LsbhvWA8A== - -"@sushiswap/currency@0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@sushiswap/currency/-/currency-0.1.1.tgz#627b20155fbf40d76f4a930251c4bf088e3d93b3" - integrity sha512-AjzrYYUvpYabel13CmGBpDk+NHNkBIExTcLyZl1QBtDKkhWl/1239NU8WgEF04Pxx0UD1wK/FTCput2n5yK50Q== - dependencies: - "@ethersproject/address" "5.7.0" - "@ethersproject/units" "^5.7.0" - "@sushiswap/chain" "0.1.2" - "@sushiswap/math" "0.1.0" - lodash.flatmap "4.5.0" - tiny-invariant "1.3.1" - zod "3.21.4" - -"@sushiswap/hardhat-config@0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@sushiswap/hardhat-config/-/hardhat-config-0.1.3.tgz#33e7a457be3094716be7cffc3e5a37f8280f200b" - integrity sha512-lc+tPdmin2j3C/KtquoqsUZdQCIh7ibWThqfx0BMqixFwyBR3REp48JzN6hWmODKwQE8PKnYmldZ1GmZczKOMw== - dependencies: - "@matterlabs/hardhat-zksync-deploy" "0.6.2" - "@matterlabs/hardhat-zksync-solc" "0.3.14" - "@nomiclabs/hardhat-ethers" "npm:hardhat-deploy-ethers@0.3.0-beta.13" - "@nomiclabs/hardhat-etherscan" "3.1.3" - "@nomiclabs/hardhat-solhint" "2.0.1" - "@nomiclabs/hardhat-waffle" "2.0.3" - "@sushiswap/types" "0.0.2" - "@tenderly/hardhat-tenderly" "1.3.2" - "@typechain/ethers-v5" "10.1.1" - "@typechain/hardhat" "6.1.4" - dotenv "16.0.3" - ethereum-waffle "3.4.4" - hardhat-deploy "0.11.22" - hardhat-deploy-ethers "0.3.0-beta.13" - typechain "8.1.1" - -"@sushiswap/math@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@sushiswap/math/-/math-0.1.0.tgz#e4821e81997a8acfcc11fdd55eccdd160cb308fe" - integrity sha512-bchOAQo7vWPHufXJQuk7+sWGxjhlbdlaI+kin3m3cLkUzKPPHqZxMwND4G9IpXsqEbko/DFrQL/M6a25gs7InA== - dependencies: - big.js "^6.1.1" - decimal.js-light "^2.5.1" - jsbi "^4.1.0" - tiny-invariant "^1.2.0" - toformat "^2.0.0" - -"@sushiswap/router-config@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sushiswap/router-config/-/router-config-2.0.0.tgz#5052f57472f1c9e72153995927ee4c72089c3b79" - integrity sha512-cVN20sur3EbC4GTxywuCVPovhXcuBh7hUMSFyhYhOQxhQGbvlPYot/+PX77UpYviTsJOTdo+ov2LyMT5AGdTHA== - -"@sushiswap/router@^0.0.12": - version "0.0.12" - resolved "https://registry.yarnpkg.com/@sushiswap/router/-/router-0.0.12.tgz#89d65dc04bfb971c5c9a987078cf8ee4ec92165c" - integrity sha512-53cPuNmZPDnt7u9l7q9CpoiJQHnOdtPMjnq1EsHKDh7Meb1pFav9zYrAFgCbn/5Np9Qs83/xxn77JtlGSh0ypw== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@sushiswap/abi" "0.0.1" - "@sushiswap/amm" "0.1.12" - "@sushiswap/bentobox" "1.0.1" - "@sushiswap/chain" "0.1.2" - "@sushiswap/currency" "0.1.1" - "@sushiswap/math" "0.1.0" - "@sushiswap/router-config" "2.0.0" - "@sushiswap/tines" "1.0.8" - "@sushiswap/trident-core" "1.0.7" - "@sushiswap/v2-sdk" "0.0.8" - "@sushiswap/v3-sdk" "1.0.9" - "@sushiswap/viem-config" "1.0.2" - date-fns "2.29.3" - ethers "5.7.2" - lodash.flatmap "^4.5.0" - node-fetch "2.6.6" - tiny-invariant "1.3.1" - tiny-warning "1.0.3" - viem "1.0.2" - zod "3.21.4" - -"@sushiswap/tines@1.0.8": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@sushiswap/tines/-/tines-1.0.8.tgz#11e7a0ed3bffe7fb0dea4141811b44294f09f95a" - integrity sha512-se9CnYcjnsuDqf7pbEXfo7FYaLgjSrBjaEc/TvEd0r8bO/goQSHUwNqklA+i9DpzYSki72GT2G5+4r6OxnActA== - dependencies: - "@ethersproject/bignumber" "5.7.0" - "@sushiswap/currency" "0.1.1" - -"@sushiswap/trident-core@1.0.7": - version "1.0.7" - resolved "https://registry.yarnpkg.com/@sushiswap/trident-core/-/trident-core-1.0.7.tgz#20c7691374332a0601e13fe1045189ae063d49b9" - integrity sha512-u2Z22726Y2hC8sx0jDj/lGMf2egFZ/uTctGUWrlUDb3KyT/LtxFVQOSYgaFw6GnRhunSfE0oOpHlYJNHEVYBpA== - dependencies: - "@openzeppelin/contracts" "4.7.3" - "@rari-capital/solmate" "6.2.0" - "@sushiswap/bentobox" "1.0.1" - "@sushiswap/currency" "0.1.1" - "@sushiswap/hardhat-config" "0.1.3" - "@sushiswap/types" "0.0.2" - -"@sushiswap/types@0.0.2": - version "0.0.2" - resolved "https://registry.yarnpkg.com/@sushiswap/types/-/types-0.0.2.tgz#9088674d01afede9c3738f6a62a908976f8bc639" - integrity sha512-Aa4MnBFq/SK/F4zZlRXNpLcqza2RsE0mLxxv4+8an1Dtr7l26lyWd+3PbVrtv1bA7OVmBXoqJhTrQKA8w3zEPA== - -"@sushiswap/v2-sdk@0.0.8": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@sushiswap/v2-sdk/-/v2-sdk-0.0.8.tgz#14c0460c8f3164314cd9d9b574815e1d365e7c06" - integrity sha512-o1h7uDkUOauNiVh2DUFZEfp5ASqt7muOs25VQxRV966YHYwDPs9SZEI9fVXn6a04jTWWOVbPP8BnDLYH+MRh8Q== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@sushiswap/chain" "0.1.2" - "@sushiswap/currency" "0.1.1" - "@sushiswap/math" "0.1.0" - tiny-invariant "1.3.1" - tiny-warning "1.0.3" - zod "3.21.4" - -"@sushiswap/v3-sdk@1.0.9": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@sushiswap/v3-sdk/-/v3-sdk-1.0.9.tgz#79d280a00b100886d8dee52dcfd0b9c2a115b32c" - integrity sha512-Lb5aJTy4atLUd8vtCQH3ZgAxFFefeZ26JqEeYlCrH2ayh73bs2CPET7E3ZKvKEOD1g2l67bvHfWesbueCyurVg== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@sushiswap/amm" "0.1.12" - "@sushiswap/chain" "0.1.2" - "@sushiswap/currency" "0.1.1" - "@sushiswap/math" "0.1.0" - "@sushiswap/tines" "1.0.8" - "@uniswap/swap-router-contracts" "1.3.0" - "@uniswap/v3-core" "1.0.1" - "@uniswap/v3-periphery" "1.4.3" - "@uniswap/v3-staker" "1.0.2" - tiny-invariant "1.3.1" - tiny-warning "1.0.3" - zod "3.21.4" - -"@sushiswap/viem-config@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@sushiswap/viem-config/-/viem-config-1.0.2.tgz#82112a2cdddc63fa902f6d568d899423402200b8" - integrity sha512-IpZ/vmgs67LeR4eqrfIF/Og/taFGD9NW3E12kzS2sFyJJ0uZQP/hpqLNtNmXTPg9oV6/JCtnTGL+6Ic0EUd+gA== - dependencies: - "@sushiswap/chain" "0.1.2" - "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -2161,21 +1554,6 @@ dependencies: defer-to-connect "^2.0.0" -"@tenderly/hardhat-tenderly@1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@tenderly/hardhat-tenderly/-/hardhat-tenderly-1.3.2.tgz#9ee69ba1fb8650d18160c637e8e487d938f6dcea" - integrity sha512-0kE0gv8RIu0N5JXKCCfYcydsMgGgj8z3qCvbeD/ynBKwOBvbFB+NZFRyTHNopbeaUKO7Q3bGFau8vS1B0EWS0g== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@nomiclabs/hardhat-ethers" "^2.1.1" - axios "^0.27.2" - ethers "^5.7.0" - fs-extra "^10.1.0" - hardhat "^2.10.2" - hardhat-deploy "^0.11.14" - js-yaml "^4.1.0" - tenderly "^0.0.3" - "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -2196,28 +1574,6 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== -"@typechain/ethers-v5@10.1.1": - version "10.1.1" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-10.1.1.tgz#fdb527d8854129cea5f139d76c6c6e1c9bb040ec" - integrity sha512-o6nffJBxwmeX1ZiZpdnP/tqGd/7M7iYvQC88ZXaFFoyAGh7eYncynzVjOJV0XmaKzAc6puqyqZrnva+gJbk4sw== - dependencies: - lodash "^4.17.15" - ts-essentials "^7.0.1" - -"@typechain/ethers-v5@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" - integrity sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw== - dependencies: - ethers "^5.0.2" - -"@typechain/hardhat@6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-6.1.4.tgz#da930bf17bdae5e0996b86d37992c6c58b8a49c8" - integrity sha512-S8k5d1Rjc+plwKpkorlifmh72M7Ki0XNUOVVLtdbcA/vLaEkuqZSJFdddpBgS5QxiJP+6CbRa/yO6EVTE2+fMQ== - dependencies: - fs-extra "^9.1.0" - "@types/async-eventemitter@^0.2.1": version "0.2.1" resolved "https://registry.yarnpkg.com/@types/async-eventemitter/-/async-eventemitter-0.2.1.tgz#f8e6280e87e8c60b2b938624b0a3530fb3e24712" @@ -2268,13 +1624,6 @@ dependencies: "@babel/types" "^7.3.0" -"@types/bn.js@*", "@types/bn.js@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" - integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== - dependencies: - "@types/node" "*" - "@types/bn.js@^4.11.0", "@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": version "4.11.6" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" @@ -2282,6 +1631,13 @@ dependencies: "@types/node" "*" +"@types/bn.js@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== + dependencies: + "@types/node" "*" + "@types/body-parser@*": version "1.19.2" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" @@ -2300,11 +1656,6 @@ "@types/node" "*" "@types/responselike" "*" -"@types/chai@*": - version "4.3.5" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b" - integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== - "@types/connect@*": version "3.4.35" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" @@ -2407,21 +1758,6 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== -"@types/mkdirp@^0.5.2": - version "0.5.2" - resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" - integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== - dependencies: - "@types/node" "*" - -"@types/node-fetch@^2.5.5": - version "2.6.4" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" - integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg== - dependencies: - "@types/node" "*" - form-data "^3.0.0" - "@types/node@*": version "18.11.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.3.tgz#78a6d7ec962b596fc2d2ec102c4dd3ef073fea6a" @@ -2444,11 +1780,6 @@ dependencies: "@types/node" "*" -"@types/prettier@^2.1.1": - version "2.7.3" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" - integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== - "@types/prettier@^2.1.5": version "2.7.1" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e" @@ -2459,7 +1790,7 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== -"@types/qs@*", "@types/qs@^6.9.7": +"@types/qs@*": version "6.9.7" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== @@ -2478,21 +1809,6 @@ "@types/scheduler" "*" csstype "^3.0.2" -"@types/readable-stream@^2.3.13": - version "2.3.15" - resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.15.tgz#3d79c9ceb1b6a57d5f6e6976f489b9b5384321ae" - integrity sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ== - dependencies: - "@types/node" "*" - safe-buffer "~5.1.1" - -"@types/resolve@^0.0.8": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" - integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== - dependencies: - "@types/node" "*" - "@types/responselike@*", "@types/responselike@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" @@ -2525,49 +1841,16 @@ "@types/mime" "*" "@types/node" "*" -"@types/sinon-chai@^3.2.3": - version "3.2.9" - resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.9.tgz#71feb938574bbadcb176c68e5ff1a6014c5e69d4" - integrity sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ== - dependencies: - "@types/chai" "*" - "@types/sinon" "*" - -"@types/sinon@*": - version "10.0.15" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.15.tgz#513fded9c3cf85e589bbfefbf02b2a0541186b48" - integrity sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ== - dependencies: - "@types/sinonjs__fake-timers" "*" - -"@types/sinonjs__fake-timers@*": - version "8.1.2" - resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz#bf2e02a3dbd4aecaf95942ecd99b7402e03fad5e" - integrity sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA== - "@types/stack-utils@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== -"@types/underscore@*": - version "1.11.5" - resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.5.tgz#963de9bc8c8908d9ba1777d3978c63484fbb9fe1" - integrity sha512-b8e//LrIlhoXaaBcMC0J/s2/lIF9y5VJYKqbW4nA+tW/nqqDk1Dacd1ULLT7zgGsKs7PGbSnqCPzqEniZ0RxYg== - "@types/uuid@^9.0.1": version "9.0.2" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.2.tgz#ede1d1b1e451548d44919dc226253e32a6952c4b" integrity sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ== -"@types/web3@1.0.19": - version "1.0.19" - resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.0.19.tgz#46b85d91d398ded9ab7c85a5dd57cb33ac558924" - integrity sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A== - dependencies: - "@types/bn.js" "*" - "@types/underscore" "*" - "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" @@ -2670,109 +1953,22 @@ "@typescript-eslint/types" "5.47.0" eslint-visitor-keys "^3.3.0" -"@uniswap/lib@^4.0.1-alpha": - version "4.0.1-alpha" - resolved "https://registry.yarnpkg.com/@uniswap/lib/-/lib-4.0.1-alpha.tgz#2881008e55f075344675b3bca93f020b028fbd02" - integrity sha512-f6UIliwBbRsgVLxIaBANF6w09tYqc6Y/qXdsrbEmXHyFA7ILiKrIwRFXe1yOg8M3cksgVsO9N7yuL2DdCGQKBA== - -"@uniswap/swap-router-contracts@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@uniswap/swap-router-contracts/-/swap-router-contracts-1.3.0.tgz#8d555ca6d74b888d6e02a26ebb806ce315605f1f" - integrity sha512-iKvCuRkHXEe0EMjOf8HFUISTIhlxI57kKFllf3C3PUIE0HmwxrayyoflwAz5u/TRsFGYqJ9IjX2UgzLCsrNa5A== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== dependencies: - "@openzeppelin/contracts" "3.4.2-solc-0.7" - "@uniswap/v2-core" "1.0.1" - "@uniswap/v3-core" "1.0.0" - "@uniswap/v3-periphery" "1.4.1" - dotenv "^14.2.0" - hardhat-watcher "^2.1.1" - -"@uniswap/v2-core@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@uniswap/v2-core/-/v2-core-1.0.1.tgz#af8f508bf183204779938969e2e54043e147d425" - integrity sha512-MtybtkUPSyysqLY2U210NBDeCHX+ltHt3oADGdjqoThZaFRDKwM6k1Nb3F0A3hk5hwuQvytFWhrWHOEq6nVJ8Q== - -"@uniswap/v3-core@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.0.tgz#6c24adacc4c25dceee0ba3ca142b35adbd7e359d" - integrity sha512-kSC4djMGKMHj7sLMYVnn61k9nu+lHjMIxgg9CDQT+s2QYLoA56GbSK9Oxr+qJXzzygbkrmuY6cwgP6cW2JXPFA== + event-target-shim "^5.0.0" -"@uniswap/v3-core@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.1.tgz#b6d2bdc6ba3c3fbd610bdc502395d86cd35264a0" - integrity sha512-7pVk4hEm00j9tc71Y9+ssYpO6ytkeI0y7WE9P6UcmNzhxPePwyAxImuhVsTqWK9YFvzgtvzJHi64pBl4jUzKMQ== +abortcontroller-polyfill@^1.1.9: + version "1.7.5" + resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" + integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== -"@uniswap/v3-periphery@1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.4.1.tgz#b90f08b7386163c0abfd7258831caef6339c7862" - integrity sha512-Ab0ZCKOQrQMKIcpBTezTsEhWfQjItd0TtkCG8mPhoQu+wC67nPaf4hYUhM6wGHeFUmDiYY5MpEQuokB0ENvoTg== - dependencies: - "@openzeppelin/contracts" "3.4.2-solc-0.7" - "@uniswap/lib" "^4.0.1-alpha" - "@uniswap/v2-core" "1.0.1" - "@uniswap/v3-core" "1.0.0" - base64-sol "1.0.1" - hardhat-watcher "^2.1.1" - -"@uniswap/v3-periphery@1.4.3", "@uniswap/v3-periphery@^1.0.1": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.4.3.tgz#a6da4632dbd46b139cc13a410e4ec09ad22bd19f" - integrity sha512-80c+wtVzl5JJT8UQskxVYYG3oZb4pkhY0zDe0ab/RX4+8f9+W5d8wI4BT0wLB0wFQTSnbW+QdBSpkHA/vRyGBA== - dependencies: - "@openzeppelin/contracts" "3.4.2-solc-0.7" - "@uniswap/lib" "^4.0.1-alpha" - "@uniswap/v2-core" "1.0.1" - "@uniswap/v3-core" "1.0.0" - base64-sol "1.0.1" - -"@uniswap/v3-staker@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@uniswap/v3-staker/-/v3-staker-1.0.2.tgz#febad4905903032bb114ab58138c2d5200c87a3c" - integrity sha512-+swIh/yhY9GQGyQxT4Gz54aXYLK+uc3qsmIvaAX+FjvhcL9TGOvS9tXbQsCZM4AJW63vj6TLsmHIjGMIePL1BQ== - dependencies: - "@openzeppelin/contracts" "3.4.1-solc-0.7-2" - "@uniswap/v3-core" "1.0.0" - "@uniswap/v3-periphery" "^1.0.1" - -"@wagmi/chains@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-1.1.0.tgz#d351b3dc6f472b167f180721f46f6098b6c1585b" - integrity sha512-pWZlxBk0Ql8E7DV8DwqlbBpOyUdaG9UDlQPBxJNALuEK1I0tbQ3AVvSDnlsEIt06UPmPo5o27gzs3hwPQ/A+UA== - -"@yarnpkg/lockfile@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" - integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== - -JSONStream@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" - integrity sha512-mn0KSip7N4e0UDPZHnqDsHECo5uGQrixQKnAskOM1BIB8hd7QKbd6il8IPRPudPHOeHiECoCFqhyMaRO9+nWyA== - dependencies: - jsonparse "^1.2.0" - through ">=2.2.7 <3" - -abitype@0.8.7: - version "0.8.7" - resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.8.7.tgz#e4b3f051febd08111f486c0cc6a98fa72d033622" - integrity sha512-wQ7hV8Yg/yKmGyFpqrNZufCxbszDe5es4AZGYPBitocfSqXtjrTG9JMWFcc4N30ukl2ve48aBTwt7NJxVQdU3w== - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - -abortcontroller-polyfill@^1.1.9: - version "1.7.5" - resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" - integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== - -abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" - integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== +abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" + integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== dependencies: buffer "^6.0.3" catering "^2.1.0" @@ -2782,34 +1978,6 @@ abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: module-error "^1.0.1" queue-microtask "^1.2.3" -abstract-leveldown@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" - integrity sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@^2.4.1, abstract-leveldown@~2.7.1: - version "2.7.2" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" - integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz#f7128e1f86ccabf7d2893077ce5d06d798e386c6" - integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@~2.6.0: - version "2.6.3" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" - integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== - dependencies: - xtend "~4.0.0" - accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -2818,7 +1986,7 @@ accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-jsx@^5.0.0, acorn-jsx@^5.3.2: +acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== @@ -2828,11 +1996,6 @@ acorn-walk@^8.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^6.0.7: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - acorn@^8.4.1: version "8.8.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" @@ -2853,11 +2016,6 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== -aes-js@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" - integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== - agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -2873,7 +2031,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.6.1, ajv@^6.9.1: +ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2883,16 +2041,6 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.6.1, ajv@^6.9.1: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.1: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -2903,11 +2051,6 @@ ansi-colors@^4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== -ansi-escapes@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== - ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -2915,32 +2058,12 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: dependencies: type-fest "^0.21.3" -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== - -ansi-regex@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" - integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== - -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - ansi-regex@^5.0.0, ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: +ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -2959,11 +2082,6 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -antlr4@4.7.1: - version "4.7.1" - resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.7.1.tgz#69984014f096e9e775f53dd9744bf994d8959773" - integrity sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ== - anymatch@^3.0.3: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" @@ -2997,53 +2115,6 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== - -array-back@^1.0.3, array-back@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" - integrity sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw== - dependencies: - typical "^2.6.0" - -array-back@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" - integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== - dependencies: - typical "^2.6.1" - -array-back@^3.0.1, array-back@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" - integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== - -array-back@^4.0.1, array-back@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" - integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== - -array-buffer-byte-length@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" - integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== - dependencies: - call-bind "^1.0.2" - is-array-buffer "^3.0.1" - array-differ@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" @@ -3070,11 +2141,6 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== - array.prototype.flat@^1.2.5: version "1.3.1" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" @@ -3085,17 +2151,6 @@ array.prototype.flat@^1.2.5: es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" -array.prototype.reduce@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" - integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - es-array-method-boxes-properly "^1.0.0" - is-string "^1.0.7" - arrify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" @@ -3111,7 +2166,7 @@ asn1.js@^5.2.0: minimalistic-assert "^1.0.0" safer-buffer "^2.1.0" -asn1@^0.2.6, asn1@~0.2.3: +asn1@~0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== @@ -3128,22 +2183,7 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== - -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - -async-eventemitter@^0.2.2, async-eventemitter@^0.2.4: +async-eventemitter@^0.2.4: version "0.2.4" resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== @@ -3155,19 +2195,7 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async@2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" - integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== - dependencies: - lodash "^4.17.11" - -async@^1.4.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== - -async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: +async@^2.4.0: version "2.6.4" resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== @@ -3184,16 +2212,6 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - -atob@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - available-typed-arrays@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" @@ -3225,13 +2243,6 @@ axios@0.26.0: dependencies: follow-redirects "^1.14.8" -axios@^0.21.1: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - axios@^0.27.2: version "0.27.2" resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" @@ -3240,167 +2251,6 @@ axios@^0.27.2: follow-redirects "^1.14.9" form-data "^4.0.0" -babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g== - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-core@^6.0.14, babel-core@^6.26.0: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - -babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - integrity sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q== - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - integrity sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ== - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - integrity sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA== - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - integrity sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ== - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - integrity sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q== - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - integrity sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - integrity sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - integrity sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - integrity sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg== - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - integrity sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg== - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - integrity sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw== - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ== - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-jest@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.2.1.tgz#213c47e28072de11bdb98c9d29b89f2ab99664f1" @@ -3414,20 +2264,6 @@ babel-jest@^29.2.1: graceful-fs "^4.2.9" slash "^3.0.0" -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-check-es2015-constants@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - integrity sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA== - dependencies: - babel-runtime "^6.22.0" - babel-plugin-istanbul@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" @@ -3449,244 +2285,6 @@ babel-plugin-jest-hoist@^29.2.0: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - integrity sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw== - -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - integrity sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ== - -babel-plugin-syntax-trailing-function-commas@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - integrity sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ== - -babel-plugin-transform-async-to-generator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - integrity sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw== - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-arrow-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - integrity sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - integrity sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.23.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - integrity sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw== - dependencies: - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-plugin-transform-es2015-classes@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - integrity sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag== - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - integrity sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw== - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - integrity sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - integrity sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - integrity sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - integrity sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg== - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - integrity sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - integrity sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA== - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: - version "6.26.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" - integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-types "^6.26.0" - -babel-plugin-transform-es2015-modules-systemjs@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - integrity sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg== - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - integrity sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw== - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - integrity sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA== - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - integrity sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ== - dependencies: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - integrity sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - integrity sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-sticky-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - integrity sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ== - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - integrity sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - integrity sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - integrity sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ== - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - integrity sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ== - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-regenerator@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - integrity sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg== - dependencies: - regenerator-transform "^0.10.0" - -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - integrity sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -3705,42 +2303,6 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-env@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" - integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.23.0" - babel-plugin-transform-es2015-classes "^6.23.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.23.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.23.0" - babel-plugin-transform-es2015-function-name "^6.22.0" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.23.0" - babel-plugin-transform-es2015-modules-systemjs "^6.23.0" - babel-plugin-transform-es2015-modules-umd "^6.23.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.23.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.23.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-exponentiation-operator "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - browserslist "^3.2.6" - invariant "^2.2.2" - semver "^5.3.0" - babel-preset-jest@^29.2.0: version "29.2.0" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz#3048bea3a1af222e3505e4a767a974c95a7620dc" @@ -3749,83 +2311,6 @@ babel-preset-jest@^29.2.0: babel-plugin-jest-hoist "^29.2.0" babel-preset-current-node-syntax "^1.0.0" -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A== - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.24.1, babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg== - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.24.1, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA== - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g== - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babelify@^7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" - integrity sha512-vID8Fz6pPN5pJMdlUnNFSfrlcx5MUule4k9aKs/zbZPyXxMTcRrB0M4Tarw22L8afr8eYSWxDPYCob3TdrqtlA== - dependencies: - babel-core "^6.0.14" - object-assign "^4.0.0" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - -backoff@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" - integrity sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA== - dependencies: - precond "0.2" - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -3843,25 +2328,7 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base64-sol@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/base64-sol/-/base64-sol-1.0.1.tgz#91317aa341f0bc763811783c5729f1c2574600f6" - integrity sha512-ld3cCNMeXt4uJXmLZBHFGMvVpK9KsLVEhPpFRXnvSVAqABKbuNZg/+dsq3NuM+wxFLb/UrVkz7m1ciWmkMfTbg== - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2: +bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== @@ -3873,11 +2340,6 @@ bech32@1.1.4: resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== -big.js@^6.1.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.2.1.tgz#7205ce763efb17c2e41f26f121c420c6a7c2744f" - integrity sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ== - bigint-crypto-utils@^3.0.23: version "3.1.8" resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.1.8.tgz#e2e0f40cf45488f9d7f0e32ff84152aa73819d5d" @@ -3910,40 +2372,12 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bip39@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" - integrity sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA== - dependencies: - create-hash "^1.1.0" - pbkdf2 "^3.0.9" - randombytes "^2.0.1" - safe-buffer "^5.0.1" - unorm "^1.3.3" - -bl@^1.0.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" - integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== - dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" - -bl@^4.0.3: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - blakejs@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== -bluebird@^3.5.0, bluebird@^3.5.2: +bluebird@^3.5.0: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -3953,7 +2387,7 @@ bn.js@4.11.6: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.8.0: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== @@ -3996,22 +2430,6 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -4093,14 +2511,6 @@ browserify-sign@^4.0.0: readable-stream "^3.6.0" safe-buffer "^5.2.0" -browserslist@^3.2.6: - version "3.2.8" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" - integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== - dependencies: - caniuse-lite "^1.0.30000844" - electron-to-chromium "^1.3.47" - browserslist@^4.21.3: version "4.21.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" @@ -4141,24 +2551,6 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== - buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -4179,14 +2571,7 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== -buffer-xor@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" - integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== - dependencies: - safe-buffer "^5.1.1" - -buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: +buffer@^5.0.5, buffer@^5.5.0, buffer@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -4214,11 +2599,6 @@ bufio@^1.0.7: resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.2.0.tgz#b9ad1c06b0d9010363c387c39d2810a7086d143f" integrity sha512-UlFk8z/PwdhYQTXSQQagwGAdtRI83gib2n4uy4rQnenxUM2yQi8lBDzF230BNk+3wAoZDxYRoBwVVUPgHa9MCA== -buildcheck@~0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.6.tgz#89aa6e417cfd1e2196e3f8fe915eb709d2fe4238" - integrity sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A== - busboy@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -4231,36 +2611,6 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -bytewise-core@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" - integrity sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA== - dependencies: - typewise-core "^1.2" - -bytewise@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" - integrity sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ== - dependencies: - bytewise-core "^1.2.2" - typewise "^1.0.3" - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - cacheable-lookup@^5.0.3: version "5.0.4" resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" @@ -4292,15 +2642,7 @@ cacheable-request@^7.0.2: normalize-url "^6.0.1" responselike "^2.0.0" -cachedown@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cachedown/-/cachedown-1.0.0.tgz#d43f036e4510696b31246d7db31ebf0f7ac32d15" - integrity sha512-t+yVk82vQWCJF3PsWHMld+jhhjkkWjcAzz8NbFx1iULOXWl8Tm/FdM4smZNVw3MRr0X+lVTx9PKzvEn4Ng19RQ== - dependencies: - abstract-leveldown "^2.4.1" - lru-cache "^3.2.0" - -call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: +call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== @@ -4308,25 +2650,6 @@ call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== - callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -4340,11 +2663,6 @@ camel-case@^4.1.2: pascal-case "^3.1.2" tslib "^2.0.3" -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg== - camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -4355,11 +2673,6 @@ camelcase@^6.0.0, camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30000844: - version "1.0.30001507" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001507.tgz#fae53f6286e7564783eadea9b447819410a59534" - integrity sha512-SFpUDoSLCaE5XYL2jfqe9ova/pbQHEmbheDf5r4diNwbAgR3qxM9NQtfsiSscjqoya5K7kFcHPUQ+VsUkIJR4A== - caniuse-lite@^1.0.30001400: version "1.0.30001423" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001423.tgz#57176d460aa8cd85ee1a72016b961eb9aca55d91" @@ -4374,11 +2687,6 @@ capital-case@^1.0.4: tslib "^2.0.3" upper-case-first "^2.0.2" -case@^1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" - integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== - caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -4389,13 +2697,6 @@ catering@^2.1.0, catering@^2.1.1: resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== -cbor@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" - integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== - dependencies: - nofilter "^3.1.0" - chai@^4.3.4: version "4.3.7" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" @@ -4409,26 +2710,7 @@ chai@^4.3.4: pathval "^1.1.1" type-detect "^4.0.5" -chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -4445,6 +2727,14 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + change-case@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" @@ -4468,24 +2758,12 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== -checkpoint-store@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" - integrity sha512-J/NdY2WvIx654cc6LWSq/IYFFCUf75fFTgwzFnmbqyORH4MwgiQCgswLLKBGzmsyTI5V7i5bp/So6sMbDWhedg== - dependencies: - functional-red-black-tree "^1.0.1" - -chokidar@3.5.3, chokidar@^3.4.0, chokidar@^3.5.2, chokidar@^3.5.3: +chokidar@3.5.3, chokidar@^3.4.0: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -4500,7 +2778,7 @@ chokidar@3.5.3, chokidar@^3.4.0, chokidar@^3.5.2, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" -chownr@^1.0.1, chownr@^1.1.1, chownr@^1.1.4: +chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== @@ -4544,16 +2822,6 @@ class-is@^1.1.0: resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - classic-level@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.2.0.tgz#2d52bdec8e7a27f534e67fdeb890abef3e643c27" @@ -4570,36 +2838,6 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== - dependencies: - restore-cursor "^2.0.0" - -cli-table3@^0.6.2: - version "0.6.3" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" - integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== - dependencies: - string-width "^4.2.0" - optionalDependencies: - "@colors/colors" "1.5.0" - -cli-width@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" - integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== - -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w== - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -4625,7 +2863,7 @@ clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" -clone@2.1.2, clone@2.x, clone@^2.0.0: +clone@2.x: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== @@ -4635,24 +2873,11 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== - collect-v8-coverage@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -4689,70 +2914,16 @@ command-exists@^1.2.8: resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== -command-line-args@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46" - integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== - dependencies: - array-back "^2.0.0" - find-replace "^1.0.3" - typical "^2.6.1" - -command-line-args@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" - integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== - dependencies: - array-back "^3.1.0" - find-replace "^3.0.0" - lodash.camelcase "^4.3.0" - typical "^4.0.0" - -command-line-usage@^6.1.0: - version "6.1.3" - resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" - integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== - dependencies: - array-back "^4.0.2" - chalk "^2.4.2" - table-layout "^1.0.2" - typical "^5.2.0" - -commander@2.18.0: - version "2.18.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" - integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== - commander@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== -commander@^9.4.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" - integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== - -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -concat-stream@^1.5.1, concat-stream@~1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - confusing-browser-globals@^1.0.10: version "1.0.11" resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" @@ -4788,7 +2959,7 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== -convert-source-map@^1.4.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== @@ -4813,31 +2984,11 @@ cookiejar@^2.1.1: resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== - -core-js-pure@^3.0.1: - version "3.31.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.31.0.tgz#052fd9e82fbaaf86457f5db1fadcd06f15966ff2" - integrity sha512-/AnE9Y4OsJZicCzIe97JP5XoPKQJfTuEG43aEVLFJGOJpyqELod+pE6LEl63DfG1Mp8wX97LDaDpy1GmLEUxlg== - -core-js@^2.4.0, core-js@^2.5.0: - version "2.6.12" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" - integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== - core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - cors@^2.8.1: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" @@ -4846,24 +2997,6 @@ cors@^2.8.1: object-assign "^4" vary "^1" -cosmiconfig@^5.0.7: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - -cpu-features@~0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.8.tgz#a2d464b023b8ad09004c8cdca23b33f192f63546" - integrity sha512-BbHBvtYhUhksqTjr6bhNOjGgMnhwhGTQmOoZGD+K7BCaQDCuZl/Ve1ZxUSMRwVC4D/rkCPQ2MAIeYzrWyK7eEg== - dependencies: - buildcheck "~0.0.6" - nan "^2.17.0" - crc-32@^1.2.0: version "1.2.2" resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" @@ -4905,14 +3038,6 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-fetch@^2.1.0, cross-fetch@^2.1.1: - version "2.2.6" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.6.tgz#2ef0bb39a24ac034787965c457368a28730e220a" - integrity sha512-9JZz+vXCmfKUZ68zAptS7k4Nu8e2qcibe7WVZYps7sAgk5R8GYTc+T1WR0v1rlP9HxgARmOX1UTIJZFytajpNA== - dependencies: - node-fetch "^2.6.7" - whatwg-fetch "^2.0.4" - cross-fetch@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" @@ -4920,17 +3045,6 @@ cross-fetch@^3.1.5: dependencies: node-fetch "2.6.7" -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -4982,59 +3096,37 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -date-fns@2.29.3: - version "2.29.3" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" - integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== - date-format@^4.0.13, date-format@^4.0.14: version "4.0.14" resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.14.tgz#7a8e584434fb169a521c8b7aa481f355810d9400" integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -debug@4, debug@4.3.4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: +debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" -decamelize@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - decamelize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== -decimal.js-light@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" - integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== - decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -5066,24 +3158,7 @@ deep-eql@^4.1.2: dependencies: type-detect "^4.0.0" -deep-equal@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - -deep-extend@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deep-is@^0.1.3, deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -5103,26 +3178,6 @@ defer-to-connect@^2.0.0: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== -deferred-leveldown@~1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" - integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== - dependencies: - abstract-leveldown "~2.6.0" - -deferred-leveldown@~4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz#0b0570087827bf480a23494b398f04c128c19a20" - integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== - dependencies: - abstract-leveldown "~5.0.0" - inherits "^2.0.3" - -define-lazy-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" - integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== - define-properties@^1.1.3, define-properties@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" @@ -5131,41 +3186,6 @@ define-properties@^1.1.3, define-properties@^1.1.4: has-property-descriptors "^1.0.0" object-keys "^1.1.1" -define-properties@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" - integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -defined@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" - integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -5189,13 +3209,6 @@ destroy@1.2.0: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A== - dependencies: - repeating "^2.0.0" - detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -5242,44 +3255,6 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -docker-modem@^1.0.8: - version "1.0.9" - resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-1.0.9.tgz#a1f13e50e6afb6cf3431b2d5e7aac589db6aaba8" - integrity sha512-lVjqCSCIAUDZPAZIeyM125HXfNvOmYYInciphNrLrylUtKyW66meAjSPXWchKVzoIYZx69TPnAepVSSkeawoIw== - dependencies: - JSONStream "1.3.2" - debug "^3.2.6" - readable-stream "~1.0.26-4" - split-ca "^1.0.0" - -docker-modem@^3.0.0: - version "3.0.8" - resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-3.0.8.tgz#ef62c8bdff6e8a7d12f0160988c295ea8705e77a" - integrity sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ== - dependencies: - debug "^4.1.1" - readable-stream "^3.5.0" - split-ca "^1.0.1" - ssh2 "^1.11.0" - -dockerode@^2.5.8: - version "2.5.8" - resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-2.5.8.tgz#1b661e36e1e4f860e25f56e0deabe9f87f1d0acc" - integrity sha512-+7iOUYBeDTScmOmQqpUYQaE7F4vvIt6+gIZNHWhqAQEI887tiPFB9OvXI/HzQYqfUNvukMK+9myLW63oTJPZpw== - dependencies: - concat-stream "~1.6.2" - docker-modem "^1.0.8" - tar-fs "~1.16.3" - -dockerode@^3.3.4: - version "3.3.5" - resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-3.3.5.tgz#7ae3f40f2bec53ae5e9a741ce655fff459745629" - integrity sha512-/0YNa3ZDNeLr/tSckmD69+Gq+qVNhvKfAHNeZJBnp7EOP6RGKV8ORrJHkUn20So5wU+xxT7+1n5u8PjHbfjbSA== - dependencies: - "@balena/dockerignore" "^1.0.2" - docker-modem "^3.0.0" - tar-fs "~2.0.1" - doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -5312,23 +3287,6 @@ dotenv@16.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411" integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q== -dotenv@16.0.3: - version "16.0.3" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" - integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== - -dotenv@^14.2.0: - version "14.3.2" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-14.3.2.tgz#7c30b3a5f777c79a3429cb2db358eef6751e8369" - integrity sha512-vwEppIphpFdvaMCaHfCEv9IgwcxMljMw2TnAQBB4VWPvzXQLTb82jwmdOKzlEVUL3gNFT4l4TPKO+Bn+sqcrVQ== - -dotignore@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" - integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== - dependencies: - minimatch "^3.0.4" - duplexer3@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" @@ -5347,11 +3305,6 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.3.47: - version "1.4.439" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.439.tgz#d0748e8128c18f92354d3412dfb2104c3fb90e8f" - integrity sha512-BHpErPSNhb9FB25+OwQP6mCAf3ZXfGbmuvc4LzBNVJwpCcXQJm++LerimocYRG9FRxUVRKZqaB7d0+pImSTPSg== - electron-to-chromium@^1.4.251: version "1.4.284" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" @@ -5375,37 +3328,16 @@ emittery@^0.10.2: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933" integrity sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw== -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -encode-utf8@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" - integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -encoding-down@5.0.4, encoding-down@~5.0.0: - version "5.0.4" - resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-5.0.4.tgz#1e477da8e9e9d0f7c8293d320044f8b2cd8e9614" - integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== - dependencies: - abstract-leveldown "^5.0.0" - inherits "^2.0.3" - level-codec "^9.0.0" - level-errors "^2.0.0" - xtend "^4.0.1" - encoding@^0.1.11: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" @@ -5413,14 +3345,14 @@ encoding@^0.1.11: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: +end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" -enquirer@^2.3.0, enquirer@^2.3.6: +enquirer@^2.3.0: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -5432,14 +3364,7 @@ env-paths@^2.2.0: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== -errno@~0.1.1: - version "0.1.8" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" - integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== - dependencies: - prr "~1.0.1" - -error-ex@^1.2.0, error-ex@^1.3.1: +error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -5507,60 +3432,6 @@ es-abstract@^1.20.4: string.prototype.trimstart "^1.0.6" unbox-primitive "^1.0.2" -es-abstract@^1.21.2: - version "1.21.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" - integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== - dependencies: - array-buffer-byte-length "^1.0.0" - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-set-tostringtag "^2.0.1" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.2.0" - get-symbol-description "^1.0.0" - globalthis "^1.0.3" - gopd "^1.0.1" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.5" - is-array-buffer "^3.0.2" - is-callable "^1.2.7" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-typed-array "^1.1.10" - is-weakref "^1.0.2" - object-inspect "^1.12.3" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - safe-regex-test "^1.0.0" - string.prototype.trim "^1.2.7" - string.prototype.trimend "^1.0.6" - string.prototype.trimstart "^1.0.6" - typed-array-length "^1.0.4" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.9" - -es-array-method-boxes-properly@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" - integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== - -es-set-tostringtag@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" - integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== - dependencies: - get-intrinsic "^1.1.3" - has "^1.0.3" - has-tostringtag "^1.0.0" - es-shim-unscopables@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" @@ -5623,7 +3494,7 @@ escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== @@ -5682,14 +3553,6 @@ eslint-plugin-import@^2.26.0: resolve "^1.22.0" tsconfig-paths "^3.14.1" -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -5706,13 +3569,6 @@ eslint-scope@^7.1.1: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-utils@^1.3.1: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" - eslint-utils@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" @@ -5720,11 +3576,6 @@ eslint-utils@^3.0.0: dependencies: eslint-visitor-keys "^2.0.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - eslint-visitor-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" @@ -5735,48 +3586,6 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@^5.6.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^4.0.3" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.7.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.13.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.11" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" - table "^5.2.3" - text-table "^0.2.0" - eslint@^8.30.0: version "8.30.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.30.0.tgz#83a506125d089eef7c5b5910eeea824273a33f50" @@ -5822,15 +3631,6 @@ eslint@^8.30.0: strip-json-comments "^3.1.0" text-table "^0.2.0" -espree@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" - integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== - dependencies: - acorn "^6.0.7" - acorn-jsx "^5.0.0" - eslint-visitor-keys "^1.0.0" - espree@^9.4.0: version "9.4.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" @@ -5845,13 +3645,6 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - esquery@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" @@ -5859,7 +3652,7 @@ esquery@^1.4.0: dependencies: estraverse "^5.1.0" -esrecurse@^4.1.0, esrecurse@^4.3.0: +esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== @@ -5886,20 +3679,7 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -eth-block-tracker@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz#95cd5e763c7293e0b1b2790a2a39ac2ac188a5e1" - integrity sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug== - dependencies: - eth-query "^2.1.0" - ethereumjs-tx "^1.3.3" - ethereumjs-util "^5.1.3" - ethjs-util "^0.1.3" - json-rpc-engine "^3.6.0" - pify "^2.3.0" - tape "^4.6.3" - -eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: +eth-ens-namehash@2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" integrity sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw== @@ -5907,35 +3687,6 @@ eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: idna-uts46-hx "^2.3.1" js-sha3 "^0.5.7" -eth-json-rpc-infura@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz#26702a821067862b72d979c016fd611502c6057f" - integrity sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw== - dependencies: - cross-fetch "^2.1.1" - eth-json-rpc-middleware "^1.5.0" - json-rpc-engine "^3.4.0" - json-rpc-error "^2.0.0" - -eth-json-rpc-middleware@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" - integrity sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q== - dependencies: - async "^2.5.0" - eth-query "^2.1.2" - eth-tx-summary "^3.1.2" - ethereumjs-block "^1.6.0" - ethereumjs-tx "^1.3.3" - ethereumjs-util "^5.1.2" - ethereumjs-vm "^2.1.0" - fetch-ponyfill "^4.0.0" - json-rpc-engine "^3.6.0" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - tape "^4.6.3" - eth-lib@0.2.8: version "0.2.8" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" @@ -5957,60 +3708,6 @@ eth-lib@^0.1.26: ws "^3.0.0" xhr-request-promise "^0.1.2" -eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" - integrity sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA== - dependencies: - json-rpc-random-id "^1.0.0" - xtend "^4.0.1" - -eth-sig-util@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.0.tgz#75133b3d7c20a5731af0690c385e184ab942b97e" - integrity sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ== - dependencies: - buffer "^5.2.1" - elliptic "^6.4.0" - ethereumjs-abi "0.6.5" - ethereumjs-util "^5.1.1" - tweetnacl "^1.0.0" - tweetnacl-util "^0.15.0" - -eth-sig-util@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" - integrity sha512-iNZ576iTOGcfllftB73cPB5AN+XUQAT/T8xzsILsghXC1o8gJUqe3RHlcDqagu+biFpYQ61KQrZZJza8eRSYqw== - dependencies: - ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" - ethereumjs-util "^5.1.1" - -eth-tx-summary@^3.1.2: - version "3.2.4" - resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" - integrity sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg== - dependencies: - async "^2.1.2" - clone "^2.0.0" - concat-stream "^1.5.1" - end-of-stream "^1.1.0" - eth-query "^2.0.2" - ethereumjs-block "^1.4.1" - ethereumjs-tx "^1.1.1" - ethereumjs-util "^5.0.1" - ethereumjs-vm "^2.6.0" - through2 "^2.0.3" - -ethashjs@~0.0.7: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.8.tgz#227442f1bdee409a548fb04136e24c874f3aa6f9" - integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw== - dependencies: - async "^2.1.2" - buffer-xor "^2.0.1" - ethereumjs-util "^7.0.2" - miller-rabin "^4.0.0" - ethereum-bloom-filters@^1.0.6: version "1.0.10" resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" @@ -6018,16 +3715,6 @@ ethereum-bloom-filters@^1.0.6: dependencies: js-sha3 "^0.8.0" -ethereum-common@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" - integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== - -ethereum-common@^0.0.18: - version "0.0.18" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" - integrity sha512-EoltVQTRNg2Uy4o84qpa2aXymXDJhxm7eos/ACOg0DG4baAbMjhbdAEsx9GeE8sC3XCxnYvrrzZDH8D8MtA2iQ== - ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" @@ -6067,26 +3754,7 @@ ethereum-types@^2.1.6: "@types/node" "*" bignumber.js "~8.0.2" -ethereum-waffle@3.4.4: - version "3.4.4" - resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.4.tgz#1378b72040697857b7f5e8f473ca8f97a37b5840" - integrity sha512-PA9+jCjw4WC3Oc5ocSMBj5sXvueWQeAbvCA+hUlb6oFgwwKyq5ka3bWQ7QZcjzIX+TdFkxP4IbFmoY2D8Dkj9Q== - dependencies: - "@ethereum-waffle/chai" "^3.4.4" - "@ethereum-waffle/compiler" "^3.4.4" - "@ethereum-waffle/mock-contract" "^3.4.4" - "@ethereum-waffle/provider" "^3.4.4" - ethers "^5.0.1" - -ethereumjs-abi@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" - integrity sha512-rCjJZ/AE96c/AAZc6O3kaog4FhOsAViaysBxqJNy2+LHP0ttH0zkZ7nXdVHOAyt6lFwLO0nlCwWszysG/ao1+g== - dependencies: - bn.js "^4.10.0" - ethereumjs-util "^4.3.0" - -ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: +ethereumjs-abi@^0.6.8: version "0.6.8" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== @@ -6094,96 +3762,20 @@ ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: bn.js "^4.11.8" ethereumjs-util "^6.0.0" -"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": - version "0.6.8" - resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0" - dependencies: - bn.js "^4.11.8" - ethereumjs-util "^6.0.0" - -ethereumjs-account@3.0.0, ethereumjs-account@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz#728f060c8e0c6e87f1e987f751d3da25422570a9" - integrity sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA== - dependencies: - ethereumjs-util "^6.0.0" - rlp "^2.2.1" - safe-buffer "^5.1.1" - -ethereumjs-account@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" - integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== +ethereumjs-util@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" + integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== dependencies: - ethereumjs-util "^5.0.0" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "^0.1.3" rlp "^2.0.0" safe-buffer "^5.1.1" -ethereumjs-block@2.2.2, ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.0, ethereumjs-block@~2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" - integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== - dependencies: - async "^2.0.1" - ethereumjs-common "^1.5.0" - ethereumjs-tx "^2.1.1" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0: - version "1.7.1" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" - integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== - dependencies: - async "^2.0.1" - ethereum-common "0.2.0" - ethereumjs-tx "^1.2.2" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-blockchain@^4.0.3: - version "4.0.4" - resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz#30f2228dc35f6dcf94423692a6902604ae34960f" - integrity sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ== - dependencies: - async "^2.6.1" - ethashjs "~0.0.7" - ethereumjs-block "~2.2.2" - ethereumjs-common "^1.5.0" - ethereumjs-util "^6.1.0" - flow-stoplight "^1.0.0" - level-mem "^3.0.1" - lru-cache "^5.1.1" - rlp "^2.2.2" - semaphore "^1.1.0" - -ethereumjs-common@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd" - integrity sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ== - -ethereumjs-common@^1.1.0, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" - integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== - -ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" - integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== - dependencies: - ethereumjs-common "^1.5.0" - ethereumjs-util "^6.0.0" - -ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3: - version "1.3.7" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" - integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== - dependencies: - ethereum-common "^0.0.18" - ethereumjs-util "^5.0.0" - -ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0, ethereumjs-util@^6.2.1: +ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== @@ -6196,31 +3788,7 @@ ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumj ethjs-util "0.1.6" rlp "^2.2.3" -ethereumjs-util@^4.3.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz#f4bf9b3b515a484e3cc8781d61d9d980f7c83bd0" - integrity sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w== - dependencies: - bn.js "^4.8.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - rlp "^2.0.0" - -ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" - integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== - dependencies: - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "^0.1.3" - rlp "^2.0.0" - safe-buffer "^5.1.1" - -ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: +ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== @@ -6231,60 +3799,7 @@ ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0, ethereu ethereum-cryptography "^0.1.3" rlp "^2.2.4" -ethereumjs-vm@4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz#e885e861424e373dbc556278f7259ff3fca5edab" - integrity sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA== - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - core-js-pure "^3.0.1" - ethereumjs-account "^3.0.0" - ethereumjs-block "^2.2.2" - ethereumjs-blockchain "^4.0.3" - ethereumjs-common "^1.5.0" - ethereumjs-tx "^2.1.2" - ethereumjs-util "^6.2.0" - fake-merkle-patricia-tree "^1.0.1" - functional-red-black-tree "^1.0.1" - merkle-patricia-tree "^2.3.2" - rustbn.js "~0.2.0" - safe-buffer "^5.1.1" - util.promisify "^1.0.0" - -ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" - integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - ethereumjs-account "^2.0.3" - ethereumjs-block "~2.2.0" - ethereumjs-common "^1.1.0" - ethereumjs-util "^6.0.0" - fake-merkle-patricia-tree "^1.0.1" - functional-red-black-tree "^1.0.1" - merkle-patricia-tree "^2.3.2" - rustbn.js "~0.2.0" - safe-buffer "^5.1.1" - -ethereumjs-wallet@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz#685e9091645cee230ad125c007658833991ed474" - integrity sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA== - dependencies: - aes-js "^3.1.1" - bs58check "^2.1.2" - ethereum-cryptography "^0.1.3" - ethereumjs-util "^6.0.0" - randombytes "^2.0.6" - safe-buffer "^5.1.2" - scryptsy "^1.2.1" - utf8 "^3.0.0" - uuid "^3.3.2" - -ethers@5.7.2, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2, ethers@^5.5.3, ethers@^5.6.5, ethers@^5.7.0, ethers@^5.7.1: +ethers@^5.6.5, ethers@^5.7.0: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -6361,11 +3876,6 @@ eventemitter3@4.0.4: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== -events@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" @@ -6409,19 +3919,6 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - expect@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/expect/-/expect-29.2.1.tgz#25752d0df92d3daa5188dc8804de1f30759658cf" @@ -6433,7 +3930,7 @@ expect@^29.2.1: jest-message-util "^29.2.1" jest-util "^29.2.1" -express@^4.14.0, express@^4.18.1, express@^4.18.2: +express@^4.14.0, express@^4.18.2: version "4.18.2" resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== @@ -6477,49 +3974,11 @@ ext@^1.1.2: dependencies: type "^2.7.2" -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -6530,23 +3989,11 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== -fake-merkle-patricia-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" - integrity sha512-Tgq37lkc9pUIgIKw5uitNUKcgcYL3R6JvXtKQbOf/ZSavXbidsksgp/pAY6p//uhw0I4yoMsvTSovvVIsk/qxA== - dependencies: - checkpoint-store "^1.1.0" - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" - integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== - fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" @@ -6563,7 +4010,7 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-sta resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== @@ -6582,27 +4029,6 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -fetch-ponyfill@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" - integrity sha512-knK9sGskIg2T7OnYLdZ2hZXn0CtDrAIBxYQLpmEf0BqfdWnwmM1weccUl5+4EdA44tzNSFAuxITPbXtPehUB3g== - dependencies: - node-fetch "~1.7.1" - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -6610,16 +4036,6 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -6640,21 +4056,6 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" -find-replace@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" - integrity sha512-KrUnjzDCD9426YnCP56zGYy/eieTnhtK6Vn++j+JJzmlsWWwEkDnsyVF575spT6HJ6Ow9tlbT3TQTDsa+O4UWA== - dependencies: - array-back "^1.0.4" - test-value "^2.1.0" - -find-replace@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" - integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== - dependencies: - array-back "^3.0.1" - find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -6663,14 +4064,6 @@ find-up@5.0.0, find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA== - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -6686,30 +4079,6 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -find-yarn-workspace-root@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" - integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== - dependencies: - fs-extra "^4.0.3" - micromatch "^3.1.4" - -find-yarn-workspace-root@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" - integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== - dependencies: - micromatch "^4.0.2" - -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -6723,59 +4092,28 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== - flatted@^3.1.0, flatted@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== -flow-stoplight@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" - integrity sha512-rDjbZUKpN8OYhB0IE/vY/I8UWO/602IIJEU/76Tv4LvYnwHCk0BCsvz4eRr9n+FQcri7L5cyaXOo0+/Kh4HisA== - -fmix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c" - integrity sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w== - dependencies: - imul "^1.0.0" - -follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.14.8, follow-redirects@^1.14.9, follow-redirects@^1.15.0: +follow-redirects@^1.12.1, follow-redirects@^1.14.8, follow-redirects@^1.14.9, follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== -for-each@^0.3.3, for-each@~0.3.3: +for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== -form-data@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -6809,23 +4147,11 @@ fp-ts@^1.0.0: resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== - dependencies: - map-cache "^0.2.2" - fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" @@ -6837,16 +4163,7 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^10.0.0, fs-extra@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" - integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-extra@^4.0.2, fs-extra@^4.0.3: +fs-extra@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== @@ -6855,7 +4172,7 @@ fs-extra@^4.0.2, fs-extra@^4.0.3: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^7.0.0, fs-extra@^7.0.1: +fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== @@ -6873,16 +4190,6 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.0, fs-extra@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - fs-minipass@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" @@ -6915,63 +4222,21 @@ function.prototype.name@^1.1.5: es-abstract "^1.19.0" functions-have-names "^1.2.2" -functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: +functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== -functions-have-names@^1.2.2, functions-have-names@^1.2.3: +functions-have-names@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -ganache-core@^2.13.2: - version "2.13.2" - resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.13.2.tgz#27e6fc5417c10e6e76e2e646671869d7665814a3" - integrity sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw== - dependencies: - abstract-leveldown "3.0.0" - async "2.6.2" - bip39 "2.5.0" - cachedown "1.0.0" - clone "2.1.2" - debug "3.2.6" - encoding-down "5.0.4" - eth-sig-util "3.0.0" - ethereumjs-abi "0.6.8" - ethereumjs-account "3.0.0" - ethereumjs-block "2.2.2" - ethereumjs-common "1.5.0" - ethereumjs-tx "2.1.2" - ethereumjs-util "6.2.1" - ethereumjs-vm "4.2.0" - heap "0.2.6" - keccak "3.0.1" - level-sublevel "6.6.4" - levelup "3.1.1" - lodash "4.17.20" - lru-cache "5.1.1" - merkle-patricia-tree "3.0.0" - patch-package "6.2.2" - seedrandom "3.0.1" - source-map-support "0.5.12" - tmp "0.1.0" - web3-provider-engine "14.2.1" - websocket "1.0.32" - optionalDependencies: - ethereumjs-wallet "0.6.5" - web3 "1.2.11" - gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -6991,16 +4256,6 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@ has "^1.0.3" has-symbols "^1.0.3" -get-intrinsic@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" - integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-proto "^1.0.1" - has-symbols "^1.0.3" - get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -7033,11 +4288,6 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== - getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -7059,18 +4309,6 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@7.1.7: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" @@ -7083,7 +4321,7 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.2.3: +glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -7103,7 +4341,7 @@ global@~4.4.0: min-document "^2.19.0" process "^0.11.10" -globals@^11.1.0, globals@^11.7.0: +globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== @@ -7115,18 +4353,6 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== - -globalthis@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" - integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== - dependencies: - define-properties "^1.1.3" - globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" @@ -7180,11 +4406,6 @@ got@^11.8.5: p-cancelable "^2.0.0" responselike "^2.0.0" -graceful-fs@^4.1.11: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" @@ -7208,117 +4429,6 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" -hardhat-deploy@0.11.22: - version "0.11.22" - resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.22.tgz#9799c0266a0fc40c84690de54760f1b4dae5e487" - integrity sha512-ZhHVNB7Jo2l8Is+KIAk9F8Q3d7pptyiX+nsNbIFXztCz81kaP+6kxNODRBqRCy7SOD3It4+iKCL6tWsPAA/jVQ== - dependencies: - "@types/qs" "^6.9.7" - axios "^0.21.1" - chalk "^4.1.2" - chokidar "^3.5.2" - debug "^4.3.2" - enquirer "^2.3.6" - ethers "^5.5.3" - form-data "^4.0.0" - fs-extra "^10.0.0" - match-all "^1.2.6" - murmur-128 "^0.2.1" - qs "^6.9.4" - zksync-web3 "^0.8.1" - -hardhat-deploy@^0.11.14: - version "0.11.31" - resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.31.tgz#1f05adc280bf7c3de502693271aa6700a043db20" - integrity sha512-86LObxQri29nxDzP7cjUyfHJ8jBF5aW60ahn883dqlw4rzc5I6ylLFQc6T2aMC2gEZI1oBc2gI2idmUulXP35g== - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/contracts" "^5.7.0" - "@ethersproject/providers" "^5.7.2" - "@ethersproject/solidity" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wallet" "^5.7.0" - "@types/qs" "^6.9.7" - axios "^0.21.1" - chalk "^4.1.2" - chokidar "^3.5.2" - debug "^4.3.2" - enquirer "^2.3.6" - ethers "^5.5.3" - form-data "^4.0.0" - fs-extra "^10.0.0" - match-all "^1.2.6" - murmur-128 "^0.2.1" - qs "^6.9.4" - zksync-web3 "^0.14.3" - -hardhat-watcher@^2.1.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/hardhat-watcher/-/hardhat-watcher-2.5.0.tgz#3ee76c3cb5b99f2875b78d176207745aa484ed4a" - integrity sha512-Su2qcSMIo2YO2PrmJ0/tdkf+6pSt8zf9+4URR5edMVti6+ShI8T3xhPrwugdyTOFuyj8lKHrcTZNKUFYowYiyA== - dependencies: - chokidar "^3.5.3" - -hardhat@^2.10.2: - version "2.16.0" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.16.0.tgz#c5611d433416b31f6ce92f733b1f1b5236ad6230" - integrity sha512-7VQEJPQRAZdtrYUZaU9GgCpP3MBNy/pTdscARNJQMWKj5C+R7V32G5uIZKIqZ4QiqXa6CBfxxe+G+ahxUbHZHA== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-blockchain" "7.0.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-evm" "2.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-statemanager" "2.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - "@nomicfoundation/ethereumjs-vm" "7.0.1" - "@nomicfoundation/solidity-analyzer" "^0.1.0" - "@sentry/node" "^5.18.1" - "@types/bn.js" "^5.1.0" - "@types/lru-cache" "^5.1.0" - abort-controller "^3.0.0" - adm-zip "^0.4.16" - aggregate-error "^3.0.0" - ansi-escapes "^4.3.0" - chalk "^2.4.2" - chokidar "^3.4.0" - ci-info "^2.0.0" - debug "^4.1.1" - enquirer "^2.3.0" - env-paths "^2.2.0" - ethereum-cryptography "^1.0.3" - ethereumjs-abi "^0.6.8" - find-up "^2.1.0" - fp-ts "1.19.3" - fs-extra "^7.0.1" - glob "7.2.0" - immutable "^4.0.0-rc.12" - io-ts "1.10.4" - keccak "^3.0.2" - lodash "^4.17.11" - mnemonist "^0.38.0" - mocha "^10.0.0" - p-map "^4.0.0" - raw-body "^2.4.1" - resolve "1.17.0" - semver "^6.3.0" - solc "0.7.3" - source-map-support "^0.5.13" - stacktrace-parser "^0.1.10" - tsort "0.0.1" - undici "^5.14.0" - uuid "^8.3.2" - ws "^7.4.6" - hardhat@^2.9.6: version "2.12.6" resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.6.tgz#ea3c058bbd81850867389d10f76037cfa52a0019" @@ -7375,13 +4485,6 @@ hardhat@^2.9.6: uuid "^8.3.2" ws "^7.4.6" -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== - dependencies: - ansi-regex "^2.0.0" - has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -7404,11 +4507,6 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" @@ -7421,38 +4519,7 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has@^1.0.3, has@~1.0.3: +has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -7497,11 +4564,6 @@ header-case@^2.0.4: capital-case "^1.0.4" tslib "^2.0.3" -heap@0.2.6: - version "0.2.6" - resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" - integrity sha512-MzzWcnfB1e4EG2vHi3dXHoBupmuXNZzx6pY6HldVS55JKKBoq3xOyzfSaZRkJp37HIhEYC78knabHff3zc4dQQ== - hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -7511,19 +4573,6 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - -hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -7590,12 +4639,7 @@ husky@^8.0.2: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.2.tgz#5816a60db02650f1f22c8b69b928fd6bcd77a236" integrity sha512-Tkv80jtvbnkK3mYWxPZePGFpQ/tT3HNSs/sasF9P2YfkMezDl3ON37YN6jUUI4eTg5LcyVynlb6r4eyvOmspvg== -hyperlinker@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e" - integrity sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ== - -iconv-lite@0.4.24, iconv-lite@^0.4.24: +iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -7621,11 +4665,6 @@ ieee754@^1.1.13, ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - ignore@^5.1.4: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" @@ -7636,29 +4675,11 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== -immediate@^3.2.3: - version "3.3.0" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" - integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== - -immediate@~3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== - immutable@^4.0.0-rc.12: version "4.2.2" resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.2.tgz#2da9ff4384a4330c36d4d1bc88e90f9e0b0ccd16" integrity sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og== -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -7675,11 +4696,6 @@ import-local@^3.0.2: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" -imul@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9" - integrity sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA== - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -7698,30 +4714,11 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inquirer@^6.2.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" - integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== - dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.12" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" - internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -7731,27 +4728,6 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" -internal-slot@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" - integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== - dependencies: - get-intrinsic "^1.2.0" - has "^1.0.3" - side-channel "^1.0.4" - -invariant@^2.2.2: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ== - io-ts@1.10.4: version "1.10.4" resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" @@ -7764,20 +4740,6 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - is-arguments@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -7786,15 +4748,6 @@ is-arguments@^1.0.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" - integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.0" - is-typed-array "^1.1.10" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -7822,11 +4775,6 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -7837,20 +4785,6 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-core-module@^2.11.0: - version "2.12.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" - integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== - dependencies: - has "^1.0.3" - is-core-module@^2.8.1, is-core-module@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" @@ -7858,20 +4792,6 @@ is-core-module@^2.8.1, is-core-module@^2.9.0: dependencies: has "^1.0.3" -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - is-date-object@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" @@ -7879,73 +4799,11 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== - -is-docker@^2.0.0, is-docker@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-finite@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" - integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== - -is-fn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" - integrity sha512-XoFPJQmsAShb3jEQRfzf2rqXavq7fIqF/jOekp308JlThqrODnMpweVSGilKTCXELfLhltGP2AGgbQGVP8F1dg== - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== - is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -7992,13 +4850,6 @@ is-number-object@^1.0.4: dependencies: has-tostringtag "^1.0.0" -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== - dependencies: - kind-of "^3.0.2" - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -8014,14 +4865,7 @@ is-plain-obj@^2.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-regex@^1.0.4, is-regex@^1.1.4, is-regex@~1.1.4: +is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== @@ -8060,25 +4904,14 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.10: - version "1.1.10" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== +is-typed-array@^1.1.3, is-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.9.tgz#246d77d2871e7d9f5aeb1d54b9f52c71329ece67" + integrity sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A== dependencies: available-typed-arrays "^1.0.5" call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - -is-typed-array@^1.1.3, is-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.9.tgz#246d77d2871e7d9f5aeb1d54b9f52c71329ece67" - integrity sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.20.0" + es-abstract "^1.20.0" for-each "^0.3.3" has-tostringtag "^1.0.0" @@ -8092,16 +4925,6 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -is-url@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" - integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== - is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -8109,50 +4932,11 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-wsl@^2.1.1, is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== - isomorphic-fetch@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" @@ -8161,11 +4945,6 @@ isomorphic-fetch@2.2.1: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" -isomorphic-ws@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" - integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== - isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -8620,16 +5399,11 @@ js-sha3@^0.7.0: resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.7.0.tgz#0a5c57b36f79882573b2d84051f8bb85dd1bd63a" integrity sha512-Wpks3yBDm0UcL5qlVhwW9Jr9n9i4FfeWBFOOXP5puDS/SiudJGhw7DPyBqn3487qD4F0lsC0q3zxink37f7zeA== -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: +js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== - js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -8637,7 +5411,7 @@ js-yaml@4.1.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: +js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -8645,31 +5419,16 @@ js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -jsbi@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-4.3.0.tgz#b54ee074fb6fcbc00619559305c8f7e912b04741" - integrity sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g== - jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA== - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== - json-buffer@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" @@ -8680,50 +5439,16 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== -json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" - integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== - dependencies: - async "^2.0.1" - babel-preset-env "^1.7.0" - babelify "^7.3.0" - json-rpc-error "^2.0.0" - promise-to-callback "^1.0.0" - safe-event-emitter "^1.0.1" - -json-rpc-error@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" - integrity sha512-EwUeWP+KgAZ/xqFpaP6YDAXMtCJi+o/QQpCQFIYyxr01AdADi2y413eM8hSqJcoQym9WMePAJWoaODEJufC4Ug== - dependencies: - inherits "^2.0.1" - -json-rpc-random-id@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" - integrity sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA== - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - json-schema@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" @@ -8734,23 +5459,11 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json-stable-stringify@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" - integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== - dependencies: - jsonify "^0.0.1" - json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw== - json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -8777,25 +5490,6 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -jsonify@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" - integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== - -jsonparse@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== - jsprim@^1.2.2: version "1.4.2" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" @@ -8806,14 +5500,6 @@ jsprim@^1.2.2: json-schema "0.4.0" verror "1.10.0" -keccak@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff" - integrity sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA== - dependencies: - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - keccak@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" @@ -8846,37 +5532,6 @@ keyv@^3.0.0: dependencies: json-buffer "3.0.0" -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -klaw-sync@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" - integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== - dependencies: - graceful-fs "^4.1.11" - klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" @@ -8889,118 +5544,11 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw== - dependencies: - invert-kv "^1.0.0" - lens.ts@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/lens.ts/-/lens.ts-0.5.1.tgz#957cd81838ea7359b0c280f24f9478bc6e92bafc" integrity sha512-cxzQxbitr78SnkulxKsdPC6v/+1CHmB4j2sMt2KXcbiCXLHphYZtOWYNIB1PumO5hCHescODqwhURB/OH/j5VA== -level-codec@^9.0.0: - version "9.0.2" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" - integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== - dependencies: - buffer "^5.6.0" - -level-codec@~7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" - integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== - -level-errors@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" - integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== - dependencies: - errno "~0.1.1" - -level-errors@^2.0.0, level-errors@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" - integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== - dependencies: - errno "~0.1.1" - -level-errors@~1.0.3: - version "1.0.5" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" - integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== - dependencies: - errno "~0.1.1" - -level-iterator-stream@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz#ccfff7c046dcf47955ae9a86f46dfa06a31688b4" - integrity sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig== - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.5" - xtend "^4.0.0" - -level-iterator-stream@~1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" - integrity sha512-1qua0RHNtr4nrZBgYlpV0qHHeHpcRRWTxEZJ8xsemoHAXNL5tbooh4tPEEqIqsbWCAJBmUmkwYK/sW5OrFjWWw== - dependencies: - inherits "^2.0.1" - level-errors "^1.0.3" - readable-stream "^1.0.33" - xtend "^4.0.0" - -level-iterator-stream@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz#2c98a4f8820d87cdacab3132506815419077c730" - integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== - dependencies: - inherits "^2.0.1" - readable-stream "^2.3.6" - xtend "^4.0.0" - -level-mem@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-3.0.1.tgz#7ce8cf256eac40f716eb6489654726247f5a89e5" - integrity sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg== - dependencies: - level-packager "~4.0.0" - memdown "~3.0.0" - -level-packager@~4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-4.0.1.tgz#7e7d3016af005be0869bc5fa8de93d2a7f56ffe6" - integrity sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q== - dependencies: - encoding-down "~5.0.0" - levelup "^3.0.0" - -level-post@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/level-post/-/level-post-1.0.7.tgz#19ccca9441a7cc527879a0635000f06d5e8f27d0" - integrity sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew== - dependencies: - ltgt "^2.1.2" - -level-sublevel@6.6.4: - version "6.6.4" - resolved "https://registry.yarnpkg.com/level-sublevel/-/level-sublevel-6.6.4.tgz#f7844ae893919cd9d69ae19d7159499afd5352ba" - integrity sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA== - dependencies: - bytewise "~1.1.0" - level-codec "^9.0.0" - level-errors "^2.0.0" - level-iterator-stream "^2.0.3" - ltgt "~2.1.1" - pull-defer "^0.2.2" - pull-level "^2.0.3" - pull-stream "^3.6.8" - typewiselite "~1.0.0" - xtend "~4.0.0" - level-supports@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" @@ -9014,23 +5562,6 @@ level-transcoder@^1.0.1: buffer "^6.0.3" module-error "^1.0.1" -level-ws@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" - integrity sha512-XUTaO/+Db51Uiyp/t7fCMGVFOTdtLS/NIACxE/GHsij15mKzxksZifKVjlXDF41JMUP/oM1Oc4YNGdKnc3dVLw== - dependencies: - readable-stream "~1.0.15" - xtend "~2.1.1" - -level-ws@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-1.0.0.tgz#19a22d2d4ac57b18cc7c6ecc4bd23d899d8f603b" - integrity sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q== - dependencies: - inherits "^2.0.3" - readable-stream "^2.2.8" - xtend "^4.0.1" - level@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/level/-/level-8.0.0.tgz#41b4c515dabe28212a3e881b61c161ffead14394" @@ -9039,42 +5570,11 @@ level@^8.0.0: browser-level "^1.0.1" classic-level "^1.2.0" -levelup@3.1.1, levelup@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" - integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== - dependencies: - deferred-leveldown "~4.0.0" - level-errors "~2.0.0" - level-iterator-stream "~3.0.0" - xtend "~4.0.0" - -levelup@^1.2.1: - version "1.3.9" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" - integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== - dependencies: - deferred-leveldown "~1.2.1" - level-codec "~7.0.0" - level-errors "~1.0.3" - level-iterator-stream "~1.3.0" - prr "~1.0.1" - semver "~5.4.1" - xtend "~4.0.0" - leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -9088,17 +5588,6 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A== - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -9121,21 +5610,6 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash.assign@^4.0.3, lodash.assign@^4.0.6: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - integrity sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw== - -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== - -lodash.flatmap@4.5.0, lodash.flatmap@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e" - integrity sha512-/OcpcAGWlrZyoHGeHh3cAoa6nGdX6QYtmzNP84Jqol6UEQQ2gIaU3H+0eICcjcKGl0/XF8LWOujNn9lffsnaOg== - lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -9146,17 +5620,7 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.truncate@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" - integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== - -lodash@4.17.20: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== - -lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.4: +lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -9180,23 +5644,6 @@ log4js@6.6.1: rfdc "^1.3.0" streamroller "^3.1.2" -looper@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" - integrity sha512-6DzMHJcjbQX/UPHc1rRCBfKlLwDkvuGZ715cIR36wSdYqWXFT35uLXq5P/2orl3tz+t+VOVPxw4yPinQlUDGDQ== - -looper@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" - integrity sha512-LJ9wplN/uSn72oJRsXTx+snxPet5c8XiZmOKCm906NVYu+ag6SB6vUcnJcWxgnl2NfbIyeobAn7Bwv6xRj2XJg== - -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - loupe@^2.3.1: version "2.3.6" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" @@ -9221,20 +5668,13 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== -lru-cache@5.1.1, lru-cache@^5.1.1: +lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" -lru-cache@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" - integrity sha512-91gyOKTc2k66UG6kHiH4h3S2eltcPwE1STVfMYC/NG+nZwf8IIuiamfmpGZjpbbxzSyEJaLC0tNSmhjlQUTJow== - dependencies: - pseudomap "^1.0.1" - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -9247,16 +5687,6 @@ lru_map@^0.3.3: resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== -ltgt@^2.1.2, ltgt@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" - integrity sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA== - -ltgt@~2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" - integrity sha512-5VjHC5GsENtIi5rbJd+feEpDKhfr7j0odoUR2Uh978g+2p93nd5o34cTjQWohXsPsCZeqoDnIqEf88mPCe0Pfw== - make-dir@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -9276,23 +5706,6 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== - dependencies: - object-visit "^1.0.0" - -match-all@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" - integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== - mcl-wasm@^0.7.1: version "0.7.9" resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" @@ -9312,30 +5725,6 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -memdown@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" - integrity sha512-iVrGHZB8i4OQfM155xx8akvG9FIj+ht14DX5CQkCTG4EHzZ3d3sgckIf/Lm9ivZalEsFuEVnWv2B2WZvbrro2w== - dependencies: - abstract-leveldown "~2.7.1" - functional-red-black-tree "^1.0.1" - immediate "^3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.1.1" - -memdown@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-3.0.0.tgz#93aca055d743b20efc37492e9e399784f2958309" - integrity sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA== - dependencies: - abstract-leveldown "~5.0.0" - functional-red-black-tree "~1.0.1" - immediate "~3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.1.1" - memory-level@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" @@ -9365,33 +5754,6 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -merkle-patricia-tree@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz#448d85415565df72febc33ca362b8b614f5a58f8" - integrity sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ== - dependencies: - async "^2.6.1" - ethereumjs-util "^5.2.0" - level-mem "^3.0.1" - level-ws "^1.0.0" - readable-stream "^3.0.6" - rlp "^2.0.0" - semaphore ">=1.0.1" - -merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" - integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== - dependencies: - async "^1.4.2" - ethereumjs-util "^5.0.0" - level-ws "0.0.0" - levelup "^1.2.1" - memdown "^1.0.0" - readable-stream "^2.0.0" - rlp "^2.0.0" - semaphore ">=1.0.1" - merkletreejs@^0.2.27: version "0.2.32" resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.2.32.tgz#cf1c0760e2904e4a1cc269108d6009459fd06223" @@ -9408,26 +5770,7 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== -micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -micromatch@^4.0.2, micromatch@^4.0.4: +micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -9460,11 +5803,6 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -9516,11 +5854,6 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== -minimist@~1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" @@ -9536,19 +5869,6 @@ minizlib@^1.3.3: dependencies: minipass "^2.9.0" -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp-classic@^0.5.2: - version "0.5.3" - resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" - integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== - mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" @@ -9556,12 +5876,12 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@^1.0.4: +mkdirp@*: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@^0.5.1, mkdirp@^0.5.5: +mkdirp@^0.5.5: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -9683,25 +6003,6 @@ multimatch@^4.0.0: arrify "^2.0.1" minimatch "^3.0.4" -murmur-128@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d" - integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg== - dependencies: - encode-utf8 "^1.0.2" - fmix "^0.1.0" - imul "^1.0.0" - -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== - -nan@^2.17.0: - version "2.17.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" - integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== - nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" @@ -9712,23 +6013,6 @@ nanoid@3.3.3: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - napi-macros@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" @@ -9754,11 +6038,6 @@ next-tick@^1.1.0: resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -9779,13 +6058,6 @@ node-cache@^5.1.2: dependencies: clone "2.x" -node-fetch@2.6.6: - version "2.6.6" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89" - integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA== - dependencies: - whatwg-url "^5.0.0" - node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -9793,7 +6065,7 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@^1.0.1, node-fetch@~1.7.1: +node-fetch@^1.0.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== @@ -9801,13 +6073,6 @@ node-fetch@^1.0.1, node-fetch@~1.7.1: encoding "^0.1.11" is-stream "^1.0.1" -node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: - version "2.6.11" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25" - integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w== - dependencies: - whatwg-url "^5.0.0" - node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40" @@ -9823,21 +6088,6 @@ node-releases@^2.0.6: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== -nofilter@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" - integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== - -normalize-package-data@^2.3.2: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -9860,11 +6110,6 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== - number-to-bn@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" @@ -9878,55 +6123,21 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4, object-assign@^4.0.0, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - object-inspect@^1.12.2, object-inspect@^1.9.0: version "1.12.2" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== -object-inspect@^1.12.3, object-inspect@~1.12.3: - version "1.12.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" - integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== - -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-keys@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw== - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== - dependencies: - isobject "^3.0.0" - object.assign@^4.1.2, object.assign@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" @@ -9946,24 +6157,6 @@ object.entries@^1.1.5: define-properties "^1.1.4" es-abstract "^1.20.4" -object.getownpropertydescriptors@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz#5e5c384dd209fa4efffead39e3a0512770ccc312" - integrity sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ== - dependencies: - array.prototype.reduce "^1.0.5" - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.21.2" - safe-array-concat "^1.0.0" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== - dependencies: - isobject "^3.0.1" - object.values@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" @@ -9978,13 +6171,6 @@ obliterator@^2.0.0: resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== -oboe@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" - integrity sha512-ymBJ4xSC6GBXLT9Y7lirj+xbqBLa+jADGJldGEYG7u8sZbS9GyG+u1Xk9c5cbriKwSpCg41qUhPjvU5xOpvIyQ== - dependencies: - http-https "^1.0.0" - oboe@2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" @@ -10006,13 +6192,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== - dependencies: - mimic-fn "^1.0.0" - onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -10020,35 +6199,6 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -open@^7.4.2: - version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" - integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - -open@^8.4.0: - version "8.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" - integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== - dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" - -optionator@^0.8.2: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -10061,19 +6211,7 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== - -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g== - dependencies: - lcid "^1.0.0" - -os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: +os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== @@ -10178,21 +6316,6 @@ parse-headers@^2.0.0: resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9" integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA== -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== - dependencies: - error-ex "^1.2.0" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -10216,54 +6339,6 @@ pascal-case@^3.1.2: no-case "^3.0.4" tslib "^2.0.3" -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== - -patch-package@6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.2.tgz#71d170d650c65c26556f0d0fbbb48d92b6cc5f39" - integrity sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg== - dependencies: - "@yarnpkg/lockfile" "^1.1.0" - chalk "^2.4.2" - cross-spawn "^6.0.5" - find-yarn-workspace-root "^1.2.1" - fs-extra "^7.0.1" - is-ci "^2.0.0" - klaw-sync "^6.0.0" - minimist "^1.2.0" - rimraf "^2.6.3" - semver "^5.6.0" - slash "^2.0.0" - tmp "^0.0.33" - -patch-package@^6.2.2: - version "6.5.1" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" - integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== - dependencies: - "@yarnpkg/lockfile" "^1.1.0" - chalk "^4.1.2" - cross-spawn "^6.0.5" - find-yarn-workspace-root "^2.0.0" - fs-extra "^9.0.0" - is-ci "^2.0.0" - klaw-sync "^6.0.0" - minimist "^1.2.6" - open "^7.4.2" - rimraf "^2.6.3" - semver "^5.6.0" - slash "^2.0.0" - tmp "^0.0.33" - yaml "^1.10.2" - -path-browserify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" - integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== - path-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/path-case/-/path-case-3.0.4.tgz#9168645334eb942658375c56f80b4c0cb5f82c6f" @@ -10272,13 +6347,6 @@ path-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ== - dependencies: - pinkie-promise "^2.0.0" - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -10289,21 +6357,11 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: +path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== - -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== - path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -10319,15 +6377,6 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg== - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -10338,7 +6387,7 @@ pathval@^1.1.1: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: +pbkdf2@^3.0.17, pbkdf2@^3.0.3: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -10364,23 +6413,6 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pify@^2.0.0, pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== - pirates@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" @@ -10398,46 +6430,16 @@ popper.js@1.14.3: resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" integrity sha512-3lmujhsHXzb83+sI0PzfrE3O1XHZG8m8MXNMTupvA6LrM1/nnsiqYaacYc/RIente9VqnTDPztGEM8uvPAMGyg== -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== - -postinstall-postinstall@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" - integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== - -precond@0.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" - integrity sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ== - prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== - prepend-http@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== -prettier@^1.14.3: - version "1.19.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" - integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== - -prettier@^2.1.2, prettier@^2.3.1: - version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== - prettier@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc" @@ -10474,35 +6476,12 @@ pretty-quick@^3.1.3: mri "^1.1.5" multimatch "^4.0.0" -private@^0.1.6, private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -promise-to-callback@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" - integrity sha512-uhMIZmKM5ZteDMfLgJnoSq9GCwsNKrYau73Awf1jIy6/eUcuuZ3P+CD9zUv0kJsIUbU+x6uLNIhXhLHDs1pNPA== - dependencies: - is-fn "^1.0.0" - set-immediate-shim "^1.0.1" - -prompts@^2.0.1, prompts@^2.4.2: +prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -10523,16 +6502,6 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== - -pseudomap@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== - psl@^1.1.28: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -10550,62 +6519,6 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" -pull-cat@^1.1.9: - version "1.1.11" - resolved "https://registry.yarnpkg.com/pull-cat/-/pull-cat-1.1.11.tgz#b642dd1255da376a706b6db4fa962f5fdb74c31b" - integrity sha512-i3w+xZ3DCtTVz8S62hBOuNLRHqVDsHMNZmgrZsjPnsxXUgbWtXEee84lo1XswE7W2a3WHyqsNuDJTjVLAQR8xg== - -pull-defer@^0.2.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/pull-defer/-/pull-defer-0.2.3.tgz#4ee09c6d9e227bede9938db80391c3dac489d113" - integrity sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA== - -pull-level@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pull-level/-/pull-level-2.0.4.tgz#4822e61757c10bdcc7cf4a03af04c92734c9afac" - integrity sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg== - dependencies: - level-post "^1.0.7" - pull-cat "^1.1.9" - pull-live "^1.0.1" - pull-pushable "^2.0.0" - pull-stream "^3.4.0" - pull-window "^2.1.4" - stream-to-pull-stream "^1.7.1" - -pull-live@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pull-live/-/pull-live-1.0.1.tgz#a4ecee01e330155e9124bbbcf4761f21b38f51f5" - integrity sha512-tkNz1QT5gId8aPhV5+dmwoIiA1nmfDOzJDlOOUpU5DNusj6neNd3EePybJ5+sITr2FwyCs/FVpx74YMCfc8YeA== - dependencies: - pull-cat "^1.1.9" - pull-stream "^3.4.0" - -pull-pushable@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.2.0.tgz#5f2f3aed47ad86919f01b12a2e99d6f1bd776581" - integrity sha512-M7dp95enQ2kaHvfCt2+DJfyzgCSpWVR2h2kWYnVsW6ZpxQBx5wOu0QWOvQPVoPnBLUZYitYP2y7HyHkLQNeGXg== - -pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: - version "3.7.0" - resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.7.0.tgz#85de0e44ff38a4d2ad08cc43fc458e1922f9bf0b" - integrity sha512-Eco+/R004UaCK2qEDE8vGklcTG2OeZSVm1kTUQNrykEjDwcFXDZhygFDsW49DbXyJMEhHeRL3z5cRVqPAhXlIw== - -pull-window@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/pull-window/-/pull-window-2.1.4.tgz#fc3b86feebd1920c7ae297691e23f705f88552f0" - integrity sha512-cbDzN76BMlcGG46OImrgpkMf/VkCnupj8JhsrpBw3aWBM9ye345aYnqitmZCgauBkc0HbbRRn9hCnsa3k2FNUg== - dependencies: - looper "^2.0.0" - -pump@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" - integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -10619,11 +6532,6 @@ punycode@2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" integrity sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA== -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== - punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -10636,13 +6544,6 @@ qs@6.11.0, qs@^6.7.0: dependencies: side-channel "^1.0.4" -qs@^6.11.0, qs@^6.9.4: - version "6.11.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" - integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== - dependencies: - side-channel "^1.0.4" - qs@~6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" @@ -10667,7 +6568,7 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== @@ -10707,55 +6608,6 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A== - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ== - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -readable-stream@^1.0.33: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -10765,16 +6617,6 @@ readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@~1.0.15, readable-stream@~1.0.26-4: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -10782,47 +6624,6 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -reduce-flatten@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" - integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== - -regenerate@^1.2.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - -regenerator-transform@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== - dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" - private "^0.1.6" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexp.prototype.flags@^1.2.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" - integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - functions-have-names "^1.2.3" - regexp.prototype.flags@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" @@ -10832,55 +6633,12 @@ regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - integrity sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ== - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - integrity sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g== - -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - integrity sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw== - dependencies: - jsesc "~0.5.0" - -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A== - dependencies: - is-finite "^1.0.0" - -request@^2.79.0, request@^2.85.0: +request@^2.79.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -10911,21 +6669,11 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -require-from-string@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" - integrity sha512-H7AkJWMobeskkttHyhTVtS0fxpFLjxhbfMa6Bk3wimP7sdPRGL3EyCg3sAQenFfAe+xQ+oAc85Nmtvq0ROM83Q== - -require-from-string@^2.0.0, require-from-string@^2.0.2: +require-from-string@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== - resolve-alpn@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" @@ -10938,11 +6686,6 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -10953,11 +6696,6 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== - resolve.exports@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" @@ -10970,15 +6708,6 @@ resolve@1.17.0: dependencies: path-parse "^1.0.6" -resolve@^1.10.0, resolve@^1.8.1, resolve@~1.22.1: - version "1.22.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" - integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== - dependencies: - is-core-module "^2.11.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - resolve@^1.20.0, resolve@^1.22.0: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" @@ -11002,26 +6731,6 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -resumer@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" - integrity sha512-Fn9X8rX8yYF4m81rZCK/5VmrmsSbqS/i3rDLl6ZZHAXgC2nTAx3dhwG8q8odP/RmdLa2YrybDJaAMg+X1ajY3w== - dependencies: - through "~2.3.4" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -11032,14 +6741,7 @@ rfdc@^1.3.0: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -rimraf@^2.2.8, rimraf@^2.6.3: +rimraf@^2.2.8: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -11061,18 +6763,13 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.7: +rlp@^2.0.0, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.7: version "2.2.7" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== dependencies: bn.js "^5.2.0" -run-async@^2.2.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - run-parallel-limit@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" @@ -11092,40 +6789,16 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== -rxjs@^6.4.0: - version "6.6.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" - integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== - dependencies: - tslib "^1.9.0" - -safe-array-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" - integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.0" - has-symbols "^1.0.3" - isarray "^2.0.5" - safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@~5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-event-emitter@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" - integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== - dependencies: - events "^3.0.0" - safe-regex-test@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" @@ -11135,13 +6808,6 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== - dependencies: - ret "~0.1.10" - "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -11157,13 +6823,6 @@ scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== -scryptsy@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" - integrity sha512-aldIRgMozSJ/Gl6K6qmJZysRP82lz83Wb42vl4PWN8SaLFHIaOzLPc9nUUW2jQN88CuGm5q5HefJ9jZ3nWSmTw== - dependencies: - pbkdf2 "^3.0.3" - secp256k1@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" @@ -11173,21 +6832,6 @@ secp256k1@^4.0.1: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" -seedrandom@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.1.tgz#eb3dde015bcf55df05a233514e5df44ef9dce083" - integrity sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg== - -semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" - integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== - -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - semver@7.x, semver@^7.3.5, semver@^7.3.7: version "7.3.8" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" @@ -11195,16 +6839,16 @@ semver@7.x, semver@^7.3.5, semver@^7.3.7: dependencies: lru-cache "^6.0.0" +semver@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@~5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== - send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -11261,26 +6905,6 @@ servify@^0.1.12: request "^2.79.0" xhr "^2.3.3" -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - integrity sha512-Li5AOqrZWCVA2n5kryzEmqai6bKSIvpz5oUJHPVj6+dsbD3X1ixtsY5tEnsaNpH3pFAHmG8eIHUrtEtohrg+UQ== - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - setimmediate@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" @@ -11304,13 +6928,6 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== - dependencies: - shebang-regex "^1.0.0" - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -11318,11 +6935,6 @@ shebang-command@^2.0.0: dependencies: shebang-regex "^3.0.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== - shebang-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" @@ -11361,39 +6973,11 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg== - -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== - slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - snake-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" @@ -11402,36 +6986,6 @@ snake-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - solc@0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" @@ -11447,70 +7001,6 @@ solc@0.7.3: semver "^5.5.0" tmp "0.0.33" -solc@^0.4.20: - version "0.4.26" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.26.tgz#5390a62a99f40806b86258c737c1cf653cc35cb5" - integrity sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA== - dependencies: - fs-extra "^0.30.0" - memorystream "^0.3.1" - require-from-string "^1.1.0" - semver "^5.3.0" - yargs "^4.7.1" - -solc@^0.6.3: - version "0.6.12" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.6.12.tgz#48ac854e0c729361b22a7483645077f58cba080e" - integrity sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g== - dependencies: - command-exists "^1.2.8" - commander "3.0.2" - fs-extra "^0.30.0" - js-sha3 "0.8.0" - memorystream "^0.3.1" - require-from-string "^2.0.0" - semver "^5.5.0" - tmp "0.0.33" - -solhint@^2.0.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/solhint/-/solhint-2.3.1.tgz#6fee8fc2635112bf5812f7cba8359c14e9d9a491" - integrity sha512-wP/G+Dqj8LNWlCI9Mt6XiQRWQfZwv1rkZe/V+HKtip5SAZJVvp144PdH28KE45ZvR99Hhrp/Mujt74fSmXsFiw== - dependencies: - ajv "^6.6.1" - antlr4 "4.7.1" - chalk "^2.4.2" - commander "2.18.0" - cosmiconfig "^5.0.7" - eslint "^5.6.0" - fast-diff "^1.1.2" - glob "^7.1.3" - ignore "^4.0.6" - js-yaml "^3.12.0" - lodash "^4.17.11" - semver "^6.3.0" - optionalDependencies: - prettier "^1.14.3" - -source-map-resolve@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@0.5.12: - version "0.5.12" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" - integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -11519,13 +7009,6 @@ source-map-support@0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - source-map-support@^0.5.13: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -11534,75 +7017,16 @@ source-map-support@^0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - -source-map@^0.5.6, source-map@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== - source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -spdx-correct@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" - integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.13" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz#7189a474c46f8d47c7b0da4b987bb45e908bd2d5" - integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w== - -split-ca@^1.0.0, split-ca@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" - integrity sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ== - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -ssh2@^1.11.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-1.14.0.tgz#8f68440e1b768b66942c9e4e4620b2725b3555bb" - integrity sha512-AqzD1UCqit8tbOKoj6ztDDi1ffJZ2rV2SwlgrVVrHPkV5vWqGJOVp5pmtj18PunkPJAuKQsnInyKV+/Nb2bUnA== - dependencies: - asn1 "^0.2.6" - bcrypt-pbkdf "^1.0.2" - optionalDependencies: - cpu-features "~0.0.8" - nan "^2.17.0" - sshpk@^1.7.0: version "1.17.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" @@ -11632,27 +7056,11 @@ stacktrace-parser@^0.1.10: dependencies: type-fest "^0.7.1" -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -stream-to-pull-stream@^1.7.1: - version "1.7.3" - resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz#4161aa2d2eb9964de60bfa1af7feaf917e874ece" - integrity sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg== - dependencies: - looper "^3.0.0" - pull-stream "^3.2.3" - streamroller@^3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.1.3.tgz#d95689a8c29b30d093525d0baffe6616fd62ca7e" @@ -11672,11 +7080,6 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== -string-format@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" - integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== - string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -11685,32 +7088,6 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string-width@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -11720,15 +7097,6 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.trim@^1.2.7, string.prototype.trim@~1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" - integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - string.prototype.trimend@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" @@ -11772,39 +7140,6 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -11812,13 +7147,6 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== - dependencies: - is-utf8 "^0.2.0" - strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -11846,11 +7174,6 @@ strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1. resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strip-json-comments@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - supports-color@8.1.1, supports-color@^8.0.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -11858,11 +7181,6 @@ supports-color@8.1.1, supports-color@^8.0.0: dependencies: has-flag "^4.0.0" -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -11887,113 +7205,17 @@ swarm-js@^0.1.40: resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.42.tgz#497995c62df6696f6e22372f457120e43e727979" integrity sha512-BV7c/dVlA3R6ya1lMlSSNPLYrntt0LUq4YMgy3iwpCIc6rZnS5W2wUoctarZ5pXlpKtxDDf9hNziEkcfrxdhqQ== dependencies: - bluebird "^3.5.0" - buffer "^5.0.5" - eth-lib "^0.1.26" - fs-extra "^4.0.2" - got "^11.8.5" - mime-types "^2.1.16" - mkdirp-promise "^5.0.1" - mock-fs "^4.1.0" - setimmediate "^1.0.5" - tar "^4.0.2" - xhr-request "^1.0.1" - -table-layout@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" - integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== - dependencies: - array-back "^4.0.1" - deep-extend "~0.6.0" - typical "^5.2.0" - wordwrapjs "^4.0.0" - -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== - dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" - -table@^6.8.0: - version "6.8.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" - integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== - dependencies: - ajv "^8.0.1" - lodash.truncate "^4.4.2" - slice-ansi "^4.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" - -tape@^4.6.3: - version "4.16.2" - resolved "https://registry.yarnpkg.com/tape/-/tape-4.16.2.tgz#7565e6af20426565557266e9dda7215869b297b6" - integrity sha512-TUChV+q0GxBBCEbfCYkGLkv8hDJYjMdSWdE0/Lr331sB389dsvFUHNV9ph5iQqKzt8Ss9drzcda/YeexclBFqg== - dependencies: - call-bind "~1.0.2" - deep-equal "~1.1.1" - defined "~1.0.1" - dotignore "~0.1.2" - for-each "~0.3.3" - glob "~7.2.3" - has "~1.0.3" - inherits "~2.0.4" - is-regex "~1.1.4" - minimist "~1.2.7" - object-inspect "~1.12.3" - resolve "~1.22.1" - resumer "~0.0.0" - string.prototype.trim "~1.2.7" - through "~2.3.8" - -tar-fs@~1.16.3: - version "1.16.3" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" - integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw== - dependencies: - chownr "^1.0.1" - mkdirp "^0.5.1" - pump "^1.0.0" - tar-stream "^1.1.2" - -tar-fs@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" - integrity sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA== - dependencies: - chownr "^1.1.1" - mkdirp-classic "^0.5.2" - pump "^3.0.0" - tar-stream "^2.0.0" - -tar-stream@^1.1.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== - dependencies: - bl "^1.0.0" - buffer-alloc "^1.2.0" - end-of-stream "^1.0.0" - fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.1" - xtend "^4.0.0" - -tar-stream@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" - integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== - dependencies: - bl "^4.0.3" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" + bluebird "^3.5.0" + buffer "^5.0.5" + eth-lib "^0.1.26" + fs-extra "^4.0.2" + got "^11.8.5" + mime-types "^2.1.16" + mkdirp-promise "^5.0.1" + mock-fs "^4.1.0" + setimmediate "^1.0.5" + tar "^4.0.2" + xhr-request "^1.0.1" tar@^4.0.2: version "4.4.19" @@ -12008,20 +7230,6 @@ tar@^4.0.2: safe-buffer "^5.2.1" yallist "^3.1.1" -tenderly@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tenderly/-/tenderly-0.0.3.tgz#8c85e287e080073502420d5c6f13f4762d0f59cd" - integrity sha512-dVf2uxrIOeLDRNDEXcQlV2xJt50TIx8zGQKlNj1deYTV3FYu2L0zheHBHaDU12GqAff2iiGYk+fKqFkK0bB0+w== - dependencies: - axios "^0.27.2" - cli-table3 "^0.6.2" - commander "^9.4.0" - express "^4.18.1" - hyperlinker "^1.0.0" - js-yaml "^4.1.0" - open "^8.4.0" - prompts "^2.4.2" - test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -12031,106 +7239,38 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -test-value@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" - integrity sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w== - dependencies: - array-back "^1.0.3" - typical "^2.6.0" - -testrpc@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/testrpc/-/testrpc-0.0.1.tgz#83e2195b1f5873aec7be1af8cbe6dcf39edb7aed" - integrity sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA== - text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -through2@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -"through@>=2.2.7 <3", through@^2.3.6, through@~2.3.4, through@~2.3.8: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== -tiny-invariant@1.3.1, tiny-invariant@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" - integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== - -tiny-warning@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" - integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== - -tmp@0.0.33, tmp@^0.0.33: +tmp@0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" -tmp@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" - integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== - dependencies: - rimraf "^2.6.3" - tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== -to-buffer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== - dependencies: - kind-of "^3.0.2" - to-readable-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -12138,21 +7278,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -toformat@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/toformat/-/toformat-2.0.0.tgz#7a043fd2dfbe9021a4e36e508835ba32056739d8" - integrity sha512-03SWBVop6nU8bpyZCx7SodpYznbZF5R4ljwNLBcTQzKOD9xuihRo/psX58llS1BMFhhAI08H3luot5GoXJz2pQ== - toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -12176,61 +7301,16 @@ treeify@^1.1.0: resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== - -ts-command-line-args@^2.2.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz#e64456b580d1d4f6d948824c274cf6fa5f45f7f0" - integrity sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw== - dependencies: - chalk "^4.1.0" - command-line-args "^5.1.1" - command-line-usage "^6.1.0" - string-format "^2.0.0" - ts-essentials@9.1.2: version "9.1.2" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-9.1.2.tgz#46db6944b73b4cd603f3d959ef1123c16ba56f59" integrity sha512-EaSmXsAhEiirrTY1Oaa7TSpei9dzuCuFPmjKRJRPamERYtfaGS8/KpOSbjergLz/Y76/aZlV9i/krgzsuWEBbg== -ts-essentials@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" - integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== - -ts-essentials@^6.0.3: - version "6.0.7" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.7.tgz#5f4880911b7581a873783740ce8b94da163d18a6" - integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== - -ts-essentials@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" - integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== - ts-essentials@^9.1.2: version "9.3.0" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-9.3.0.tgz#7e639c1a76b1805c3c60d6e1b5178da2e70aea02" integrity sha512-XeiCboEyBG8UqXZtXl59bWEi4ZgOqRsogFDI6WDGIF1LmzbYiAkIwjkXN6zZWWl4re/lsOqMlYfe8KA0XiiEPw== -ts-generator@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" - integrity sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ== - dependencies: - "@types/mkdirp" "^0.5.2" - "@types/prettier" "^2.1.1" - "@types/resolve" "^0.0.8" - chalk "^2.4.1" - glob "^7.1.2" - mkdirp "^0.5.1" - prettier "^2.1.2" - resolve "^1.8.1" - ts-essentials "^1.0.0" - ts-jest@^29.0.3: version "29.0.3" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.0.3.tgz#63ea93c5401ab73595440733cefdba31fcf9cb77" @@ -12274,7 +7354,7 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.8.1, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -12303,7 +7383,7 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -tweetnacl-util@^0.15.0, tweetnacl-util@^0.15.1: +tweetnacl-util@^0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== @@ -12313,7 +7393,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== -tweetnacl@^1.0.0, tweetnacl@^1.0.3: +tweetnacl@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== @@ -12325,13 +7405,6 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== - dependencies: - prelude-ls "~1.1.2" - type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -12370,44 +7443,6 @@ type@^2.7.2: resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== -typechain@8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.1.1.tgz#9c2e8012c2c4c586536fc18402dcd7034c4ff0bd" - integrity sha512-uF/sUvnXTOVF2FHKhQYnxHk4su4JjZR8vr4mA2mBaRwHTbwh0jIlqARz9XJr1tA0l7afJGvEa1dTSi4zt039LQ== - dependencies: - "@types/prettier" "^2.1.1" - debug "^4.3.1" - fs-extra "^7.0.0" - glob "7.1.7" - js-sha3 "^0.8.0" - lodash "^4.17.15" - mkdirp "^1.0.4" - prettier "^2.3.1" - ts-command-line-args "^2.2.0" - ts-essentials "^7.0.1" - -typechain@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-3.0.0.tgz#d5a47700831f238e43f7429b987b4bb54849b92e" - integrity sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg== - dependencies: - command-line-args "^4.0.7" - debug "^4.1.1" - fs-extra "^7.0.0" - js-sha3 "^0.8.0" - lodash "^4.17.15" - ts-essentials "^6.0.3" - ts-generator "^0.1.1" - -typed-array-length@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" - integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== - dependencies: - call-bind "^1.0.2" - for-each "^0.3.3" - is-typed-array "^1.1.9" - typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -12415,48 +7450,11 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== - typescript@4.6.4: version "4.6.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg== -typewise-core@^1.2, typewise-core@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" - integrity sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg== - -typewise@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" - integrity sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ== - dependencies: - typewise-core "^1.2.0" - -typewiselite@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typewiselite/-/typewiselite-1.0.0.tgz#c8882fa1bb1092c06005a97f34ef5c8508e3664e" - integrity sha512-J9alhjVHupW3Wfz6qFRGgQw0N3gr8hOkw6zm7FZ6UR1Cse/oD9/JVok7DNE9TT9IbciDHX2Ex9+ksE6cRmtymw== - -typical@^2.6.0, typical@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" - integrity sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg== - -typical@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" - integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== - -typical@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" - integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== - ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" @@ -12477,11 +7475,6 @@ underscore@1.12.1: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== -underscore@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== - undici@^5.14.0: version "5.16.0" resolved "https://registry.yarnpkg.com/undici/-/undici-5.16.0.tgz#6b64f9b890de85489ac6332bd45ca67e4f7d9943" @@ -12489,51 +7482,16 @@ undici@^5.14.0: dependencies: busboy "^1.6.0" -undici@^5.4.0: - version "5.22.1" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.22.1.tgz#877d512effef2ac8be65e695f3586922e1a57d7b" - integrity sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw== - dependencies: - busboy "^1.6.0" - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -unorm@^1.3.3: - version "1.6.0" - resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" - integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== - unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - update-browserslist-db@^1.0.9: version "1.0.10" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" @@ -12563,11 +7521,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== - url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -12580,19 +7533,6 @@ url-set-query@^1.0.0: resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" integrity sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg== -url@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.1.tgz#26f90f615427eca1b9f4d6a28288c147e2302a32" - integrity sha512-rWS3H04/+mzzJkv0eZ7vEDGiQbgquI1fGfOad6zKvgYQi1SzMmhl7c/DdRGxhaWrVH6z0qWITo8rpnxK/RfEhA== - dependencies: - punycode "^1.4.1" - qs "^6.11.0" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - utf-8-validate@^5.0.2: version "5.0.10" resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" @@ -12600,29 +7540,16 @@ utf-8-validate@^5.0.2: dependencies: node-gyp-build "^4.3.0" -utf8@3.0.0, utf8@^3.0.0: +utf8@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -util.promisify@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.2.tgz#02b3dbadbb80071eee4c43aed58747afdfc516db" - integrity sha512-PBdZ03m1kBnQ5cjjO0ZvJMJS+QsbyIcFwi4hY4U76OQsCO9JrOYjbCFgIF76ccFg9xnJo7ZHPkqyj1GqmdS7MA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - for-each "^0.3.3" - has-proto "^1.0.1" - has-symbols "^1.0.3" - object.getownpropertydescriptors "^2.1.6" - safe-array-concat "^1.0.0" - util@^0.12.0: version "0.12.5" resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" @@ -12678,14 +7605,6 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - varint@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" @@ -12705,21 +7624,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -viem@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/viem/-/viem-1.0.2.tgz#0798c80598daddc05b7132b642ae2f60811c4fbe" - integrity sha512-3Bn+CuInU8zsdKqqzFDWL018x4B9HDjPIISztReGcBjikY+04tP7CrQQCf1lbinK3wWrEoFU9VDiptCciNjUQA== - dependencies: - "@adraffy/ens-normalize" "1.9.0" - "@noble/curves" "1.0.0" - "@noble/hashes" "1.3.0" - "@scure/bip32" "1.3.0" - "@scure/bip39" "1.2.0" - "@wagmi/chains" "1.1.0" - abitype "0.8.7" - isomorphic-ws "5.0.0" - ws "8.12.0" - walker@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -12727,16 +7631,6 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" -web3-bzz@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" - integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== - dependencies: - "@types/node" "^12.12.6" - got "9.6.0" - swarm-js "^0.1.40" - underscore "1.9.1" - web3-bzz@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.6.0.tgz#584b51339f21eedff159abc9239b4b7ef6ded840" @@ -12746,15 +7640,6 @@ web3-bzz@1.6.0: got "9.6.0" swarm-js "^0.1.40" -web3-core-helpers@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" - integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== - dependencies: - underscore "1.9.1" - web3-eth-iban "1.2.11" - web3-utils "1.2.11" - web3-core-helpers@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.6.0.tgz#77e161b6ba930a4008a0df804ab379e0aa7e1e7f" @@ -12763,18 +7648,6 @@ web3-core-helpers@1.6.0: web3-eth-iban "1.6.0" web3-utils "1.6.0" -web3-core-method@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" - integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== - dependencies: - "@ethersproject/transactions" "^5.0.0-beta.135" - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-core-promievent "1.2.11" - web3-core-subscriptions "1.2.11" - web3-utils "1.2.11" - web3-core-method@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.6.0.tgz#ebe4ea51f5a4fa809bb68185576186359d3982e9" @@ -12787,13 +7660,6 @@ web3-core-method@1.6.0: web3-core-subscriptions "1.6.0" web3-utils "1.6.0" -web3-core-promievent@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" - integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== - dependencies: - eventemitter3 "4.0.4" - web3-core-promievent@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.6.0.tgz#8b6053ae83cb47164540167fc361469fc604d2dd" @@ -12801,17 +7667,6 @@ web3-core-promievent@1.6.0: dependencies: eventemitter3 "4.0.4" -web3-core-requestmanager@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" - integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== - dependencies: - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-providers-http "1.2.11" - web3-providers-ipc "1.2.11" - web3-providers-ws "1.2.11" - web3-core-requestmanager@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.6.0.tgz#8ef3a3b89cd08983bd94574f9c5893f70a8a6aea" @@ -12823,15 +7678,6 @@ web3-core-requestmanager@1.6.0: web3-providers-ipc "1.6.0" web3-providers-ws "1.6.0" -web3-core-subscriptions@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" - integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== - dependencies: - eventemitter3 "4.0.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-core-subscriptions@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.6.0.tgz#8c23b15b434a7c9f937652ecca45d7108e2c54df" @@ -12840,19 +7686,6 @@ web3-core-subscriptions@1.6.0: eventemitter3 "4.0.4" web3-core-helpers "1.6.0" -web3-core@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" - integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== - dependencies: - "@types/bn.js" "^4.11.5" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-requestmanager "1.2.11" - web3-utils "1.2.11" - web3-core@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.6.0.tgz#144eb00f651c9812faf7176abd7ee99d5f45e212" @@ -12866,15 +7699,6 @@ web3-core@1.6.0: web3-core-requestmanager "1.6.0" web3-utils "1.6.0" -web3-eth-abi@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" - integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== - dependencies: - "@ethersproject/abi" "5.0.0-beta.153" - underscore "1.9.1" - web3-utils "1.2.11" - web3-eth-abi@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.4.0.tgz#83f9f0ce48fd6d6b233a30a33bd674b3518e472b" @@ -12892,23 +7716,6 @@ web3-eth-abi@1.6.0: "@ethersproject/abi" "5.0.7" web3-utils "1.6.0" -web3-eth-accounts@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" - integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== - dependencies: - crypto-browserify "3.12.0" - eth-lib "0.2.8" - ethereumjs-common "^1.3.2" - ethereumjs-tx "^2.1.1" - scrypt-js "^3.0.1" - underscore "1.9.1" - uuid "3.3.2" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" - web3-eth-accounts@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.6.0.tgz#530927f4c5b78df93b3ea1203abbb467de29cd04" @@ -12926,21 +7733,6 @@ web3-eth-accounts@1.6.0: web3-core-method "1.6.0" web3-utils "1.6.0" -web3-eth-contract@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" - integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== - dependencies: - "@types/bn.js" "^4.11.5" - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-promievent "1.2.11" - web3-core-subscriptions "1.2.11" - web3-eth-abi "1.2.11" - web3-utils "1.2.11" - web3-eth-contract@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.6.0.tgz#deb946867ad86d32bcbba899d733b681b25ea674" @@ -12955,21 +7747,6 @@ web3-eth-contract@1.6.0: web3-eth-abi "1.6.0" web3-utils "1.6.0" -web3-eth-ens@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" - integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== - dependencies: - content-hash "^2.5.2" - eth-ens-namehash "2.0.8" - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-promievent "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-contract "1.2.11" - web3-utils "1.2.11" - web3-eth-ens@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.6.0.tgz#af13852168d56fa71b9198eb097e96fb93831c2a" @@ -12984,14 +7761,6 @@ web3-eth-ens@1.6.0: web3-eth-contract "1.6.0" web3-utils "1.6.0" -web3-eth-iban@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" - integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== - dependencies: - bn.js "^4.11.9" - web3-utils "1.2.11" - web3-eth-iban@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.6.0.tgz#edbe46cedc5b148d53fa455edea6b4eef53b2be7" @@ -13000,18 +7769,6 @@ web3-eth-iban@1.6.0: bn.js "^4.11.9" web3-utils "1.6.0" -web3-eth-personal@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" - integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== - dependencies: - "@types/node" "^12.12.6" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" - web3-eth-personal@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.6.0.tgz#b75a61c0737b8b8bcc11d05db2ed7bfce7e4b262" @@ -13024,25 +7781,6 @@ web3-eth-personal@1.6.0: web3-net "1.6.0" web3-utils "1.6.0" -web3-eth@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" - integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== - dependencies: - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-accounts "1.2.11" - web3-eth-contract "1.2.11" - web3-eth-ens "1.2.11" - web3-eth-iban "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" - web3-eth@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.6.0.tgz#4c9d5fb4eccf9f8744828281757e6ea76af58cbd" @@ -13061,15 +7799,6 @@ web3-eth@1.6.0: web3-net "1.6.0" web3-utils "1.6.0" -web3-net@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" - integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== - dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" - web3-net@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.6.0.tgz#2c28f8787073110a7c2310336889d2dad647e500" @@ -13079,40 +7808,6 @@ web3-net@1.6.0: web3-core-method "1.6.0" web3-utils "1.6.0" -web3-provider-engine@14.2.1: - version "14.2.1" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz#ef351578797bf170e08d529cb5b02f8751329b95" - integrity sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw== - dependencies: - async "^2.5.0" - backoff "^2.5.0" - clone "^2.0.0" - cross-fetch "^2.1.0" - eth-block-tracker "^3.0.0" - eth-json-rpc-infura "^3.1.0" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.1.5" - ethereumjs-vm "^2.3.4" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.85.0" - semaphore "^1.0.3" - ws "^5.1.1" - xhr "^2.2.0" - xtend "^4.0.1" - -web3-providers-http@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" - integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== - dependencies: - web3-core-helpers "1.2.11" - xhr2-cookies "1.1.0" - web3-providers-http@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.6.0.tgz#8db4e589abf7197f5d65b12af1bf9726c45f4160" @@ -13121,15 +7816,6 @@ web3-providers-http@1.6.0: web3-core-helpers "1.6.0" xhr2-cookies "1.1.0" -web3-providers-ipc@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" - integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== - dependencies: - oboe "2.1.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-providers-ipc@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.6.0.tgz#6a3410fd47a67c4a36719fb97f99534ae12aac98" @@ -13138,16 +7824,6 @@ web3-providers-ipc@1.6.0: oboe "2.1.5" web3-core-helpers "1.6.0" -web3-providers-ws@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" - integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== - dependencies: - eventemitter3 "4.0.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - websocket "^1.0.31" - web3-providers-ws@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.6.0.tgz#dc15dc18c30089efda992015fd5254bd2b77af5f" @@ -13157,16 +7833,6 @@ web3-providers-ws@1.6.0: web3-core-helpers "1.6.0" websocket "^1.0.32" -web3-shh@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" - integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== - dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-net "1.2.11" - web3-shh@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.6.0.tgz#838a3435dce1039f669a48e53e948062de197931" @@ -13177,20 +7843,6 @@ web3-shh@1.6.0: web3-core-subscriptions "1.6.0" web3-net "1.6.0" -web3-utils@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" - integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== - dependencies: - bn.js "^4.11.9" - eth-lib "0.2.8" - ethereum-bloom-filters "^1.0.6" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - underscore "1.9.1" - utf8 "3.0.0" - web3-utils@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.4.0.tgz#e8cb381c81b242dc1d4ecb397200356d404410e6" @@ -13218,19 +7870,6 @@ web3-utils@1.6.0: randombytes "^2.1.0" utf8 "3.0.0" -web3-utils@^1.0.0-beta.31: - version "1.10.0" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.0.tgz#ca4c1b431a765c14ac7f773e92e0fd9377ccf578" - integrity sha512-kSaCM0uMcZTNUSmn5vMEhlo02RObGNRRCkdX0V9UTAU0+lrvn0HSaudyCo6CQzuXUsnuY2ERJGCGPfeWmv19Rg== - dependencies: - bn.js "^5.2.1" - ethereum-bloom-filters "^1.0.6" - ethereumjs-util "^7.1.0" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - utf8 "3.0.0" - web3-utils@^1.3.4: version "1.8.1" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.8.1.tgz#f2f7ca7eb65e6feb9f3d61056d0de6bbd57125ff" @@ -13244,19 +7883,6 @@ web3-utils@^1.3.4: randombytes "^2.1.0" utf8 "3.0.0" -web3@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" - integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== - dependencies: - web3-bzz "1.2.11" - web3-core "1.2.11" - web3-eth "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-shh "1.2.11" - web3-utils "1.2.11" - web3@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3/-/web3-1.6.0.tgz#d8fa0cd9e7bf252f9fe43bb77dc42bc6671affde" @@ -13275,19 +7901,7 @@ webidl-conversions@^3.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== -websocket@1.0.32: - version "1.0.32" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.32.tgz#1f16ddab3a21a2d929dec1687ab21cfdc6d3dbb1" - integrity sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q== - dependencies: - bufferutil "^4.0.1" - debug "^2.2.0" - es5-ext "^0.10.50" - typedarray-to-buffer "^3.1.5" - utf-8-validate "^5.0.2" - yaeti "^0.0.6" - -websocket@^1.0.31, websocket@^1.0.32: +websocket@^1.0.32: version "1.0.34" resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== @@ -13304,11 +7918,6 @@ whatwg-fetch@>=0.10.0: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== -whatwg-fetch@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" - integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== - whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -13328,11 +7937,6 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ== - which-typed-array@^1.1.2: version "1.1.8" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.8.tgz#0cfd53401a6f334d90ed1125754a42ed663eb01f" @@ -13345,25 +7949,6 @@ which-typed-array@^1.1.2: has-tostringtag "^1.0.0" is-typed-array "^1.1.9" -which-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" - integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" - -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -13371,37 +7956,16 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -window-size@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - integrity sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw== - -word-wrap@^1.2.3, word-wrap@~1.2.3: +word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -wordwrapjs@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" - integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== - dependencies: - reduce-flatten "^2.0.0" - typical "^5.2.0" - workerpool@6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw== - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -13424,23 +7988,11 @@ write-file-atomic@^4.0.1: imurmurhash "^0.1.4" signal-exit "^3.0.7" -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - ws@7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== -ws@8.12.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" - integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== - ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" @@ -13450,13 +8002,6 @@ ws@^3.0.0: safe-buffer "~5.1.0" ultron "~1.1.0" -ws@^5.1.1: - version "5.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" - integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== - dependencies: - async-limiter "~1.0.0" - ws@^7.4.6: version "7.5.9" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" @@ -13489,7 +8034,7 @@ xhr2-cookies@1.1.0: dependencies: cookiejar "^2.1.1" -xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: +xhr@^2.0.4, xhr@^2.3.3: version "2.6.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== @@ -13504,23 +8049,11 @@ xmlhttprequest@1.8.0: resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA== -xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: +xtend@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -xtend@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ== - dependencies: - object-keys "~0.4.0" - -y18n@^3.2.1: - version "3.2.2" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" - integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== - y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -13541,24 +8074,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== -yargs-parser@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" - integrity sha512-9pIKIJhnI5tonzG6OnCFlz/yln8xHYcGl+pn3xR0Vzff0vzN1PbNRaelgfgRUwZ3s4i3jvxT9WhmUGL4whnasA== - dependencies: - camelcase "^3.0.0" - lodash.assign "^4.0.6" - yargs-parser@^20.2.2: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" @@ -13605,26 +8125,6 @@ yargs@^17.0.1, yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.0.0" -yargs@^4.7.1: - version "4.8.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" - integrity sha512-LqodLrnIDM3IFT+Hf/5sxBnEGECrfdC1uIbgZeJmESCSo4HoCAaKEus8MylXHAkdacGc0ye+Qa+dpkuom8uVYA== - dependencies: - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - lodash.assign "^4.0.3" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.1" - which-module "^1.0.0" - window-size "^0.2.0" - y18n "^3.2.1" - yargs-parser "^2.4.1" - yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" @@ -13634,18 +8134,3 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zksync-web3@^0.14.3: - version "0.14.3" - resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.14.3.tgz#64ac2a16d597464c3fc4ae07447a8007631c57c9" - integrity sha512-hT72th4AnqyLW1d5Jlv8N2B/qhEnl2NePK2A3org7tAa24niem/UAaHMkEvmWI3SF9waYUPtqAtjpf+yvQ9zvQ== - -zksync-web3@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.8.1.tgz#db289d8f6caf61f4d5ddc471fa3448d93208dc14" - integrity sha512-1A4aHPQ3MyuGjpv5X/8pVEN+MdZqMjfVmiweQSRjOlklXYu65wT9BGEOtCmMs5d3gIvLp4ssfTeuR5OCKOD2kw== - -zod@3.21.4: - version "3.21.4" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db" - integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw== From 4a81d2d620d10e0612871c118383d3c81248bdce Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 23 Aug 2023 14:55:01 +0300 Subject: [PATCH 119/833] fix typo --- src/dex/uniswap-v3/uniswap-v3.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 64abd7c37..26ec486e0 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -279,7 +279,7 @@ export class UniswapV3 e, ); } else { - // on unkown error mark as failed and increase retryCount for retry init strategy + // on unknown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, From 2a7ce8d066cf15f5202ea0b740f421fe7fa8a882 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 23 Aug 2023 13:46:24 +0100 Subject: [PATCH 120/833] fix: use array of pools to support new types --- src/dex/balancer-v2/balancer-v2.ts | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/dex/balancer-v2/balancer-v2.ts b/src/dex/balancer-v2/balancer-v2.ts index ac1c3f443..72554d4ba 100644 --- a/src/dex/balancer-v2/balancer-v2.ts +++ b/src/dex/balancer-v2/balancer-v2.ts @@ -72,6 +72,26 @@ import { } from './constants'; import { NumberAsString, OptimalSwapExchange } from '@paraswap/core'; +const enabledPoolTypes = [ + // BalancerPoolTypes.MetaStable, + // BalancerPoolTypes.Stable, + BalancerPoolTypes.Weighted, + // BalancerPoolTypes.LiquidityBootstrapping, + // BalancerPoolTypes.Investment, + // BalancerPoolTypes.StablePhantom, + BalancerPoolTypes.AaveLinear, + BalancerPoolTypes.ERC4626Linear, + BalancerPoolTypes.Linear, + // BalancerPoolTypes.ComposableStable, + BalancerPoolTypes.BeefyLinear, + BalancerPoolTypes.GearboxLinear, + BalancerPoolTypes.MidasLinear, + BalancerPoolTypes.ReaperLinear, + BalancerPoolTypes.SiloLinear, + BalancerPoolTypes.TetuLinear, + BalancerPoolTypes.YearnLinear, +]; + const fetchAllPools = `query ($count: Int) { pools: pools( first: $count @@ -93,9 +113,7 @@ const fetchAllPools = `query ($count: Int) { ], swapEnabled: true, poolType_in: [ - "MetaStable", "Stable", "Weighted", "LiquidityBootstrapping", "Investment", "StablePhantom", "AaveLinear", - "ERC4626Linear", "Linear", "ComposableStable", "BeefyLinear", "GearboxLinear", "MidasLinear", - "ReaperLinear", "SiloLinear", "TetuLinear", "YearnLinear" + ${enabledPoolTypes.join(', ')} ] } ) { @@ -1223,6 +1241,9 @@ export class BalancerV2 pools (first: $count, orderBy: totalLiquidity, orderDirection: desc, where: {id_in: $poolIds, swapEnabled: true, + poolType_in: [ + ${enabledPoolTypes.join(', ')} + ], totalLiquidity_gt: ${MIN_USD_LIQUIDITY_TO_FETCH.toString()}}) { address totalLiquidity From e774f7bdb19bdf7d39ed830c13c28ad43c786623 Mon Sep 17 00:00:00 2001 From: Tudor Anastasiu Date: Wed, 23 Aug 2023 15:47:22 +0300 Subject: [PATCH 121/833] Add extra param `partner` to firm rate request. --- src/dex/generic-rfq/generic-rfq.ts | 1 + src/dex/generic-rfq/rate-fetcher.ts | 6 ++++-- src/dex/generic-rfq/types.ts | 1 + src/types.ts | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/dex/generic-rfq/generic-rfq.ts b/src/dex/generic-rfq/generic-rfq.ts index 389a9a4a3..0cb0d998b 100644 --- a/src/dex/generic-rfq/generic-rfq.ts +++ b/src/dex/generic-rfq/generic-rfq.ts @@ -203,6 +203,7 @@ export class GenericRFQ extends ParaSwapLimitOrders { : overOrder(optimalSwapExchange.destAmount, 1), side, options.txOrigin, + options.partner, ); const expiryAsBigInt = BigInt(order.order.expiry); diff --git a/src/dex/generic-rfq/rate-fetcher.ts b/src/dex/generic-rfq/rate-fetcher.ts index 64442d157..f5760c532 100644 --- a/src/dex/generic-rfq/rate-fetcher.ts +++ b/src/dex/generic-rfq/rate-fetcher.ts @@ -226,7 +226,7 @@ export class RateFetcher { private handleRatesResponse(resp: RatesResponse) { const pairs = this.pairs; - if(isEmpty(pairs)) return; + if (isEmpty(pairs)) return; Object.keys(resp.prices).forEach(pairName => { const pair = pairs[pairName]; @@ -239,7 +239,7 @@ export class RateFetcher { return; } - if(isEmpty(this.tokens)) return; + if (isEmpty(this.tokens)) return; const baseToken = this.tokens[pair.base]; const quoteToken = this.tokens[pair.quote]; @@ -376,6 +376,7 @@ export class RateFetcher { srcAmount: string, side: SwapSide, userAddress: Address, + partner?: string, ): Promise { const srcToken = this.dexHelper.config.wrapETH(_srcToken); const destToken = this.dexHelper.config.wrapETH(_destToken); @@ -390,6 +391,7 @@ export class RateFetcher { makerAmount: side === SwapSide.BUY ? srcAmount : undefined, takerAmount: side === SwapSide.SELL ? srcAmount : undefined, userAddress, + partner, }; try { diff --git a/src/dex/generic-rfq/types.ts b/src/dex/generic-rfq/types.ts index 1ded4dc7a..dc2d3fcf2 100644 --- a/src/dex/generic-rfq/types.ts +++ b/src/dex/generic-rfq/types.ts @@ -84,6 +84,7 @@ export type RFQPayload = { makerAmount?: string; takerAmount?: string; userAddress: Address; + partner?: string; }; export type AugustusOrderWithStringAndSignature = AugustusOrderWithString & { diff --git a/src/types.ts b/src/types.ts index 9d914b038..922247bd6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -291,6 +291,7 @@ export type PreprocessTransactionOptions = { hmac?: string; mockRfqAndLO?: boolean; isDirectMethod?: boolean; + partner?: string; }; export type TransferFeeParams = { From 617f44a62b19a54a76be92534826e35051d99a66 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 23 Aug 2023 13:47:40 +0100 Subject: [PATCH 122/833] 2.31.1-balancer-restrict-types.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8609a6a0e..241a1ad99 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.0", + "version": "2.31.1-balancer-restrict-types.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From cc1a319f21064869eff250b536e97731ff6a3ad9 Mon Sep 17 00:00:00 2001 From: Tudor Anastasiu Date: Wed, 23 Aug 2023 15:48:24 +0300 Subject: [PATCH 123/833] 2.31.1-rfq-partner.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8609a6a0e..8003f35dc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.0", + "version": "2.31.1-rfq-partner.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 4d07a21f7a355b68726c0dec7807a5872279efb4 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 23 Aug 2023 14:12:23 +0100 Subject: [PATCH 124/833] fix: use map before join --- src/dex/balancer-v2/balancer-v2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/balancer-v2/balancer-v2.ts b/src/dex/balancer-v2/balancer-v2.ts index 72554d4ba..0992a71fa 100644 --- a/src/dex/balancer-v2/balancer-v2.ts +++ b/src/dex/balancer-v2/balancer-v2.ts @@ -113,7 +113,7 @@ const fetchAllPools = `query ($count: Int) { ], swapEnabled: true, poolType_in: [ - ${enabledPoolTypes.join(', ')} + ${enabledPoolTypes.map(p => `"${p}"`).join(', ')} ] } ) { From a14b238513868c366a3eab26cbd44fc729822fc3 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 23 Aug 2023 14:13:08 +0100 Subject: [PATCH 125/833] 2.31.1-balancer-restrict-types.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 241a1ad99..4c6afb0d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.1-balancer-restrict-types.0", + "version": "2.31.1-balancer-restrict-types.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 8bdfd88fb0e211978ad230ce6c39c8fc50fff0d4 Mon Sep 17 00:00:00 2001 From: Tudor Anastasiu Date: Wed, 23 Aug 2023 16:28:52 +0300 Subject: [PATCH 126/833] 2.31.1-limit-pools.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8609a6a0e..29e539b76 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.0", + "version": "2.31.1-limit-pools.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1603657a0441ef006cf9f7f67102a04bb885b37c Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 23 Aug 2023 14:59:37 +0100 Subject: [PATCH 127/833] fix: remove check in subgraph query for pooltracker --- src/dex/balancer-v2/balancer-v2-e2e.test.ts | 18 ++++++++++++++---- src/dex/balancer-v2/balancer-v2.ts | 3 --- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/dex/balancer-v2/balancer-v2-e2e.test.ts b/src/dex/balancer-v2/balancer-v2-e2e.test.ts index 1aadf7669..1f7de204b 100644 --- a/src/dex/balancer-v2/balancer-v2-e2e.test.ts +++ b/src/dex/balancer-v2/balancer-v2-e2e.test.ts @@ -96,6 +96,18 @@ describe('BalancerV2 E2E', () => { buyAmount: '10000000000', }, ], + [ + { + name: 'USDC', + sellAmount: '111000000', + buyAmount: '111000000', + }, + { + name: 'wstETH', + sellAmount: '100000000000000000', + buyAmount: '100000000000000000', + }, + ], ]; sideToContractMethods.forEach((contractMethods, side) => @@ -1054,7 +1066,7 @@ describe('BalancerV2 E2E', () => { sellAmount: '200000000', buyAmount: '2000000000', }, - ] + ], ]; sideToContractMethods.forEach((contractMethods, side) => @@ -1137,7 +1149,7 @@ describe('BalancerV2 E2E', () => { sellAmount: '200000000', buyAmount: '2000000000000000', }, - ] + ], ]; sideToContractMethods.forEach((contractMethods, side) => @@ -1181,7 +1193,6 @@ describe('BalancerV2 E2E', () => { }), ); }); - }); describe('BeetsFi OPTIMISM', () => { @@ -1436,5 +1447,4 @@ describe('BalancerV2 E2E', () => { }); }); }); - }); diff --git a/src/dex/balancer-v2/balancer-v2.ts b/src/dex/balancer-v2/balancer-v2.ts index 0992a71fa..d8fbd5b27 100644 --- a/src/dex/balancer-v2/balancer-v2.ts +++ b/src/dex/balancer-v2/balancer-v2.ts @@ -1241,9 +1241,6 @@ export class BalancerV2 pools (first: $count, orderBy: totalLiquidity, orderDirection: desc, where: {id_in: $poolIds, swapEnabled: true, - poolType_in: [ - ${enabledPoolTypes.join(', ')} - ], totalLiquidity_gt: ${MIN_USD_LIQUIDITY_TO_FETCH.toString()}}) { address totalLiquidity From 610f90413ee9aacb53e3a0cf76f4bfa5a133f676 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 23 Aug 2023 15:02:00 +0100 Subject: [PATCH 128/833] style: add comment regarding cache --- src/dex/balancer-v2/balancer-v2.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dex/balancer-v2/balancer-v2.ts b/src/dex/balancer-v2/balancer-v2.ts index d8fbd5b27..c7afdc50f 100644 --- a/src/dex/balancer-v2/balancer-v2.ts +++ b/src/dex/balancer-v2/balancer-v2.ts @@ -72,6 +72,7 @@ import { } from './constants'; import { NumberAsString, OptimalSwapExchange } from '@paraswap/core'; +// If you disable some pool, don't forget to clear the cache, otherwise changes won't be applied immediately const enabledPoolTypes = [ // BalancerPoolTypes.MetaStable, // BalancerPoolTypes.Stable, From 5000229f365def055566e372ea4f718874824bce Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 23 Aug 2023 15:19:29 +0100 Subject: [PATCH 129/833] 2.31.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4c6afb0d8..8b30260a2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.1-balancer-restrict-types.1", + "version": "2.31.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 3d81758477f0515f0bb8b205caea488951eb1aad Mon Sep 17 00:00:00 2001 From: Tudor Anastasiu Date: Thu, 24 Aug 2023 13:14:26 +0300 Subject: [PATCH 130/833] 2.31.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8b30260a2..a79b926e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.1", + "version": "2.31.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 8ca9cdf498b8fb88c7d3fec67d4fff44d6d68177 Mon Sep 17 00:00:00 2001 From: Tudor Anastasiu Date: Thu, 24 Aug 2023 13:21:35 +0300 Subject: [PATCH 131/833] 2.31.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a79b926e3..0f431afad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.2", + "version": "2.31.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From cf5c965abbab922ddf09dbf1466e6ef1d23e7541 Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 24 Aug 2023 14:42:50 +0100 Subject: [PATCH 132/833] feat: implement force regenerate state if EP is not working for zkEVM --- src/dex/algebra/algebra.ts | 2 +- src/stateful-event-subscriber.ts | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 0cbe60fd5..0d00e79c6 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -167,7 +167,7 @@ export class Algebra extends SimpleExchange implements IDex { /* reload state, on zkEVM this would most likely timeout during request life * but would allow to rely on staleState for couple of min for next requests */ - await pool.initialize(blockNumber); + await pool.initialize(blockNumber, { forceRegenerate: true }); } return pool; diff --git a/src/stateful-event-subscriber.ts b/src/stateful-event-subscriber.ts index 313cfa6fb..e76e47ffc 100644 --- a/src/stateful-event-subscriber.ts +++ b/src/stateful-event-subscriber.ts @@ -18,6 +18,7 @@ type StateCache = { export type InitializeStateOptions = { state?: DeepReadonly; initCallback?: (state: DeepReadonly) => void; + forceRegenerate?: boolean; }; export abstract class StatefulEventSubscriber @@ -89,6 +90,13 @@ export abstract class StatefulEventSubscriber let masterBn: undefined | number = undefined; if (options && options.state) { this.setState(options.state, blockNumber); + } else if (options && options.forceRegenerate) { + // ZkEVM forces to always regenerate state when it is old + this.logger.debug( + `${this.parentName}: ${this.name}: forced to regenerate state`, + ); + const state = await this.generateState(blockNumber); + this.setState(state, blockNumber); } else { if (this.dexHelper.config.isSlave && this.masterPoolNeeded) { let stateAsString = await this.dexHelper.cache.hget( From 6af2f7c12f45e7695324cb760f936200b0c9304f Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 24 Aug 2023 14:48:17 +0100 Subject: [PATCH 133/833] 2.31.4-zkevm-revive.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f431afad..2e09436b7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.3", + "version": "2.31.4-zkevm-revive.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From c861ea946e191d967160585c86907a403ff58ce5 Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Thu, 24 Aug 2023 20:23:16 +0100 Subject: [PATCH 134/833] feat: add dexalot integration --- src/abi/dexalot/DexalotMainnetRFQ.json | 975 ++++++++++++++++++++ src/dex/dexalot/config.ts | 18 + src/dex/dexalot/constants.ts | 21 + src/dex/dexalot/dexalot-e2e.test.ts | 186 ++++ src/dex/dexalot/dexalot-integration.test.ts | 188 ++++ src/dex/dexalot/dexalot.ts | 784 ++++++++++++++++ src/dex/dexalot/rate-fetcher.ts | 209 +++++ src/dex/dexalot/types.ts | 134 +++ src/dex/dexalot/validators.ts | 43 + src/dex/index.ts | 2 + 10 files changed, 2560 insertions(+) create mode 100644 src/abi/dexalot/DexalotMainnetRFQ.json create mode 100644 src/dex/dexalot/config.ts create mode 100644 src/dex/dexalot/constants.ts create mode 100644 src/dex/dexalot/dexalot-e2e.test.ts create mode 100644 src/dex/dexalot/dexalot-integration.test.ts create mode 100644 src/dex/dexalot/dexalot.ts create mode 100644 src/dex/dexalot/rate-fetcher.ts create mode 100644 src/dex/dexalot/types.ts create mode 100644 src/dex/dexalot/validators.ts diff --git a/src/abi/dexalot/DexalotMainnetRFQ.json b/src/abi/dexalot/DexalotMainnetRFQ.json new file mode 100644 index 000000000..6c3e212b2 --- /dev/null +++ b/src/abi/dexalot/DexalotMainnetRFQ.json @@ -0,0 +1,975 @@ +[ + { + "name": "AddressSet", + "type": "event", + "inputs": [ + { + "name": "name", + "type": "string", + "indexed": true, + "internalType": "string" + }, + { + "name": "actionName", + "type": "string", + "indexed": false, + "internalType": "string" + }, + { + "name": "newAddress", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "name": "ExpiryUpdated", + "type": "event", + "inputs": [ + { + "name": "nonceAndMeta", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "newExpiry", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "name": "Initialized", + "type": "event", + "inputs": [ + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + }, + { + "name": "Paused", + "type": "event", + "inputs": [ + { + "name": "account", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "name": "RebalancerWithdraw", + "type": "event", + "inputs": [ + { + "name": "asset", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "name": "RoleAdminChanged", + "type": "event", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "previousAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "newAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "name": "RoleGranted", + "type": "event", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "name": "RoleRevoked", + "type": "event", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "name": "RoleUpdated", + "type": "event", + "inputs": [ + { + "name": "name", + "type": "string", + "indexed": true, + "internalType": "string" + }, + { + "name": "actionName", + "type": "string", + "indexed": false, + "internalType": "string" + }, + { + "name": "updatedRole", + "type": "bytes32", + "indexed": false, + "internalType": "bytes32" + }, + { + "name": "updatedAddress", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "name": "SlippageApplied", + "type": "event", + "inputs": [ + { + "name": "nonceAndMeta", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "newMakerAmount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "name": "SlippageToleranceUpdated", + "type": "event", + "inputs": [ + { + "name": "newSlippageTolerance", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "name": "SwapExecuted", + "type": "event", + "inputs": [ + { + "name": "nonceAndMeta", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "maker", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "taker", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "makerAsset", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "takerAsset", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "makerAmountReceived", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "takerAmountReceived", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "name": "SwapSignerUpdated", + "type": "event", + "inputs": [ + { + "name": "newSwapSigner", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "name": "Unpaused", + "type": "event", + "inputs": [ + { + "name": "account", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "name": "DEFAULT_ADMIN_ROLE", + "type": "function", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "name": "REBALANCER_ADMIN_ROLE", + "type": "function", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "name": "VERSION", + "type": "function", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "name": "addAdmin", + "type": "function", + "inputs": [ + { + "name": "_address", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "addRebalancer", + "type": "function", + "inputs": [ + { + "name": "_address", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "addTrustedContract", + "type": "function", + "inputs": [ + { + "name": "_contract", + "type": "address", + "internalType": "address" + }, + { + "name": "_organization", + "type": "string", + "internalType": "string" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "batchClaimBalance", + "type": "function", + "inputs": [ + { + "name": "_assets", + "type": "address[]", + "internalType": "address[]" + }, + { + "name": "_amounts", + "type": "uint256[]", + "internalType": "uint256[]" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "claimBalance", + "type": "function", + "inputs": [ + { + "name": "_asset", + "type": "address", + "internalType": "address" + }, + { + "name": "_amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "getRoleAdmin", + "type": "function", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "name": "getRoleMember", + "type": "function", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "index", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "name": "getRoleMemberCount", + "type": "function", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "name": "grantRole", + "type": "function", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "hasRole", + "type": "function", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "name": "initialize", + "type": "function", + "inputs": [ + { + "name": "_swapSigner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "isAdmin", + "type": "function", + "inputs": [ + { + "name": "_address", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "name": "isRebalancer", + "type": "function", + "inputs": [ + { + "name": "_address", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "name": "isTrustedContract", + "type": "function", + "inputs": [ + { + "name": "_contract", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "name": "isValidSignature", + "type": "function", + "inputs": [ + { + "name": "_hash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "_signature", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes4", + "internalType": "bytes4" + } + ], + "stateMutability": "view" + }, + { + "name": "orderExpiryUpdated", + "type": "function", + "inputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "name": "orderMakerAmountUpdated", + "type": "function", + "inputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "name": "pause", + "type": "function", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "paused", + "type": "function", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "name": "removeAdmin", + "type": "function", + "inputs": [ + { + "name": "_address", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "removeRebalancer", + "type": "function", + "inputs": [ + { + "name": "_address", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "removeTrustedContract", + "type": "function", + "inputs": [ + { + "name": "_contract", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "renounceRole", + "type": "function", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "revokeRole", + "type": "function", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "setSlippageTolerance", + "type": "function", + "inputs": [ + { + "name": "_newSlippageTolerance", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "setSwapSigner", + "type": "function", + "inputs": [ + { + "name": "_swapSigner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "simpleSwap", + "type": "function", + "inputs": [ + { + "name": "_order", + "type": "tuple", + "components": [ + { + "name": "nonceAndMeta", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "expiry", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "makerAsset", + "type": "address", + "internalType": "address" + }, + { + "name": "takerAsset", + "type": "address", + "internalType": "address" + }, + { + "name": "maker", + "type": "address", + "internalType": "address" + }, + { + "name": "taker", + "type": "address", + "internalType": "address" + }, + { + "name": "makerAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "takerAmount", + "type": "uint256", + "internalType": "uint256" + } + ], + "internalType": "struct MainnetRFQ.Order" + }, + { + "name": "_signature", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "name": "slippageTolerance", + "type": "function", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "name": "supportsInterface", + "type": "function", + "inputs": [ + { + "name": "interfaceId", + "type": "bytes4", + "internalType": "bytes4" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "name": "swapSigner", + "type": "function", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "name": "trustedContractToIntegrator", + "type": "function", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "name": "trustedContracts", + "type": "function", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "name": "unpause", + "type": "function", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "updateOrderExpiry", + "type": "function", + "inputs": [ + { + "name": "_nonceAndMeta", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_newExpiry", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "name": "updateOrderMakerAmount", + "type": "function", + "inputs": [ + { + "name": "_nonceAndMeta", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_newMakerAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "_oldMakerAmount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "receive", + "stateMutability": "payable" + } +] diff --git a/src/dex/dexalot/config.ts b/src/dex/dexalot/config.ts new file mode 100644 index 000000000..28751cd17 --- /dev/null +++ b/src/dex/dexalot/config.ts @@ -0,0 +1,18 @@ +import { DexParams } from './types'; +import { DexConfigMap, AdapterMappings } from '../../types'; +import { Network, SwapSide } from '../../constants'; + +export const DexalotConfig: DexConfigMap = { + Dexalot: { + [Network.AVALANCHE]: { + mainnetRFQAddress: '0xd62f9E53Be8884C21f5aa523B3c7D6F9a0050af5', + }, + }, +}; + +export const Adapters: Record = { + [Network.AVALANCHE]: { + [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 1 }], + [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 3 }], + }, +}; diff --git a/src/dex/dexalot/constants.ts b/src/dex/dexalot/constants.ts new file mode 100644 index 000000000..25a3e5d77 --- /dev/null +++ b/src/dex/dexalot/constants.ts @@ -0,0 +1,21 @@ +import BigNumber from 'bignumber.js'; + +export const DEXALOT_RATE_LIMITED_TTL_S = 60 * 60; // 1 hour + +export const DEXALOT_PRICES_CACHES_TTL_S = 200; + +export const DEXALOT_PAIRS_CACHES_TTL_S = 200; + +export const DEXALOT_TOKENS_CACHES_TTL_S = 200; + +export const DEXALOT_API_PRICES_POLLING_INTERVAL_MS = 1000; + +export const DEXALOT_API_PAIRS_POLLING_INTERVAL_MS = 1000 * 30; // 28 secs + +export const DEXALOT_API_TOKENS_POLLING_INTERVAL_MS = 1000 * 30; // 28 secs + +export const DEXALOT_API_BLACKLIST_POLLING_INTERVAL_MS = 1000 * 60 * 60; // 1 hour + +export const DEXALOT_API_URL = 'https://api.dexalot.com'; + +export const DEXALOT_GAS_COST = 100_000; diff --git a/src/dex/dexalot/dexalot-e2e.test.ts b/src/dex/dexalot/dexalot-e2e.test.ts new file mode 100644 index 000000000..5bf573b62 --- /dev/null +++ b/src/dex/dexalot/dexalot-e2e.test.ts @@ -0,0 +1,186 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { testE2E } from '../../../tests/utils-e2e'; +import { + Tokens, + NativeTokenSymbols, + Holders, +} from '../../../tests/constants-e2e'; +import { Network, ContractMethod, SwapSide } from '../../constants'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; + +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, + excludeNativeTokenTests: boolean = false, +) { + const config = generateConfig(network); + const provider = new StaticJsonRpcProvider( + config.privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + const sleepMs = 5000; + + const sideToContractMethods = new Map([ + [SwapSide.SELL, [ContractMethod.simpleSwap]], + [SwapSide.BUY, [ContractMethod.simpleSwap]], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + 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, + ); + }); + } + }); + }); + }), + ); + }); +} + +describe('Dexalot E2E', () => { + const dexKey = 'Dexalot'; + + describe('Avalanche', () => { + const network = Network.AVALANCHE; + + const tokenASymbol: string = 'AVAX'; + const tokenBSymbol: string = 'USDC'; + + const tokenAAmount: string = '1000000000000000000'; + const tokenBAmount: string = '1000000'; + const nativeTokenAmount = '1000000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + true, + ); + }); +}); diff --git a/src/dex/dexalot/dexalot-integration.test.ts b/src/dex/dexalot/dexalot-integration.test.ts new file mode 100644 index 000000000..5c767a34f --- /dev/null +++ b/src/dex/dexalot/dexalot-integration.test.ts @@ -0,0 +1,188 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { DummyDexHelper } from '../../dex-helper/index'; +import { Network, SwapSide } from '../../constants'; +import { BI_POWS } from '../../bigint-constants'; +import { Dexalot } from './dexalot'; +import { + checkPoolPrices, + checkPoolsLiquidity, + checkConstantPoolPrices, + sleep, +} from '../../../tests/utils'; +import { Tokens } from '../../../tests/constants-e2e'; + +async function testPricingOnNetwork( + dexalot: Dexalot, + network: Network, + dexKey: string, + blockNumber: number, + srcTokenSymbol: string, + destTokenSymbol: string, + side: SwapSide, + amounts: bigint[], +) { + const networkTokens = Tokens[network]; + + const pools = await dexalot.getPoolIdentifiers( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + side, + blockNumber, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await dexalot.getPricesVolume( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + amounts, + side, + blockNumber, + pools, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + if (dexalot.hasConstantPriceLargeAmounts) { + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + } else { + checkPoolPrices(poolPrices!, amounts, side, dexKey); + } +} + +describe('Dexalot', function () { + const dexKey = 'Dexalot'; + let blockNumber: number; + let dexalot: Dexalot; + + describe('Avalanche', () => { + const network = Network.AVALANCHE; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + + const tokenASymbol = 'AVAX'; + const tokenBSymbol = 'USDC'; + + const amountsForTokenA = [ + 0n, + 1n * BI_POWS[tokens[tokenASymbol].decimals], + 2n * BI_POWS[tokens[tokenASymbol].decimals], + 3n * BI_POWS[tokens[tokenASymbol].decimals], + 4n * BI_POWS[tokens[tokenASymbol].decimals], + 5n * BI_POWS[tokens[tokenASymbol].decimals], + 6n * BI_POWS[tokens[tokenASymbol].decimals], + 7n * BI_POWS[tokens[tokenASymbol].decimals], + 8n * BI_POWS[tokens[tokenASymbol].decimals], + 9n * BI_POWS[tokens[tokenASymbol].decimals], + 10n * BI_POWS[tokens[tokenASymbol].decimals], + ]; + + const amountsForTokenB = [ + 0n, + 1n * BI_POWS[tokens[tokenBSymbol].decimals], + 2n * BI_POWS[tokens[tokenBSymbol].decimals], + 3n * BI_POWS[tokens[tokenBSymbol].decimals], + 4n * BI_POWS[tokens[tokenBSymbol].decimals], + 5n * BI_POWS[tokens[tokenBSymbol].decimals], + 6n * BI_POWS[tokens[tokenBSymbol].decimals], + 7n * BI_POWS[tokens[tokenBSymbol].decimals], + 8n * BI_POWS[tokens[tokenBSymbol].decimals], + 9n * BI_POWS[tokens[tokenBSymbol].decimals], + 10n * BI_POWS[tokens[tokenBSymbol].decimals], + ]; + + beforeEach(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + dexalot = new Dexalot(network, dexKey, dexHelper); + await dexalot.initializePricing(blockNumber); + await sleep(5000); + }); + + afterEach(async () => { + dexalot.releaseResources(); + await sleep(5000); + }); + + it(`getPoolIdentifiers and getPricesVolume SELL ${tokenASymbol} ${tokenBSymbol}`, async function () { + await testPricingOnNetwork( + dexalot, + network, + dexKey, + blockNumber, + tokenASymbol, + tokenBSymbol, + SwapSide.SELL, + amountsForTokenA, + ); + }); + + it(`getPoolIdentifiers and getPricesVolume BUY ${tokenASymbol} ${tokenBSymbol}`, async function () { + await testPricingOnNetwork( + dexalot, + network, + dexKey, + blockNumber, + tokenASymbol, + tokenBSymbol, + SwapSide.BUY, + amountsForTokenB, + ); + }); + + it(`getPoolIdentifiers and getPricesVolume SELL ${tokenBSymbol} ${tokenASymbol}`, async function () { + await testPricingOnNetwork( + dexalot, + network, + dexKey, + blockNumber, + tokenBSymbol, + tokenASymbol, + SwapSide.SELL, + amountsForTokenB, + ); + }); + + it(`getPoolIdentifiers and getPricesVolume BUY ${tokenBSymbol} ${tokenASymbol}`, async function () { + await testPricingOnNetwork( + dexalot, + network, + dexKey, + blockNumber, + tokenBSymbol, + tokenASymbol, + SwapSide.BUY, + amountsForTokenA, + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const dexalot = new Dexalot(network, dexKey, dexHelper); + const poolLiquidity = await dexalot.getTopPoolsForToken( + tokens[tokenASymbol].address, + 10, + ); + console.log(`${tokenASymbol} Top Pools:`, poolLiquidity); + + if (!dexalot.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][tokenASymbol].address, + dexKey, + ); + } + }); + }); +}); diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts new file mode 100644 index 000000000..6436d4cd5 --- /dev/null +++ b/src/dex/dexalot/dexalot.ts @@ -0,0 +1,784 @@ +import { + Token, + Address, + ExchangePrices, + PoolPrices, + AdapterExchangeParam, + SimpleExchangeParam, + PoolLiquidity, + Logger, + ExchangeTxInfo, + OptimalSwapExchange, + PreprocessTransactionOptions, +} from '../../types'; +import { + SwapSide, + Network, + ETHER_ADDRESS, + CACHE_PREFIX, +} from '../../constants'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { getDexKeysWithNetwork, isAxiosError } from '../../utils'; +import { IDex } from '../idex'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { + ClobSide, + DexalotData, + PairData, + PairDataMap, + PriceDataMap, + RfqError, + RFQResponse, + RFQResponseError, + TokenAddrDataMap, + TokenDataMap, +} from './types'; +import { SimpleExchange } from '../simple-exchange'; +import { Adapters, DexalotConfig } from './config'; +import { RateFetcher } from './rate-fetcher'; +import mainnetRFQAbi from '../../abi/dexalot/DexalotMainnetRFQ.json'; +import { Interface } from 'ethers/lib/utils'; +import { assert } from 'ts-essentials'; +import { + DEXALOT_API_URL, + DEXALOT_API_PRICES_POLLING_INTERVAL_MS, + DEXALOT_PRICES_CACHES_TTL_S, + DEXALOT_GAS_COST, + DEXALOT_PAIRS_CACHES_TTL_S, + DEXALOT_API_PAIRS_POLLING_INTERVAL_MS, + DEXALOT_API_TOKENS_POLLING_INTERVAL_MS, + DEXALOT_TOKENS_CACHES_TTL_S, + DEXALOT_API_BLACKLIST_POLLING_INTERVAL_MS, + DEXALOT_RATE_LIMITED_TTL_S, +} from './constants'; +import { BI_MAX_UINT256 } from '../../bigint-constants'; +import { TooStrictSlippageCheckError } from '../generic-rfq/types'; +import { ethers } from 'ethers'; + +export class Dexalot extends SimpleExchange implements IDex { + readonly isStatePollingDex = true; + readonly hasConstantPriceLargeAmounts = false; + readonly needWrapNative = false; + readonly isFeeOnTransferSupported = false; + private rateFetcher: RateFetcher; + + private pricesCacheKey: string; + private pairsCacheKey: string; + private tokensAddrCacheKey: string; + private tokensCacheKey: string; + private blacklistCacheKey: string; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(DexalotConfig); + + logger: Logger; + + constructor( + readonly network: Network, + readonly dexKey: string, + readonly dexHelper: IDexHelper, + protected adapters = Adapters[network] || {}, + readonly mainnetRFQAddress: string = DexalotConfig['Dexalot'][network] + .mainnetRFQAddress, + protected rfqInterface = new Interface(mainnetRFQAbi), + ) { + super(dexHelper, dexKey); + this.logger = dexHelper.getLogger(dexKey); + + this.pricesCacheKey = `${CACHE_PREFIX}_prices`; + this.pairsCacheKey = `${CACHE_PREFIX}_pairs`; + this.tokensAddrCacheKey = `${CACHE_PREFIX}_tokens_addr`; + this.tokensCacheKey = `${CACHE_PREFIX}_tokens`; + this.blacklistCacheKey = `${CACHE_PREFIX}_blacklist`; + + this.rateFetcher = new RateFetcher( + this.dexHelper, + this.dexKey, + this.network, + this.logger, + { + rateConfig: { + pairsIntervalMs: DEXALOT_API_PAIRS_POLLING_INTERVAL_MS, + pricesIntervalMs: DEXALOT_API_PRICES_POLLING_INTERVAL_MS, + tokensIntervalMs: DEXALOT_API_TOKENS_POLLING_INTERVAL_MS, + blacklistIntervalMs: DEXALOT_API_BLACKLIST_POLLING_INTERVAL_MS, + pairsReqParams: { + url: `${DEXALOT_API_URL}/api/rfq/pairs`, + }, + pricesReqParams: { + url: `${DEXALOT_API_URL}/api/rfq/prices`, + }, + tokensReqParams: { + url: `${DEXALOT_API_URL}/api/rfq/tokens`, + }, + blacklistReqParams: { + url: `${DEXALOT_API_URL}/api/rfq/blacklist`, + }, + pairsCacheKey: this.pairsCacheKey, + pairsCacheTTLSecs: DEXALOT_PAIRS_CACHES_TTL_S, + pricesCacheKey: this.pricesCacheKey, + pricesCacheTTLSecs: DEXALOT_PRICES_CACHES_TTL_S, + tokensAddrCacheKey: this.tokensAddrCacheKey, + tokensCacheKey: this.tokensCacheKey, + tokensCacheTTLSecs: DEXALOT_TOKENS_CACHES_TTL_S, + blacklistCacheKey: this.blacklistCacheKey, + }, + }, + ); + } + + async initializePricing(blockNumber: number): Promise { + if (!this.dexHelper.config.isSlave) { + this.rateFetcher.start(); + } + + return; + } + + getAdapters(side: SwapSide): { name: string; index: number }[] | null { + return this.adapters[side] ? this.adapters[side] : null; + } + + getPairString(baseToken: Token, quoteToken: Token): string { + return `${baseToken.symbol}/${quoteToken.symbol}`.toLowerCase(); + } + + async getPairData( + srcToken: Token, + destToken: Token, + ): Promise { + const normalizedSrcToken = this.normalizeToken(srcToken); + const normalizedDestToken = this.normalizeToken(destToken); + if (normalizedSrcToken.address === normalizedDestToken.address) { + return null; + } + + const cachedTokens = (await this.getCachedTokens()) || {}; + if ( + !(normalizedSrcToken.address in cachedTokens) || + !(normalizedDestToken.address in cachedTokens) + ) { + return null; + } + normalizedSrcToken.symbol = cachedTokens[normalizedSrcToken.address].symbol; + normalizedDestToken.symbol = + cachedTokens[normalizedDestToken.address].symbol; + + const cachedPairs = (await this.getCachedPairs()) || {}; + + const potentialPairs = [ + { + identifier: this.getPairString(normalizedSrcToken, normalizedDestToken), + isSrcBase: true, + }, + { + identifier: this.getPairString(normalizedDestToken, normalizedSrcToken), + isSrcBase: false, + }, + ]; + + for (const pair of potentialPairs) { + if (pair.identifier in cachedPairs) { + const pairData = cachedPairs[pair.identifier]; + pairData.isSrcBase = pair.isSrcBase; + return pairData; + } + } + return null; + } + + getIdentifier(baseSymbol: string, quoteSymbol: string) { + return `${this.dexKey}_${baseSymbol}_${quoteSymbol}`.toLowerCase(); + } + + async getPoolIdentifiers( + srcToken: Token, + destToken: Token, + side: SwapSide, + blockNumber: number, + ): Promise { + if (!srcToken || !destToken) { + return []; + } + const pairData = await this.getPairData(srcToken, destToken); + if (!pairData) { + return []; + } + return [this.getIdentifier(pairData.base, pairData.quote)]; + } + + async getCachedPairs(): Promise { + const cachedPairs = await this.dexHelper.cache.get( + this.dexKey, + this.network, + this.pairsCacheKey, + ); + + if (cachedPairs) { + return JSON.parse(cachedPairs) as PairDataMap; + } + + return null; + } + + async getCachedPrices(): Promise { + const cachedPrices = await this.dexHelper.cache.get( + this.dexKey, + this.network, + this.pricesCacheKey, + ); + + if (cachedPrices) { + return JSON.parse(cachedPrices) as PriceDataMap; + } + + return null; + } + + async getCachedTokensAddr(): Promise { + const cachedTokensAddr = await this.dexHelper.cache.get( + this.dexKey, + this.network, + this.tokensAddrCacheKey, + ); + + if (cachedTokensAddr) { + return JSON.parse(cachedTokensAddr) as TokenAddrDataMap; + } + + return null; + } + + async getCachedTokens(): Promise { + const cachedTokens = await this.dexHelper.cache.get( + this.dexKey, + this.network, + this.tokensCacheKey, + ); + + if (cachedTokens) { + return JSON.parse(cachedTokens) as TokenDataMap; + } + + return null; + } + + normalizeAddress(address: string): string { + return address.toLowerCase() === ETHER_ADDRESS + ? ethers.constants.AddressZero.toLowerCase() + : address.toLowerCase(); + } + + // Dexalot protocol for native token expects 0x00000... instead of 0xeeeee... + normalizeToken(token: Token): Token { + return { + address: this.normalizeAddress(token.address), + decimals: token.decimals, + }; + } + + calculateOrderPrice( + amounts: bigint[], + orderbook: string[][], + baseToken: Token, + quoteToken: Token, + side: ClobSide, + ) { + let result = []; + + for (let i = 0; i < amounts.length; i++) { + let amt = amounts[i]; + if (amt === 0n) { + result.push(amt); + continue; + } + + let totalVolume = 0n; + let combinedPrice = 0n; + + for (let j = 0; j < orderbook.length; j++) { + const order = orderbook[j]; + const priceBN = ethers.utils.parseUnits(order[0], quoteToken.decimals); + const price = BigInt(priceBN.toString()); + const qtyBN = ethers.utils.parseUnits(order[1], baseToken.decimals); + const qty = BigInt(qtyBN.toString()); + let vol = qty; + if (side === ClobSide.BID) { + vol = (qty * price) / BigInt(10 ** baseToken.decimals); + } + if (amt < vol) { + totalVolume += amt; + combinedPrice += amt * price; + amt = 0n; + } else { + amt -= vol; + totalVolume += vol; + combinedPrice += vol * price; + } + if (amt === 0n) { + break; + } + } + const avgPrice = combinedPrice / totalVolume; + if (side === ClobSide.BID) { + result.push((amounts[i] * BigInt(10 ** baseToken.decimals)) / avgPrice); + } else { + result.push((avgPrice * amounts[i]) / BigInt(10 ** baseToken.decimals)); + } + } + return result; + } + + async getPricesVolume( + srcToken: Token, + destToken: Token, + amounts: bigint[], + side: SwapSide, + blockNumber: number, + limitPools?: string[], + ): Promise> { + try { + const normalizedSrcToken = this.normalizeToken(srcToken); + const normalizedDestToken = this.normalizeToken(destToken); + + if (normalizedSrcToken.address === normalizedDestToken.address) { + return null; + } + + if (limitPools && limitPools.length != 1) { + return null; + } + + const pairData = await this.getPairData( + normalizedSrcToken, + normalizedDestToken, + ); + if (!pairData) { + return null; + } + + const priceMap = await this.getCachedPrices(); + if (!priceMap) { + return null; + } + + const pairKey = `${pairData.base}/${pairData.quote}`.toLowerCase(); + if (!(pairKey in priceMap)) { + return null; + } + + const priceData = priceMap[pairKey]; + const baseToken = pairData.isSrcBase + ? normalizedSrcToken + : normalizedDestToken; + const quoteToken = pairData.isSrcBase + ? normalizedDestToken + : normalizedSrcToken; + + // convert from swap to clob side + let orderbook = priceData.asks; + let clobSide = ClobSide.BID; + if ( + (side === SwapSide.SELL && pairData.isSrcBase) || + (side === SwapSide.BUY && !pairData.isSrcBase) + ) { + orderbook = priceData.bids; + clobSide = ClobSide.ASK; + } + if (orderbook.length === 0) { + throw new Error(`Empty orderbook for ${pairKey}`); + } + + const prices = this.calculateOrderPrice( + amounts, + orderbook, + baseToken, + quoteToken, + clobSide, + ); + const outDecimals = + clobSide === ClobSide.BID ? baseToken.decimals : quoteToken.decimals; + const poolIdentifier = this.getIdentifier(pairData.base, pairData.quote); + + return [ + { + prices, + unit: BigInt(outDecimals), + data: {}, + poolIdentifier: poolIdentifier, + exchange: this.dexKey, + gasCost: DEXALOT_GAS_COST, + poolAddresses: [this.mainnetRFQAddress], + }, + ]; + } catch (e: unknown) { + this.logger.error(e); + this.logger.error( + `Error_getPricesVolume ${srcToken.symbol || srcToken.address}, ${ + destToken.symbol || destToken.address + }, ${side}:`, + e, + ); + return null; + } + } + + generateRFQError(errorStr: string, swapIdentifier: string) { + const message = `${this.dexKey}-${this.network}: Failed to fetch RFQ for ${swapIdentifier}. ${errorStr}`; + this.logger.warn(message); + throw new RfqError(message); + } + + async preProcessTransaction( + optimalSwapExchange: OptimalSwapExchange, + srcToken: Token, + destToken: Token, + side: SwapSide, + options: PreprocessTransactionOptions, + ): Promise<[OptimalSwapExchange, ExchangeTxInfo]> { + if (await this.isBlacklisted(options.txOrigin)) { + this.logger.warn( + `${this.dexKey}-${this.network}: blacklisted TX Origin address '${options.txOrigin}' trying to build a transaction. Bailing...`, + ); + throw new Error( + `${this.dexKey}-${ + this.network + }: user=${options.txOrigin.toLowerCase()} is blacklisted`, + ); + } + if (await this.isRateLimited(options.txOrigin)) { + this.logger.warn( + `${this.dexKey}-${this.network}: rate limited TX Origin address '${options.txOrigin}' trying to build a transaction. Bailing...`, + ); + throw new Error( + `${this.dexKey}-${ + this.network + }: user=${options.txOrigin.toLowerCase()} is rate limited`, + ); + } + if (BigInt(optimalSwapExchange.srcAmount) === 0n) { + throw new Error('getFirmRate failed with srcAmount == 0'); + } + + const normalizedSrcToken = this.normalizeToken(srcToken); + const normalizedDestToken = this.normalizeToken(destToken); + const swapIdentifier = `${this.getIdentifier( + normalizedSrcToken.address, + normalizedDestToken.address, + )}_${side}`; + + try { + const makerToken = normalizedDestToken; + const takerToken = normalizedSrcToken; + + const rfqParams = { + makerAsset: ethers.utils.getAddress(makerToken.address), + takerAsset: ethers.utils.getAddress(takerToken.address), + makerAmount: + side === SwapSide.BUY ? optimalSwapExchange.destAmount : undefined, + takerAmount: + side === SwapSide.SELL ? optimalSwapExchange.srcAmount : undefined, + userAddress: options.txOrigin, + }; + + const rfq: RFQResponse = await this.dexHelper.httpRequest.post( + `${DEXALOT_API_URL}/api/rfq/firm`, + rfqParams, + ); + if (!rfq) { + this.generateRFQError( + 'Missing quote data', + `RFQ ${swapIdentifier} ${JSON.stringify(rfq)}`, + ); + } else if (!rfq.order.signature) { + this.generateRFQError('Missing signature', swapIdentifier); + } + + const { order } = rfq; + + assert( + order.makerAsset.toLowerCase() === makerToken.address, + `QuoteData makerAsset=${order.makerAsset} is different from Paraswap makerAsset=${makerToken.address}`, + ); + assert( + order.takerAsset.toLowerCase() === takerToken.address, + `QuoteData takerAsset=${order.takerAsset} is different from Paraswap takerAsset=${takerToken.address}`, + ); + + const expiryAsBigInt = BigInt(order.expiry); + const minDeadline = expiryAsBigInt > 0 ? expiryAsBigInt : BI_MAX_UINT256; + + // if (side === SwapSide.SELL) { + // const makerAmountLowerBounds: bigint = + // (BigInt(optimalSwapExchange.destAmount.toString()) * BigInt(9900)) / + // BigInt(10000); + // const makerAmountUpperBounds: bigint = + // (BigInt(optimalSwapExchange.destAmount.toString()) * BigInt(10100)) / + // BigInt(10000); + // assert( + // BigInt(order.makerAmount) < makerAmountUpperBounds, + // 'Too much Slippage', + // ); + // assert( + // BigInt(order.makerAmount) > makerAmountLowerBounds, + // 'Too much Slippage', + // ); + // } else { + // const takerAmountLowerBounds: bigint = + // (BigInt(optimalSwapExchange.srcAmount.toString()) * BigInt(9900)) / + // BigInt(10000); + // const takerAmountUpperBounds: bigint = + // (BigInt(optimalSwapExchange.srcAmount.toString()) * BigInt(10100)) / + // BigInt(10000); + // assert( + // BigInt(order.takerAmount) < takerAmountUpperBounds, + // 'Too much Slippage', + // ); + // assert( + // BigInt(order.takerAmount) > takerAmountLowerBounds, + // 'Too much Slippage', + // ); + // } + + return [ + { + ...optimalSwapExchange, + data: { + quoteData: order, + }, + }, + { deadline: minDeadline }, + ]; + } catch (e) { + if (isAxiosError(e) && e.response && e.response.data) { + const errorData: RFQResponseError = e.response.data; + if (errorData.ReasonCode === 'FQ-009') { + this.logger.warn( + `${this.dexKey}-${this.network}: Encountered rate limited user=${options.txOrigin}. Adding to local rate limit cache`, + ); + await this.setRateLimited(options.txOrigin, errorData.RetryAfter); + } else { + this.logger.error( + `${this.dexKey}-${this.network}: Failed to fetch RFQ for ${swapIdentifier}: ${errorData.Reason}`, + ); + } + } else if (e instanceof TooStrictSlippageCheckError) { + this.logger.warn( + `${this.dexKey}-${this.network}: Failed to build transaction on side ${side} with too strict slippage. Skipping restriction`, + ); + } else { + this.logger.error( + `${this.dexKey}-${this.network}: Failed to fetch RFQ for ${swapIdentifier}:`, + JSON.stringify(e), + ); + } + + throw e; + } + } + + getCalldataGasCost(poolPrices: PoolPrices): number | number[] { + return ( + CALLDATA_GAS_COST.DEX_OVERHEAD + + // addresses: makerAsset, takerAsset, maker, taker + CALLDATA_GAS_COST.ADDRESS * 4 + + // uint256: expiry + CALLDATA_GAS_COST.wordNonZeroBytes(16) + + // uint256: nonceAndMeta, makerAmount, takerAmount + CALLDATA_GAS_COST.AMOUNT * 3 + + // bytes: _signature (65 bytes) + CALLDATA_GAS_COST.FULL_WORD * 2 + + CALLDATA_GAS_COST.OFFSET_SMALL + ); + } + + getTokenFromAddress?(address: Address): Token { + // We don't have predefined set of tokens with decimals + // Anyway we don't use decimals, so it is fine to do this + return { address, decimals: 0 }; + } + + getAdapterParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: DexalotData, + side: SwapSide, + ): AdapterExchangeParam { + const { quoteData } = data; + + assert( + quoteData !== undefined, + `${this.dexKey}-${this.network}: quoteData undefined`, + ); + + const swapFunction = 'simpleSwap'; + const swapFunctionParams = [ + [ + quoteData.nonceAndMeta, + quoteData.expiry, + quoteData.makerAsset, + quoteData.takerAsset, + quoteData.maker, + quoteData.taker, + quoteData.makerAmount, + quoteData.takerAmount, + ], + quoteData.signature, + ]; + + const payload = this.rfqInterface.encodeFunctionData( + swapFunction, + swapFunctionParams, + ); + + return { + targetExchange: this.mainnetRFQAddress, + payload, + networkFee: '0', + }; + } + + async setBlacklist(txOrigin: Address): Promise { + await this.dexHelper.cache.sadd( + this.blacklistCacheKey, + txOrigin.toLowerCase(), + ); + return true; + } + + async isBlacklisted(txOrigin: Address): Promise { + return this.dexHelper.cache.sismember( + this.blacklistCacheKey, + txOrigin.toLowerCase(), + ); + } + + getRateLimitedKey(address: Address) { + return `rate_limited_${address}`.toLowerCase(); + } + + async isRateLimited(txOrigin: Address): Promise { + const result = await this.dexHelper.cache.get( + this.dexKey, + this.network, + this.getRateLimitedKey(txOrigin), + ); + return result === 'limited'; + } + + async setRateLimited(txOrigin: Address, ttl?: number) { + await this.dexHelper.cache.setex( + this.dexKey, + this.network, + this.getRateLimitedKey(txOrigin), + ttl || DEXALOT_RATE_LIMITED_TTL_S, + 'limited', + ); + return true; + } + + async getSimpleParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: DexalotData, + side: SwapSide, + ): Promise { + const { quoteData } = data; + + assert( + quoteData !== undefined, + `${this.dexKey}-${this.network}: quoteData undefined`, + ); + + const swapFunction = 'simpleSwap'; + const swapFunctionParams = [ + [ + quoteData.nonceAndMeta, + quoteData.expiry, + quoteData.makerAsset, + quoteData.takerAsset, + quoteData.maker, + quoteData.taker, + quoteData.makerAmount, + quoteData.takerAmount, + ], + quoteData.signature, + ]; + + const swapData = this.rfqInterface.encodeFunctionData( + swapFunction, + swapFunctionParams, + ); + + return this.buildSimpleParamWithoutWETHConversion( + srcToken, + srcAmount, + destToken, + destAmount, + swapData, + this.mainnetRFQAddress, + ); + } + + async getTopPoolsForToken( + tokenAddress: Address, + limit: number, + ): Promise { + const normalizedAddress = this.normalizeAddress(tokenAddress); + + const pairs = (await this.getCachedPairs()) || {}; + const tokens = (await this.getCachedTokens()) || {}; + const tokensAddr = (await this.getCachedTokensAddr()) || {}; + if (!tokens[normalizedAddress]) { + return []; + } + + const token = tokens[normalizedAddress]; + const tokenSymbol = token.symbol?.toLowerCase() || ''; + + let pairsByLiquidity = []; + for (const pairName of Object.keys(pairs)) { + if (pairName.includes(tokenSymbol)) { + const tokensInPair = pairName.split('/'); + if (tokensInPair.length !== 2) { + continue; + } + + const addr = tokensAddr[tokensInPair[0].toLowerCase()]; + let outputToken = tokens[addr]; + if (tokensInPair[0] === tokenSymbol) { + const addr = tokensAddr[tokensInPair[1].toLowerCase()]; + outputToken = tokens[addr]; + } + + const connectorToken = { + address: outputToken.address, + decimals: outputToken.decimals, + }; + const pairData: PoolLiquidity = { + exchange: this.dexKey, + address: this.mainnetRFQAddress, + connectorTokens: [connectorToken], + liquidityUSD: pairs[pairName].liquidityUSD, + }; + pairsByLiquidity.push(pairData); + } + } + + pairsByLiquidity.sort( + (a: PoolLiquidity, b: PoolLiquidity) => b.liquidityUSD - a.liquidityUSD, + ); + + return pairsByLiquidity.slice(0, limit); + } + + releaseResources(): void { + if (this.rateFetcher) { + this.rateFetcher.stop(); + } + } +} diff --git a/src/dex/dexalot/rate-fetcher.ts b/src/dex/dexalot/rate-fetcher.ts new file mode 100644 index 000000000..5b1cbf75c --- /dev/null +++ b/src/dex/dexalot/rate-fetcher.ts @@ -0,0 +1,209 @@ +import { IDexHelper } from '../../dex-helper'; +import { Fetcher } from '../../lib/fetcher/fetcher'; +import { validateAndCast } from '../../lib/validators'; +import { Logger, Token } from '../../types'; +import { + DexalotRateFetcherConfig, + DexalotPairsResponse, + PairDataMap, + DexalotPricesResponse, + PriceDataMap, + DexalotTokensResponse, + DexalotBlacklistResponse, +} from './types'; +import { + pricesResponseValidator, + pairsResponseValidator, + tokensResponseValidator, + blacklistResponseValidator, +} from './validators'; +import { Network } from '../../constants'; + +export class RateFetcher { + private pairsFetcher: Fetcher; + private pairsCacheKey: string; + private pairsCacheTTL: number; + + private rateFetcher: Fetcher; + private pricesCacheKey: string; + private pricesCacheTTL: number; + + private tokensFetcher: Fetcher; + private tokensAddrCacheKey: string; + private tokensCacheKey: string; + private tokensCacheTTL: number; + + private blacklistFetcher: Fetcher; + private blacklistCacheKey: string; + + constructor( + private dexHelper: IDexHelper, + private dexKey: string, + private network: Network, + private logger: Logger, + config: DexalotRateFetcherConfig, + ) { + this.pairsCacheKey = config.rateConfig.pairsCacheKey; + this.pairsCacheTTL = config.rateConfig.pairsCacheTTLSecs; + this.pricesCacheKey = config.rateConfig.pricesCacheKey; + this.pricesCacheTTL = config.rateConfig.pricesCacheTTLSecs; + this.tokensAddrCacheKey = config.rateConfig.tokensAddrCacheKey; + this.tokensCacheKey = config.rateConfig.tokensCacheKey; + this.tokensCacheTTL = config.rateConfig.tokensCacheTTLSecs; + this.blacklistCacheKey = config.rateConfig.blacklistCacheKey; + + this.pairsFetcher = new Fetcher( + dexHelper.httpRequest, + { + info: { + requestOptions: config.rateConfig.pairsReqParams, + caster: (data: unknown) => { + return validateAndCast( + data, + pairsResponseValidator, + ); + }, + }, + handler: this.handlePairsResponse.bind(this), + }, + config.rateConfig.pairsIntervalMs, + logger, + ); + + this.rateFetcher = new Fetcher( + dexHelper.httpRequest, + { + info: { + requestOptions: config.rateConfig.pricesReqParams, + caster: (data: unknown) => { + return validateAndCast( + data, + pricesResponseValidator, + ); + }, + }, + handler: this.handleRatesResponse.bind(this), + }, + config.rateConfig.pricesIntervalMs, + logger, + ); + + this.tokensFetcher = new Fetcher( + dexHelper.httpRequest, + { + info: { + requestOptions: config.rateConfig.tokensReqParams, + caster: (data: unknown) => { + return validateAndCast( + data, + tokensResponseValidator, + ); + }, + }, + handler: this.handleTokensResponse.bind(this), + }, + config.rateConfig.tokensIntervalMs, + logger, + ); + + this.blacklistFetcher = new Fetcher( + dexHelper.httpRequest, + { + info: { + requestOptions: config.rateConfig.blacklistReqParams, + caster: (data: unknown) => { + return validateAndCast( + data, + blacklistResponseValidator, + ); + }, + }, + handler: this.handleBlacklistResponse.bind(this), + }, + config.rateConfig.blacklistIntervalMs, + logger, + ); + } + + start() { + this.pairsFetcher.startPolling(); + this.rateFetcher.startPolling(); + this.tokensFetcher.startPolling(); + this.blacklistFetcher.startPolling(); + } + + stop() { + this.pairsFetcher.stopPolling(); + this.rateFetcher.stopPolling(); + this.tokensFetcher.stopPolling(); + this.blacklistFetcher.stopPolling(); + } + + private handlePairsResponse(resp: DexalotPairsResponse): void { + const { pairs } = resp; + const dexPairs: PairDataMap = {}; + Object.keys(pairs).forEach(pair => { + dexPairs[pair.toLowerCase()] = pairs[pair]; + }); + this.dexHelper.cache.setex( + this.dexKey, + this.network, + this.pairsCacheKey, + this.pairsCacheTTL, + JSON.stringify(dexPairs), + ); + } + + private handleRatesResponse(resp: DexalotPricesResponse): void { + const { prices } = resp; + const dexPrices: PriceDataMap = {}; + Object.keys(prices).forEach(pair => { + dexPrices[pair.toLowerCase()] = prices[pair]; + }); + this.dexHelper.cache.setex( + this.dexKey, + this.network, + this.pricesCacheKey, + this.pricesCacheTTL, + JSON.stringify(dexPrices), + ); + } + + private handleTokensResponse(resp: DexalotTokensResponse): void { + const { tokens } = resp; + const tokenMap: { [address: string]: Token } = {}; + const tokenAddrMap: { [pair: string]: string } = {}; + Object.keys(tokens).forEach(symbol => { + const token = tokens[symbol]; + tokenMap[token.address.toLowerCase()] = { + address: token.address.toLowerCase(), + symbol: token.symbol, + decimals: token.decimals, + }; + tokenAddrMap[token.symbol.toLowerCase()] = token.address.toLowerCase(); + }); + this.dexHelper.cache.setex( + this.dexKey, + this.network, + this.tokensCacheKey, + this.tokensCacheTTL, + JSON.stringify(tokenMap), + ); + this.dexHelper.cache.setex( + this.dexKey, + this.network, + this.tokensAddrCacheKey, + this.tokensCacheTTL, + JSON.stringify(tokenAddrMap), + ); + } + + private async handleBlacklistResponse( + resp: DexalotBlacklistResponse, + ): Promise { + const { blacklist } = resp; + for (const address of blacklist) { + this.dexHelper.cache.sadd(this.blacklistCacheKey, address.toLowerCase()); + } + } +} diff --git a/src/dex/dexalot/types.ts b/src/dex/dexalot/types.ts new file mode 100644 index 000000000..fba44c1cd --- /dev/null +++ b/src/dex/dexalot/types.ts @@ -0,0 +1,134 @@ +import { RequestHeaders } from '../../dex-helper'; +import { Token } from '../../types'; + +type RFQOrder = { + nonceAndMeta: string; + expiry: number; + makerAsset: string; + takerAsset: string; + maker: string; + taker: string; + makerAmount: string; + takerAmount: string; + signature: string; +}; + +export type RFQResponse = { + order: RFQOrder; +}; + +export type RFQResponseError = { + Reason: string; + ReasonCode: string; + Success: boolean; + RetryAfter?: number; +}; + +export type DexalotData = { + quoteData?: RFQOrder; +}; + +export type DexParams = { + mainnetRFQAddress: string; +}; + +export enum ClobSide { + BID = 'BID', + ASK = 'ASK', +} + +export class RfqError extends Error {} + +export class SlippageCheckError extends Error {} + +export type PairData = { + base: string; + quote: string; + liquidityUSD: number; + isSrcBase?: boolean; +}; + +export type PairDataMap = { + [pair: string]: PairData; +}; + +export type DexalotPairsResponse = { + pairs: PairDataMap; +}; + +type PriceData = { + bids: string[][]; + asks: string[][]; +}; + +export type PriceDataMap = { + [pair: string]: PriceData; +}; + +export type DexalotPricesResponse = { + prices: PriceDataMap; +}; + +export type TokenAddrDataMap = { + [symbol: string]: string; +}; + +type TokenData = { + symbol: string; + name: string; + description: string; + address: any; + decimals: number; + type: string; +}; + +export type TokenDataMap = { + [address: string]: Token; +}; + +export type DexalotTokensResponse = { + tokens: { + [token: string]: TokenData; + }; +}; + +export type DexalotBlacklistResponse = { + blacklist: string[]; +}; + +export type DexalotRateFetcherConfig = { + rateConfig: { + pairsReqParams: { + url: string; + headers?: RequestHeaders; + params?: any; + }; + pricesReqParams: { + url: string; + headers?: RequestHeaders; + params?: any; + }; + tokensReqParams: { + url: string; + headers?: RequestHeaders; + params?: any; + }; + blacklistReqParams: { + url: string; + headers?: RequestHeaders; + params?: any; + }; + pairsIntervalMs: number; + pricesIntervalMs: number; + tokensIntervalMs: number; + blacklistIntervalMs: number; + pairsCacheKey: string; + pricesCacheKey: string; + tokensAddrCacheKey: string; + tokensCacheKey: string; + blacklistCacheKey: string; + pairsCacheTTLSecs: number; + pricesCacheTTLSecs: number; + tokensCacheTTLSecs: number; + }; +}; diff --git a/src/dex/dexalot/validators.ts b/src/dex/dexalot/validators.ts new file mode 100644 index 000000000..52ca64a57 --- /dev/null +++ b/src/dex/dexalot/validators.ts @@ -0,0 +1,43 @@ +import joi from 'joi'; + +const pairValidator = joi.object({ + base: joi.string().min(1).required(), + quote: joi.string().min(1).required(), + liquidityUSD: joi.number().min(0).required(), +}); + +export const pairsResponseValidator = joi.object({ + pairs: joi.object().pattern(joi.string(), pairValidator), +}); + +const orderbookRecordValidator = joi + .array() + .items(joi.string().min(1)) + .length(2) + .required(); + +const orderbookValidator = joi.object({ + bids: joi.array().items(orderbookRecordValidator).required(), + asks: joi.array().items(orderbookRecordValidator).required(), +}); + +export const pricesResponseValidator = joi.object({ + prices: joi.object().pattern(joi.string(), orderbookValidator), +}); + +const tokenValidator = joi.object({ + symbol: joi.string().min(1).required(), + name: joi.string().min(1).required(), + description: joi.string().min(1).required(), + address: joi.string().min(1).required(), + decimals: joi.number().min(0).required(), + type: joi.string().min(1).required(), +}); + +export const tokensResponseValidator = joi.object({ + tokens: joi.object().pattern(joi.string(), tokenValidator), +}); + +export const blacklistResponseValidator = joi.object({ + blacklist: joi.array().items(joi.string().min(1)).required(), +}); diff --git a/src/dex/index.ts b/src/dex/index.ts index f32c7d800..539d58fb9 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -70,6 +70,7 @@ import { SpiritSwapV3 } from './quickswap/spiritswap-v3'; import { TraderJoeV21 } from './trader-joe-v2.1'; import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3'; import { Algebra } from './algebra/algebra'; +import { Dexalot } from './dexalot/dexalot'; const LegacyDexes = [ CurveV2, @@ -96,6 +97,7 @@ const LegacyDexes = [ ]; const Dexes = [ + Dexalot, CurveV1, CurveFork, Swerve, From cc1425f6681ed4292cdc10e91c67d171e7b855ac Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 25 Aug 2023 11:09:39 +0200 Subject: [PATCH 135/833] reactivating stable and composableStable and manually blacklist pool ids --- src/dex/balancer-v2/balancer-v2.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/dex/balancer-v2/balancer-v2.ts b/src/dex/balancer-v2/balancer-v2.ts index c7afdc50f..dc8d6bad7 100644 --- a/src/dex/balancer-v2/balancer-v2.ts +++ b/src/dex/balancer-v2/balancer-v2.ts @@ -74,8 +74,8 @@ import { NumberAsString, OptimalSwapExchange } from '@paraswap/core'; // If you disable some pool, don't forget to clear the cache, otherwise changes won't be applied immediately const enabledPoolTypes = [ - // BalancerPoolTypes.MetaStable, - // BalancerPoolTypes.Stable, + // BalancerPoolTypes.MetaStable, // BOOSTED POOLS Disabled since vulnerability https://github.com/BalancerMaxis/multisig-ops/blob/main/BIPs/00notGov/2023-08-mitigation.md + BalancerPoolTypes.Stable, BalancerPoolTypes.Weighted, // BalancerPoolTypes.LiquidityBootstrapping, // BalancerPoolTypes.Investment, @@ -83,7 +83,7 @@ const enabledPoolTypes = [ BalancerPoolTypes.AaveLinear, BalancerPoolTypes.ERC4626Linear, BalancerPoolTypes.Linear, - // BalancerPoolTypes.ComposableStable, + BalancerPoolTypes.ComposableStable, BalancerPoolTypes.BeefyLinear, BalancerPoolTypes.GearboxLinear, BalancerPoolTypes.MidasLinear, @@ -102,7 +102,18 @@ const fetchAllPools = `query ($count: Int) { totalLiquidity_gt: ${MIN_USD_LIQUIDITY_TO_FETCH.toString()}, totalShares_not_in: ["0", "0.000000000001"], id_not_in: [ - "0xbd482ffb3e6e50dc1c437557c3bea2b68f3683ee0000000000000000000003c6" + "0xbd482ffb3e6e50dc1c437557c3bea2b68f3683ee0000000000000000000003c6", + "0xbf2ef8bdc2fc0f3203b3a01778e3ec5009aeef3300000000000000000000058d", + "0x99c88ad7dc566616548adde8ed3effa730eb6c3400000000000000000000049a", + "0x60683b05e9a39e3509d8fdb9c959f23170f8a0fa000000000000000000000489", + "0xa13a9247ea42d743238089903570127dda72fe4400000000000000000000035d", + "0x7b50775383d3d6f0215a8f290f2c9e2eebbeceb20000000000000000000000fe", + "0x25accb7943fd73dda5e23ba6329085a3c24bfb6a000200000000000000000387", + "0x50cf90b954958480b8df7958a9e965752f62712400000000000000000000046f", + "0x133d241f225750d2c92948e464a5a80111920331000000000000000000000476", + "0x8a6b25e33b12d1bb6929a8793961076bd1f9d3eb0002000000000000000003e8", + "0x959216bb492b2efa72b15b7aacea5b5c984c3cca000200000000000000000472", + "0x9b692f571b256140a39a34676bffa30634c586e100000000000000000000059d" ], address_not_in: [ "0x0afbd58beca09545e4fb67772faf3858e610bcd0", From 9780780a6be35b8d65ef3b0263a6a6126b3a3e73 Mon Sep 17 00:00:00 2001 From: pbnather <33466053+pbnather@users.noreply.github.com> Date: Fri, 25 Aug 2023 11:13:49 +0200 Subject: [PATCH 136/833] Add Morphex BSC --- src/dex/morphex/config.ts | 18 ++- src/dex/morphex/morphex-e2e.test.ts | 75 +++++++++++ src/dex/morphex/morphex-events.test.ts | 64 ++++++++- src/dex/morphex/morphex-integration.test.ts | 138 +++++++++++++++++--- 4 files changed, 271 insertions(+), 24 deletions(-) diff --git a/src/dex/morphex/config.ts b/src/dex/morphex/config.ts index 7d576f158..be57e017c 100644 --- a/src/dex/morphex/config.ts +++ b/src/dex/morphex/config.ts @@ -12,6 +12,14 @@ export const MorphexConfig: DexConfigMap = { fastPriceEvents: '0xDc7C389be5da32e326A261dC0126feCa7AE04d79', usdg: '0xe135c7BFfda932b5B862Da442cF4CbC4d43DC3Ad', }, + [Network.BSC]: { + vault: '0x46940Dc651bFe3F2CC3E04cf9dC5579B50Cf0765', + reader: '0x49A97680938B4F1f73816d1B70C3Ab801FAd124B', + priceFeed: '0x0144b19D1B9338fC7C286d6767bd9b29F0347f27', + fastPriceFeed: '0x55e6e6A968e485abEC1e1d957f408586e45a4f99', + fastPriceEvents: '0x491Df61db853761d42C4F38BeD220E9D807143dE', + usdg: '0x548f93779fBC992010C07467cBaf329DD5F059B7', + }, }, }; @@ -24,7 +32,15 @@ export const Adapters: { [SwapSide.SELL]: [ { name: 'FantomAdapter01', - index: 6, // TODO: it's for aavev3, but there is no Morphex adapter + index: 6, // TODO: there is no Morphex adapter + }, + ], + }, + [Network.BSC]: { + [SwapSide.SELL]: [ + { + name: 'BscAdapter01', + index: 6, // TODO: there is no Morphex adapter }, ], }, diff --git a/src/dex/morphex/morphex-e2e.test.ts b/src/dex/morphex/morphex-e2e.test.ts index 47d04c20a..cf701af17 100644 --- a/src/dex/morphex/morphex-e2e.test.ts +++ b/src/dex/morphex/morphex-e2e.test.ts @@ -88,4 +88,79 @@ describe('Morphex E2E', () => { }), ); }); + + describe('Morphex BSC', () => { + const network = Network.BSC; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'USDT'; + const tokenBSymbol: string = 'ETH'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '2000000000000000000000'; // 2000 USDT + const tokenBAmount: string = '1000000000000000000'; // 1 ETH + const nativeTokenAmount = '1000000000000000000'; // 1 BNB + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(nativeTokenSymbol + ' -> TOKEN', async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it('TOKEN -> ' + nativeTokenSymbol, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it('TOKEN -> TOKEN', async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); }); diff --git a/src/dex/morphex/morphex-events.test.ts b/src/dex/morphex/morphex-events.test.ts index e488738af..f2bf62360 100644 --- a/src/dex/morphex/morphex-events.test.ts +++ b/src/dex/morphex/morphex-events.test.ts @@ -10,8 +10,6 @@ import { PoolState } from '../gmx/types'; jest.setTimeout(50 * 1000); const dexKey = 'Morphex'; -const network = Network.FANTOM; -const params = MorphexConfig[dexKey][network]; async function fetchPoolState( gmxPool: GMXEventPool, @@ -38,7 +36,9 @@ function compareState(state: PoolState, expectedState: PoolState) { ); } -describe('Morphex Event', function () { +describe('Morphex Fantom Events', function () { + const network = Network.FANTOM; + const params = MorphexConfig[dexKey][network]; const blockNumbers: { [eventName: string]: number[] } = { IncreaseUsdgAmount: [ 67247602, 67247565, 67247561, 67247508, 67247393, 67247305, 67247303, @@ -90,3 +90,61 @@ describe('Morphex Event', function () { }); }); }); + +describe('Morphex BSC Events', function () { + const network = Network.BSC; + const params = MorphexConfig[dexKey][network]; + const blockNumbers: { [eventName: string]: number[] } = { + IncreaseUsdgAmount: [ + 31152256, 31138628, 31137790, 31137788, 31131427, 31123797, 31120641, + 31116766, 31116335, 31116205, 31115380, 31112437, 31112433, 31107317, + 31106077, 31106044, 31105166, 31104580, 31104252, 31104234, 31102490, + 31097010, + ], + DecreaseUsdgAmount: [ + 31152256, 31137790, 31137788, 31136832, 31136830, 31136827, 31136825, + 31136823, 31136820, 31136818, 31136815, 31131427, 31112437, 31112433, + 31106077, 31106044, 31105166, 31104580, 31099233, 31099169, 31098990, + 31097010, 31093513, + ], + Transfer: [ + 31138628, 31123797, 31120641, 31116766, 31116335, 31116205, 31115380, + 31107317, 31104252, 31104234, 31102490, 31099233, 31099233, 31099169, + ], + PriceUpdate: [31156757, 31156707, 31156648, 31156597, 31156526], + }; + + describe('MorphexEventPool', function () { + Object.keys(blockNumbers).forEach((event: string) => { + blockNumbers[event].forEach((blockNumber: number) => { + it(`Should return the correct state after the ${blockNumber}:${event}`, async function () { + const dexHelper = new DummyDexHelper(network); + const logger = dexHelper.getLogger(dexKey); + + const config = await GMXEventPool.getConfig( + params, + blockNumber, + dexHelper.multiContract, + ); + const gmxPool = new GMXEventPool( + dexKey, + network, + dexHelper, + logger, + config, + ); + + await testEventSubscriber( + gmxPool, + gmxPool.addressesSubscribed, + (_blockNumber: number) => fetchPoolState(gmxPool, _blockNumber), + blockNumber, + `${dexKey}_${params.vault}`, + dexHelper.provider, + compareState, + ); + }); + }); + }); + }); +}); diff --git a/src/dex/morphex/morphex-integration.test.ts b/src/dex/morphex/morphex-integration.test.ts index 6300b74f6..7574e5767 100644 --- a/src/dex/morphex/morphex-integration.test.ts +++ b/src/dex/morphex/morphex-integration.test.ts @@ -14,28 +14,126 @@ import { import { Tokens } from '../../../tests/constants-e2e'; import ReaderABI from '../../abi/gmx/reader.json'; -const network = Network.FANTOM; -const TokenASymbol = 'axlUSDC'; -const TokenA = Tokens[network][TokenASymbol]; - -const TokenBSymbol = 'WFTM'; -const TokenB = Tokens[network][TokenBSymbol]; - -const amounts = [ - 0n, - 1000000000n, - 2000000000n, - 3000000000n, - 4000000000n, - 5000000000n, -]; - const dexKey = 'Morphex'; -const params = MorphexConfig[dexKey][network]; -const readerInterface = new Interface(ReaderABI); -const readerAddress = params.reader; -describe('Morphex', function () { +describe('Morphex Fantom', function () { + const network = Network.FANTOM; + const TokenASymbol = 'axlUSDC'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'WFTM'; + const TokenB = Tokens[network][TokenBSymbol]; + + const amounts = [ + 0n, + 1000000000n, + 2000000000n, + 3000000000n, + 4000000000n, + 5000000000n, + ]; + + const readerInterface = new Interface(ReaderABI); + const params = MorphexConfig[dexKey][network]; + const readerAddress = params.reader; + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + const dexHelper = new DummyDexHelper(network); + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const gmx = new Morphex(network, dexKey, dexHelper); + + await gmx.initializePricing(blocknumber); + + const pools = await gmx.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blocknumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await gmx.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + if (gmx.hasConstantPriceLargeAmounts) { + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + } else { + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + } + + // Do on chain pricing based on reader to compare + const readerCallData = amounts.map(a => ({ + target: readerAddress, + callData: readerInterface.encodeFunctionData('getAmountOut', [ + params.vault, + TokenA.address, + TokenB.address, + a.toString(), + ]), + })); + + const readerResult = ( + await dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blocknumber) + ).returnData; + const expectedPrices = readerResult.map((p: any) => + BigInt( + readerInterface.decodeFunctionResult('getAmountOut', p)[0].toString(), + ), + ); + + expect(poolPrices![0].prices).toEqual(expectedPrices); + }); + + it('getTopPoolsForToken', async function () { + const dexHelper = new DummyDexHelper(network); + const gmx = new Morphex(network, dexKey, dexHelper); + + await gmx.updatePoolState(); + const poolLiquidity = await gmx.getTopPoolsForToken(TokenA.address, 10); + console.log( + `${TokenASymbol} Top Pools:`, + JSON.stringify(poolLiquidity, null, 2), + ); + + if (!gmx.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); + } + }); +}); + +describe('Morphex BSC', function () { + const network = Network.BSC; + const TokenASymbol = 'ETH'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDT'; + const TokenB = Tokens[network][TokenBSymbol]; + + const amounts = [ + 0n, + 1000000000000000000n, + 2000000000000000000n, + 3000000000000000000n, + 4000000000000000000n, + 5000000000000000000n, + ]; + + const readerInterface = new Interface(ReaderABI); + const params = MorphexConfig[dexKey][network]; + const readerAddress = params.reader; + it('getPoolIdentifiers and getPricesVolume SELL', async function () { const dexHelper = new DummyDexHelper(network); const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); From f98a72cba45ff99f60dfbb42ef5d34c7e0f521d3 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 25 Aug 2023 11:19:43 +0200 Subject: [PATCH 137/833] 2.31.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f431afad..8911d4dc8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.3", + "version": "2.31.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 8f59f7bcbe3c2ec947ef7b4be03e9b57f1f82aaa Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 25 Aug 2023 13:39:06 +0200 Subject: [PATCH 138/833] disable more pool ids for balancerv2 --- src/dex/balancer-v2/balancer-v2.ts | 83 ++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 15 deletions(-) diff --git a/src/dex/balancer-v2/balancer-v2.ts b/src/dex/balancer-v2/balancer-v2.ts index dc8d6bad7..d6c34b3bf 100644 --- a/src/dex/balancer-v2/balancer-v2.ts +++ b/src/dex/balancer-v2/balancer-v2.ts @@ -77,9 +77,9 @@ const enabledPoolTypes = [ // BalancerPoolTypes.MetaStable, // BOOSTED POOLS Disabled since vulnerability https://github.com/BalancerMaxis/multisig-ops/blob/main/BIPs/00notGov/2023-08-mitigation.md BalancerPoolTypes.Stable, BalancerPoolTypes.Weighted, - // BalancerPoolTypes.LiquidityBootstrapping, - // BalancerPoolTypes.Investment, - // BalancerPoolTypes.StablePhantom, + BalancerPoolTypes.LiquidityBootstrapping, + BalancerPoolTypes.Investment, + BalancerPoolTypes.StablePhantom, BalancerPoolTypes.AaveLinear, BalancerPoolTypes.ERC4626Linear, BalancerPoolTypes.Linear, @@ -93,6 +93,70 @@ const enabledPoolTypes = [ BalancerPoolTypes.YearnLinear, ]; +const disabledPoolIds = [ + // broken ? + '0xbd482ffb3e6e50dc1c437557c3bea2b68f3683ee0000000000000000000003c6', + + /* DISABLED POOLS SINCE VULNERABILITY https://github.com/BalancerMaxis/multisig-ops/blob/main/BIPs/00notGov/2023-08-mitigation.md*/ + /* START:2023-08-mitigation */ + //mainnet + '0xbf2ef8bdc2fc0f3203b3a01778e3ec5009aeef3300000000000000000000058d', + '0x99c88ad7dc566616548adde8ed3effa730eb6c3400000000000000000000049a', + '0x60683b05e9a39e3509d8fdb9c959f23170f8a0fa000000000000000000000489', + '0xa13a9247ea42d743238089903570127dda72fe4400000000000000000000035d', + '0x7b50775383d3d6f0215a8f290f2c9e2eebbeceb20000000000000000000000fe', + '0x25accb7943fd73dda5e23ba6329085a3c24bfb6a000200000000000000000387', + '0x50cf90b954958480b8df7958a9e965752f62712400000000000000000000046f', + '0x133d241f225750d2c92948e464a5a80111920331000000000000000000000476', + '0x8a6b25e33b12d1bb6929a8793961076bd1f9d3eb0002000000000000000003e8', + '0x959216bb492b2efa72b15b7aacea5b5c984c3cca000200000000000000000472', + '0x9b692f571b256140a39a34676bffa30634c586e100000000000000000000059d', + + // polygon + '0xb3d658d5b95bf04e2932370dd1ff976fe18dd66a000000000000000000000ace', + '0x48e6b98ef6329f8f0a30ebb8c7c960330d64808500000000000000000000075b', + '0xb54b2125b711cd183edd3dd09433439d5396165200000000000000000000075e', + + // arbitrum + '0xa8af146d79ac0bb981e4e0d8b788ec5711b1d5d000000000000000000000047b', + '0x077794c30afeccdf5ad2abc0588e8cee7197b71a000000000000000000000352', + '0x519cce718fcd11ac09194cff4517f12d263be067000000000000000000000382', + + // optimism + '0x23ca0306b21ea71552b148cf3c4db4fc85ae19290000000000000000000000ac', + '0x62cf35db540152e94936de63efc90d880d4e241b0000000000000000000000ef', + '0x098f32d98d0d64dba199fc1923d3bf4192e787190001000000000000000000d2', + '0x43da214fab3315aa6c02e0b8f2bfb7ef2e3c60a50000000000000000000000ae', + '0xb1c9ac57594e9b1ec0f3787d9f6744ef4cb0a02400000000000000000000006e', + '0xde45f101250f2ca1c0f8adfc172576d10c12072d00000000000000000000003f', + '0x05e7732bf9ae5592e6aa05afe8cd80f7ab0a7bea00020000000000000000005a', + '0x981fb05b738e981ac532a99e77170ecb4bc27aef00010000000000000000004b', + '0x6222ae1d2a9f6894da50aa25cb7b303497f9bebd000000000000000000000046', + '0x3c74c4ed512050eb843d89fb9dcd5ebb4668eb6d0002000000000000000000cc', + + // fantom + '0xc0064b291bd3d4ba0e44ccfc81bf8e7f7a579cd200000000000000000000042c', + '0x6e6dc948ce85c62125ff7a1e543d761a88f0a4cb000000000000000000000743', + '0x78ab08bf98f90f29a09c9b1d85b3b549369b03a3000100000000000000000354', + '0x302b8b64795b064cadc32f74993a6372498608070001000000000000000003e0', + '0x5ddb92a5340fd0ead3987d3661afcd6104c3b757000000000000000000000187', + '0xdfc65c1f15ad3507754ef0fd4ba67060c108db7e000000000000000000000406', + '0x6da14f5acd58dd5c8e486cfa1dc1c550f5c61c1c0000000000000000000003cf', + '0x592fa9f9d58065096f2b7838709c116957d7b5cf00020000000000000000043c', + '0xf47f4d59c863c02cbfa3eefe6771b9c9fbe7b97800000000000000000000072b', + '0xff2753aaba51c9f84689b9bd0a21b3cf380a1cff00000000000000000000072e', + '0x10441785a928040b456a179691141c48356eb3a50001000000000000000002fa', + '0x64b301e21d640f9bef90458b0987d81fb4cf1b9e00020000000000000000022e', + '0xba0e9aea8a7fa1daab4edf244191f2387a4e472b000100000000000000000737', + '0x1e2576344d49779bdbb71b1b76193d27e6f996b700020000000000000000032d', + '0xa10285f445bcb521f1d623300dc4998b02f11c8f00000000000000000000043b', + + // zkevm + '0x6f34a44fce1506352a171232163e7716dd073ade000200000000000000000015', + '0xe274c9deb6ed34cfe4130f8d0a8a948dea5bb28600000000000000000000000d', + /* END:2023-08-mitigation */ +]; + const fetchAllPools = `query ($count: Int) { pools: pools( first: $count @@ -102,18 +166,7 @@ const fetchAllPools = `query ($count: Int) { totalLiquidity_gt: ${MIN_USD_LIQUIDITY_TO_FETCH.toString()}, totalShares_not_in: ["0", "0.000000000001"], id_not_in: [ - "0xbd482ffb3e6e50dc1c437557c3bea2b68f3683ee0000000000000000000003c6", - "0xbf2ef8bdc2fc0f3203b3a01778e3ec5009aeef3300000000000000000000058d", - "0x99c88ad7dc566616548adde8ed3effa730eb6c3400000000000000000000049a", - "0x60683b05e9a39e3509d8fdb9c959f23170f8a0fa000000000000000000000489", - "0xa13a9247ea42d743238089903570127dda72fe4400000000000000000000035d", - "0x7b50775383d3d6f0215a8f290f2c9e2eebbeceb20000000000000000000000fe", - "0x25accb7943fd73dda5e23ba6329085a3c24bfb6a000200000000000000000387", - "0x50cf90b954958480b8df7958a9e965752f62712400000000000000000000046f", - "0x133d241f225750d2c92948e464a5a80111920331000000000000000000000476", - "0x8a6b25e33b12d1bb6929a8793961076bd1f9d3eb0002000000000000000003e8", - "0x959216bb492b2efa72b15b7aacea5b5c984c3cca000200000000000000000472", - "0x9b692f571b256140a39a34676bffa30634c586e100000000000000000000059d" + ${disabledPoolIds.map(p => `"${p}"`).join(', ')} ], address_not_in: [ "0x0afbd58beca09545e4fb67772faf3858e610bcd0", From 442ba4f82a25130936f5479af456cbb9f2a45ac1 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 25 Aug 2023 13:41:24 +0200 Subject: [PATCH 139/833] 2.31.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8911d4dc8..58414449c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4", + "version": "2.31.5", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 3540849c08288b04c88827debbc24b511ac70141 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 15:39:57 +0100 Subject: [PATCH 140/833] feat: implement manual state fetching for algebra pool --- src/abi/algebra/AlgebraFactory-v1_1.abi.json | 250 +++++++++++++++++++ src/config.ts | 30 +++ src/dex/algebra/algebra-integration.test.ts | 74 ++++++ src/dex/algebra/algebra-pool-v1_1.ts | 200 ++++++++++++++- src/dex/algebra/algebra.ts | 3 +- src/dex/algebra/types.ts | 5 +- src/dex/algebra/utils.ts | 85 ++++++- src/lib/decoders.ts | 12 + 8 files changed, 646 insertions(+), 13 deletions(-) create mode 100644 src/abi/algebra/AlgebraFactory-v1_1.abi.json diff --git a/src/abi/algebra/AlgebraFactory-v1_1.abi.json b/src/abi/algebra/AlgebraFactory-v1_1.abi.json new file mode 100644 index 000000000..c582f39e2 --- /dev/null +++ b/src/abi/algebra/AlgebraFactory-v1_1.abi.json @@ -0,0 +1,250 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "_poolDeployer", "type": "address" }, + { "internalType": "address", "name": "_vaultAddress", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newFarmingAddress", + "type": "address" + } + ], + "name": "FarmingAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "alpha1", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "alpha2", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "beta1", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "beta2", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "gamma1", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "gamma2", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "volumeBeta", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "volumeGamma", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "baseFee", + "type": "uint16" + } + ], + "name": "FeeConfiguration", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "Owner", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "Pool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newVaultAddress", + "type": "address" + } + ], + "name": "VaultAddress", + "type": "event" + }, + { + "inputs": [], + "name": "baseFeeConfiguration", + "outputs": [ + { "internalType": "uint16", "name": "alpha1", "type": "uint16" }, + { "internalType": "uint16", "name": "alpha2", "type": "uint16" }, + { "internalType": "uint32", "name": "beta1", "type": "uint32" }, + { "internalType": "uint32", "name": "beta2", "type": "uint32" }, + { "internalType": "uint16", "name": "gamma1", "type": "uint16" }, + { "internalType": "uint16", "name": "gamma2", "type": "uint16" }, + { "internalType": "uint32", "name": "volumeBeta", "type": "uint32" }, + { "internalType": "uint16", "name": "volumeGamma", "type": "uint16" }, + { "internalType": "uint16", "name": "baseFee", "type": "uint16" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenA", "type": "address" }, + { "internalType": "address", "name": "tokenB", "type": "address" } + ], + "name": "createPool", + "outputs": [ + { "internalType": "address", "name": "pool", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "farmingAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" } + ], + "name": "poolByPair", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolDeployer", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "alpha1", "type": "uint16" }, + { "internalType": "uint16", "name": "alpha2", "type": "uint16" }, + { "internalType": "uint32", "name": "beta1", "type": "uint32" }, + { "internalType": "uint32", "name": "beta2", "type": "uint32" }, + { "internalType": "uint16", "name": "gamma1", "type": "uint16" }, + { "internalType": "uint16", "name": "gamma2", "type": "uint16" }, + { "internalType": "uint32", "name": "volumeBeta", "type": "uint32" }, + { "internalType": "uint16", "name": "volumeGamma", "type": "uint16" }, + { "internalType": "uint16", "name": "baseFee", "type": "uint16" } + ], + "name": "setBaseFeeConfiguration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_farmingAddress", + "type": "address" + } + ], + "name": "setFarmingAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_owner", "type": "address" } + ], + "name": "setOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_vaultAddress", "type": "address" } + ], + "name": "setVaultAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vaultAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/config.ts b/src/config.ts index 45b466f84..399298705 100644 --- a/src/config.ts +++ b/src/config.ts @@ -317,6 +317,36 @@ const baseConfigs: { [network: number]: BaseConfig } = { rpcPollingBlocksBackToTriggerUpdate: 3, forceRpcFallbackDexs: [], }, + + [Network.ZKEVM]: { + network: Network.ZKEVM, + networkName: 'Polygon zkEVM', + isTestnet: false, + nativeTokenName: 'Ether', + nativeTokenSymbol: 'ETH', + wrappedNativeTokenAddress: '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9', + hasEIP1559: true, + augustusAddress: '0xB83B554730d29cE4Cb55BB42206c3E2c03E4A40A', + augustusRFQAddress: '0x7Ee1F7fa4C0b2eDB0Fdd5944c14A07167700486E', + tokenTransferProxyAddress: '0xc8a21fcd5a100c3ecc037c97e2f9c53a8d3a02a1', + multicallV2Address: '0x6cA478C852DfA8941FC819fDf248606eA04780B6', + privateHttpProvider: process.env.HTTP_PROVIDER_1101, + adapterAddresses: { + PolygonZkEvmAdapter01: '0x760870be538e7b4E2110e2890473CC17ADB1fdC1', + PolygonZkEvmBuyAdapter: '0x61bFA60A992472869F8d7b4705609A6E0BCf383f', + }, + + rpcPollingMaxAllowedStateDelayInBlocks: 0, + rpcPollingBlocksBackToTriggerUpdate: 0, + hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', + hashFlowDisabledMMs: + process.env[`HASHFLOW_DISABLED_MMS_10`]?.split(',') || [], + uniswapV3EventLoggingSampleRate: 0, + rfqConfigs: {}, + forceRpcFallbackDexs: [], + // FIXME: Not set properly + uniswapV2ExchangeRouterAddress: '', + }, }; // Should not be used, except by internal test code diff --git a/src/dex/algebra/algebra-integration.test.ts b/src/dex/algebra/algebra-integration.test.ts index 54c674fb7..20b8ef98a 100644 --- a/src/dex/algebra/algebra-integration.test.ts +++ b/src/dex/algebra/algebra-integration.test.ts @@ -14,6 +14,8 @@ import { } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; import { Address } from '@paraswap/core'; +import { AlgebraEventPoolV1_1 } from './algebra-pool-v1_1'; +import { DecodedStateMultiCallResultWithRelativeBitmapsV1_1 } from './types'; function getReaderCalldata( exchangeAddress: string, @@ -432,5 +434,77 @@ describe('Algebra', function () { ); } }); + + it('both generate state result match', async function () { + const pool = (await algebra.getPool( + tokens[srcTokenSymbol].address, + tokens[destTokenSymbol].address, + blockNumber, + )) as AlgebraEventPoolV1_1; + + const [balance0, balance1, stateMulticallFull] = + await pool.fetchPoolStateSingleStep(blockNumber); + + const stateMulticall = { + pool: stateMulticallFull.pool.toLowerCase(), + globalState: { + price: stateMulticallFull.globalState.price, + tick: stateMulticallFull.globalState.tick, + fee: stateMulticallFull.globalState.fee, + communityFeeToken0: stateMulticallFull.globalState.communityFeeToken0, + communityFeeToken1: stateMulticallFull.globalState.communityFeeToken1, + }, + liquidity: stateMulticallFull.liquidity, + tickSpacing: stateMulticallFull.tickSpacing, + maxLiquidityPerTick: stateMulticallFull.maxLiquidityPerTick, + tickBitmap: stateMulticallFull.tickBitmap.map(t => ({ + index: t.index, + value: t.value, + })), + ticks: stateMulticallFull.ticks.map(t => ({ + index: t.index, + value: { + liquidityNet: t.value.liquidityNet, + liquidityGross: t.value.liquidityGross, + secondsOutside: t.value.secondsOutside, + secondsPerLiquidityOutsideX128: + t.value.secondsPerLiquidityOutsideX128, + tickCumulativeOutside: t.value.tickCumulativeOutside, + initialized: t.value.initialized, + }, + })), + }; + + const stateMulticallWithBalance = [balance0, balance1, stateMulticall]; + const stateManually = await pool.fetchStateManually(blockNumber); + // @ts-ignore + delete stateManually[2]['blockTimestamp']; + stateManually[2].pool = stateManually[2].pool.toLowerCase(); + + expect(stateMulticallWithBalance).toStrictEqual(stateManually); + }); + }); + + describe('ZKEVM', () => { + const network = Network.ZKEVM; + const dexHelper = new DummyDexHelper(network); + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + algebra = new Algebra(network, dexKey, dexHelper); + if (algebra.initializePricing) { + await algebra.initializePricing(blockNumber); + } + }); + + it('both generate state result match', async function () { + const pool = (await algebra.getPool( + '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9', + '0xc5015b9d9161dca7e18e32f6f25c4ad850731fd4', + blockNumber, + )) as AlgebraEventPoolV1_1; + + const stateManually = await pool.fetchStateManually(blockNumber); + }); }); }); diff --git a/src/dex/algebra/algebra-pool-v1_1.ts b/src/dex/algebra/algebra-pool-v1_1.ts index 2b9746de5..2548123be 100644 --- a/src/dex/algebra/algebra-pool-v1_1.ts +++ b/src/dex/algebra/algebra-pool-v1_1.ts @@ -2,29 +2,41 @@ import _ from 'lodash'; import { Interface } from '@ethersproject/abi'; import { DeepReadonly, assert } from 'ts-essentials'; import { Address, BlockHeader, Log, Logger } from '../../types'; -import { bigIntify, catchParseLogError, int16 } from '../../utils'; +import { bigIntify, catchParseLogError, int16, uint128 } from '../../utils'; import { InitializeStateOptions, StatefulEventSubscriber, } from '../../stateful-event-subscriber'; import { IDexHelper } from '../../dex-helper/idex-helper'; import { + DecodedGlobalStateV1_1, PoolStateV1_1, TickBitMapMappingsWithBigNumber, TickInfoMappingsWithBigNumber, + TickInfoWithBigNumber, } from './types'; -import { ethers } from 'ethers'; +import { BigNumber, ethers } from 'ethers'; import { Contract } from 'web3-eth-contract'; import AlgebraABI from '../../abi/algebra/AlgebraPool-v1_1.abi.json'; +import FactoryABI from '../../abi/algebra/AlgebraFactory-v1_1.abi.json'; import { DecodedStateMultiCallResultWithRelativeBitmapsV1_1 } from './types'; import { OUT_OF_RANGE_ERROR_POSTFIX, TICK_BITMAP_BUFFER, TICK_BITMAP_TO_USE, } from '../uniswap-v3/constants'; -import { uint256ToBigInt } from '../../lib/decoders'; +import { + addressDecode, + uint256ToBigInt, + uint128ToBigInt, + int24ToBigInt, +} from '../../lib/decoders'; import { MultiCallParams } from '../../lib/multi-wrapper'; -import { decodeStateMultiCallResultWithRelativeBitmapsV1_1 } from './utils'; +import { + decodeGlobalStateV1_1, + decodeStateMultiCallResultWithRelativeBitmapsV1_1, + decodeTicksV1_1, +} from './utils'; import { AlgebraMath } from './lib/AlgebraMath'; import { _reduceTickBitmap, @@ -53,6 +65,7 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber readonly token1: Address; public readonly poolIface = new Interface(AlgebraABI); + public readonly factoryIface = new Interface(FactoryABI); public initFailed = false; public initRetryAttemptCount = 0; @@ -69,6 +82,7 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber mapKey: string = '', readonly poolInitCodeHash: string, readonly poolDeployer: string, + private readonly forceManualStateGeneration: boolean = false, ) { super(parentName, `${token0}_${token1}`, dexHelper, logger, true, mapKey); this.token0 = token0.toLowerCase(); @@ -174,7 +188,7 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber return TICK_BITMAP_TO_USE + TICK_BITMAP_BUFFER; } - private async _fetchPoolStateSingleStep( + async fetchPoolStateSingleStep( blockNumber: number, ): Promise< [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmapsV1_1] @@ -330,13 +344,14 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber return [balance0, balance1, _state]; } + // FIXME: Here happens double conversion in types, but for prototyping and to check if this approach helps, it is nor very important async _fetchInitStateMultiStrategies( blockNumber: number, ): Promise< [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmapsV1_1] > { try { - return await this._fetchPoolStateSingleStep(blockNumber); + return await this.fetchPoolStateSingleStep(blockNumber); } catch (e) { if (e instanceof Error && e.message.includes('Pool does not exist')) throw e; @@ -347,9 +362,178 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber } } + async fetchStateManually( + blockNumber: number, + ): Promise< + [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmapsV1_1] + > { + // FIXME: If this approach works, need to add caching of multicalls + const [poolAddress] = await this.dexHelper.multiWrapper.aggregate([ + { + target: this.factoryAddress, + callData: this.factoryIface.encodeFunctionData('poolByPair', [ + this.token0, + this.token1, + ]), + decodeFunction: addressDecode, + }, + ]); + assert( + poolAddress === this.poolAddress, + `Pool address mismatch: ${poolAddress} != ${this.poolAddress}`, + ); + + const [ + balance0, + balance1, + liquidity, + tickSpacing, + maxLiquidityPerTick, + globalState, + ] = (await this.dexHelper.multiWrapper.aggregate< + bigint | number | DecodedGlobalStateV1_1 + >([ + { + target: this.token0, + callData: this.erc20Interface.encodeFunctionData('balanceOf', [ + this.poolAddress, + ]), + decodeFunction: uint256ToBigInt, + }, + { + target: this.token1, + callData: this.erc20Interface.encodeFunctionData('balanceOf', [ + this.poolAddress, + ]), + decodeFunction: uint256ToBigInt, + }, + { + target: poolAddress, + callData: this.poolIface.encodeFunctionData('liquidity', []), + decodeFunction: uint128ToBigInt, + }, + { + target: poolAddress, + callData: this.poolIface.encodeFunctionData('tickSpacing', []), + decodeFunction: int24ToBigInt, + }, + { + target: poolAddress, + callData: this.poolIface.encodeFunctionData('maxLiquidityPerTick', []), + decodeFunction: uint128ToBigInt, + }, + { + target: poolAddress, + callData: this.poolIface.encodeFunctionData('globalState', []), + decodeFunction: decodeGlobalStateV1_1, + }, + ])) as [bigint, bigint, bigint, bigint, bigint, DecodedGlobalStateV1_1]; + + const currentBitMapIndex = TickTable.position( + BigInt(BigInt(globalState.tick) / BigInt(tickSpacing)), + )[0]; + + const leftBitMapIndex = currentBitMapIndex - this.getBitmapRangeToRequest(); + const rightBitMapIndex = + currentBitMapIndex + this.getBitmapRangeToRequest(); + + const allTickBitMaps = await this.dexHelper.multiWrapper.aggregate( + _.range(Number(leftBitMapIndex), Number(rightBitMapIndex + 1n)).map( + index => { + return { + target: poolAddress, + callData: this.poolIface.encodeFunctionData('tickTable', [ + int16(BigInt(index)), + ]), + decodeFunction: uint256ToBigInt, + }; + }, + ), + ); + + const tickBitmap: TickBitMapMappingsWithBigNumber[] = []; + + let globalIndex = 0; + + for (let i = leftBitMapIndex; i <= rightBitMapIndex; i++) { + const index = int16(i); + const bitmap = allTickBitMaps[globalIndex]; + globalIndex++; + if (bitmap == 0n) continue; + tickBitmap.push({ index: Number(index), value: BigNumber.from(bitmap) }); + } + + const tickIndexes: bigint[] = []; + const ticksValues = await this.dexHelper.multiWrapper.aggregate( + tickBitmap + .map(tb => { + const allBits: MultiCallParams[] = []; + if (tb.value === BigNumber.from(0)) return allBits; + + _.range(0, 256).forEach(j => { + if ((tb.value.toBigInt() & (1n << BigInt(j))) > 0n) { + const populatedTick = + (BigInt.asIntN(16, BigInt(tb.index) << 8n) + BigInt(j)) * + tickSpacing; + + tickIndexes.push(populatedTick); + allBits.push({ + target: poolAddress, + callData: this.poolIface.encodeFunctionData('ticks', [ + populatedTick, + ]), + decodeFunction: decodeTicksV1_1, + }); + } + }); + return allBits; + }) + .flat(), + ); + assert( + tickIndexes.length === ticksValues.length, + `Tick indexes mismatch: ${tickIndexes.length} != ${ticksValues.length}`, + ); + + const ticks: TickInfoMappingsWithBigNumber[] = new Array( + tickIndexes.length, + ); + + tickIndexes.forEach((tickIndex, index) => { + ticks[index] = { + index: Number(tickIndex), + value: ticksValues[index], + }; + }); + + return [ + balance0, + balance1, + // FIXME: If we validate that this is working, remove redundant conversions + { + pool: poolAddress, + blockTimestamp: BigNumber.from(Date.now()), + globalState, + liquidity: BigNumber.from(liquidity), + tickSpacing: Number(tickSpacing), + maxLiquidityPerTick: BigNumber.from(maxLiquidityPerTick), + tickBitmap, + ticks, + }, + ]; + } + async generateState(blockNumber: number): Promise> { - const [balance0, balance1, _state] = - await this._fetchInitStateMultiStrategies(blockNumber); + let balance0 = 0n; + let balance1 = 0n; + let _state: DecodedStateMultiCallResultWithRelativeBitmapsV1_1; + if (this.forceManualStateGeneration) { + [balance0, balance1, _state] = await this.fetchStateManually(blockNumber); + } else { + [balance0, balance1, _state] = await this._fetchInitStateMultiStrategies( + blockNumber, + ); + } const tickBitmap = {}; const ticks = {}; diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 0d00e79c6..3b978c80b 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -226,6 +226,7 @@ export class Algebra extends SimpleExchange implements IDex { this.cacheStateKey, this.config.initHash, this.config.deployer, + this.config.forceManualStateGenerate, ); try { @@ -258,7 +259,7 @@ export class Algebra extends SimpleExchange implements IDex { // on unkown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, e, ); pool.initFailed = true; diff --git a/src/dex/algebra/types.ts b/src/dex/algebra/types.ts index 98a8c1d33..891983100 100644 --- a/src/dex/algebra/types.ts +++ b/src/dex/algebra/types.ts @@ -2,7 +2,7 @@ import { BigNumber } from 'ethers'; import { Address, NumberAsString } from '../../types'; import { TickInfo } from '../uniswap-v3/types'; -type GlobalStateV1_1 = { +export type GlobalStateV1_1 = { price: bigint; // The square root of the current price in Q64.96 format tick: bigint; // The current tick fee: bigint; // The current fee in hundredths of a bip, i.e. 1e-6 @@ -72,6 +72,7 @@ export type DexParams = { initHash: string; version: 'v1.1' | 'v1.9'; forceRPC?: boolean; + forceManualStateGenerate?: boolean; }; export type IAlgebraPoolState = PoolStateV1_1 | PoolState_v1_9; @@ -95,7 +96,7 @@ export type TickInfoMappingsWithBigNumber = { value: TickInfoWithBigNumber; }; -type DecodedGlobalStateV1_1 = { +export type DecodedGlobalStateV1_1 = { price: BigNumber; tick: number; fee: number; diff --git a/src/dex/algebra/utils.ts b/src/dex/algebra/utils.ts index b0f7f73e5..05b5962c1 100644 --- a/src/dex/algebra/utils.ts +++ b/src/dex/algebra/utils.ts @@ -1,11 +1,12 @@ -import { BytesLike, ethers } from 'ethers'; +import { BigNumber, BytesLike, ethers } from 'ethers'; import { assert } from 'ts-essentials'; import { extractSuccessAndValue } from '../../lib/decoders'; import { MultiResult } from '../../lib/multi-wrapper'; import { - DecodedGlobalStateV1_9, + DecodedGlobalStateV1_1, DecodedStateMultiCallResultWithRelativeBitmapsV1_1, DecodedStateMultiCallResultWithRelativeBitmapsV1_9, + TickInfoWithBigNumber, } from './types'; export function decodeStateMultiCallResultWithRelativeBitmapsV1_1( @@ -134,3 +135,83 @@ export function decodeStateMultiCallResultWithRelativeBitmapsV1_9( // But I typed only the ones that are used later return decoded as DecodedStateMultiCallResultWithRelativeBitmapsV1_9; } + +export function decodeGlobalStateV1_1( + result: MultiResult | BytesLike, +): DecodedGlobalStateV1_1 { + const [isSuccess, toDecode] = extractSuccessAndValue(result); + + assert( + isSuccess && toDecode !== '0x', + `decodeGlobalStateV1_1 failed to get decodable result: ${result}`, + ); + + const results: DecodedGlobalStateV1_1 = { + price: BigNumber.from(0), + tick: 0, + fee: 0, + communityFeeToken0: 0, + communityFeeToken1: 0, + }; + + [ + results.price, + results.tick, + results.fee, + , + results.communityFeeToken0, + results.communityFeeToken1, + ] = ethers.utils.defaultAbiCoder.decode( + [`uint160`, `int24`, `uint16`, `uint16`, `uint8`, `uint8`, `bool`], + toDecode, + ); + // This conversion is not precise, because when we decode, we have more values + // But used later + return results; +} + +export function decodeTicksV1_1( + result: MultiResult | BytesLike, +): TickInfoWithBigNumber { + const [isSuccess, toDecode] = extractSuccessAndValue(result); + + assert( + isSuccess && toDecode !== '0x', + `decodeGlobalStateV1_1 failed to get decodable result: ${result}`, + ); + + const results: TickInfoWithBigNumber = { + liquidityNet: BigNumber.from(0), + liquidityGross: BigNumber.from(0), + secondsOutside: 0, + secondsPerLiquidityOutsideX128: BigNumber.from(0), + tickCumulativeOutside: BigNumber.from(0), + initialized: false, + }; + + [ + results.liquidityGross, + results.liquidityNet, + , + , + results.tickCumulativeOutside, + results.secondsPerLiquidityOutsideX128, + results.secondsOutside, + results.initialized, + ] = ethers.utils.defaultAbiCoder.decode( + [ + `uint128`, + `int128`, + `uint256`, + `uint256`, + `int256`, + `uint160`, + `uint32`, + `bool`, + ], + toDecode, + ); + // This conversion is not precise, because when we decode, we have more values + // But used later + return results; +} diff --git a/src/lib/decoders.ts b/src/lib/decoders.ts index ebafa3401..6c2453b0c 100644 --- a/src/lib/decoders.ts +++ b/src/lib/decoders.ts @@ -50,6 +50,18 @@ export const uint256ToBigInt = ( return generalDecoder(result, ['uint256'], 0n, value => value[0].toBigInt()); }; +export const uint128ToBigInt = ( + result: MultiResult | BytesLike, +): bigint => { + return generalDecoder(result, ['uint128'], 0n, value => value[0].toBigInt()); +}; + +export const int24ToBigInt = ( + result: MultiResult | BytesLike, +): bigint => { + return generalDecoder(result, ['int24'], 0n, value => BigInt(value[0])); +}; + export const uint256ArrayDecode = ( result: MultiResult | BytesLike, ): bigint => { From 9e58585dafbe6345a344ee7ac05d356a8ac4c99f Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 15:42:05 +0100 Subject: [PATCH 141/833] 2.31.4-zkevm-revive.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2e09436b7..b9b13bcc3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.0", + "version": "2.31.4-zkevm-revive.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From bc00ee233b4c07c19260a0c101191bb93d800011 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 16:03:42 +0100 Subject: [PATCH 142/833] fix: set boolean flag to true --- src/dex/algebra/config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dex/algebra/config.ts b/src/dex/algebra/config.ts index 9b6147a17..5809d2037 100644 --- a/src/dex/algebra/config.ts +++ b/src/dex/algebra/config.ts @@ -33,6 +33,7 @@ export const AlgebraConfig: DexConfigMap = { uniswapMulticall: '0x61530d6E1c7A47BBB3e48e8b8EdF7569DcFeE121', deployer: '0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270', version: 'v1.1', + forceManualStateGenerate: true, }, }, ZyberSwapV3: { From 0082148a0592dedb755f4a496b1af558782fb5b2 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 16:05:06 +0100 Subject: [PATCH 143/833] 2.31.4-zkevm-revive.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b9b13bcc3..b26d0e7a7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.1", + "version": "2.31.4-zkevm-revive.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From a2dc773d7cc3691b28d111c4e891571f411929cd Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 16:12:51 +0100 Subject: [PATCH 144/833] fix: add new field to lower func --- src/dex/algebra/algebra.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 3b978c80b..d824785e7 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -791,6 +791,7 @@ export class Algebra extends SimpleExchange implements IDex { subgraphURL: this.config.subgraphURL, version: this.config.version, forceRPC: this.config.forceRPC, + forceManualStateGenerate: this.config.forceManualStateGenerate, }; return newConfig; } From 300e0bdeb52109708f2ef217120e0357a399b4dd Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 16:13:24 +0100 Subject: [PATCH 145/833] 2.31.4-zkevm-revive.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b26d0e7a7..ace03f4e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.2", + "version": "2.31.4-zkevm-revive.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 75b45f806aa492cfa95476d4506716f4b60ea137 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 16:19:06 +0100 Subject: [PATCH 146/833] fix: issue pool address case --- src/dex/algebra/algebra-pool-v1_1.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/algebra/algebra-pool-v1_1.ts b/src/dex/algebra/algebra-pool-v1_1.ts index 2548123be..4d36f0a14 100644 --- a/src/dex/algebra/algebra-pool-v1_1.ts +++ b/src/dex/algebra/algebra-pool-v1_1.ts @@ -380,7 +380,7 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber ]); assert( poolAddress === this.poolAddress, - `Pool address mismatch: ${poolAddress} != ${this.poolAddress}`, + `Pool address mismatch: ${poolAddress.toLowerCase()} != ${this.poolAddress.toLowerCase()}`, ); const [ From b8d981059332aeb6551fc743f0fad082aa04da48 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 16:19:48 +0100 Subject: [PATCH 147/833] 2.31.4-zkevm-revive.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ace03f4e1..fd63b5bfc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.3", + "version": "2.31.4-zkevm-revive.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From f5c31fa0d14e9234af32f0fc5fc49f935486e4a7 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 16:24:00 +0100 Subject: [PATCH 148/833] fix: fix pool address mismatch --- src/dex/algebra/algebra-pool-v1_1.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/algebra/algebra-pool-v1_1.ts b/src/dex/algebra/algebra-pool-v1_1.ts index 4d36f0a14..cd11b8976 100644 --- a/src/dex/algebra/algebra-pool-v1_1.ts +++ b/src/dex/algebra/algebra-pool-v1_1.ts @@ -379,7 +379,7 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber }, ]); assert( - poolAddress === this.poolAddress, + poolAddress.toLowerCase() === this.poolAddress.toLowerCase(), `Pool address mismatch: ${poolAddress.toLowerCase()} != ${this.poolAddress.toLowerCase()}`, ); From 586d7811fb80f442205aa291a8cd9afcf8a2d9cc Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 16:24:39 +0100 Subject: [PATCH 149/833] 2.31.4-zkevm-revive.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fd63b5bfc..af7b7250f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.4", + "version": "2.31.4-zkevm-revive.5", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From b82d3a32e640737b45d8d7a4547dae4261053c65 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 16:49:11 +0100 Subject: [PATCH 150/833] fix: split tick generating into 100 tick chunks --- src/dex/algebra/algebra-pool-v1_1.ts | 59 ++++++++++++++++------------ 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/dex/algebra/algebra-pool-v1_1.ts b/src/dex/algebra/algebra-pool-v1_1.ts index cd11b8976..0f9e3ccb1 100644 --- a/src/dex/algebra/algebra-pool-v1_1.ts +++ b/src/dex/algebra/algebra-pool-v1_1.ts @@ -464,32 +464,39 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber } const tickIndexes: bigint[] = []; - const ticksValues = await this.dexHelper.multiWrapper.aggregate( - tickBitmap - .map(tb => { - const allBits: MultiCallParams[] = []; - if (tb.value === BigNumber.from(0)) return allBits; - - _.range(0, 256).forEach(j => { - if ((tb.value.toBigInt() & (1n << BigInt(j))) > 0n) { - const populatedTick = - (BigInt.asIntN(16, BigInt(tb.index) << 8n) + BigInt(j)) * - tickSpacing; - - tickIndexes.push(populatedTick); - allBits.push({ - target: poolAddress, - callData: this.poolIface.encodeFunctionData('ticks', [ - populatedTick, - ]), - decodeFunction: decodeTicksV1_1, - }); - } - }); - return allBits; - }) - .flat(), - ); + + const tickRequests = tickBitmap + .map(tb => { + const allBits: MultiCallParams[] = []; + if (tb.value === BigNumber.from(0)) return allBits; + + _.range(0, 256).forEach(j => { + if ((tb.value.toBigInt() & (1n << BigInt(j))) > 0n) { + const populatedTick = + (BigInt.asIntN(16, BigInt(tb.index) << 8n) + BigInt(j)) * + tickSpacing; + + tickIndexes.push(populatedTick); + allBits.push({ + target: poolAddress, + callData: this.poolIface.encodeFunctionData('ticks', [ + populatedTick, + ]), + decodeFunction: decodeTicksV1_1, + }); + } + }); + return allBits; + }) + .flat(); + + const ticksValues = ( + await Promise.all( + _.chunk(tickRequests, 100).map(tickRequestChunk => + this.dexHelper.multiWrapper.aggregate(tickRequestChunk), + ), + ) + ).flat(); assert( tickIndexes.length === ticksValues.length, `Tick indexes mismatch: ${tickIndexes.length} != ${ticksValues.length}`, From 74b067c4506f0d5d27db54bcfa047cafa011d941 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 16:49:50 +0100 Subject: [PATCH 151/833] 2.31.4-zkevm-revive.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index af7b7250f..ea9060025 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.5", + "version": "2.31.4-zkevm-revive.6", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 3fa186ece102fdf2319886e40800f7457f1f5d8c Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 17:21:18 +0100 Subject: [PATCH 152/833] fix: sometimes stale is null regenerate in that case too --- src/dex/algebra/algebra.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index d824785e7..0178f2307 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -160,9 +160,10 @@ export class Algebra extends SimpleExchange implements IDex { if (this.network !== Network.ZKEVM) return pool; if ( - pool.getState(blockNumber) === null && - blockNumber - pool.getStateBlockNumber() > - MAX_STALE_STATE_BLOCK_AGE[this.network] + pool.getStaleState() === null || + (pool.getState(blockNumber) === null && + blockNumber - pool.getStateBlockNumber() > + MAX_STALE_STATE_BLOCK_AGE[this.network]) ) { /* reload state, on zkEVM this would most likely timeout during request life * but would allow to rely on staleState for couple of min for next requests From b21e737e65a1e0702e3abf5f93a4fe4fe10362fb Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 25 Aug 2023 17:22:05 +0100 Subject: [PATCH 153/833] 2.31.4-zkevm-revive.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ea9060025..32f20b96a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.6", + "version": "2.31.4-zkevm-revive.7", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From c18c6a2636fb40efe1f4d7e8ed8cbdf6c53446fa Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Fri, 25 Aug 2023 21:28:25 +0100 Subject: [PATCH 154/833] feat: add slippage check for rfq --- src/dex/dexalot/dexalot.ts | 71 +++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 6436d4cd5..2d3dbb7a6 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -30,6 +30,7 @@ import { RfqError, RFQResponse, RFQResponseError, + SlippageCheckError, TokenAddrDataMap, TokenDataMap, } from './types'; @@ -54,6 +55,7 @@ import { import { BI_MAX_UINT256 } from '../../bigint-constants'; import { TooStrictSlippageCheckError } from '../generic-rfq/types'; import { ethers } from 'ethers'; +import BigNumber from 'bignumber.js'; export class Dexalot extends SimpleExchange implements IDex { readonly isStatePollingDex = true; @@ -508,37 +510,38 @@ export class Dexalot extends SimpleExchange implements IDex { const expiryAsBigInt = BigInt(order.expiry); const minDeadline = expiryAsBigInt > 0 ? expiryAsBigInt : BI_MAX_UINT256; - // if (side === SwapSide.SELL) { - // const makerAmountLowerBounds: bigint = - // (BigInt(optimalSwapExchange.destAmount.toString()) * BigInt(9900)) / - // BigInt(10000); - // const makerAmountUpperBounds: bigint = - // (BigInt(optimalSwapExchange.destAmount.toString()) * BigInt(10100)) / - // BigInt(10000); - // assert( - // BigInt(order.makerAmount) < makerAmountUpperBounds, - // 'Too much Slippage', - // ); - // assert( - // BigInt(order.makerAmount) > makerAmountLowerBounds, - // 'Too much Slippage', - // ); - // } else { - // const takerAmountLowerBounds: bigint = - // (BigInt(optimalSwapExchange.srcAmount.toString()) * BigInt(9900)) / - // BigInt(10000); - // const takerAmountUpperBounds: bigint = - // (BigInt(optimalSwapExchange.srcAmount.toString()) * BigInt(10100)) / - // BigInt(10000); - // assert( - // BigInt(order.takerAmount) < takerAmountUpperBounds, - // 'Too much Slippage', - // ); - // assert( - // BigInt(order.takerAmount) > takerAmountLowerBounds, - // 'Too much Slippage', - // ); - // } + const slippageFactor = options.slippageFactor; + if (side === SwapSide.SELL) { + if ( + BigInt(order.makerAmount) < + BigInt( + new BigNumber(optimalSwapExchange.destAmount) + .times(slippageFactor) + .toFixed(0), + ) + ) { + const message = `${this.dexKey}-${this.network}: too much slippage on quote ${side} quoteTokenAmount ${order.makerAmount} / destAmount ${optimalSwapExchange.destAmount} < ${slippageFactor}`; + throw new SlippageCheckError(message); + } + } else { + if ( + BigInt(order.takerAmount) < + BigInt( + new BigNumber(optimalSwapExchange.srcAmount) + .times(slippageFactor) + .toFixed(0), + ) + ) { + const message = `${this.dexKey}-${ + this.network + }: too much slippage on quote ${side} baseTokenAmount ${ + order.takerAmount + } / srcAmount ${ + optimalSwapExchange.srcAmount + } > ${slippageFactor.toFixed()}`; + throw new SlippageCheckError(message); + } + } return [ { @@ -562,10 +565,8 @@ export class Dexalot extends SimpleExchange implements IDex { `${this.dexKey}-${this.network}: Failed to fetch RFQ for ${swapIdentifier}: ${errorData.Reason}`, ); } - } else if (e instanceof TooStrictSlippageCheckError) { - this.logger.warn( - `${this.dexKey}-${this.network}: Failed to build transaction on side ${side} with too strict slippage. Skipping restriction`, - ); + } else if (e instanceof SlippageCheckError) { + this.logger.warn(e.message); } else { this.logger.error( `${this.dexKey}-${this.network}: Failed to fetch RFQ for ${swapIdentifier}:`, From e214ca9948b55a5bf632fd580bbf3699206861e4 Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Fri, 25 Aug 2023 21:41:13 +0100 Subject: [PATCH 155/833] feat: update polling interval + remove adapters --- src/dex/dexalot/config.ts | 7 ++----- src/dex/dexalot/constants.ts | 14 ++++++-------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/dex/dexalot/config.ts b/src/dex/dexalot/config.ts index 28751cd17..258d5f1a0 100644 --- a/src/dex/dexalot/config.ts +++ b/src/dex/dexalot/config.ts @@ -1,6 +1,6 @@ import { DexParams } from './types'; import { DexConfigMap, AdapterMappings } from '../../types'; -import { Network, SwapSide } from '../../constants'; +import { Network } from '../../constants'; export const DexalotConfig: DexConfigMap = { Dexalot: { @@ -11,8 +11,5 @@ export const DexalotConfig: DexConfigMap = { }; export const Adapters: Record = { - [Network.AVALANCHE]: { - [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 1 }], - [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 3 }], - }, + [Network.AVALANCHE]: {}, }; diff --git a/src/dex/dexalot/constants.ts b/src/dex/dexalot/constants.ts index 25a3e5d77..e46d3b0fb 100644 --- a/src/dex/dexalot/constants.ts +++ b/src/dex/dexalot/constants.ts @@ -1,21 +1,19 @@ -import BigNumber from 'bignumber.js'; - export const DEXALOT_RATE_LIMITED_TTL_S = 60 * 60; // 1 hour -export const DEXALOT_PRICES_CACHES_TTL_S = 200; +export const DEXALOT_PRICES_CACHES_TTL_S = 3; -export const DEXALOT_PAIRS_CACHES_TTL_S = 200; +export const DEXALOT_PAIRS_CACHES_TTL_S = 11; -export const DEXALOT_TOKENS_CACHES_TTL_S = 200; +export const DEXALOT_TOKENS_CACHES_TTL_S = 11; export const DEXALOT_API_PRICES_POLLING_INTERVAL_MS = 1000; -export const DEXALOT_API_PAIRS_POLLING_INTERVAL_MS = 1000 * 30; // 28 secs +export const DEXALOT_API_PAIRS_POLLING_INTERVAL_MS = 1000 * 60 * 10; // 10 mins -export const DEXALOT_API_TOKENS_POLLING_INTERVAL_MS = 1000 * 30; // 28 secs +export const DEXALOT_API_TOKENS_POLLING_INTERVAL_MS = 1000 * 60 * 10; // 10 mins export const DEXALOT_API_BLACKLIST_POLLING_INTERVAL_MS = 1000 * 60 * 60; // 1 hour export const DEXALOT_API_URL = 'https://api.dexalot.com'; -export const DEXALOT_GAS_COST = 100_000; +export const DEXALOT_GAS_COST = 120_000; From 2927c1dfa5be87c34dd6e3f840b4c3842d3ad0f0 Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Sun, 27 Aug 2023 14:15:33 +0100 Subject: [PATCH 156/833] feat: return if order amount not filled --- src/dex/dexalot/dexalot.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 2d3dbb7a6..a9e9915e4 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -321,6 +321,9 @@ export class Dexalot extends SimpleExchange implements IDex { break; } } + if (amt > 0n) { + return result; + } const avgPrice = combinedPrice / totalVolume; if (side === ClobSide.BID) { result.push((amounts[i] * BigInt(10 ** baseToken.decimals)) / avgPrice); From 24daba1a955f8ff73cd597c0e70390f5683eef93 Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Sun, 27 Aug 2023 14:20:03 +0100 Subject: [PATCH 157/833] feat: remove buy side --- src/dex/dexalot/dexalot-e2e.test.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/dex/dexalot/dexalot-e2e.test.ts b/src/dex/dexalot/dexalot-e2e.test.ts index 5bf573b62..7c0c4a1ae 100644 --- a/src/dex/dexalot/dexalot-e2e.test.ts +++ b/src/dex/dexalot/dexalot-e2e.test.ts @@ -33,7 +33,6 @@ function testForNetwork( const sideToContractMethods = new Map([ [SwapSide.SELL, [ContractMethod.simpleSwap]], - [SwapSide.BUY, [ContractMethod.simpleSwap]], ]); describe(`${network}`, () => { @@ -165,10 +164,10 @@ describe('Dexalot E2E', () => { describe('Avalanche', () => { const network = Network.AVALANCHE; - const tokenASymbol: string = 'AVAX'; - const tokenBSymbol: string = 'USDC'; + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; - const tokenAAmount: string = '1000000000000000000'; + const tokenAAmount: string = '1000000'; const tokenBAmount: string = '1000000'; const nativeTokenAmount = '1000000000000000000'; @@ -180,7 +179,6 @@ describe('Dexalot E2E', () => { tokenAAmount, tokenBAmount, nativeTokenAmount, - true, ); }); }); From 63a7585dbb89e56d493c18f69d0b3ae64d5a1d53 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 28 Aug 2023 11:44:12 +0300 Subject: [PATCH 158/833] refactor --- package.json | 2 + src/abi/sushiswap-v3/QuoterV2.json | 267 + src/abi/sushiswap-v3/RouterProcessor3.json | 289 + src/config.ts | 4 +- src/dex/index.ts | 2 + src/dex/sushiswap-v3/config.ts | 137 + src/dex/sushiswap-v3/constants.ts | 32 + src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts | 419 ++ .../sushiswap-v3-integration.test.ts | 251 + src/dex/sushiswap-v3/sushiswap-v3-original.ts | 1017 +++ src/dex/sushiswap-v3/sushiswap-v3.ts | 268 + src/dex/sushiswap-v3/types.ts | 12 + src/dex/uniswap-v3/config.ts | 100 +- src/dex/uniswap-v3/types.ts | 2 + src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 329 - .../uniswap-v3/uniswap-v3-integration.test.ts | 135 - src/dex/uniswap-v3/uniswap-v3.ts | 8 +- yarn.lock | 5901 ++++++++++++++++- 18 files changed, 8472 insertions(+), 703 deletions(-) create mode 100644 src/abi/sushiswap-v3/QuoterV2.json create mode 100644 src/abi/sushiswap-v3/RouterProcessor3.json create mode 100644 src/dex/sushiswap-v3/config.ts create mode 100644 src/dex/sushiswap-v3/constants.ts create mode 100644 src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts create mode 100644 src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts create mode 100644 src/dex/sushiswap-v3/sushiswap-v3-original.ts create mode 100644 src/dex/sushiswap-v3/sushiswap-v3.ts create mode 100644 src/dex/sushiswap-v3/types.ts diff --git a/package.json b/package.json index 8609a6a0e..de49a2b36 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,8 @@ "@hashflow/sdk": "1.2.4", "@hashflow/taker-js": "0.0.2", "@paraswap/core": "1.1.0", + "@sushiswap/router": "^0.0.12", + "@sushiswap/viem-config": "^1.0.2", "async": "^3.2.4", "axios": "0.26.0", "bignumber.js": "9.1.0", diff --git a/src/abi/sushiswap-v3/QuoterV2.json b/src/abi/sushiswap-v3/QuoterV2.json new file mode 100644 index 000000000..ce1374e69 --- /dev/null +++ b/src/abi/sushiswap-v3/QuoterV2.json @@ -0,0 +1,267 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_WETH9", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "WETH9", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "path", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + } + ], + "name": "quoteExactInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint160[]", + "name": "sqrtPriceX96AfterList", + "type": "uint160[]" + }, + { + "internalType": "uint32[]", + "name": "initializedTicksCrossedList", + "type": "uint32[]" + }, + { + "internalType": "uint256", + "name": "gasEstimate", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "uint160", + "name": "sqrtPriceLimitX96", + "type": "uint160" + } + ], + "internalType": "struct IQuoterV2.QuoteExactInputSingleParams", + "name": "params", + "type": "tuple" + } + ], + "name": "quoteExactInputSingle", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + }, + { + "internalType": "uint160", + "name": "sqrtPriceX96After", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "initializedTicksCrossed", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasEstimate", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "path", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "quoteExactOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint160[]", + "name": "sqrtPriceX96AfterList", + "type": "uint160[]" + }, + { + "internalType": "uint32[]", + "name": "initializedTicksCrossedList", + "type": "uint32[]" + }, + { + "internalType": "uint256", + "name": "gasEstimate", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "internalType": "uint160", + "name": "sqrtPriceLimitX96", + "type": "uint160" + } + ], + "internalType": "struct IQuoterV2.QuoteExactOutputSingleParams", + "name": "params", + "type": "tuple" + } + ], + "name": "quoteExactOutputSingle", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint160", + "name": "sqrtPriceX96After", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "initializedTicksCrossed", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasEstimate", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "path", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/abi/sushiswap-v3/RouterProcessor3.json b/src/abi/sushiswap-v3/RouterProcessor3.json new file mode 100644 index 000000000..d8959084f --- /dev/null +++ b/src/abi/sushiswap-v3/RouterProcessor3.json @@ -0,0 +1,289 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/src/config.ts b/src/config.ts index 45b466f84..32e10ee75 100644 --- a/src/config.ts +++ b/src/config.ts @@ -277,8 +277,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], adapterAddresses: { ArbitrumAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9', - ArbitrumAdapter02: '0x3ad7f275E27AC579cA88e0b4765828242A9E8C49', - ArbitrumBuyAdapter: '0x6c33C7f6CBB4a428fe9ee31ca500a787c9f1525b', + ArbitrumAdapter02: '0x68be90b86BC3A8f1d958A179043Ce6C3bae4aA27', + ArbitrumBuyAdapter: '0x2880C3971CCaE35a9609DC2397AdeE4AA9dFdF35', }, uniswapV2ExchangeRouterAddress: '0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC', diff --git a/src/dex/index.ts b/src/dex/index.ts index 11302d4c3..ffbbaf018 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -70,6 +70,7 @@ import { SwaapV2 } from './swaap-v2/swaap-v2'; import { SpiritSwapV3 } from './quickswap/spiritswap-v3'; import { TraderJoeV21 } from './trader-joe-v2.1'; import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3'; +import { SushiSwapV3 } from './sushiswap-v3/sushiswap-v3'; import { Algebra } from './algebra/algebra'; const LegacyDexes = [ @@ -106,6 +107,7 @@ const Dexes = [ UniswapV3, Algebra, PancakeswapV3, + SushiSwapV3, BiSwap, MDEX, Dfyn, diff --git a/src/dex/sushiswap-v3/config.ts b/src/dex/sushiswap-v3/config.ts new file mode 100644 index 000000000..8421b9194 --- /dev/null +++ b/src/dex/sushiswap-v3/config.ts @@ -0,0 +1,137 @@ +import { Network, SwapSide } from '../../constants'; +import { DexParams } from '../uniswap-v3/types'; +import { DexConfigMap, AdapterMappings } from '../../types'; +import { SUPPORTED_FEES } from '../uniswap-v3/config'; + +export const SushiSwapV3Config: DexConfigMap = { + SushiSwapV3: { + [Network.MAINNET]: { + factory: '0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F', + quoter: '0x64e8802FE490fa7cc61d3463958199161Bb608A7', + router: '0x827179dD56d07A7eeA32e3873493835da2866976', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-ethereum', + }, + [Network.POLYGON]: { + factory: '0x917933899c6a5f8e37f31e19f92cdbff7e8ff0e2', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-polygon', + }, + [Network.BSC]: { + factory: '0x126555dd55a39328F69400d6aE4F782Bd4C34ABb', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x400d75dAb26bBc18D163AEA3e83D9Ea68F6c1804', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x593F39A4Ba26A9c8ed2128ac95D109E8e403C485', + uniswapMulticall: '0x963Df249eD09c358A4819E39d9Cd5736c3087184', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-bsc', + }, + [Network.AVALANCHE]: { + factory: '0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x717b7948AA264DeCf4D780aa6914482e5F46Da3e', + supportedFees: SUPPORTED_FEES, + stateMulticall: '', + uniswapMulticall: '0x8C0F842791F03C095b6c633759224FcC9ACe68ea', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-avalanche', + }, + [Network.FANTOM]: { + factory: '0x7770978eED668a3ba661d51a773d3a992Fc9DDCB', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x2214A42d8e2A1d20635c2cb0664422c528B6A432', + supportedFees: SUPPORTED_FEES, + stateMulticall: '', + uniswapMulticall: '0xB1395e098c0a847CC719Bcf1Fc8114421a9F8232', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-fantom', + }, + [Network.ARBITRUM]: { + factory: '0x1af415a1eba07a4986a52b6f2e7de7003d82231e', + quoter: '0x0524E833cCD057e4d7A296e3aaAb9f7675964Ce1', + router: '0xfc506AaA1340b4dedFfd88bE278bEe058952D674', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-arbitrum', + }, + [Network.OPTIMISM]: { + factory: '0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x4C5D5234f232BD2D76B96aA33F5AE4FCF0E4BFAb', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x4FF0dEC5f9a763Aa1E5C2a962aa6f4eDFeE4f9eA', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-optimism', + }, + }, +}; + +export const Adapters: Record = { + [Network.MAINNET]: { + [SwapSide.SELL]: [{ name: 'Adapter01', index: 6 }], + [SwapSide.BUY]: [{ name: 'BuyAdapter', index: 2 }], + }, + [Network.BSC]: { + [SwapSide.SELL]: [{ name: 'BscAdapter02', index: 4 }], + [SwapSide.BUY]: [{ name: 'BscBuyAdapter', index: 5 }], + }, + [Network.POLYGON]: { + [SwapSide.SELL]: [{ name: 'PolygonAdapter01', index: 13 }], + [SwapSide.BUY]: [{ name: 'PolygonBuyAdapter', index: 2 }], + }, + [Network.ARBITRUM]: { + [SwapSide.SELL]: [{ name: 'ArbitrumAdapter02', index: 6 }], + [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 8 }], + }, + [Network.OPTIMISM]: { + [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 3 }], + [SwapSide.BUY]: [{ name: 'OptimismBuyAdapter', index: 2 }], + }, + [Network.FANTOM]: { + [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 11 }], + [SwapSide.BUY]: [{ name: 'FantomBuyAdapter', index: 3 }], + }, + [Network.ZKEVM]: { + [SwapSide.SELL]: [{ name: 'PolygonZkEvmAdapter01', index: 1 }], + [SwapSide.BUY]: [{ name: 'PolygonZkEvmBuyAdapter', index: 1 }], + }, + [Network.AVALANCHE]: { + [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 5 }], + [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 6 }], + }, + [Network.FANTOM]: { + [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 11 }], + [SwapSide.BUY]: [{ name: 'FantomBuyAdapter', index: 3 }], + }, +}; diff --git a/src/dex/sushiswap-v3/constants.ts b/src/dex/sushiswap-v3/constants.ts new file mode 100644 index 000000000..e61b75fe3 --- /dev/null +++ b/src/dex/sushiswap-v3/constants.ts @@ -0,0 +1,32 @@ +import { + arbitrum, + avalanche, + bsc, + fantom, + mainnet, + optimism, + polygon, +} from '@sushiswap/viem-config'; +import { Network } from '../../constants'; +import { Chain } from 'viem'; + +export function getViemChain(network: Network): Chain { + switch (network) { + case Network.ARBITRUM: + return arbitrum; + case Network.AVALANCHE: + return avalanche; + case Network.BSC: + return bsc; + case Network.FANTOM: + return fantom; + case Network.MAINNET: + return mainnet; + case Network.OPTIMISM: + return optimism; + case Network.POLYGON: + return polygon; + default: + throw new Error(`Chain with id ${network} is not supported`); + } +} diff --git a/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts b/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts new file mode 100644 index 000000000..81b071757 --- /dev/null +++ b/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts @@ -0,0 +1,419 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { ContractMethod, Network, SwapSide } from '../../constants'; +import { + Holders, + NativeTokenSymbols, + Tokens, +} from '../../../tests/constants-e2e'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; +import { testE2E } from '../../../tests/utils-e2e'; + +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, + slippage?: number | undefined, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + // ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + // ContractMethod.buy, + // ContractMethod.directUniV3Buy, + ], + ], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + 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, + 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, + network, + provider, + undefined, + undefined, + undefined, + slippage, + ); + }); + }); + }); + }), + ); + }); +} + +describe('SushiSwapV3 E2E', () => { + const dexKey = 'SushiSwapV3'; + + describe('MAINNET', () => { + const network = Network.MAINNET; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '1100000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + 500, // 5% + ); + }); + + describe('ARBITRUM', () => { + const network = Network.ARBITRUM; + + const tokenASymbol: string = 'USDCe'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '11111000'; + const tokenBAmount: string = '10000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + 500, // 5% + ); + }); + + describe('POLYGON', () => { + const network = Network.POLYGON; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '21111000'; + const tokenBAmount: string = '200000000'; + const nativeTokenAmount = '110000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + 500, // 5% + ); + }); + + describe('BSC', () => { + const network = Network.BSC; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, + ], + ], + ]); + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ + [ + { + name: 'USDC', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + { + name: 'USDT', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + ], + [ + { + name: 'BNB', + sellAmount: '1000000000000000000', + buyAmount: '10000000000000000000', + }, + { + name: 'USDT', + sellAmount: '1000000000000000000000', + buyAmount: '20000000000000000', + }, + ], + ]; + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }); + }), + ); + }); + + describe('AVALANCHE', () => { + const network = Network.AVALANCHE; + + const tokenASymbol: string = 'USDT'; + const tokenBSymbol: string = 'USDC'; + + const tokenAAmount: string = '111110'; + const tokenBAmount: string = '100000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + 500, // 5% + ); + }); + + describe('FANTOM', () => { + const network = Network.FANTOM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, + ], + ], + ]); + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ + [ + { + name: 'USDC', + sellAmount: '111110', + buyAmount: '111110', + }, + { + name: 'FUSDT', + sellAmount: '111110', + buyAmount: '111110', + }, + ], + // [ + // { + // name: 'BNB', + // sellAmount: '1000000000000000000', + // buyAmount: '10000000000000000000', + // }, + // { name: 'USDT', sellAmount: '1000000000000000000000', buyAmount: '20000000000000000' }, + // ], + ]; + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }); + }), + ); + }); + + describe('OPTIMISM', () => { + const network = Network.OPTIMISM; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '10000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + 500, // 5% + ); + }); +}); diff --git a/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts b/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts new file mode 100644 index 000000000..998271fad --- /dev/null +++ b/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts @@ -0,0 +1,251 @@ +import { UniswapV3 } from '../uniswap-v3/uniswap-v3'; +import { Network, SwapSide } from '../../constants'; +import { DummyDexHelper, IDexHelper } from '../../dex-helper'; +import { Tokens } from '../../../tests/constants-e2e'; +import { BI_POWS } from '../../bigint-constants'; +import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; +import { Interface, Result } from '@ethersproject/abi'; +import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; +import { Address } from '@paraswap/core'; + +const quoterIface = new Interface(UniswapV3QuoterV2ABI); + +function getReaderCalldata( + exchangeAddress: string, + readerIface: Interface, + amounts: bigint[], + funcName: string, + tokenIn: Address, + tokenOut: Address, + fee: bigint, +) { + return amounts.map(amount => ({ + target: exchangeAddress, + callData: readerIface.encodeFunctionData(funcName, [ + [tokenIn, tokenOut, amount.toString(), fee.toString(), 0], + ]), + })); +} + +function decodeReaderResult( + results: Result, + readerIface: Interface, + funcName: string, +) { + return results.map(result => { + const parsed = readerIface.decodeFunctionResult(funcName, result); + return BigInt(parsed[0]._hex); + }); +} + +async function checkOnChainPricing( + dexHelper: IDexHelper, + uniswapV3: UniswapV3, + funcName: string, + blockNumber: number, + exchangeAddress: string, + prices: bigint[], + tokenIn: Address, + tokenOut: Address, + fee: bigint, + _amounts: bigint[], +) { + // Quoter address + // const exchangeAddress = '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'; + const readerIface = quoterIface; + + // const sum = prices.reduce((acc, curr) => (acc += curr), 0n); + // + // if (sum === 0n) { + // console.log( + // `Prices were not calculated for tokenIn=${tokenIn}, tokenOut=${tokenOut}, fee=${fee.toString()}. Most likely price impact is too big for requested amount`, + // ); + // return false; + // } + + const readerCallData = getReaderCalldata( + exchangeAddress, + readerIface, + _amounts.slice(1), + funcName, + tokenIn, + tokenOut, + fee, + ); + + let readerResult; + try { + readerResult = ( + await dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blockNumber) + ).returnData; + } catch (e) { + console.log( + `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, + e, + ); + return false; + } + + const expectedPrices = [0n].concat( + decodeReaderResult(readerResult, readerIface, funcName), + ); + + console.log('EXPECTED PRICES: ', expectedPrices); + + let firstZeroIndex = prices.slice(1).indexOf(0n); + + // we skipped first, so add +1 on result + firstZeroIndex = firstZeroIndex === -1 ? prices.length : firstZeroIndex; + + // Compare only the ones for which we were able to calculate prices + expect(prices.slice(0, firstZeroIndex)).toEqual( + expectedPrices.slice(0, firstZeroIndex), + ); + return true; +} + +describe('SushiSwapV3', () => { + const dexKey = 'SushiSwapV3'; + + describe('Mainnet', () => { + let blockNumber: number; + let uniswapV3: UniswapV3; + let uniswapV3Mainnet: UniswapV3; + + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + const TokenASymbol = 'USDC'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDT'; + const TokenB = Tokens[network][TokenBSymbol]; + + beforeEach(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + uniswapV3 = new UniswapV3(network, dexKey, dexHelper); + uniswapV3Mainnet = new UniswapV3(Network.MAINNET, dexKey, dexHelper); + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + const amounts = [0n, BI_POWS[6], 2000000n]; + + const pools = await uniswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await uniswapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + uniswapV3, + 'quoteExactInputSingle', + blockNumber, + '0x64e8802FE490fa7cc61d3463958199161Bb608A7', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + const amounts = [0n, BI_POWS[6], 2000000n]; + + const pools = await uniswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await uniswapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + uniswapV3, + 'quoteExactOutputSingle', + blockNumber, + '0x64e8802FE490fa7cc61d3463958199161Bb608A7', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getTopPoolsForToken', async function () { + const poolLiquidity = await uniswapV3.getTopPoolsForToken( + TokenB.address, + 10, + ); + console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); + }); + }); +}); diff --git a/src/dex/sushiswap-v3/sushiswap-v3-original.ts b/src/dex/sushiswap-v3/sushiswap-v3-original.ts new file mode 100644 index 000000000..19ef285d4 --- /dev/null +++ b/src/dex/sushiswap-v3/sushiswap-v3-original.ts @@ -0,0 +1,1017 @@ +import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; +import { + Token, + Address, + ExchangePrices, + PoolPrices, + AdapterExchangeParam, + SimpleExchangeParam, + PoolLiquidity, + Logger, + NumberAsString, +} from '../../types'; +import { SwapSide, Network, CACHE_PREFIX } from '../../constants'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { + getBigIntPow, + getDexKeysWithNetwork, + interpolate, + isTruthy, +} from '../../utils'; +import { IDex } from '../../dex/idex'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { + DexParams, + OutputResult, + PoolState, + QuoteExactInputSingleParams, + QuoteExactOutputSingleParams, + UniswapV3Data as SushiswapV3Data, +} from './types'; +import { + SimpleExchange, + getLocalDeadlineAsFriendlyPlaceholder, +} from '../simple-exchange'; +import { SushiswapV3Config, Adapters } from './config'; +import { SushiswapV3EventPool } from './sushiswap-v3-pool'; +import { Interface, defaultAbiCoder } from 'ethers/lib/utils'; +import { AbiItem } from 'web3-utils'; +import { Contract } from 'web3-eth-contract'; +import { pack } from '@ethersproject/solidity'; +import { + UNISWAPV3_EFFICIENCY_FACTOR, + UNISWAPV3_POOL_SEARCH_OVERHEAD, + UNISWAPV3_TICK_BASE_OVERHEAD, + UNISWAPV3_TICK_GAS_COST, + ViemChain, +} from './constants'; +import { uniswapV3Math } from '../uniswap-v3/contract-math/uniswap-v3-math'; +import { BalanceRequest, getBalances } from '../../lib/tokens/balancer-fetcher'; +import { + AssetType, + DEFAULT_ID_ERC20, + DEFAULT_ID_ERC20_AS_STRING, +} from '../../lib/tokens/types'; +import { DataFetcher, LiquidityProviders, Router } from '@sushiswap/router'; +import { ChainId } from '@sushiswap/chain'; +import { createPublicClient, http } from 'viem'; + +import SushiswapV3RouterABI from '../../abi/sushiswap-v3/RouterProcessor3.json'; +import SushiswapV3QuoterV2ABI from '../../abi/sushiswap-v3/QuoterV2.json'; +import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; +import UniswapV3StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; +import { generateConfig } from '../../config'; +import { BigNumber } from 'ethers'; +import { getToken } from './token'; +import _ from 'lodash'; +import { UniswapV3Config } from '../uniswap-v3/config'; + +const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 60 * 60 * 24 * 1000; // 24 hours +const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 30 * 60 * 1000; // Once in 30 minutes +const UNISWAPV3_QUOTE_GASLIMIT = 200_000; + +export class SushiswapV3 + extends SimpleExchange + implements IDex +{ + readonly eventPools: Record = {}; + + readonly hasConstantPriceLargeAmounts = false; + readonly needWrapNative = true; + + intervalTask?: NodeJS.Timeout; + + readonly isFeeOnTransferSupported = false; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(SushiswapV3Config); + + logger: Logger; + + private uniswapMulti: Contract; + private stateMultiContract: Contract; + + private notExistingPoolSetKey: string; + + constructor( + readonly network: Network, + readonly dexKey: string, + readonly dexHelper: IDexHelper, + protected adapters = Adapters[network] || {}, + readonly routerIface = new Interface(SushiswapV3RouterABI), + readonly quoterIface = new Interface(SushiswapV3QuoterV2ABI), + readonly config = SushiswapV3Config[dexKey][network], + ) { + super(dexHelper, dexKey); + this.logger = dexHelper.getLogger(dexKey + '-' + network); + + this.uniswapMulti = new this.dexHelper.web3Provider.eth.Contract( + UniswapV3MultiABI as AbiItem[], + this.config.uniswapMulticall, + ); + this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( + UniswapV3StateMulticallABI as AbiItem[], + this.config.stateMulticall, + ); + + // To receive revert reasons + this.dexHelper.web3Provider.eth.handleRevert = false; + + // Normalise once all config addresses and use across all scenarios + this.config = this._toLowerForAllConfigAddresses(); + + this.notExistingPoolSetKey = + `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); + } + + // Initialize pricing is called once in the start of + // pricing service. It is intended to setup the integration + // for pricing requests. It is optional for a DEX to + // implement this function + async initializePricing(blockNumber: number) { + if (!this.dexHelper.config.isSlave) { + const cleanExpiredNotExistingPoolsKeys = async () => { + const maxTimestamp = + Date.now() - UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS; + await this.dexHelper.cache.zremrangebyscore( + this.notExistingPoolSetKey, + 0, + maxTimestamp, + ); + }; + + this.intervalTask = setInterval( + cleanExpiredNotExistingPoolsKeys.bind(this), + UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS, + ); + } + } + + get supportedFees() { + return this.config.supportedFees; + } + + // Returns the list of contract adapters (name and index) + // for a buy/sell. Return null if there are no adapters. + getAdapters(side: SwapSide): { name: string; index: number }[] | null { + return this.adapters[side] ? this.adapters[side] : null; + } + + getPoolIdentifier(srcAddress: Address, destAddress: Address, fee: bigint) { + const tokenAddresses = this._sortTokens(srcAddress, destAddress).join('_'); + return `${this.dexKey}_${tokenAddresses}_${fee}`; + } + + // Returns pool prices for amounts. + // If limitPools is defined only pools in limitPools + // should be used. If limitPools is undefined then + // any pools can be used. + async getPricesVolume( + srcToken: Token, + destToken: Token, + amounts: bigint[], + side: SwapSide, + blockNumber: number, + limitPools?: string[], + ): Promise> { + try { + const _srcToken = this.dexHelper.config.wrapETH(srcToken); + const _destToken = this.dexHelper.config.wrapETH(destToken); + + const [_srcAddress, _destAddress] = this._getLoweredAddresses( + _srcToken, + _destToken, + ); + + if (_srcAddress === _destAddress) return null; + + let selectedPools: SushiswapV3EventPool[] = []; + + if (!limitPools) { + selectedPools = ( + await Promise.all( + this.supportedFees.map(async fee => { + const locallyFoundPool = + this.eventPools[ + this.getPoolIdentifier(_srcAddress, _destAddress, fee) + ]; + if (locallyFoundPool) return locallyFoundPool; + + const newlyFetchedPool = await this.getPool( + _srcAddress, + _destAddress, + fee, + blockNumber, + ); + return newlyFetchedPool; + }), + ) + ).filter(isTruthy); + } else { + const pairIdentifierWithoutFee = this.getPoolIdentifier( + _srcAddress, + _destAddress, + 0n, + // Trim from 0 fee postfix, so it become comparable + ).slice(0, -1); + + const poolIdentifiers = limitPools.filter(identifier => + identifier.startsWith(pairIdentifierWithoutFee), + ); + + selectedPools = ( + await Promise.all( + poolIdentifiers.map(async identifier => { + let locallyFoundPool = this.eventPools[identifier]; + if (locallyFoundPool) return locallyFoundPool; + + const [, srcAddress, destAddress, fee] = identifier.split('_'); + const newlyFetchedPool = await this.getPool( + srcAddress, + destAddress, + BigInt(fee), + blockNumber, + ); + return newlyFetchedPool; + }), + ) + ).filter(isTruthy); + } + + if (selectedPools.length === 0) return null; + + const poolsToUse = selectedPools.reduce( + (acc, pool) => { + let state = pool.getState(blockNumber); + if (state === null) { + this.logger.trace( + `${this.dexKey}: State === null. Fallback to rpc ${pool.name}`, + ); + acc.poolWithoutState.push(pool); + } else { + acc.poolWithState.push(pool); + } + return acc; + }, + { + poolWithState: [] as SushiswapV3EventPool[], + poolWithoutState: [] as SushiswapV3EventPool[], + }, + ); + + const rpcResultsPromise = this.getPricingFromRpc( + _srcToken, + _destToken, + amounts, + side, + poolsToUse.poolWithoutState, + ); + + const states = poolsToUse.poolWithState.map( + p => p.getState(blockNumber)!, + ); + + const unitAmount = getBigIntPow( + side == SwapSide.SELL ? _srcToken.decimals : _destToken.decimals, + ); + + const _amounts = [...amounts.slice(1)]; + + const [token0] = this._sortTokens(_srcAddress, _destAddress); + + const zeroForOne = token0 === _srcAddress ? true : false; + + const result = await Promise.all( + poolsToUse.poolWithState.map(async (pool, i) => { + const state = states[i]; + + if (state.liquidity <= 0n) { + this.logger.trace(`pool have 0 liquidity`); + return null; + } + + const balanceDestToken = + _destAddress === pool.token0 ? state.balance0 : state.balance1; + + const unitResult = this._getOutputs( + state, + [unitAmount], + zeroForOne, + side, + balanceDestToken, + ); + const pricesResult = this._getOutputs( + state, + _amounts, + zeroForOne, + side, + balanceDestToken, + ); + + if (!unitResult || !pricesResult) { + this.logger.debug('Prices or unit is not calculated'); + return null; + } + + const prices = [0n, ...pricesResult.outputs]; + const gasCost = [ + 0, + ...pricesResult.outputs.map((p, index) => { + if (p == 0n) { + return 0; + } else { + return ( + UNISWAPV3_POOL_SEARCH_OVERHEAD + + UNISWAPV3_TICK_BASE_OVERHEAD + + pricesResult.tickCounts[index] * UNISWAPV3_TICK_GAS_COST + ); + } + }), + ]; + return { + unit: unitResult.outputs[0], + prices, + data: { + path: [ + { + tokenIn: _srcAddress, + tokenOut: _destAddress, + fee: pool.feeCode.toString(), + }, + ], + }, + poolIdentifier: this.getPoolIdentifier( + pool.token0, + pool.token1, + pool.feeCode, + ), + exchange: this.dexKey, + gasCost: gasCost, + poolAddresses: [pool.poolAddress], + }; + }), + ); + const rpcResults = await rpcResultsPromise; + + const notNullResult = result.filter( + res => res !== null, + ) as ExchangePrices; + + if (rpcResults) { + rpcResults.forEach(r => { + if (r) { + notNullResult.push(r); + } + }); + } + + return notNullResult; + } catch (e) { + this.logger.error( + `Error_getPricesVolume ${srcToken.symbol || srcToken.address}, ${ + destToken.symbol || destToken.address + }, ${side}:`, + e, + ); + return null; + } + } + + private getQuoterV2CallData( + funcName: string, + tokenIn: Address, + tokenOut: Address, + amount: bigint, + fee: bigint, + ): QuoteExactInputSingleParams | QuoteExactOutputSingleParams { + return funcName === 'quoteExactInputSingle' + ? { tokenIn, tokenOut, fee, sqrtPriceLimitX96: 0n, amountIn: amount } + : { tokenIn, tokenOut, fee, sqrtPriceLimitX96: 0n, amount }; + } + + async getPricingFromRpc( + from: Token, + to: Token, + amounts: bigint[], + side: SwapSide, + pools: SushiswapV3EventPool[], + ): Promise | null> { + if (pools.length === 0) { + return null; + } + this.logger.warn(`fallback to rpc for ${pools.length} pool(s)`); + + const requests = pools.map( + pool => ({ + owner: pool.poolAddress, + asset: side == SwapSide.SELL ? from.address : to.address, + assetType: AssetType.ERC20, + ids: [ + { + id: DEFAULT_ID_ERC20, + spenders: [], + }, + ], + }), + [], + ); + + const balances = await getBalances(this.dexHelper.multiWrapper, requests); + + pools = pools.filter((pool, index) => { + const balance = balances[index].amounts[DEFAULT_ID_ERC20_AS_STRING]; + if (balance >= amounts[amounts.length - 1]) { + return true; + } + this.logger.warn( + `[${this.network}][${pool.parentName}] have no balance ${pool.poolAddress} ${from.address} ${to.address}. (Balance: ${balance})`, + ); + return false; + }); + + pools.forEach(pool => { + this.logger.warn( + `[${this.network}][${pool.parentName}] fallback to rpc for ${pool.name}`, + ); + }); + + const unitVolume = getBigIntPow( + (side === SwapSide.SELL ? from : to).decimals, + ); + + const chunks = amounts.length - 1; + + const _width = Math.floor(chunks / this.config.chunksCount); + + const _amounts = [unitVolume].concat( + Array.from(Array(this.config.chunksCount).keys()).map( + i => amounts[(i + 1) * _width], + ), + ); + + const funcName = + side === SwapSide.SELL + ? 'quoteExactInputSingle' + : 'quoteExactOutputSingle'; + + const calldata = pools.map(pool => + _amounts.map(_amount => ({ + target: this.config.quoter, + gasLimit: UNISWAPV3_QUOTE_GASLIMIT, + callData: this.quoterIface.encodeFunctionData(funcName, [ + this.getQuoterV2CallData( + funcName, + from.address, + to.address, + _amount, + pool.feeCode, + ), + ]), + })), + ); + + const data = await new this.dexHelper.web3Provider.eth.Contract( + UniswapV3MultiABI as AbiItem[], + this.config.uniswapMulticall, + ).methods + .multicall(calldata.flat()) + .call(); + + const decode = (j: number): bigint => { + if (!data.returnData[j].success) { + return 0n; + } + const decoded = defaultAbiCoder.decode( + ['uint256'], + data.returnData[j].returnData, + ); + return BigInt(decoded[0].toString()); + }; + + let i = 0; + const result = pools.map(pool => { + const _rates = _amounts.map(() => decode(i++)); + const unit: bigint = _rates[0]; + + const prices = interpolate( + _amounts.slice(1), + _rates.slice(1), + amounts, + side, + ); + + return { + prices, + unit, + data: { + path: [ + { + tokenIn: from.address, + tokenOut: to.address, + fee: pool.feeCodeAsString, + }, + ], + }, + poolIdentifier: this.getPoolIdentifier( + pool.token0, + pool.token1, + pool.feeCode, + ), + exchange: this.dexKey, + gasCost: prices.map(p => (p === 0n ? 0 : UNISWAPV3_QUOTE_GASLIMIT)), + poolAddresses: [pool.poolAddress], + }; + }); + + return result; + } + + // Returns estimated gas cost of calldata for this DEX in multiSwap + getCalldataGasCost( + poolPrices: PoolPrices, + ): number | number[] { + const gasCost = + CALLDATA_GAS_COST.DEX_OVERHEAD + + CALLDATA_GAS_COST.LENGTH_SMALL + + // ParentStruct header + CALLDATA_GAS_COST.OFFSET_SMALL + + // ParentStruct -> path header + CALLDATA_GAS_COST.OFFSET_SMALL + + // ParentStruct -> deadline + CALLDATA_GAS_COST.TIMESTAMP + + // ParentStruct -> path (20+3+20 = 43 = 32+11 bytes) + CALLDATA_GAS_COST.LENGTH_SMALL + + CALLDATA_GAS_COST.FULL_WORD + + CALLDATA_GAS_COST.wordNonZeroBytes(11); + const arr = new Array(poolPrices.prices.length); + poolPrices.prices.forEach((p, index) => { + if (p == 0n) { + arr[index] = 0; + } else { + arr[index] = gasCost; + } + }); + return arr; + } + + // Encode params required by the exchange adapter + // Used for multiSwap, buy & megaSwap + getAdapterParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: SushiswapV3Data, + side: SwapSide, + ): AdapterExchangeParam { + const { path: rawPath } = data; + const path = this._encodePath(rawPath, side); + + const payload = this.abiCoder.encodeParameter( + { + ParentStruct: { + path: 'bytes', + deadline: 'uint256', + }, + }, + { + path, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), // FIXME: more gas efficient to pass block.timestamp in adapter + }, + ); + + return { + targetExchange: UniswapV3Config['UniswapV3'][this.network].router, + payload, + networkFee: '0', + }; + } + + // Encode call data used by simpleSwap like routers + // Used for simpleSwap & simpleBuy + async getSimpleParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: SushiswapV3Data, + ): Promise { + const web3Client = createPublicClient({ + chain: ViemChain[this.network], + transport: http(generateConfig(this.network).privateHttpProvider), + }); + + const dataFetcher = new DataFetcher( + web3Client.chain.id as ChainId, + web3Client, + ); + + dataFetcher.startDataFetching([LiquidityProviders.SushiSwapV3]); + + const fromToken = await getToken({ web3Client, address: srcToken }); + + const toToken = await getToken({ web3Client, address: destToken }); + + await dataFetcher.fetchPoolsForToken(fromToken, toToken); + + const pcMap = dataFetcher.getCurrentPoolCodeMap(fromToken, toToken); + + const route = Router.findBestRoute( + pcMap, + this.network as unknown as ChainId, + fromToken, + BigNumber.from(srcAmount), + toToken, + 50e9, + [LiquidityProviders.SushiSwapV3], + ); + + const rpParams = Router.routeProcessor2Params( + pcMap, + route, + fromToken, + toToken, + this.augustusAddress, + this.config.router, + ); + + const swapData = this.routerIface.encodeFunctionData('processRoute', [ + rpParams.tokenIn, + rpParams.amountIn, + rpParams.tokenOut, + rpParams.amountOutMin, + rpParams.to, + rpParams.routeCode, + ]); + + dataFetcher.stopDataFetching(); + + return this.buildSimpleParamWithoutWETHConversion( + srcToken, + srcAmount, + destToken, + destAmount, + swapData, + this.config.router, + ); + } + + async getTopPoolsForToken( + tokenAddress: Address, + limit: number, + ): Promise { + const _tokenAddress = tokenAddress.toLowerCase(); + + const res = await this._querySubgraph( + `query ($token: Bytes!, $count: Int) { + pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + }`, + { + token: _tokenAddress, + count: limit, + }, + ); + + if (!(res && res.pools0 && res.pools1)) { + this.logger.error( + `Error_${this.dexKey}_Subgraph: couldn't fetch the pools from the subgraph`, + ); + return []; + } + + const pools0 = _.map(res.pools0, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token1.id.toLowerCase(), + decimals: parseInt(pool.token1.decimals), + }, + ], + liquidityUSD: + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + })); + + const pools1 = _.map(res.pools1, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token0.id.toLowerCase(), + decimals: parseInt(pool.token0.decimals), + }, + ], + liquidityUSD: + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + })); + + const pools = _.slice( + _.sortBy(_.concat(pools0, pools1), [pool => -1 * pool.liquidityUSD]), + 0, + limit, + ); + return pools; + } + + private _encodePath( + path: { + tokenIn: Address; + tokenOut: Address; + fee: NumberAsString; + }[], + side: SwapSide, + ): string { + if (path.length === 0) { + this.logger.error( + `${this.dexKey}: Received invalid path=${path} for side=${side} to encode`, + ); + return '0x'; + } + + const { _path, types } = path.reduce( + ( + { _path, types }: { _path: string[]; types: string[] }, + curr, + index, + ): { _path: string[]; types: string[] } => { + if (index === 0) { + return { + types: ['address', 'uint24', 'address'], + _path: [curr.tokenIn, curr.fee, curr.tokenOut], + }; + } else { + return { + types: [...types, 'uint24', 'address'], + _path: [..._path, curr.fee, curr.tokenOut], + }; + } + }, + { _path: [], types: [] }, + ); + + return side === SwapSide.BUY + ? pack(types.reverse(), _path.reverse()) + : pack(types, _path); + } + + async getPoolIdentifiers( + srcToken: Token, + destToken: Token, + side: SwapSide, + blockNumber: number, + ): Promise { + const _srcToken = this.dexHelper.config.wrapETH(srcToken); + const _destToken = this.dexHelper.config.wrapETH(destToken); + + const [_srcAddress, _destAddress] = this._getLoweredAddresses( + _srcToken, + _destToken, + ); + + if (_srcAddress === _destAddress) return []; + + const pools = ( + await Promise.all( + this.supportedFees.map(async fee => + this.getPool(_srcAddress, _destAddress, fee, blockNumber), + ), + ) + ).filter(pool => pool); + + if (pools.length === 0) return []; + + return pools.map(pool => + this.getPoolIdentifier(_srcAddress, _destAddress, pool!.feeCode), + ); + } + + async getPool( + srcAddress: Address, + destAddress: Address, + fee: bigint, + blockNumber: number, + ): Promise { + let pool = + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)]; + + if (pool === undefined) { + const [token0, token1] = this._sortTokens(srcAddress, destAddress); + + const key = `${token0}_${token1}_${fee}`.toLowerCase(); + + const notExistingPoolScore = await this.dexHelper.cache.zscore( + this.notExistingPoolSetKey, + key, + ); + + const poolDoesNotExist = notExistingPoolScore !== null; + + if (poolDoesNotExist) { + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = + null; + return null; + } + + await this.dexHelper.cache.hset( + this.dexmapKey, + key, + JSON.stringify({ + token0, + token1, + fee: fee.toString(), + }), + ); + + this.logger.trace(`starting to listen to new pool: ${key}`); + pool = new SushiswapV3EventPool( + this.dexHelper, + this.dexKey, + this.stateMultiContract, + this.erc20Interface, + this.config.factory, + fee, + token0, + token1, + this.logger, + this.cacheStateKey, + this.config.initHash, + ); + + try { + await pool.initialize(blockNumber, { + initCallback: (state: DeepReadonly) => { + //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber + pool!.addressesSubscribed[0] = state.pool; + pool!.poolAddress = state.pool; + }, + }); + } catch (e) { + if (e instanceof Error && e.message.endsWith('Pool does not exist')) { + // no need to await we want the set to have the pool key but it's not blocking + this.dexHelper.cache.zadd( + this.notExistingPoolSetKey, + [Date.now(), key], + 'NX', + ); + + // Pool does not exist for this feeCode, so we can set it to null + // to prevent more requests for this pool + pool = null; + this.logger.trace( + `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, + e, + ); + } else { + // Unexpected Error. Break execution. Do not save the pool in this.eventPools + this.logger.error( + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool`, + e, + ); + throw new Error('Cannot generate pool state'); + } + } + + if (pool !== null) { + const allEventPools = Object.values(this.eventPools); + this.logger.info( + `starting to listen to new non-null pool: ${key}. Already following ${allEventPools + // Not that I like this reduce, but since it is done only on initialization, expect this to be ok + .reduce( + (acc, curr) => (curr !== null ? ++acc : acc), + 0, + )} non-null pools or ${allEventPools.length} total pools`, + ); + } + + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = + pool; + } + return pool; + } + + private _getLoweredAddresses(srcToken: Token, destToken: Token) { + return [srcToken.address.toLowerCase(), destToken.address.toLowerCase()]; + } + + private _sortTokens(srcAddress: Address, destAddress: Address) { + return [srcAddress, destAddress].sort((a, b) => (a < b ? -1 : 1)); + } + + private _toLowerForAllConfigAddresses() { + // If new config property will be added, the TS will throw compile error + const newConfig: DexParams = { + router: this.config.router.toLowerCase(), + quoter: this.config.quoter.toLowerCase(), + factory: this.config.factory.toLowerCase(), + supportedFees: this.config.supportedFees, + stateMulticall: this.config.stateMulticall.toLowerCase(), + chunksCount: this.config.chunksCount, + uniswapMulticall: this.config.uniswapMulticall, + deployer: this.config.deployer?.toLowerCase(), + initHash: this.config.initHash, + subgraphURL: this.config.subgraphURL, + }; + return newConfig; + } + + private async _querySubgraph( + query: string, + variables: Object, + timeout = 30000, + ) { + try { + const res = await this.dexHelper.httpRequest.post( + this.config.subgraphURL, + { query, variables }, + undefined, + { timeout: timeout }, + ); + return res.data; + } catch (e) { + this.logger.error(`${this.dexKey}: can not query subgraph: `, e); + return {}; + } + } + + private _getOutputs( + state: DeepReadonly, + amounts: bigint[], + zeroForOne: boolean, + side: SwapSide, + destTokenBalance: bigint, + ): OutputResult | null { + try { + const outputsResult = uniswapV3Math.queryOutputs( + state, + amounts, + zeroForOne, + side, + ); + + if (side === SwapSide.SELL) { + if (outputsResult.outputs[0] > destTokenBalance) { + return null; + } + + for (let i = 0; i < outputsResult.outputs.length; i++) { + if (outputsResult.outputs[i] > destTokenBalance) { + outputsResult.outputs[i] = 0n; + outputsResult.tickCounts[i] = 0; + } + } + } else { + if (amounts[0] > destTokenBalance) { + return null; + } + + // This may be improved by first checking outputs and requesting outputs + // only for amounts that makes more sense, but I don't think this is really + // important now + for (let i = 0; i < amounts.length; i++) { + if (amounts[i] > destTokenBalance) { + outputsResult.outputs[i] = 0n; + outputsResult.tickCounts[i] = 0; + } + } + } + + return outputsResult; + } catch (e) { + this.logger.debug( + `${this.dexKey}: received error in _getOutputs while calculating outputs`, + e, + ); + return null; + } + } + + releaseResources(): AsyncOrSync { + if (this.intervalTask !== undefined) { + clearInterval(this.intervalTask); + this.intervalTask = undefined; + } + } +} diff --git a/src/dex/sushiswap-v3/sushiswap-v3.ts b/src/dex/sushiswap-v3/sushiswap-v3.ts new file mode 100644 index 000000000..9423fe345 --- /dev/null +++ b/src/dex/sushiswap-v3/sushiswap-v3.ts @@ -0,0 +1,268 @@ +import _ from 'lodash'; +import { createPublicClient, http } from 'viem'; +import { DataFetcher, LiquidityProviders, Router, RPParams } from '@sushiswap/router'; +import { Token as SushiToken } from '@sushiswap/currency'; +import { SushiSwapV3Config, Adapters } from './config'; +import { UniswapV3 } from '../uniswap-v3/uniswap-v3'; +import { getViemChain } from './constants'; +import { Network, SwapSide } from '../../constants'; +import { getDexKeysWithNetwork } from '../../utils'; +import SushiswapV3RouterABI from '../../abi/sushiswap-v3/RouterProcessor3.json'; +import SushiswapV3QuoterV2ABI from '../../abi/sushiswap-v3/QuoterV2.json'; +import { IDexHelper } from '../../dex-helper'; +import { Interface } from '@ethersproject/abi'; +import { + AdapterExchangeParam, + ExchangeTxInfo, + PreprocessTransactionOptions, + SimpleExchangeParam, + Token, +} from '../../types'; +import { generateConfig } from '../../config'; +import { BigNumber } from 'ethers'; +import { getLocalDeadlineAsFriendlyPlaceholder, SimpleExchange } from '../simple-exchange'; +import { OptimalSwapExchange } from '@paraswap/core'; +import { assert } from 'ts-essentials'; +import { SushiSwapV3Data } from './types'; +import { UniswapV3Data} from '../uniswap-v3/types'; +import { MultiCallParams } from '../../lib/multi-wrapper'; +import { uint256DecodeToNumber } from '../../lib/decoders'; + +export class SushiSwapV3 extends UniswapV3 { + + constructor( + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + protected adapters = Adapters[network] || {}, + readonly routerIface = new Interface(SushiswapV3RouterABI), + readonly quoterIface = new Interface(SushiswapV3QuoterV2ABI), + protected config = SushiSwapV3Config[dexKey][network], + protected poolsToPreload = [], + ) { + super( + network, + dexKey, + dexHelper, + adapters, + routerIface, + quoterIface, + config, + poolsToPreload, + ); + } + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(_.pick(SushiSwapV3Config, ['SushiSwapV3'])); + + async preProcessTransaction( + optimalSwapExchange: OptimalSwapExchange, + srcToken: Token, + destToken: Token, + side: SwapSide, + options: PreprocessTransactionOptions, + ): Promise<[OptimalSwapExchange, ExchangeTxInfo]> { + if (!options.isDirectMethod) { + return [ + optimalSwapExchange, + { + deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), + }, + ]; + } + + assert( + optimalSwapExchange.data !== undefined, + `preProcessTransaction: data field is missing`, + ); + + let isApproved: boolean | undefined; + + try { + this.erc20Contract.options.address = + this.dexHelper.config.wrapETH(srcToken).address; + const allowance = await this.erc20Contract.methods + .allowance(this.augustusAddress, this.config.router) + .call(undefined, 'latest'); + isApproved = + BigInt(allowance.toString()) >= BigInt(optimalSwapExchange.srcAmount); + } catch (e) { + this.logger.error( + `preProcessTransaction failed to retrieve allowance info: `, + e, + ); + } + + const rpParams = await this.getSushiV3Params( + srcToken.address, + destToken.address, + optimalSwapExchange.srcAmount, + ); + + console.log('preprocess tx: ', rpParams); + + return [ + { + ...optimalSwapExchange, + data: { + ...optimalSwapExchange.data, + isApproved, + rpParams, + }, + }, + { + deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), + }, + ]; + } + + async getSushiV3Params( + srcToken: string, + destToken: string, + srcAmount: string, + ): Promise { + const web3Client = createPublicClient({ + transport: http(generateConfig(this.network).privateHttpProvider), + chain: getViemChain(this.network), + }); + + const dataFetcher = new DataFetcher( + this.network, + web3Client, + ); + + const callData: MultiCallParams[] = [ + { + target: srcToken, + callData: this.erc20Interface.encodeFunctionData('decimals'), + decodeFunction: uint256DecodeToNumber, + }, + { + target: destToken, + callData: this.erc20Interface.encodeFunctionData('decimals'), + decodeFunction: uint256DecodeToNumber, + } + ]; + + const [decimals0, decimals1] = + await this.dexHelper.multiWrapper.tryAggregate( + false, + callData, + undefined, + this.dexHelper.multiWrapper.defaultBatchSize, + false, + ); + + dataFetcher.startDataFetching([LiquidityProviders.SushiSwapV3]); + + const fromToken = new SushiToken({ + address: srcToken, + decimals: decimals0.returnData, + chainId: this.network, + }); + + const toToken = new SushiToken({ + address: destToken, + decimals: decimals1.returnData, + chainId: this.network, + }); + + await dataFetcher.fetchPoolsForToken(fromToken, toToken); + + const pcMap = dataFetcher.getCurrentPoolCodeMap(fromToken, toToken); + + const route = Router.findBestRoute( + pcMap, + this.network, + fromToken, + BigNumber.from(srcAmount), + toToken, + 50e9, + [LiquidityProviders.SushiSwapV3], + ); + + console.log('ROUTE: ', route); + + const rpParams = Router.routeProcessor2Params( + pcMap, + route, + fromToken, + toToken, + this.augustusAddress, + this.config.router, + ); + + dataFetcher.stopDataFetching(); + + return rpParams; + } + + getAdapterParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: SushiSwapV3Data, + side: SwapSide, + ): AdapterExchangeParam { + console.log('getAdapterParam: ', data.rpParams); + + const payload = this.abiCoder.encodeParameter( + { + ParentStruct: { + tokenIn: 'address', + amountIn: 'uint256', + tokenOut: 'address', + amountOutMin: 'uint256', + to: 'address', + route: 'bytes', + }, + }, + { + tokenIn: data.rpParams!.tokenIn, + amountIn: data.rpParams!.amountIn, + tokenOut: data.rpParams!.tokenOut, + amountOutMin: data.rpParams!.amountOutMin, + to: data.rpParams!.to, + route: data.rpParams!.routeCode, + }, + ); + + return { + targetExchange: this.config.router, + payload, + networkFee: '0', + }; + } + + async getSimpleParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: SushiSwapV3Data, + ): Promise { + + const routerParams = await this.getSushiV3Params(srcToken, destToken, destAmount); + + console.log('getSimpleParam: ', routerParams); + + const swapData = this.routerIface.encodeFunctionData('processRoute', [ + routerParams.tokenIn, + routerParams.amountIn, + routerParams.tokenOut, + routerParams.amountOutMin, + routerParams.to, + routerParams.routeCode, + ]); + + return this.buildSimpleParamWithoutWETHConversion( + srcToken, + srcAmount, + destToken, + destAmount, + swapData, + this.config.router, + ); + } +} diff --git a/src/dex/sushiswap-v3/types.ts b/src/dex/sushiswap-v3/types.ts new file mode 100644 index 000000000..347136af5 --- /dev/null +++ b/src/dex/sushiswap-v3/types.ts @@ -0,0 +1,12 @@ +import { Address, NumberAsString } from '../../types'; +import { RPParams } from '@sushiswap/router'; + +export type SushiSwapV3Data = { + path: { + tokenIn: Address; + tokenOut: Address; + fee: NumberAsString; + }[]; + isApproved?: boolean; + rpParams?: RPParams; +}; diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index e4b27a163..7cf4ad24d 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -6,7 +6,7 @@ import RamsesV2StateMulticallABI from '../../abi/RamsesV2StateMulticall.abi.json import { AbiItem } from 'web3-utils'; import { decodeStateMultiCallResultWithRelativeBitmaps } from './forks/ramses-v2/utils'; -const SUPPORTED_FEES = [10000n, 3000n, 500n, 100n]; +export const SUPPORTED_FEES = [10000n, 3000n, 500n, 100n]; // Pools that will be initialized on app startup // They are added for testing @@ -123,104 +123,6 @@ export const UniswapV3Config: DexConfigMap = { 'https://subgraph.chronos.exchange/subgraphs/name/chronos-v3', }, }, - SushiSwapV3: { - [Network.MAINNET]: { - factory: '0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F', - quoter: '0x64e8802FE490fa7cc61d3463958199161Bb608A7', - router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', - // router: '0x827179dD56d07A7eeA32e3873493835da2866976', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-ethereum', - }, - [Network.POLYGON]: { - factory: '0x917933899c6a5f8e37f31e19f92cdbff7e8ff0e2', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', - // router: '0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-polygon', - }, - [Network.BSC]: { - factory: '0x126555dd55a39328F69400d6aE4F782Bd4C34ABb', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x83c346ba3d4bf36b308705e24fad80999401854b', - // router: '0x400d75dAb26bBc18D163AEA3e83D9Ea68F6c1804', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x593F39A4Ba26A9c8ed2128ac95D109E8e403C485', - uniswapMulticall: '0x963Df249eD09c358A4819E39d9Cd5736c3087184', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-bsc', - }, - [Network.AVALANCHE]: { - factory: '0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x33895c09a0ec0718ce66ab35dfd0b656d77cd053', - // router: '0x717b7948AA264DeCf4D780aa6914482e5F46Da3e', - supportedFees: SUPPORTED_FEES, - stateMulticall: '', - uniswapMulticall: '0x8C0F842791F03C095b6c633759224FcC9ACe68ea', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-avalanche', - }, - [Network.FANTOM]: { - factory: '0x7770978eED668a3ba661d51a773d3a992Fc9DDCB', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x940438cEd3062E3F7aE311c789FA9dDd3a5eA951', - // router: '0x2214A42d8e2A1d20635c2cb0664422c528B6A432', - supportedFees: SUPPORTED_FEES, - stateMulticall: '', - uniswapMulticall: '0xB1395e098c0a847CC719Bcf1Fc8114421a9F8232', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-fantom', - }, - [Network.ARBITRUM]: { - factory: '0x1af415a1eba07a4986a52b6f2e7de7003d82231e', - quoter: '0x0524E833cCD057e4d7A296e3aaAb9f7675964Ce1', - router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', - // router: '0xfc506AaA1340b4dedFfd88bE278bEe058952D674', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-arbitrum', - }, - [Network.OPTIMISM]: { - factory: '0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', - // router: '0x4C5D5234f232BD2D76B96aA33F5AE4FCF0E4BFAb', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x4FF0dEC5f9a763Aa1E5C2a962aa6f4eDFeE4f9eA', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-optimism', - }, - }, RamsesV2: { [Network.ARBITRUM]: { factory: '0xAA2cd7477c451E703f3B9Ba5663334914763edF8', diff --git a/src/dex/uniswap-v3/types.ts b/src/dex/uniswap-v3/types.ts index b7c314500..a06a8cd66 100644 --- a/src/dex/uniswap-v3/types.ts +++ b/src/dex/uniswap-v3/types.ts @@ -3,6 +3,7 @@ import { NumberAsString } from '../../types'; import { Address } from '../../types'; import { AbiItem } from 'web3-utils'; import { MultiResult } from '../../lib/multi-wrapper'; +import { RPParams } from '@sushiswap/router'; export type OracleObservation = { blockTimestamp: bigint; @@ -60,6 +61,7 @@ export type UniswapV3Data = { fee: NumberAsString; }[]; isApproved?: boolean; + rpParams?: RPParams; }; export type DecodeStateMultiCallFunc = ( diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index 94bb2821c..294251034 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -11,100 +11,6 @@ import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; -function testForNetwork( - network: Network, - dexKey: string, - tokenASymbol: string, - tokenBSymbol: string, - tokenAAmount: string, - tokenBAmount: string, - nativeTokenAmount: string, - slippage?: number | undefined, -) { - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - const tokens = Tokens[network]; - const holders = Holders[network]; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ContractMethod.directUniV3Swap, - ], - ], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy, ContractMethod.directUniV3Buy]], - ]); - - describe(`${network}`, () => { - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - 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, - 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, - 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, - network, - provider, - undefined, - undefined, - undefined, - slippage, - ); - }); - }); - }); - }), - ); - }); -} - describe('UniswapV3 E2E', () => { describe('UniswapV3', () => { @@ -687,239 +593,4 @@ describe('UniswapV3 E2E', () => { ); }); }); - - describe('SushiswapV3', () => { - const dexKey = 'SushiSwapV3'; - - describe('MAINNET', () => { - const network = Network.MAINNET; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; - - const tokenAAmount: string = '111110000'; - const tokenBAmount: string = '1100000000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - 500, // 5% - ); - }); - - describe('ARBITRUM', () => { - const network = Network.ARBITRUM; - - const tokenASymbol: string = 'USDCe'; - const tokenBSymbol: string = 'USDT'; - - const tokenAAmount: string = '111110000'; - const tokenBAmount: string = '10000000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - 500, // 5% - ); - }); - - describe('POLYGON', () => { - const network = Network.POLYGON; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; - - const tokenAAmount: string = '21111000'; - const tokenBAmount: string = '200000000'; - const nativeTokenAmount = '110000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - 500, // 5% - ); - }); - - describe('BSC', () => { - const network = Network.BSC; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ContractMethod.directUniV3Buy, - ], - ], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy, ContractMethod.directUniV3Buy]], - ]); - - const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ - [ - { - name: 'USDT', - sellAmount: '10000000000', - buyAmount: '10000000000000', - }, - { - name: 'BNB', - sellAmount: '10000000000000', - buyAmount: '10000000', - }, - ], - [ - { - name: 'USDC', - sellAmount: '111110000', - buyAmount: '111110000', - }, - { - name: 'USDT', - sellAmount: '111110000', - buyAmount: '111110000', - }, - ], - [ - { - name: 'ETH', - sellAmount: '1000000000000000000', - buyAmount: '500000', - }, - { name: 'USDT', sellAmount: '1000000', buyAmount: '20000000000000000' }, - ], - ]; - - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - contractMethods.forEach((contractMethod: ContractMethod) => { - pairs.forEach(pair => { - describe(`${contractMethod}`, () => { - it(`${pair[0].name} -> ${pair[1].name}`, async () => { - await testE2E( - tokens[pair[0].name], - tokens[pair[1].name], - holders[pair[0].name], - side === SwapSide.SELL - ? pair[0].sellAmount - : pair[0].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${pair[1].name} -> ${pair[0].name}`, async () => { - await testE2E( - tokens[pair[1].name], - tokens[pair[0].name], - holders[pair[1].name], - side === SwapSide.SELL - ? pair[1].sellAmount - : pair[1].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }); - }); - }), - ); - }); - - describe('AVALANCHE', () => { - const network = Network.AVALANCHE; - - const tokenASymbol: string = 'USDCe'; - const tokenBSymbol: string = 'USDC'; - - const tokenAAmount: string = '111110000'; - const tokenBAmount: string = '100000000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - 500, // 5% - ); - }); - - describe('FANTOM', () => { - const network = Network.FANTOM; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'DAI'; - - const tokenAAmount: string = '111110000'; - const tokenBAmount: string = '10000000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - 500, // 5% - ); - }); - - describe('OPTIMISM', () => { - const network = Network.OPTIMISM; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; - - const tokenAAmount: string = '111110000'; - const tokenBAmount: string = '10000000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - 500, // 5% - ); - }); - }); }); diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index 4583a2bbf..6df249331 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -746,138 +746,3 @@ describe('ChronosV3', () => { checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); }); }); - -describe('SushiSwapV3', () => { - const dexKey = 'SushiSwapV3'; - let blockNumber: number; - let uniswapV3: UniswapV3; - let uniswapV3Mainnet: UniswapV3; - - const network = Network.MAINNET; - const dexHelper = new DummyDexHelper(network); - const TokenASymbol = 'USDC'; - const TokenA = Tokens[network][TokenASymbol]; - - const TokenBSymbol = 'USDT'; - const TokenB = Tokens[network][TokenBSymbol]; - - beforeEach(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - uniswapV3 = new UniswapV3(network, dexKey, dexHelper); - uniswapV3Mainnet = new UniswapV3( - Network.ARBITRUM, - dexKey, - dexHelper, - ); - }); - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - - const amounts = [0n, BI_POWS[6], 2000000n]; - - const pools = await uniswapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.SELL, - blockNumber, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await uniswapV3.getPricesVolume( - TokenA, - TokenB, - amounts, - SwapSide.SELL, - blockNumber, - pools, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); - - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - dexHelper, - uniswapV3, - 'quoteExactInputSingle', - blockNumber, - '0x64e8802FE490fa7cc61d3463958199161Bb608A7', - price.prices, - TokenA.address, - TokenB.address, - fee, - amounts, - ); - if (res === false) falseChecksCounter++; - }), - ); - - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - - const amounts = [0n, BI_POWS[6], 2000000n]; - - const pools = await uniswapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.BUY, - blockNumber, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await uniswapV3.getPricesVolume( - TokenA, - TokenB, - amounts, - SwapSide.BUY, - blockNumber, - pools, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); - - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - dexHelper, - uniswapV3, - 'quoteExactOutputSingle', - blockNumber, - '0x64e8802FE490fa7cc61d3463958199161Bb608A7', - price.prices, - TokenA.address, - TokenB.address, - fee, - amounts, - ); - if (res === false) falseChecksCounter++; - }), - ); - - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - it('getTopPoolsForToken', async function () { - const poolLiquidity = await uniswapV3.getTopPoolsForToken( - TokenB.address, - 10, - ); - console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); - - checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); - }); -}); diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 26ec486e0..478f8e0bf 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -91,15 +91,15 @@ export class UniswapV3 public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork( - _.pick(UniswapV3Config, ['UniswapV3', 'QuickSwapV3.1', 'RamsesV2', 'ChronosV3', 'SushiSwapV3']), + _.pick(UniswapV3Config, ['UniswapV3', 'QuickSwapV3.1', 'RamsesV2', 'ChronosV3']), ); logger: Logger; - private uniswapMulti: Contract; - private stateMultiContract: Contract; + protected uniswapMulti: Contract; + protected stateMultiContract: Contract; - private notExistingPoolSetKey: string; + protected notExistingPoolSetKey: string; constructor( protected network: Network, diff --git a/yarn.lock b/yarn.lock index eb77e24a1..1b6079b1a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -41,6 +41,11 @@ js-sha3 "^0.7.0" lodash "^4.17.11" +"@adraffy/ens-normalize@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.9.0.tgz#223572538f6bea336750039bb43a4016dcc8182d" + integrity sha512-iowxq3U30sghZotgl4s/oJRci6WPBfNO5YYgk2cIOMCHr3LeGPcsZjCEr+33Q4N+oV3OABDAtA+pyvWjbvBifQ== + "@ampproject/remapping@^2.1.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" @@ -331,11 +336,57 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@balena/dockerignore@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" + integrity sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q== + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@chainsafe/as-sha256@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz#3639df0e1435cab03f4d9870cc3ac079e57a6fc9" + integrity sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg== + +"@chainsafe/persistent-merkle-tree@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz#4c9ee80cc57cd3be7208d98c40014ad38f36f7ff" + integrity sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + +"@chainsafe/persistent-merkle-tree@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz#2b4a62c9489a5739dedd197250d8d2f5427e9f63" + integrity sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + +"@chainsafe/ssz@^0.10.0": + version "0.10.2" + resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.10.2.tgz#c782929e1bb25fec66ba72e75934b31fd087579e" + integrity sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + "@chainsafe/persistent-merkle-tree" "^0.5.0" + +"@chainsafe/ssz@^0.9.2": + version "0.9.4" + resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.9.4.tgz#696a8db46d6975b600f8309ad3a12f7c0e310497" + integrity sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + "@chainsafe/persistent-merkle-tree" "^0.4.2" + case "^1.6.3" + +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -343,6 +394,22 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@ensdomains/ens@^0.4.4": + version "0.4.5" + resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" + integrity sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw== + dependencies: + bluebird "^3.5.2" + eth-ens-namehash "^2.0.8" + solc "^0.4.20" + testrpc "0.0.1" + web3-utils "^1.0.0-beta.31" + +"@ensdomains/resolver@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" + integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== + "@eslint/eslintrc@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.0.tgz#8ec64e0df3e7a1971ee1ff5158da87389f167a63" @@ -412,6 +479,59 @@ merkletreejs "^0.2.27" rlp "^2.2.7" +"@ethereum-waffle/chai@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.4.tgz#16c4cc877df31b035d6d92486dfdf983df9138ff" + integrity sha512-/K8czydBtXXkcM9X6q29EqEkc5dN3oYenyH2a9hF7rGAApAJUpH8QBtojxOY/xQ2up5W332jqgxwp0yPiYug1g== + dependencies: + "@ethereum-waffle/provider" "^3.4.4" + ethers "^5.5.2" + +"@ethereum-waffle/compiler@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.4.tgz#d568ee0f6029e68b5c645506079fbf67d0dfcf19" + integrity sha512-RUK3axJ8IkD5xpWjWoJgyHclOeEzDLQFga6gKpeGxiS/zBu+HB0W2FvsrrLalTFIaPw/CGYACRBSIxqiCqwqTQ== + dependencies: + "@resolver-engine/imports" "^0.3.3" + "@resolver-engine/imports-fs" "^0.3.3" + "@typechain/ethers-v5" "^2.0.0" + "@types/mkdirp" "^0.5.2" + "@types/node-fetch" "^2.5.5" + ethers "^5.0.1" + mkdirp "^0.5.1" + node-fetch "^2.6.1" + solc "^0.6.3" + ts-generator "^0.1.1" + typechain "^3.0.0" + +"@ethereum-waffle/ens@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.4.4.tgz#db97ea2c9decbb70b9205d53de2ccbd6f3182ba1" + integrity sha512-0m4NdwWxliy3heBYva1Wr4WbJKLnwXizmy5FfSSr5PMbjI7SIGCdCB59U7/ZzY773/hY3bLnzLwvG5mggVjJWg== + dependencies: + "@ensdomains/ens" "^0.4.4" + "@ensdomains/resolver" "^0.2.4" + ethers "^5.5.2" + +"@ethereum-waffle/mock-contract@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.4.4.tgz#fc6ffa18813546f4950a69f5892d4dd54b2c685a" + integrity sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA== + dependencies: + "@ethersproject/abi" "^5.5.0" + ethers "^5.5.2" + +"@ethereum-waffle/provider@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.4.tgz#398fc1f7eb91cc2df7d011272eacba8af0c7fffb" + integrity sha512-GK8oKJAM8+PKy2nK08yDgl4A80mFuI8zBkE0C9GqTRYQqvuxIyXoLmJ5NZU9lIwyWVv5/KsoA11BgAv2jXE82g== + dependencies: + "@ethereum-waffle/ens" "^3.4.4" + ethers "^5.5.2" + ganache-core "^2.13.2" + patch-package "^6.2.2" + postinstall-postinstall "^2.1.0" + "@ethereumjs/common@^2.3.0", "@ethereumjs/common@^2.4.0", "@ethereumjs/common@^2.6.4": version "2.6.5" resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30" @@ -420,6 +540,11 @@ crc-32 "^1.2.0" ethereumjs-util "^7.1.5" +"@ethereumjs/rlp@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" + integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== + "@ethereumjs/tx@^3.2.1": version "3.5.2" resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.2.tgz#197b9b6299582ad84f9527ca961466fce2296c1c" @@ -428,6 +553,30 @@ "@ethereumjs/common" "^2.6.4" ethereumjs-util "^7.1.5" +"@ethereumjs/util@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4" + integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA== + dependencies: + "@ethereumjs/rlp" "^4.0.1" + ethereum-cryptography "^2.0.0" + micro-ftch "^0.3.1" + +"@ethersproject/abi@5.0.0-beta.153": + version "5.0.0-beta.153" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" + integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg== + dependencies: + "@ethersproject/address" ">=5.0.0-beta.128" + "@ethersproject/bignumber" ">=5.0.0-beta.130" + "@ethersproject/bytes" ">=5.0.0-beta.129" + "@ethersproject/constants" ">=5.0.0-beta.128" + "@ethersproject/hash" ">=5.0.0-beta.128" + "@ethersproject/keccak256" ">=5.0.0-beta.127" + "@ethersproject/logger" ">=5.0.0-beta.129" + "@ethersproject/properties" ">=5.0.0-beta.131" + "@ethersproject/strings" ">=5.0.0-beta.130" + "@ethersproject/abi@5.0.7": version "5.0.7" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" @@ -443,7 +592,7 @@ "@ethersproject/properties" "^5.0.3" "@ethersproject/strings" "^5.0.4" -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== @@ -482,7 +631,7 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/address@5.7.0", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.7.0": +"@ethersproject/address@5.7.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== @@ -508,7 +657,7 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.7.0": +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== @@ -517,14 +666,14 @@ "@ethersproject/logger" "^5.7.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.7.0": +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.7.0": +"@ethersproject/constants@5.7.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== @@ -547,7 +696,7 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/transactions" "^5.7.0" -"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.7.0": +"@ethersproject/hash@5.7.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== @@ -599,7 +748,7 @@ aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.7.0": +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== @@ -607,7 +756,7 @@ "@ethersproject/bytes" "^5.7.0" js-sha3 "0.8.0" -"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.7.0": +"@ethersproject/logger@5.7.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== @@ -627,14 +776,14 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/sha2" "^5.7.0" -"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.7.0": +"@ethersproject/properties@5.7.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.0": +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.0", "@ethersproject/providers@^5.7.1", "@ethersproject/providers@^5.7.2": version "5.7.2" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== @@ -697,7 +846,7 @@ elliptic "6.5.4" hash.js "1.1.7" -"@ethersproject/solidity@5.7.0": +"@ethersproject/solidity@5.7.0", "@ethersproject/solidity@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== @@ -709,7 +858,7 @@ "@ethersproject/sha2" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.7.0": +"@ethersproject/strings@5.7.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== @@ -733,7 +882,7 @@ "@ethersproject/rlp" "^5.7.0" "@ethersproject/signing-key" "^5.7.0" -"@ethersproject/units@5.7.0": +"@ethersproject/units@5.7.0", "@ethersproject/units@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== @@ -742,7 +891,7 @@ "@ethersproject/constants" "^5.7.0" "@ethersproject/logger" "^5.7.0" -"@ethersproject/wallet@5.7.0": +"@ethersproject/wallet@5.7.0", "@ethersproject/wallet@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== @@ -1125,6 +1274,22 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" +"@matterlabs/hardhat-zksync-deploy@0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-deploy/-/hardhat-zksync-deploy-0.6.2.tgz#077beeaadc28af5afc469c0a94f394bbc9d96ad4" + integrity sha512-TRGbYXqFdLspaGRjNRWFcej0i8+OgYodDPFVRMg/3KJvC0QLViEEcBZ2cpBqC/R5fydsIql5KXe8ZVMz22AeqA== + dependencies: + chalk "4.1.2" + +"@matterlabs/hardhat-zksync-solc@0.3.14": + version "0.3.14" + resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-solc/-/hardhat-zksync-solc-0.3.14.tgz#0a32f01b4cd8631ecd8dfe0547e3ac49ab8290d5" + integrity sha512-iKuQ+vvnpv3K2lkFO41xpJcNWH0KHJ/5JbOboTlPZATVR7F3GJeHfJL+GG4wkxKXnxZczpxyQqC4rAfMKvRaDg== + dependencies: + "@nomiclabs/hardhat-docker" "^2.0.0" + chalk "4.1.2" + dockerode "^3.3.4" + "@metamask/eth-sig-util@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" @@ -1136,16 +1301,45 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" +"@noble/curves@1.0.0", "@noble/curves@~1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.0.0.tgz#e40be8c7daf088aaf291887cbc73f43464a92932" + integrity sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw== + dependencies: + "@noble/hashes" "1.3.0" + +"@noble/curves@1.1.0", "@noble/curves@~1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" + integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA== + dependencies: + "@noble/hashes" "1.3.1" + "@noble/hashes@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== +"@noble/hashes@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" + integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== + +"@noble/hashes@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" + integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== + "@noble/hashes@~1.1.1": version "1.1.5" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.5.tgz#1a0377f3b9020efe2fae03290bd2a12140c95c11" integrity sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ== +"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + "@noble/secp256k1@1.6.3", "@noble/secp256k1@~1.6.0": version "1.6.3" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.6.3.tgz#7eed12d9f4404b416999d0c87686836c4c5c9b94" @@ -1172,6 +1366,19 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@nomicfoundation/ethereumjs-block@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.1.tgz#6f89664f55febbd723195b6d0974773d29ee133d" + integrity sha512-u1Yioemi6Ckj3xspygu/SfFvm8vZEO8/Yx5a1QLzi6nVU0jz3Pg2OmHKJ5w+D9Ogk1vhwRiqEBAqcb0GVhCyHw== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + ethereum-cryptography "0.1.3" + ethers "^5.7.1" + "@nomicfoundation/ethereumjs-block@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.0.0.tgz#fdd5c045e7baa5169abeed0e1202bf94e4481c49" @@ -1184,6 +1391,25 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" ethereum-cryptography "0.1.3" +"@nomicfoundation/ethereumjs-blockchain@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.1.tgz#80e0bd3535bfeb9baa29836b6f25123dab06a726" + integrity sha512-NhzndlGg829XXbqJEYrF1VeZhAwSPgsK/OB7TVrdzft3y918hW5KNd7gIZ85sn6peDZOdjBsAXIpXZ38oBYE5A== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-ethash" "3.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + abstract-level "^1.0.3" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + level "^8.0.0" + lru-cache "^5.1.1" + memory-level "^1.0.0" + "@nomicfoundation/ethereumjs-blockchain@^6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.0.0.tgz#1a8c243a46d4d3691631f139bfb3a4a157187b0c" @@ -1202,6 +1428,14 @@ lru-cache "^5.1.1" memory-level "^1.0.0" +"@nomicfoundation/ethereumjs-common@4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.1.tgz#4702d82df35b07b5407583b54a45bf728e46a2f0" + integrity sha512-OBErlkfp54GpeiE06brBW/TTbtbuBJV5YI5Nz/aB2evTDo+KawyEzPjBlSr84z/8MFfj8wS2wxzQX1o32cev5g== + dependencies: + "@nomicfoundation/ethereumjs-util" "9.0.1" + crc-32 "^1.2.0" + "@nomicfoundation/ethereumjs-common@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.0.0.tgz#f6bcc7753994555e49ab3aa517fc8bcf89c280b9" @@ -1210,6 +1444,18 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" crc-32 "^1.2.0" +"@nomicfoundation/ethereumjs-ethash@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.1.tgz#65ca494d53e71e8415c9a49ef48bc921c538fc41" + integrity sha512-KDjGIB5igzWOp8Ik5I6QiRH5DH+XgILlplsHR7TEuWANZA759G6krQ6o8bvj+tRUz08YygMQu/sGd9mJ1DYT8w== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + abstract-level "^1.0.3" + bigint-crypto-utils "^3.0.23" + ethereum-cryptography "0.1.3" + "@nomicfoundation/ethereumjs-ethash@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.0.tgz#11539c32fe0990e1122ff987d1b84cfa34774e81" @@ -1222,6 +1468,20 @@ bigint-crypto-utils "^3.0.23" ethereum-cryptography "0.1.3" +"@nomicfoundation/ethereumjs-evm@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.1.tgz#f35681e203363f69ce2b3d3bf9f44d4e883ca1f1" + integrity sha512-oL8vJcnk0Bx/onl+TgQOQ1t/534GKFaEG17fZmwtPFeH8S5soiBYPCLUrvANOl4sCp9elYxIMzIiTtMtNNN8EQ== + dependencies: + "@ethersproject/providers" "^5.7.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + "@nomicfoundation/ethereumjs-evm@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.0.0.tgz#99cd173c03b59107c156a69c5e215409098a370b" @@ -1236,11 +1496,28 @@ mcl-wasm "^0.7.1" rustbn.js "~0.2.0" +"@nomicfoundation/ethereumjs-rlp@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.1.tgz#0b30c1cf77d125d390408e391c4bb5291ef43c28" + integrity sha512-xtxrMGa8kP4zF5ApBQBtjlSbN5E2HI8m8FYgVSYAnO6ssUoY5pVPGy2H8+xdf/bmMa22Ce8nWMH3aEW8CcqMeQ== + "@nomicfoundation/ethereumjs-rlp@^4.0.0", "@nomicfoundation/ethereumjs-rlp@^4.0.0-beta.2": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.0.tgz#d9a9c5f0f10310c8849b6525101de455a53e771d" integrity sha512-GaSOGk5QbUk4eBP5qFbpXoZoZUj/NrW7MRa0tKY4Ew4c2HAS0GXArEMAamtFrkazp0BO4K5p2ZCG3b2FmbShmw== +"@nomicfoundation/ethereumjs-statemanager@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.1.tgz#8824a97938db4471911e2d2f140f79195def5935" + integrity sha512-B5ApMOnlruVOR7gisBaYwFX+L/AP7i/2oAahatssjPIBVDF6wTX1K7Qpa39E/nzsH8iYuL3krkYeUFIdO3EMUQ== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + ethers "^5.7.1" + js-sdsl "^4.1.4" + "@nomicfoundation/ethereumjs-statemanager@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.0.tgz#14a9d4e1c828230368f7ab520c144c34d8721e4b" @@ -1254,6 +1531,17 @@ ethereum-cryptography "0.1.3" functional-red-black-tree "^1.0.1" +"@nomicfoundation/ethereumjs-trie@6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.1.tgz#662c55f6b50659fd4b22ea9f806a7401cafb7717" + integrity sha512-A64It/IMpDVODzCgxDgAAla8jNjNtsoQZIzZUfIV5AY6Coi4nvn7+VReBn5itlxMiL2yaTlQr9TRWp3CSI6VoA== + dependencies: + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + "@types/readable-stream" "^2.3.13" + ethereum-cryptography "0.1.3" + readable-stream "^3.6.0" + "@nomicfoundation/ethereumjs-trie@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.0.tgz#dcfbe3be53a94bc061c9767a396c16702bc2f5b7" @@ -1264,6 +1552,18 @@ ethereum-cryptography "0.1.3" readable-stream "^3.6.0" +"@nomicfoundation/ethereumjs-tx@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.1.tgz#7629dc2036b4a33c34e9f0a592b43227ef4f0c7d" + integrity sha512-0HwxUF2u2hrsIM1fsasjXvlbDOq1ZHFV2dd1yGq8CA+MEYhaxZr8OTScpVkkxqMwBcc5y83FyPl0J9MZn3kY0w== + dependencies: + "@chainsafe/ssz" "^0.9.2" + "@ethersproject/providers" "^5.7.2" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + ethereum-cryptography "0.1.3" + "@nomicfoundation/ethereumjs-tx@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.0.0.tgz#59dc7452b0862b30342966f7052ab9a1f7802f52" @@ -1274,6 +1574,15 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" ethereum-cryptography "0.1.3" +"@nomicfoundation/ethereumjs-util@9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.1.tgz#530cda8bae33f8b5020a8f199ed1d0a2ce48ec89" + integrity sha512-TwbhOWQ8QoSCFhV/DDfSmyfFIHjPjFBj957219+V3jTZYZ2rf9PmDtNOeZWAE3p3vlp8xb02XGpd0v6nTUPbsA== + dependencies: + "@chainsafe/ssz" "^0.10.0" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + ethereum-cryptography "0.1.3" + "@nomicfoundation/ethereumjs-util@^8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.0.tgz#deb2b15d2c308a731e82977aefc4e61ca0ece6c5" @@ -1282,6 +1591,25 @@ "@nomicfoundation/ethereumjs-rlp" "^4.0.0-beta.2" ethereum-cryptography "0.1.3" +"@nomicfoundation/ethereumjs-vm@7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.1.tgz#7d035e0993bcad10716c8b36e61dfb87fa3ca05f" + integrity sha512-rArhyn0jPsS/D+ApFsz3yVJMQ29+pVzNZ0VJgkzAZ+7FqXSRtThl1C1prhmlVr3YNUlfpZ69Ak+RUT4g7VoOuQ== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-blockchain" "7.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-evm" "2.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-statemanager" "2.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + debug "^4.3.3" + ethereum-cryptography "0.1.3" + mcl-wasm "^0.7.1" + rustbn.js "~0.2.0" + "@nomicfoundation/ethereumjs-vm@^6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.0.0.tgz#2bb50d332bf41790b01a3767ffec3987585d1de6" @@ -1370,6 +1698,57 @@ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.0" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.0" +"@nomiclabs/hardhat-docker@^2.0.0": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-docker/-/hardhat-docker-2.0.2.tgz#ae964be17951275a55859ff7358e9e7c77448846" + integrity sha512-XgGEpRT3wlA1VslyB57zyAHV+oll8KnV1TjwnxxC1tpAL04/lbdwpdO5KxInVN8irMSepqFpsiSkqlcnvbE7Ng== + dependencies: + dockerode "^2.5.8" + fs-extra "^7.0.1" + node-fetch "^2.6.0" + +"@nomiclabs/hardhat-ethers@^2.1.1": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz#b41053e360c31a32c2640c9a45ee981a7e603fe0" + integrity sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg== + +"@nomiclabs/hardhat-ethers@npm:hardhat-deploy-ethers@0.3.0-beta.13", hardhat-deploy-ethers@0.3.0-beta.13: + name "@nomiclabs/hardhat-ethers" + version "0.3.0-beta.13" + resolved "https://registry.yarnpkg.com/hardhat-deploy-ethers/-/hardhat-deploy-ethers-0.3.0-beta.13.tgz#b96086ff768ddf69928984d5eb0a8d78cfca9366" + integrity sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw== + +"@nomiclabs/hardhat-etherscan@3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.3.tgz#c9dbaa4174edfa075a464a0e9142bc8710a2c4e2" + integrity sha512-UeNO97j0lwOHqX7mrH6SfQQBdXq1Ng6eFr7uJKuQOrq2UVTWGD70lE5QO4fAFVPz9ao+xlNpMyIqSR7+OaDR+Q== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@ethersproject/address" "^5.0.2" + cbor "^8.1.0" + chalk "^2.4.2" + debug "^4.1.1" + fs-extra "^7.0.1" + lodash "^4.17.11" + semver "^6.3.0" + table "^6.8.0" + undici "^5.4.0" + +"@nomiclabs/hardhat-solhint@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-solhint/-/hardhat-solhint-2.0.1.tgz#62896569d10c95a17cefab0229701cfffd19246f" + integrity sha512-SrTLufY21t78KLpJL5fS6gHIsCwVv0yWsHp1aQOPL1qwRWpe0Mnh5wb2YzBHd3Dbr/KzUYys+j2ui0PsSVU9pg== + dependencies: + solhint "^2.0.0" + +"@nomiclabs/hardhat-waffle@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.3.tgz#9c538a09c5ed89f68f5fd2dc3f78f16ed1d6e0b1" + integrity sha512-049PHSnI1CZq6+XTbrMbMv5NaL7cednTfPenx02k3cEh8wBMLa6ys++dBETJa6JjfwgA9nBhhHQ173LJv6k2Pg== + dependencies: + "@types/sinon-chai" "^3.2.3" + "@types/web3" "1.0.19" + "@openzeppelin/contracts-upgradeable@4.7.3": version "4.7.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.7.3.tgz#f1d606e2827d409053f3e908ba4eb8adb1dd6995" @@ -1380,6 +1759,16 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.1.tgz#363f7dd08f25f8f77e16d374350c3d6b43340a7a" integrity sha512-1wTv+20lNiC0R07jyIAbHU7TNHKRwGiTGRfiNnA8jOWjKT98g5OgLpYWOi40Vgpk8SPLA9EvfJAbAeIyVn+7Bw== +"@openzeppelin/contracts@3.4.1-solc-0.7-2": + version "3.4.1-solc-0.7-2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.1-solc-0.7-2.tgz#371c67ebffe50f551c3146a9eec5fe6ffe862e92" + integrity sha512-tAG9LWg8+M2CMu7hIsqHPaTyG4uDzjr6mhvH96LvOpLZZj6tgzTluBt+LsCf1/QaYrlis6pITvpIaIhE+iZB+Q== + +"@openzeppelin/contracts@3.4.2-solc-0.7": + version "3.4.2-solc-0.7" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.2-solc-0.7.tgz#38f4dbab672631034076ccdf2f3201fab1726635" + integrity sha512-W6QmqgkADuFcTLzHL8vVoNBtkwjvQRpYIAom7KiUNoLKghyx3FgH0GBjt8NRvigV1ZmMOBllvE1By1C+bi8WpA== + "@openzeppelin/contracts@4.7.3": version "4.7.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.3.tgz#939534757a81f8d69cc854c7692805684ff3111e" @@ -1404,6 +1793,48 @@ bignumber.js "^9.0.2" ts-essentials "^9.1.2" +"@rari-capital/solmate@6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@rari-capital/solmate/-/solmate-6.2.0.tgz#4f70dc236606c27ec2cb1b4261dd830235d01fe4" + integrity sha512-g94F+Ra9ixyJyNgvnOIufNjUz488uEG0nxIEEtJ7+g+tA1XGUupRB2kB5b+VO7WYO26RNOVD2fW6xE4e14iWpg== + +"@resolver-engine/core@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" + integrity sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ== + dependencies: + debug "^3.1.0" + is-url "^1.2.4" + request "^2.85.0" + +"@resolver-engine/fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.3.3.tgz#fbf83fa0c4f60154a82c817d2fe3f3b0c049a973" + integrity sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports-fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz#4085db4b8d3c03feb7a425fbfcf5325c0d1e6c1b" + integrity sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA== + dependencies: + "@resolver-engine/fs" "^0.3.3" + "@resolver-engine/imports" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.3.3.tgz#badfb513bb3ff3c1ee9fd56073e3144245588bcc" + integrity sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + hosted-git-info "^2.6.0" + path-browserify "^1.0.0" + url "^0.11.0" + "@scure/base@~1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" @@ -1418,6 +1849,24 @@ "@noble/secp256k1" "~1.6.0" "@scure/base" "~1.1.0" +"@scure/bip32@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.0.tgz#6c8d980ef3f290987736acd0ee2e0f0d50068d87" + integrity sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q== + dependencies: + "@noble/curves" "~1.0.0" + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + +"@scure/bip32@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10" + integrity sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A== + dependencies: + "@noble/curves" "~1.1.0" + "@noble/hashes" "~1.3.1" + "@scure/base" "~1.1.0" + "@scure/bip39@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.0.tgz#92f11d095bae025f166bef3defcc5bf4945d419a" @@ -1426,6 +1875,22 @@ "@noble/hashes" "~1.1.1" "@scure/base" "~1.1.0" +"@scure/bip39@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.0.tgz#a207e2ef96de354de7d0002292ba1503538fc77b" + integrity sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" + integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + "@sentry/core@5.30.0": version "5.30.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" @@ -1540,6 +2005,191 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@sushiswap/abi@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@sushiswap/abi/-/abi-0.0.1.tgz#2bb8ab632e4a95ec2152603c489f88fcc8ffdf7d" + integrity sha512-J4zWyfZdFiDIBa28MV/yYmr9nmWDqX8CXVfUoLfg48RVUyqPsu57dKtEKiBqAO/xpl7d9ZciNcya0d09NXvm8w== + +"@sushiswap/amm@0.1.12": + version "0.1.12" + resolved "https://registry.yarnpkg.com/@sushiswap/amm/-/amm-0.1.12.tgz#e4ddd4e8dfc6eccb3b6dbd203557333db1d3d655" + integrity sha512-SvgRfKZnNxSUwocuUbQFfHi2VYysrgPVxGnDC7iOTVU+4mS27XcNUmWXeJ/qciQe/f6x7z/GNbbeXjM2ZdehVg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@sushiswap/chain" "0.1.2" + "@sushiswap/currency" "0.1.1" + "@sushiswap/math" "0.1.0" + "@sushiswap/tines" "1.0.8" + "@sushiswap/trident-core" "1.0.7" + "@sushiswap/types" "0.0.2" + "@sushiswap/v2-sdk" "0.0.8" + tiny-invariant "1.3.1" + tiny-warning "1.0.3" + zod "3.21.4" + +"@sushiswap/bentobox@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@sushiswap/bentobox/-/bentobox-1.0.1.tgz#a3fb265d66b28e4ddba290182ccf2f3e565a7da7" + integrity sha512-Wg3QVWie0YIVHch0oE0y6Dy+qpX/e5fsiF0MSaXgYNhTki1Uc5IPTcJ2wCISbkMjDpEP+HiLWivftNdc7gc+aw== + +"@sushiswap/chain@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@sushiswap/chain/-/chain-0.1.2.tgz#dc164887ace62edd781a8d9afac1054cbdefd582" + integrity sha512-A0S5fYxYxUZu3UQj3AwekCRgjDQ8hzLRjc1p9XwV9i+0r9ZxAdXafWFrpQufDoXS0lfKd/4XiFh50LsbhvWA8A== + +"@sushiswap/currency@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@sushiswap/currency/-/currency-0.1.1.tgz#627b20155fbf40d76f4a930251c4bf088e3d93b3" + integrity sha512-AjzrYYUvpYabel13CmGBpDk+NHNkBIExTcLyZl1QBtDKkhWl/1239NU8WgEF04Pxx0UD1wK/FTCput2n5yK50Q== + dependencies: + "@ethersproject/address" "5.7.0" + "@ethersproject/units" "^5.7.0" + "@sushiswap/chain" "0.1.2" + "@sushiswap/math" "0.1.0" + lodash.flatmap "4.5.0" + tiny-invariant "1.3.1" + zod "3.21.4" + +"@sushiswap/hardhat-config@0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@sushiswap/hardhat-config/-/hardhat-config-0.1.3.tgz#33e7a457be3094716be7cffc3e5a37f8280f200b" + integrity sha512-lc+tPdmin2j3C/KtquoqsUZdQCIh7ibWThqfx0BMqixFwyBR3REp48JzN6hWmODKwQE8PKnYmldZ1GmZczKOMw== + dependencies: + "@matterlabs/hardhat-zksync-deploy" "0.6.2" + "@matterlabs/hardhat-zksync-solc" "0.3.14" + "@nomiclabs/hardhat-ethers" "npm:hardhat-deploy-ethers@0.3.0-beta.13" + "@nomiclabs/hardhat-etherscan" "3.1.3" + "@nomiclabs/hardhat-solhint" "2.0.1" + "@nomiclabs/hardhat-waffle" "2.0.3" + "@sushiswap/types" "0.0.2" + "@tenderly/hardhat-tenderly" "1.3.2" + "@typechain/ethers-v5" "10.1.1" + "@typechain/hardhat" "6.1.4" + dotenv "16.0.3" + ethereum-waffle "3.4.4" + hardhat-deploy "0.11.22" + hardhat-deploy-ethers "0.3.0-beta.13" + typechain "8.1.1" + +"@sushiswap/math@0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@sushiswap/math/-/math-0.1.0.tgz#e4821e81997a8acfcc11fdd55eccdd160cb308fe" + integrity sha512-bchOAQo7vWPHufXJQuk7+sWGxjhlbdlaI+kin3m3cLkUzKPPHqZxMwND4G9IpXsqEbko/DFrQL/M6a25gs7InA== + dependencies: + big.js "^6.1.1" + decimal.js-light "^2.5.1" + jsbi "^4.1.0" + tiny-invariant "^1.2.0" + toformat "^2.0.0" + +"@sushiswap/router-config@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sushiswap/router-config/-/router-config-2.0.0.tgz#5052f57472f1c9e72153995927ee4c72089c3b79" + integrity sha512-cVN20sur3EbC4GTxywuCVPovhXcuBh7hUMSFyhYhOQxhQGbvlPYot/+PX77UpYviTsJOTdo+ov2LyMT5AGdTHA== + +"@sushiswap/router@^0.0.12": + version "0.0.12" + resolved "https://registry.yarnpkg.com/@sushiswap/router/-/router-0.0.12.tgz#89d65dc04bfb971c5c9a987078cf8ee4ec92165c" + integrity sha512-53cPuNmZPDnt7u9l7q9CpoiJQHnOdtPMjnq1EsHKDh7Meb1pFav9zYrAFgCbn/5Np9Qs83/xxn77JtlGSh0ypw== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@sushiswap/abi" "0.0.1" + "@sushiswap/amm" "0.1.12" + "@sushiswap/bentobox" "1.0.1" + "@sushiswap/chain" "0.1.2" + "@sushiswap/currency" "0.1.1" + "@sushiswap/math" "0.1.0" + "@sushiswap/router-config" "2.0.0" + "@sushiswap/tines" "1.0.8" + "@sushiswap/trident-core" "1.0.7" + "@sushiswap/v2-sdk" "0.0.8" + "@sushiswap/v3-sdk" "1.0.9" + "@sushiswap/viem-config" "1.0.2" + date-fns "2.29.3" + ethers "5.7.2" + lodash.flatmap "^4.5.0" + node-fetch "2.6.6" + tiny-invariant "1.3.1" + tiny-warning "1.0.3" + viem "1.0.2" + zod "3.21.4" + +"@sushiswap/tines@1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@sushiswap/tines/-/tines-1.0.8.tgz#11e7a0ed3bffe7fb0dea4141811b44294f09f95a" + integrity sha512-se9CnYcjnsuDqf7pbEXfo7FYaLgjSrBjaEc/TvEd0r8bO/goQSHUwNqklA+i9DpzYSki72GT2G5+4r6OxnActA== + dependencies: + "@ethersproject/bignumber" "5.7.0" + "@sushiswap/currency" "0.1.1" + +"@sushiswap/trident-core@1.0.7": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@sushiswap/trident-core/-/trident-core-1.0.7.tgz#20c7691374332a0601e13fe1045189ae063d49b9" + integrity sha512-u2Z22726Y2hC8sx0jDj/lGMf2egFZ/uTctGUWrlUDb3KyT/LtxFVQOSYgaFw6GnRhunSfE0oOpHlYJNHEVYBpA== + dependencies: + "@openzeppelin/contracts" "4.7.3" + "@rari-capital/solmate" "6.2.0" + "@sushiswap/bentobox" "1.0.1" + "@sushiswap/currency" "0.1.1" + "@sushiswap/hardhat-config" "0.1.3" + "@sushiswap/types" "0.0.2" + +"@sushiswap/types@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@sushiswap/types/-/types-0.0.2.tgz#9088674d01afede9c3738f6a62a908976f8bc639" + integrity sha512-Aa4MnBFq/SK/F4zZlRXNpLcqza2RsE0mLxxv4+8an1Dtr7l26lyWd+3PbVrtv1bA7OVmBXoqJhTrQKA8w3zEPA== + +"@sushiswap/v2-sdk@0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@sushiswap/v2-sdk/-/v2-sdk-0.0.8.tgz#14c0460c8f3164314cd9d9b574815e1d365e7c06" + integrity sha512-o1h7uDkUOauNiVh2DUFZEfp5ASqt7muOs25VQxRV966YHYwDPs9SZEI9fVXn6a04jTWWOVbPP8BnDLYH+MRh8Q== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@sushiswap/chain" "0.1.2" + "@sushiswap/currency" "0.1.1" + "@sushiswap/math" "0.1.0" + tiny-invariant "1.3.1" + tiny-warning "1.0.3" + zod "3.21.4" + +"@sushiswap/v3-sdk@1.0.9": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@sushiswap/v3-sdk/-/v3-sdk-1.0.9.tgz#79d280a00b100886d8dee52dcfd0b9c2a115b32c" + integrity sha512-Lb5aJTy4atLUd8vtCQH3ZgAxFFefeZ26JqEeYlCrH2ayh73bs2CPET7E3ZKvKEOD1g2l67bvHfWesbueCyurVg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/address" "5.7.0" + "@ethersproject/bignumber" "5.7.0" + "@ethersproject/solidity" "5.7.0" + "@sushiswap/amm" "0.1.12" + "@sushiswap/chain" "0.1.2" + "@sushiswap/currency" "0.1.1" + "@sushiswap/math" "0.1.0" + "@sushiswap/tines" "1.0.8" + "@uniswap/swap-router-contracts" "1.3.0" + "@uniswap/v3-core" "1.0.1" + "@uniswap/v3-periphery" "1.4.3" + "@uniswap/v3-staker" "1.0.2" + tiny-invariant "1.3.1" + tiny-warning "1.0.3" + zod "3.21.4" + +"@sushiswap/viem-config@1.0.2", "@sushiswap/viem-config@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@sushiswap/viem-config/-/viem-config-1.0.2.tgz#82112a2cdddc63fa902f6d568d899423402200b8" + integrity sha512-IpZ/vmgs67LeR4eqrfIF/Og/taFGD9NW3E12kzS2sFyJJ0uZQP/hpqLNtNmXTPg9oV6/JCtnTGL+6Ic0EUd+gA== + dependencies: + "@sushiswap/chain" "0.1.2" + "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -1554,6 +2204,21 @@ dependencies: defer-to-connect "^2.0.0" +"@tenderly/hardhat-tenderly@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@tenderly/hardhat-tenderly/-/hardhat-tenderly-1.3.2.tgz#9ee69ba1fb8650d18160c637e8e487d938f6dcea" + integrity sha512-0kE0gv8RIu0N5JXKCCfYcydsMgGgj8z3qCvbeD/ynBKwOBvbFB+NZFRyTHNopbeaUKO7Q3bGFau8vS1B0EWS0g== + dependencies: + "@ethersproject/bignumber" "^5.7.0" + "@nomiclabs/hardhat-ethers" "^2.1.1" + axios "^0.27.2" + ethers "^5.7.0" + fs-extra "^10.1.0" + hardhat "^2.10.2" + hardhat-deploy "^0.11.14" + js-yaml "^4.1.0" + tenderly "^0.0.3" + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -1574,6 +2239,28 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== +"@typechain/ethers-v5@10.1.1": + version "10.1.1" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-10.1.1.tgz#fdb527d8854129cea5f139d76c6c6e1c9bb040ec" + integrity sha512-o6nffJBxwmeX1ZiZpdnP/tqGd/7M7iYvQC88ZXaFFoyAGh7eYncynzVjOJV0XmaKzAc6puqyqZrnva+gJbk4sw== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + +"@typechain/ethers-v5@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" + integrity sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw== + dependencies: + ethers "^5.0.2" + +"@typechain/hardhat@6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-6.1.4.tgz#da930bf17bdae5e0996b86d37992c6c58b8a49c8" + integrity sha512-S8k5d1Rjc+plwKpkorlifmh72M7Ki0XNUOVVLtdbcA/vLaEkuqZSJFdddpBgS5QxiJP+6CbRa/yO6EVTE2+fMQ== + dependencies: + fs-extra "^9.1.0" + "@types/async-eventemitter@^0.2.1": version "0.2.1" resolved "https://registry.yarnpkg.com/@types/async-eventemitter/-/async-eventemitter-0.2.1.tgz#f8e6280e87e8c60b2b938624b0a3530fb3e24712" @@ -1624,6 +2311,13 @@ dependencies: "@babel/types" "^7.3.0" +"@types/bn.js@*", "@types/bn.js@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== + dependencies: + "@types/node" "*" + "@types/bn.js@^4.11.0", "@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": version "4.11.6" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" @@ -1631,13 +2325,6 @@ dependencies: "@types/node" "*" -"@types/bn.js@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" - integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== - dependencies: - "@types/node" "*" - "@types/body-parser@*": version "1.19.2" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" @@ -1656,6 +2343,11 @@ "@types/node" "*" "@types/responselike" "*" +"@types/chai@*": + version "4.3.5" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b" + integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== + "@types/connect@*": version "3.4.35" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" @@ -1758,6 +2450,21 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== +"@types/mkdirp@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" + integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== + dependencies: + "@types/node" "*" + +"@types/node-fetch@^2.5.5": + version "2.6.4" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" + integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*": version "18.11.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.3.tgz#78a6d7ec962b596fc2d2ec102c4dd3ef073fea6a" @@ -1780,6 +2487,11 @@ dependencies: "@types/node" "*" +"@types/prettier@^2.1.1": + version "2.7.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" + integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== + "@types/prettier@^2.1.5": version "2.7.1" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e" @@ -1790,7 +2502,7 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== -"@types/qs@*": +"@types/qs@*", "@types/qs@^6.9.7": version "6.9.7" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== @@ -1809,6 +2521,21 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/readable-stream@^2.3.13": + version "2.3.15" + resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.15.tgz#3d79c9ceb1b6a57d5f6e6976f489b9b5384321ae" + integrity sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ== + dependencies: + "@types/node" "*" + safe-buffer "~5.1.1" + +"@types/resolve@^0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" + integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== + dependencies: + "@types/node" "*" + "@types/responselike@*", "@types/responselike@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" @@ -1841,16 +2568,49 @@ "@types/mime" "*" "@types/node" "*" +"@types/sinon-chai@^3.2.3": + version "3.2.9" + resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.9.tgz#71feb938574bbadcb176c68e5ff1a6014c5e69d4" + integrity sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ== + dependencies: + "@types/chai" "*" + "@types/sinon" "*" + +"@types/sinon@*": + version "10.0.16" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.16.tgz#4bf10313bd9aa8eef1e50ec9f4decd3dd455b4d3" + integrity sha512-j2Du5SYpXZjJVJtXBokASpPRj+e2z+VUhCPHmM6WMfe3dpHu6iVKJMU6AiBcMp/XTAYnEj6Wc1trJUWwZ0QaAQ== + dependencies: + "@types/sinonjs__fake-timers" "*" + +"@types/sinonjs__fake-timers@*": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz#bf2e02a3dbd4aecaf95942ecd99b7402e03fad5e" + integrity sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA== + "@types/stack-utils@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== +"@types/underscore@*": + version "1.11.7" + resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.7.tgz#fa644dd948a34b4e102e6d31c30823ecba6ba9c7" + integrity sha512-uXFrH3+/R8AkckdYPJdmJm537rAOWOUt4DW3ni2l2GdXe1YrdREqab6lqsq1hm76xEihV39/qTxKIevNpZw2Zg== + "@types/uuid@^9.0.1": version "9.0.2" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.2.tgz#ede1d1b1e451548d44919dc226253e32a6952c4b" integrity sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ== +"@types/web3@1.0.19": + version "1.0.19" + resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.0.19.tgz#46b85d91d398ded9ab7c85a5dd57cb33ac558924" + integrity sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A== + dependencies: + "@types/bn.js" "*" + "@types/underscore" "*" + "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" @@ -1953,12 +2713,99 @@ "@typescript-eslint/types" "5.47.0" eslint-visitor-keys "^3.3.0" -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== +"@uniswap/lib@^4.0.1-alpha": + version "4.0.1-alpha" + resolved "https://registry.yarnpkg.com/@uniswap/lib/-/lib-4.0.1-alpha.tgz#2881008e55f075344675b3bca93f020b028fbd02" + integrity sha512-f6UIliwBbRsgVLxIaBANF6w09tYqc6Y/qXdsrbEmXHyFA7ILiKrIwRFXe1yOg8M3cksgVsO9N7yuL2DdCGQKBA== + +"@uniswap/swap-router-contracts@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@uniswap/swap-router-contracts/-/swap-router-contracts-1.3.0.tgz#8d555ca6d74b888d6e02a26ebb806ce315605f1f" + integrity sha512-iKvCuRkHXEe0EMjOf8HFUISTIhlxI57kKFllf3C3PUIE0HmwxrayyoflwAz5u/TRsFGYqJ9IjX2UgzLCsrNa5A== dependencies: - event-target-shim "^5.0.0" + "@openzeppelin/contracts" "3.4.2-solc-0.7" + "@uniswap/v2-core" "1.0.1" + "@uniswap/v3-core" "1.0.0" + "@uniswap/v3-periphery" "1.4.1" + dotenv "^14.2.0" + hardhat-watcher "^2.1.1" + +"@uniswap/v2-core@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@uniswap/v2-core/-/v2-core-1.0.1.tgz#af8f508bf183204779938969e2e54043e147d425" + integrity sha512-MtybtkUPSyysqLY2U210NBDeCHX+ltHt3oADGdjqoThZaFRDKwM6k1Nb3F0A3hk5hwuQvytFWhrWHOEq6nVJ8Q== + +"@uniswap/v3-core@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.0.tgz#6c24adacc4c25dceee0ba3ca142b35adbd7e359d" + integrity sha512-kSC4djMGKMHj7sLMYVnn61k9nu+lHjMIxgg9CDQT+s2QYLoA56GbSK9Oxr+qJXzzygbkrmuY6cwgP6cW2JXPFA== + +"@uniswap/v3-core@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.1.tgz#b6d2bdc6ba3c3fbd610bdc502395d86cd35264a0" + integrity sha512-7pVk4hEm00j9tc71Y9+ssYpO6ytkeI0y7WE9P6UcmNzhxPePwyAxImuhVsTqWK9YFvzgtvzJHi64pBl4jUzKMQ== + +"@uniswap/v3-periphery@1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.4.1.tgz#b90f08b7386163c0abfd7258831caef6339c7862" + integrity sha512-Ab0ZCKOQrQMKIcpBTezTsEhWfQjItd0TtkCG8mPhoQu+wC67nPaf4hYUhM6wGHeFUmDiYY5MpEQuokB0ENvoTg== + dependencies: + "@openzeppelin/contracts" "3.4.2-solc-0.7" + "@uniswap/lib" "^4.0.1-alpha" + "@uniswap/v2-core" "1.0.1" + "@uniswap/v3-core" "1.0.0" + base64-sol "1.0.1" + hardhat-watcher "^2.1.1" + +"@uniswap/v3-periphery@1.4.3", "@uniswap/v3-periphery@^1.0.1": + version "1.4.3" + resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.4.3.tgz#a6da4632dbd46b139cc13a410e4ec09ad22bd19f" + integrity sha512-80c+wtVzl5JJT8UQskxVYYG3oZb4pkhY0zDe0ab/RX4+8f9+W5d8wI4BT0wLB0wFQTSnbW+QdBSpkHA/vRyGBA== + dependencies: + "@openzeppelin/contracts" "3.4.2-solc-0.7" + "@uniswap/lib" "^4.0.1-alpha" + "@uniswap/v2-core" "1.0.1" + "@uniswap/v3-core" "1.0.0" + base64-sol "1.0.1" + +"@uniswap/v3-staker@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@uniswap/v3-staker/-/v3-staker-1.0.2.tgz#febad4905903032bb114ab58138c2d5200c87a3c" + integrity sha512-+swIh/yhY9GQGyQxT4Gz54aXYLK+uc3qsmIvaAX+FjvhcL9TGOvS9tXbQsCZM4AJW63vj6TLsmHIjGMIePL1BQ== + dependencies: + "@openzeppelin/contracts" "3.4.1-solc-0.7-2" + "@uniswap/v3-core" "1.0.0" + "@uniswap/v3-periphery" "^1.0.1" + +"@wagmi/chains@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-1.1.0.tgz#d351b3dc6f472b167f180721f46f6098b6c1585b" + integrity sha512-pWZlxBk0Ql8E7DV8DwqlbBpOyUdaG9UDlQPBxJNALuEK1I0tbQ3AVvSDnlsEIt06UPmPo5o27gzs3hwPQ/A+UA== + +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + +JSONStream@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" + integrity sha512-mn0KSip7N4e0UDPZHnqDsHECo5uGQrixQKnAskOM1BIB8hd7QKbd6il8IPRPudPHOeHiECoCFqhyMaRO9+nWyA== + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +abitype@0.8.7: + version "0.8.7" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.8.7.tgz#e4b3f051febd08111f486c0cc6a98fa72d033622" + integrity sha512-wQ7hV8Yg/yKmGyFpqrNZufCxbszDe5es4AZGYPBitocfSqXtjrTG9JMWFcc4N30ukl2ve48aBTwt7NJxVQdU3w== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" abortcontroller-polyfill@^1.1.9: version "1.7.5" @@ -1978,6 +2825,34 @@ abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: module-error "^1.0.1" queue-microtask "^1.2.3" +abstract-leveldown@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" + integrity sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^2.4.1, abstract-leveldown@~2.7.1: + version "2.7.2" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" + integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz#f7128e1f86ccabf7d2893077ce5d06d798e386c6" + integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@~2.6.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" + integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== + dependencies: + xtend "~4.0.0" + accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -1986,7 +2861,7 @@ accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-jsx@^5.3.2: +acorn-jsx@^5.0.0, acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== @@ -1996,6 +2871,11 @@ acorn-walk@^8.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== +acorn@^6.0.7: + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== + acorn@^8.4.1: version "8.8.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" @@ -2016,6 +2896,11 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== +aes-js@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" + integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -2031,7 +2916,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.6.1, ajv@^6.9.1: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2041,6 +2926,16 @@ ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.0.1: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -2051,6 +2946,11 @@ ansi-colors@^4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -2058,12 +2958,32 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: dependencies: type-fest "^0.21.3" +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== + +ansi-regex@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + ansi-regex@^5.0.0, ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^3.2.1: +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -2082,6 +3002,11 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== +antlr4@4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.7.1.tgz#69984014f096e9e775f53dd9744bf994d8959773" + integrity sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ== + anymatch@^3.0.3: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" @@ -2115,6 +3040,53 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== + +array-back@^1.0.3, array-back@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" + integrity sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw== + dependencies: + typical "^2.6.0" + +array-back@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" + integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== + dependencies: + typical "^2.6.1" + +array-back@^3.0.1, array-back@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + +array-back@^4.0.1, array-back@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== + +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + array-differ@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" @@ -2141,6 +3113,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== + array.prototype.flat@^1.2.5: version "1.3.1" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" @@ -2151,6 +3128,29 @@ array.prototype.flat@^1.2.5: es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" +array.prototype.reduce@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" + integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + +arraybuffer.prototype.slice@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz#9b5ea3868a6eebc30273da577eb888381c0044bb" + integrity sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" + arrify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" @@ -2166,7 +3166,7 @@ asn1.js@^5.2.0: minimalistic-assert "^1.0.0" safer-buffer "^2.1.0" -asn1@~0.2.3: +asn1@^0.2.6, asn1@~0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== @@ -2183,7 +3183,22 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== -async-eventemitter@^0.2.4: +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async-eventemitter@^0.2.2, async-eventemitter@^0.2.4: version "0.2.4" resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== @@ -2195,7 +3210,19 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async@^2.4.0: +async@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" + integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== + dependencies: + lodash "^4.17.11" + +async@^1.4.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== + +async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: version "2.6.4" resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== @@ -2212,6 +3239,16 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + available-typed-arrays@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" @@ -2243,6 +3280,13 @@ axios@0.26.0: dependencies: follow-redirects "^1.14.8" +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + axios@^0.27.2: version "0.27.2" resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" @@ -2251,6 +3295,167 @@ axios@^0.27.2: follow-redirects "^1.14.9" form-data "^4.0.0" +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g== + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.0.14, babel-core@^6.26.0: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + +babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + integrity sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q== + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + integrity sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ== + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + integrity sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA== + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + integrity sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ== + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + integrity sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q== + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + integrity sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + integrity sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + integrity sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + integrity sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg== + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + integrity sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg== + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + integrity sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw== + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + integrity sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ== + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-jest@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.2.1.tgz#213c47e28072de11bdb98c9d29b89f2ab99664f1" @@ -2264,6 +3469,20 @@ babel-jest@^29.2.1: graceful-fs "^4.2.9" slash "^3.0.0" +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + integrity sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA== + dependencies: + babel-runtime "^6.22.0" + babel-plugin-istanbul@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" @@ -2285,6 +3504,244 @@ babel-plugin-jest-hoist@^29.2.0: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + integrity sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw== + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + integrity sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ== + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + integrity sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ== + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + integrity sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw== + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + integrity sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + integrity sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + integrity sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw== + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + integrity sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag== + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + integrity sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw== + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + integrity sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + integrity sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + integrity sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + integrity sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg== + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + integrity sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + integrity sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA== + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + integrity sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg== + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + integrity sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw== + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + integrity sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA== + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + integrity sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ== + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + integrity sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + integrity sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + integrity sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ== + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + integrity sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + integrity sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw== + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + integrity sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ== + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + integrity sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ== + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + integrity sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg== + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + integrity sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw== + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -2303,6 +3760,42 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" +babel-preset-env@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^3.2.6" + invariant "^2.2.2" + semver "^5.3.0" + babel-preset-jest@^29.2.0: version "29.2.0" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz#3048bea3a1af222e3505e4a767a974c95a7620dc" @@ -2311,6 +3804,83 @@ babel-preset-jest@^29.2.0: babel-plugin-jest-hoist "^29.2.0" babel-preset-current-node-syntax "^1.0.0" +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + integrity sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A== + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + integrity sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg== + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA== + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g== + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babelify@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" + integrity sha512-vID8Fz6pPN5pJMdlUnNFSfrlcx5MUule4k9aKs/zbZPyXxMTcRrB0M4Tarw22L8afr8eYSWxDPYCob3TdrqtlA== + dependencies: + babel-core "^6.0.14" + object-assign "^4.0.0" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +backoff@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" + integrity sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA== + dependencies: + precond "0.2" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -2328,7 +3898,25 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -bcrypt-pbkdf@^1.0.0: +base64-sol@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/base64-sol/-/base64-sol-1.0.1.tgz#91317aa341f0bc763811783c5729f1c2574600f6" + integrity sha512-ld3cCNMeXt4uJXmLZBHFGMvVpK9KsLVEhPpFRXnvSVAqABKbuNZg/+dsq3NuM+wxFLb/UrVkz7m1ciWmkMfTbg== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== @@ -2340,6 +3928,11 @@ bech32@1.1.4: resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== +big.js@^6.1.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.2.1.tgz#7205ce763efb17c2e41f26f121c420c6a7c2744f" + integrity sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ== + bigint-crypto-utils@^3.0.23: version "3.1.8" resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.1.8.tgz#e2e0f40cf45488f9d7f0e32ff84152aa73819d5d" @@ -2372,12 +3965,40 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== +bip39@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" + integrity sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA== + dependencies: + create-hash "^1.1.0" + pbkdf2 "^3.0.9" + randombytes "^2.0.1" + safe-buffer "^5.0.1" + unorm "^1.3.3" + +bl@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" + integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + blakejs@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== -bluebird@^3.5.0: +bluebird@^3.5.0, bluebird@^3.5.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -2387,7 +4008,7 @@ bn.js@4.11.6: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.8.0: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== @@ -2430,6 +4051,22 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -2511,6 +4148,14 @@ browserify-sign@^4.0.0: readable-stream "^3.6.0" safe-buffer "^5.2.0" +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + browserslist@^4.21.3: version "4.21.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" @@ -2551,6 +4196,24 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -2571,7 +4234,14 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== -buffer@^5.0.5, buffer@^5.5.0, buffer@^5.6.0: +buffer-xor@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" + integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== + dependencies: + safe-buffer "^5.1.1" + +buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -2599,6 +4269,11 @@ bufio@^1.0.7: resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.2.0.tgz#b9ad1c06b0d9010363c387c39d2810a7086d143f" integrity sha512-UlFk8z/PwdhYQTXSQQagwGAdtRI83gib2n4uy4rQnenxUM2yQi8lBDzF230BNk+3wAoZDxYRoBwVVUPgHa9MCA== +buildcheck@~0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.6.tgz#89aa6e417cfd1e2196e3f8fe915eb709d2fe4238" + integrity sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A== + busboy@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -2611,6 +4286,36 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +bytewise-core@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" + integrity sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA== + dependencies: + typewise-core "^1.2" + +bytewise@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" + integrity sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ== + dependencies: + bytewise-core "^1.2.2" + typewise "^1.0.3" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + cacheable-lookup@^5.0.3: version "5.0.4" resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" @@ -2642,7 +4347,15 @@ cacheable-request@^7.0.2: normalize-url "^6.0.1" responselike "^2.0.0" -call-bind@^1.0.0, call-bind@^1.0.2: +cachedown@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cachedown/-/cachedown-1.0.0.tgz#d43f036e4510696b31246d7db31ebf0f7ac32d15" + integrity sha512-t+yVk82vQWCJF3PsWHMld+jhhjkkWjcAzz8NbFx1iULOXWl8Tm/FdM4smZNVw3MRr0X+lVTx9PKzvEn4Ng19RQ== + dependencies: + abstract-leveldown "^2.4.1" + lru-cache "^3.2.0" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== @@ -2650,6 +4363,25 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -2663,6 +4395,11 @@ camel-case@^4.1.2: pascal-case "^3.1.2" tslib "^2.0.3" +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg== + camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -2673,6 +4410,11 @@ camelcase@^6.0.0, camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== +caniuse-lite@^1.0.30000844: + version "1.0.30001522" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001522.tgz#44b87a406c901269adcdb834713e23582dd71856" + integrity sha512-TKiyTVZxJGhsTszLuzb+6vUZSjVOAhClszBr2Ta2k9IwtNBT/4dzmL6aywt0HCgEZlmwJzXJd8yNiob6HgwTRg== + caniuse-lite@^1.0.30001400: version "1.0.30001423" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001423.tgz#57176d460aa8cd85ee1a72016b961eb9aca55d91" @@ -2687,6 +4429,11 @@ capital-case@^1.0.4: tslib "^2.0.3" upper-case-first "^2.0.2" +case@^1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" + integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -2697,6 +4444,13 @@ catering@^2.1.0, catering@^2.1.1: resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== +cbor@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" + integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== + dependencies: + nofilter "^3.1.0" + chai@^4.3.4: version "4.3.7" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" @@ -2710,7 +4464,26 @@ chai@^4.3.4: pathval "^1.1.1" type-detect "^4.0.5" -chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.2: +chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2727,14 +4500,6 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0, chalk@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - change-case@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" @@ -2758,12 +4523,24 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== -chokidar@3.5.3, chokidar@^3.4.0: +checkpoint-store@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" + integrity sha512-J/NdY2WvIx654cc6LWSq/IYFFCUf75fFTgwzFnmbqyORH4MwgiQCgswLLKBGzmsyTI5V7i5bp/So6sMbDWhedg== + dependencies: + functional-red-black-tree "^1.0.1" + +chokidar@3.5.3, chokidar@^3.4.0, chokidar@^3.5.2, chokidar@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -2778,7 +4555,7 @@ chokidar@3.5.3, chokidar@^3.4.0: optionalDependencies: fsevents "~2.3.2" -chownr@^1.1.4: +chownr@^1.0.1, chownr@^1.1.1, chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== @@ -2822,6 +4599,16 @@ class-is@^1.1.0: resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + classic-level@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.2.0.tgz#2d52bdec8e7a27f534e67fdeb890abef3e643c27" @@ -2838,6 +4625,36 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== + dependencies: + restore-cursor "^2.0.0" + +cli-table3@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + +cli-width@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" + integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w== + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -2863,7 +4680,7 @@ clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" -clone@2.x: +clone@2.1.2, clone@2.x, clone@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== @@ -2873,11 +4690,24 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== + collect-v8-coverage@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -2914,16 +4744,70 @@ command-exists@^1.2.8: resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== +command-line-args@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46" + integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== + dependencies: + array-back "^2.0.0" + find-replace "^1.0.3" + typical "^2.6.1" + +command-line-args@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== + dependencies: + array-back "^3.1.0" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + +command-line-usage@^6.1.0: + version "6.1.3" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" + integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== + dependencies: + array-back "^4.0.2" + chalk "^2.4.2" + table-layout "^1.0.2" + typical "^5.2.0" + +commander@2.18.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" + integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== + commander@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== +commander@^9.4.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +concat-stream@^1.5.1, concat-stream@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + confusing-browser-globals@^1.0.10: version "1.0.11" resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" @@ -2959,7 +4843,7 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== -convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== @@ -2984,11 +4868,31 @@ cookiejar@^2.1.1: resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== -core-util-is@1.0.2: - version "1.0.2" +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== + +core-js-pure@^3.0.1: + version "3.32.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.32.1.tgz#5775b88f9062885f67b6d7edce59984e89d276f3" + integrity sha512-f52QZwkFVDPf7UEQZGHKx6NYxsxmVGJe5DIvbzOdRMJlmT6yv0KDjR8rmy3ngr/t5wU54c7Sp/qIJH0ppbhVpQ== + +core-js@^2.4.0, core-js@^2.5.0: + version "2.6.12" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + +core-util-is@1.0.2: + version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + cors@^2.8.1: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" @@ -2997,6 +4901,24 @@ cors@^2.8.1: object-assign "^4" vary "^1" +cosmiconfig@^5.0.7: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +cpu-features@~0.0.8: + version "0.0.9" + resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.9.tgz#5226b92f0f1c63122b0a3eb84cb8335a4de499fc" + integrity sha512-AKjgn2rP2yJyfbepsmLfiYcmtNn/2eUvocUyM/09yB0YDiz39HteK/5/T4Onf0pmdYDMgkBoGvRLvEguzyL7wQ== + dependencies: + buildcheck "~0.0.6" + nan "^2.17.0" + crc-32@^1.2.0: version "1.2.2" resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" @@ -3038,6 +4960,14 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-fetch@^2.1.0, cross-fetch@^2.1.1: + version "2.2.6" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.6.tgz#2ef0bb39a24ac034787965c457368a28730e220a" + integrity sha512-9JZz+vXCmfKUZ68zAptS7k4Nu8e2qcibe7WVZYps7sAgk5R8GYTc+T1WR0v1rlP9HxgARmOX1UTIJZFytajpNA== + dependencies: + node-fetch "^2.6.7" + whatwg-fetch "^2.0.4" + cross-fetch@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" @@ -3045,6 +4975,17 @@ cross-fetch@^3.1.5: dependencies: node-fetch "2.6.7" +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -3096,37 +5037,59 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +date-fns@2.29.3: + version "2.29.3" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" + integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== + date-format@^4.0.13, date-format@^4.0.14: version "4.0.14" resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.14.tgz#7a8e584434fb169a521c8b7aa481f355810d9400" integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg== -debug@2.6.9, debug@^2.2.0, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@4, debug@4.3.4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^3.2.7: +debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + decamelize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== +decimal.js-light@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" + integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -3158,7 +5121,24 @@ deep-eql@^4.1.2: dependencies: type-detect "^4.0.0" -deep-is@^0.1.3: +deep-equal@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + +deep-extend@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -3178,6 +5158,26 @@ defer-to-connect@^2.0.0: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== +deferred-leveldown@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" + integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== + dependencies: + abstract-leveldown "~2.6.0" + +deferred-leveldown@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz#0b0570087827bf480a23494b398f04c128c19a20" + integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== + dependencies: + abstract-leveldown "~5.0.0" + inherits "^2.0.3" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + define-properties@^1.1.3, define-properties@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" @@ -3186,6 +5186,41 @@ define-properties@^1.1.3, define-properties@^1.1.4: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +define-properties@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +defined@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" + integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -3209,6 +5244,13 @@ destroy@1.2.0: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + integrity sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A== + dependencies: + repeating "^2.0.0" + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -3255,6 +5297,44 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +docker-modem@^1.0.8: + version "1.0.9" + resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-1.0.9.tgz#a1f13e50e6afb6cf3431b2d5e7aac589db6aaba8" + integrity sha512-lVjqCSCIAUDZPAZIeyM125HXfNvOmYYInciphNrLrylUtKyW66meAjSPXWchKVzoIYZx69TPnAepVSSkeawoIw== + dependencies: + JSONStream "1.3.2" + debug "^3.2.6" + readable-stream "~1.0.26-4" + split-ca "^1.0.0" + +docker-modem@^3.0.0: + version "3.0.8" + resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-3.0.8.tgz#ef62c8bdff6e8a7d12f0160988c295ea8705e77a" + integrity sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ== + dependencies: + debug "^4.1.1" + readable-stream "^3.5.0" + split-ca "^1.0.1" + ssh2 "^1.11.0" + +dockerode@^2.5.8: + version "2.5.8" + resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-2.5.8.tgz#1b661e36e1e4f860e25f56e0deabe9f87f1d0acc" + integrity sha512-+7iOUYBeDTScmOmQqpUYQaE7F4vvIt6+gIZNHWhqAQEI887tiPFB9OvXI/HzQYqfUNvukMK+9myLW63oTJPZpw== + dependencies: + concat-stream "~1.6.2" + docker-modem "^1.0.8" + tar-fs "~1.16.3" + +dockerode@^3.3.4: + version "3.3.5" + resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-3.3.5.tgz#7ae3f40f2bec53ae5e9a741ce655fff459745629" + integrity sha512-/0YNa3ZDNeLr/tSckmD69+Gq+qVNhvKfAHNeZJBnp7EOP6RGKV8ORrJHkUn20So5wU+xxT7+1n5u8PjHbfjbSA== + dependencies: + "@balena/dockerignore" "^1.0.2" + docker-modem "^3.0.0" + tar-fs "~2.0.1" + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -3287,6 +5367,23 @@ dotenv@16.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411" integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q== +dotenv@16.0.3: + version "16.0.3" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" + integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== + +dotenv@^14.2.0: + version "14.3.2" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-14.3.2.tgz#7c30b3a5f777c79a3429cb2db358eef6751e8369" + integrity sha512-vwEppIphpFdvaMCaHfCEv9IgwcxMljMw2TnAQBB4VWPvzXQLTb82jwmdOKzlEVUL3gNFT4l4TPKO+Bn+sqcrVQ== + +dotignore@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" + integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== + dependencies: + minimatch "^3.0.4" + duplexer3@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" @@ -3305,6 +5402,11 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== +electron-to-chromium@^1.3.47: + version "1.4.500" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.500.tgz#7dd05fdfbe02ed34b9f6099cfe01407b473d5af7" + integrity sha512-P38NO8eOuWOKY1sQk5yE0crNtrjgjJj6r3NrbIKtG18KzCHmHE2Bt+aQA7/y0w3uYsHWxDa6icOohzjLJ4vJ4A== + electron-to-chromium@^1.4.251: version "1.4.284" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" @@ -3328,16 +5430,37 @@ emittery@^0.10.2: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933" integrity sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw== +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +encode-utf8@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== +encoding-down@5.0.4, encoding-down@~5.0.0: + version "5.0.4" + resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-5.0.4.tgz#1e477da8e9e9d0f7c8293d320044f8b2cd8e9614" + integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== + dependencies: + abstract-leveldown "^5.0.0" + inherits "^2.0.3" + level-codec "^9.0.0" + level-errors "^2.0.0" + xtend "^4.0.1" + encoding@^0.1.11: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" @@ -3345,7 +5468,7 @@ encoding@^0.1.11: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.1.0: +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -3359,12 +5482,27 @@ enquirer@^2.3.0: dependencies: ansi-colors "^4.1.1" +enquirer@^2.3.6: + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== + dependencies: + ansi-colors "^4.1.1" + strip-ansi "^6.0.1" + env-paths@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== -error-ex@^1.3.1: +errno@~0.1.1: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -3432,6 +5570,65 @@ es-abstract@^1.20.4: string.prototype.trimstart "^1.0.6" unbox-primitive "^1.0.2" +es-abstract@^1.21.2: + version "1.22.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc" + integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw== + dependencies: + array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.1" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.2.1" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.0" + safe-array-concat "^1.0.0" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" + typed-array-byte-offset "^1.0.0" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.10" + +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + es-shim-unscopables@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" @@ -3494,7 +5691,7 @@ escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== @@ -3553,6 +5750,14 @@ eslint-plugin-import@^2.26.0: resolve "^1.22.0" tsconfig-paths "^3.14.1" +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -3569,6 +5774,13 @@ eslint-scope@^7.1.1: esrecurse "^4.3.0" estraverse "^5.2.0" +eslint-utils@^1.3.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: + eslint-visitor-keys "^1.1.0" + eslint-utils@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" @@ -3576,6 +5788,11 @@ eslint-utils@^3.0.0: dependencies: eslint-visitor-keys "^2.0.0" +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + eslint-visitor-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" @@ -3586,6 +5803,48 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== +eslint@^5.6.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" + integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.9.1" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^4.0.3" + eslint-utils "^1.3.1" + eslint-visitor-keys "^1.0.0" + espree "^5.0.1" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^6.2.2" + js-yaml "^3.13.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.11" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^5.5.1" + strip-ansi "^4.0.0" + strip-json-comments "^2.0.1" + table "^5.2.3" + text-table "^0.2.0" + eslint@^8.30.0: version "8.30.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.30.0.tgz#83a506125d089eef7c5b5910eeea824273a33f50" @@ -3631,6 +5890,15 @@ eslint@^8.30.0: strip-json-comments "^3.1.0" text-table "^0.2.0" +espree@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" + integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== + dependencies: + acorn "^6.0.7" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" + espree@^9.4.0: version "9.4.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" @@ -3645,6 +5913,13 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== +esquery@^1.0.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + esquery@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" @@ -3652,7 +5927,7 @@ esquery@^1.4.0: dependencies: estraverse "^5.1.0" -esrecurse@^4.3.0: +esrecurse@^4.1.0, esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== @@ -3679,7 +5954,20 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -eth-ens-namehash@2.0.8: +eth-block-tracker@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz#95cd5e763c7293e0b1b2790a2a39ac2ac188a5e1" + integrity sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug== + dependencies: + eth-query "^2.1.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.3" + ethjs-util "^0.1.3" + json-rpc-engine "^3.6.0" + pify "^2.3.0" + tape "^4.6.3" + +eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" integrity sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw== @@ -3687,6 +5975,35 @@ eth-ens-namehash@2.0.8: idna-uts46-hx "^2.3.1" js-sha3 "^0.5.7" +eth-json-rpc-infura@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz#26702a821067862b72d979c016fd611502c6057f" + integrity sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw== + dependencies: + cross-fetch "^2.1.1" + eth-json-rpc-middleware "^1.5.0" + json-rpc-engine "^3.4.0" + json-rpc-error "^2.0.0" + +eth-json-rpc-middleware@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" + integrity sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q== + dependencies: + async "^2.5.0" + eth-query "^2.1.2" + eth-tx-summary "^3.1.2" + ethereumjs-block "^1.6.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.2" + ethereumjs-vm "^2.1.0" + fetch-ponyfill "^4.0.0" + json-rpc-engine "^3.6.0" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + tape "^4.6.3" + eth-lib@0.2.8: version "0.2.8" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" @@ -3708,6 +6025,60 @@ eth-lib@^0.1.26: ws "^3.0.0" xhr-request-promise "^0.1.2" +eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" + integrity sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA== + dependencies: + json-rpc-random-id "^1.0.0" + xtend "^4.0.1" + +eth-sig-util@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.0.tgz#75133b3d7c20a5731af0690c385e184ab942b97e" + integrity sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ== + dependencies: + buffer "^5.2.1" + elliptic "^6.4.0" + ethereumjs-abi "0.6.5" + ethereumjs-util "^5.1.1" + tweetnacl "^1.0.0" + tweetnacl-util "^0.15.0" + +eth-sig-util@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" + integrity sha512-iNZ576iTOGcfllftB73cPB5AN+XUQAT/T8xzsILsghXC1o8gJUqe3RHlcDqagu+biFpYQ61KQrZZJza8eRSYqw== + dependencies: + ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" + ethereumjs-util "^5.1.1" + +eth-tx-summary@^3.1.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" + integrity sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg== + dependencies: + async "^2.1.2" + clone "^2.0.0" + concat-stream "^1.5.1" + end-of-stream "^1.1.0" + eth-query "^2.0.2" + ethereumjs-block "^1.4.1" + ethereumjs-tx "^1.1.1" + ethereumjs-util "^5.0.1" + ethereumjs-vm "^2.6.0" + through2 "^2.0.3" + +ethashjs@~0.0.7: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.8.tgz#227442f1bdee409a548fb04136e24c874f3aa6f9" + integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw== + dependencies: + async "^2.1.2" + buffer-xor "^2.0.1" + ethereumjs-util "^7.0.2" + miller-rabin "^4.0.0" + ethereum-bloom-filters@^1.0.6: version "1.0.10" resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" @@ -3715,6 +6086,16 @@ ethereum-bloom-filters@^1.0.6: dependencies: js-sha3 "^0.8.0" +ethereum-common@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" + integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== + +ethereum-common@^0.0.18: + version "0.0.18" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" + integrity sha512-EoltVQTRNg2Uy4o84qpa2aXymXDJhxm7eos/ACOg0DG4baAbMjhbdAEsx9GeE8sC3XCxnYvrrzZDH8D8MtA2iQ== + ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" @@ -3746,6 +6127,16 @@ ethereum-cryptography@^1.0.3: "@scure/bip32" "1.1.0" "@scure/bip39" "1.1.0" +ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz#18fa7108622e56481157a5cb7c01c0c6a672eb67" + integrity sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug== + dependencies: + "@noble/curves" "1.1.0" + "@noble/hashes" "1.3.1" + "@scure/bip32" "1.3.1" + "@scure/bip39" "1.2.1" + ethereum-types@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/ethereum-types/-/ethereum-types-2.1.6.tgz#57d9d515fad86ab987c0f6962c4203be37da8579" @@ -3754,7 +6145,26 @@ ethereum-types@^2.1.6: "@types/node" "*" bignumber.js "~8.0.2" -ethereumjs-abi@^0.6.8: +ethereum-waffle@3.4.4: + version "3.4.4" + resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.4.tgz#1378b72040697857b7f5e8f473ca8f97a37b5840" + integrity sha512-PA9+jCjw4WC3Oc5ocSMBj5sXvueWQeAbvCA+hUlb6oFgwwKyq5ka3bWQ7QZcjzIX+TdFkxP4IbFmoY2D8Dkj9Q== + dependencies: + "@ethereum-waffle/chai" "^3.4.4" + "@ethereum-waffle/compiler" "^3.4.4" + "@ethereum-waffle/mock-contract" "^3.4.4" + "@ethereum-waffle/provider" "^3.4.4" + ethers "^5.0.1" + +ethereumjs-abi@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" + integrity sha512-rCjJZ/AE96c/AAZc6O3kaog4FhOsAViaysBxqJNy2+LHP0ttH0zkZ7nXdVHOAyt6lFwLO0nlCwWszysG/ao1+g== + dependencies: + bn.js "^4.10.0" + ethereumjs-util "^4.3.0" + +ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: version "0.6.8" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== @@ -3762,20 +6172,96 @@ ethereumjs-abi@^0.6.8: bn.js "^4.11.8" ethereumjs-util "^6.0.0" -ethereumjs-util@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" - integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== +"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": + version "0.6.8" + resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0" dependencies: - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "^0.1.3" + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-account@3.0.0, ethereumjs-account@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz#728f060c8e0c6e87f1e987f751d3da25422570a9" + integrity sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA== + dependencies: + ethereumjs-util "^6.0.0" + rlp "^2.2.1" + safe-buffer "^5.1.1" + +ethereumjs-account@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" + integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== + dependencies: + ethereumjs-util "^5.0.0" rlp "^2.0.0" safe-buffer "^5.1.1" -ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: +ethereumjs-block@2.2.2, ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.0, ethereumjs-block@~2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" + integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== + dependencies: + async "^2.0.1" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.1" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" + integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== + dependencies: + async "^2.0.1" + ethereum-common "0.2.0" + ethereumjs-tx "^1.2.2" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-blockchain@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz#30f2228dc35f6dcf94423692a6902604ae34960f" + integrity sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ== + dependencies: + async "^2.6.1" + ethashjs "~0.0.7" + ethereumjs-block "~2.2.2" + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.1.0" + flow-stoplight "^1.0.0" + level-mem "^3.0.1" + lru-cache "^5.1.1" + rlp "^2.2.2" + semaphore "^1.1.0" + +ethereumjs-common@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd" + integrity sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ== + +ethereumjs-common@^1.1.0, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" + integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== + +ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" + integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== + dependencies: + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.0.0" + +ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" + integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== + dependencies: + ethereum-common "^0.0.18" + ethereumjs-util "^5.0.0" + +ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0, ethereumjs-util@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== @@ -3788,7 +6274,31 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: ethjs-util "0.1.6" rlp "^2.2.3" -ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: +ethereumjs-util@^4.3.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz#f4bf9b3b515a484e3cc8781d61d9d980f7c83bd0" + integrity sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w== + dependencies: + bn.js "^4.8.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + rlp "^2.0.0" + +ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" + integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== + dependencies: + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "^0.1.3" + rlp "^2.0.0" + safe-buffer "^5.1.1" + +ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== @@ -3799,13 +6309,66 @@ ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: ethereum-cryptography "^0.1.3" rlp "^2.2.4" -ethers@^5.6.5, ethers@^5.7.0: - version "5.7.2" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" - integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== +ethereumjs-vm@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz#e885e861424e373dbc556278f7259ff3fca5edab" + integrity sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + core-js-pure "^3.0.1" + ethereumjs-account "^3.0.0" + ethereumjs-block "^2.2.2" + ethereumjs-blockchain "^4.0.3" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.2" + ethereumjs-util "^6.2.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + util.promisify "^1.0.0" + +ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" + integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + ethereumjs-account "^2.0.3" + ethereumjs-block "~2.2.0" + ethereumjs-common "^1.1.0" + ethereumjs-util "^6.0.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + +ethereumjs-wallet@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz#685e9091645cee230ad125c007658833991ed474" + integrity sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA== dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" + aes-js "^3.1.1" + bs58check "^2.1.2" + ethereum-cryptography "^0.1.3" + ethereumjs-util "^6.0.0" + randombytes "^2.0.6" + safe-buffer "^5.1.2" + scryptsy "^1.2.1" + utf8 "^3.0.0" + uuid "^3.3.2" + +ethers@5.7.2, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2, ethers@^5.5.3, ethers@^5.6.5, ethers@^5.7.0, ethers@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" + integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== + dependencies: + "@ethersproject/abi" "5.7.0" + "@ethersproject/abstract-provider" "5.7.0" "@ethersproject/abstract-signer" "5.7.0" "@ethersproject/address" "5.7.0" "@ethersproject/base64" "5.7.0" @@ -3876,6 +6439,11 @@ eventemitter3@4.0.4: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== +events@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" @@ -3919,6 +6487,19 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + expect@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/expect/-/expect-29.2.1.tgz#25752d0df92d3daa5188dc8804de1f30759658cf" @@ -3930,7 +6511,7 @@ expect@^29.2.1: jest-message-util "^29.2.1" jest-util "^29.2.1" -express@^4.14.0, express@^4.18.2: +express@^4.14.0, express@^4.18.1, express@^4.18.2: version "4.18.2" resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== @@ -3974,11 +6555,49 @@ ext@^1.1.2: dependencies: type "^2.7.2" +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -3989,11 +6608,23 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== +fake-merkle-patricia-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" + integrity sha512-Tgq37lkc9pUIgIKw5uitNUKcgcYL3R6JvXtKQbOf/ZSavXbidsksgp/pAY6p//uhw0I4yoMsvTSovvVIsk/qxA== + dependencies: + checkpoint-store "^1.1.0" + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" @@ -4010,7 +6641,7 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-sta resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6: +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== @@ -4029,6 +6660,27 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fetch-ponyfill@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" + integrity sha512-knK9sGskIg2T7OnYLdZ2hZXn0CtDrAIBxYQLpmEf0BqfdWnwmM1weccUl5+4EdA44tzNSFAuxITPbXtPehUB3g== + dependencies: + node-fetch "~1.7.1" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -4036,6 +6688,16 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -4056,6 +6718,21 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" +find-replace@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" + integrity sha512-KrUnjzDCD9426YnCP56zGYy/eieTnhtK6Vn++j+JJzmlsWWwEkDnsyVF575spT6HJ6Ow9tlbT3TQTDsa+O4UWA== + dependencies: + array-back "^1.0.4" + test-value "^2.1.0" + +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -4064,6 +6741,14 @@ find-up@5.0.0, find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA== + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -4079,6 +6764,30 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-yarn-workspace-root@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" + integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== + dependencies: + fs-extra "^4.0.3" + micromatch "^3.1.4" + +find-yarn-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -4092,28 +6801,59 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== +flatted@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + flatted@^3.1.0, flatted@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== -follow-redirects@^1.12.1, follow-redirects@^1.14.8, follow-redirects@^1.14.9, follow-redirects@^1.15.0: +flow-stoplight@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" + integrity sha512-rDjbZUKpN8OYhB0IE/vY/I8UWO/602IIJEU/76Tv4LvYnwHCk0BCsvz4eRr9n+FQcri7L5cyaXOo0+/Kh4HisA== + +fmix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c" + integrity sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w== + dependencies: + imul "^1.0.0" + +follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.14.8, follow-redirects@^1.14.9, follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== -for-each@^0.3.3: +for-each@^0.3.3, for-each@~0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -4147,11 +6887,23 @@ fp-ts@^1.0.0: resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== + dependencies: + map-cache "^0.2.2" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" @@ -4163,7 +6915,16 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^4.0.2: +fs-extra@^10.0.0, fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^4.0.2, fs-extra@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== @@ -4172,7 +6933,7 @@ fs-extra@^4.0.2: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^7.0.1: +fs-extra@^7.0.0, fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== @@ -4190,6 +6951,16 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^9.0.0, fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-minipass@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" @@ -4222,21 +6993,63 @@ function.prototype.name@^1.1.5: es-abstract "^1.19.0" functions-have-names "^1.2.2" -functional-red-black-tree@^1.0.1: +functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== -functions-have-names@^1.2.2: +functions-have-names@^1.2.2, functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +ganache-core@^2.13.2: + version "2.13.2" + resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.13.2.tgz#27e6fc5417c10e6e76e2e646671869d7665814a3" + integrity sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw== + dependencies: + abstract-leveldown "3.0.0" + async "2.6.2" + bip39 "2.5.0" + cachedown "1.0.0" + clone "2.1.2" + debug "3.2.6" + encoding-down "5.0.4" + eth-sig-util "3.0.0" + ethereumjs-abi "0.6.8" + ethereumjs-account "3.0.0" + ethereumjs-block "2.2.2" + ethereumjs-common "1.5.0" + ethereumjs-tx "2.1.2" + ethereumjs-util "6.2.1" + ethereumjs-vm "4.2.0" + heap "0.2.6" + keccak "3.0.1" + level-sublevel "6.6.4" + levelup "3.1.1" + lodash "4.17.20" + lru-cache "5.1.1" + merkle-patricia-tree "3.0.0" + patch-package "6.2.2" + seedrandom "3.0.1" + source-map-support "0.5.12" + tmp "0.1.0" + web3-provider-engine "14.2.1" + websocket "1.0.32" + optionalDependencies: + ethereumjs-wallet "0.6.5" + web3 "1.2.11" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -4256,6 +7069,16 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@ has "^1.0.3" has-symbols "^1.0.3" +get-intrinsic@^1.2.0, get-intrinsic@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -4288,6 +7111,11 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -4309,6 +7137,18 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" +glob@7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" @@ -4321,7 +7161,7 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3, glob@^7.1.4: +glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.2.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -4341,7 +7181,7 @@ global@~4.4.0: min-document "^2.19.0" process "^0.11.10" -globals@^11.1.0: +globals@^11.1.0, globals@^11.7.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== @@ -4353,6 +7193,18 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" @@ -4406,6 +7258,11 @@ got@^11.8.5: p-cancelable "^2.0.0" responselike "^2.0.0" +graceful-fs@^4.1.11: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" @@ -4429,6 +7286,116 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" +hardhat-deploy@0.11.22: + version "0.11.22" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.22.tgz#9799c0266a0fc40c84690de54760f1b4dae5e487" + integrity sha512-ZhHVNB7Jo2l8Is+KIAk9F8Q3d7pptyiX+nsNbIFXztCz81kaP+6kxNODRBqRCy7SOD3It4+iKCL6tWsPAA/jVQ== + dependencies: + "@types/qs" "^6.9.7" + axios "^0.21.1" + chalk "^4.1.2" + chokidar "^3.5.2" + debug "^4.3.2" + enquirer "^2.3.6" + ethers "^5.5.3" + form-data "^4.0.0" + fs-extra "^10.0.0" + match-all "^1.2.6" + murmur-128 "^0.2.1" + qs "^6.9.4" + zksync-web3 "^0.8.1" + +hardhat-deploy@^0.11.14: + version "0.11.37" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.37.tgz#6a771b859c82ae25292321a6d510d7c0eda09d2b" + integrity sha512-pohPSEEo/X9Yfv0Fc0kXBQW6JO0LNOILBGCP69Ci1COJvLht1hLjAtXt/hccyvD9qY/uwJAM75fmsf41Y9N7lg== + dependencies: + "@ethersproject/abi" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/contracts" "^5.7.0" + "@ethersproject/providers" "^5.7.2" + "@ethersproject/solidity" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/wallet" "^5.7.0" + "@types/qs" "^6.9.7" + axios "^0.21.1" + chalk "^4.1.2" + chokidar "^3.5.2" + debug "^4.3.2" + enquirer "^2.3.6" + ethers "^5.5.3" + form-data "^4.0.0" + fs-extra "^10.0.0" + match-all "^1.2.6" + murmur-128 "^0.2.1" + qs "^6.9.4" + zksync-web3 "^0.14.3" + +hardhat-watcher@^2.1.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/hardhat-watcher/-/hardhat-watcher-2.5.0.tgz#3ee76c3cb5b99f2875b78d176207745aa484ed4a" + integrity sha512-Su2qcSMIo2YO2PrmJ0/tdkf+6pSt8zf9+4URR5edMVti6+ShI8T3xhPrwugdyTOFuyj8lKHrcTZNKUFYowYiyA== + dependencies: + chokidar "^3.5.3" + +hardhat@^2.10.2: + version "2.17.1" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.17.1.tgz#4b6c8c8f624fd23d9f40185a4af24815d05a486a" + integrity sha512-1PxRkfjhEzXs/wDxI5YgzYBxNmvzifBTjYzuopwel+vXpAhCudplusJthN5eig0FTs4qbi828DBIITEDh8x9LA== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@nomicfoundation/ethereumjs-block" "5.0.1" + "@nomicfoundation/ethereumjs-blockchain" "7.0.1" + "@nomicfoundation/ethereumjs-common" "4.0.1" + "@nomicfoundation/ethereumjs-evm" "2.0.1" + "@nomicfoundation/ethereumjs-rlp" "5.0.1" + "@nomicfoundation/ethereumjs-statemanager" "2.0.1" + "@nomicfoundation/ethereumjs-trie" "6.0.1" + "@nomicfoundation/ethereumjs-tx" "5.0.1" + "@nomicfoundation/ethereumjs-util" "9.0.1" + "@nomicfoundation/ethereumjs-vm" "7.0.1" + "@nomicfoundation/solidity-analyzer" "^0.1.0" + "@sentry/node" "^5.18.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + ethereumjs-abi "^0.6.8" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "7.2.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + keccak "^3.0.2" + lodash "^4.17.11" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + solc "0.7.3" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + tsort "0.0.1" + undici "^5.14.0" + uuid "^8.3.2" + ws "^7.4.6" + hardhat@^2.9.6: version "2.12.6" resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.6.tgz#ea3c058bbd81850867389d10f76037cfa52a0019" @@ -4485,6 +7452,13 @@ hardhat@^2.9.6: uuid "^8.3.2" ws "^7.4.6" +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== + dependencies: + ansi-regex "^2.0.0" + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -4507,6 +7481,11 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" @@ -4519,7 +7498,38 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" -has@^1.0.3: +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.3, has@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -4564,6 +7574,11 @@ header-case@^2.0.4: capital-case "^1.0.4" tslib "^2.0.3" +heap@0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" + integrity sha512-MzzWcnfB1e4EG2vHi3dXHoBupmuXNZzx6pY6HldVS55JKKBoq3xOyzfSaZRkJp37HIhEYC78knabHff3zc4dQQ== + hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -4573,6 +7588,19 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + integrity sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -4639,7 +7667,12 @@ husky@^8.0.2: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.2.tgz#5816a60db02650f1f22c8b69b928fd6bcd77a236" integrity sha512-Tkv80jtvbnkK3mYWxPZePGFpQ/tT3HNSs/sasF9P2YfkMezDl3ON37YN6jUUI4eTg5LcyVynlb6r4eyvOmspvg== -iconv-lite@0.4.24: +hyperlinker@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e" + integrity sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ== + +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -4665,6 +7698,11 @@ ieee754@^1.1.13, ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + ignore@^5.1.4: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" @@ -4675,11 +7713,29 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== +immediate@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + +immediate@~3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" + integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== + immutable@^4.0.0-rc.12: version "4.2.2" resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.2.tgz#2da9ff4384a4330c36d4d1bc88e90f9e0b0ccd16" integrity sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og== +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -4696,6 +7752,11 @@ import-local@^3.0.2: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" +imul@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9" + integrity sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA== + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -4714,11 +7775,30 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +inquirer@^6.2.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -4728,6 +7808,27 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" +internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + dependencies: + get-intrinsic "^1.2.0" + has "^1.0.3" + side-channel "^1.0.4" + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ== + io-ts@1.10.4: version "1.10.4" resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" @@ -4740,6 +7841,20 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + is-arguments@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -4748,6 +7863,15 @@ is-arguments@^1.0.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -4775,6 +7899,11 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -4785,6 +7914,20 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + is-core-module@^2.8.1, is-core-module@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" @@ -4792,6 +7935,20 @@ is-core-module@^2.8.1, is-core-module@^2.9.0: dependencies: has "^1.0.3" +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + is-date-object@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" @@ -4799,15 +7956,77 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-finite@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + +is-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" + integrity sha512-XoFPJQmsAShb3jEQRfzf2rqXavq7fIqF/jOekp308JlThqrODnMpweVSGilKTCXELfLhltGP2AGgbQGVP8F1dg== + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-function@^1.0.1: version "1.0.2" @@ -4850,6 +8069,13 @@ is-number-object@^1.0.4: dependencies: has-tostringtag "^1.0.0" +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== + dependencies: + kind-of "^3.0.2" + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -4865,7 +8091,14 @@ is-plain-obj@^2.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== -is-regex@^1.1.4: +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.0.4, is-regex@^1.1.4, is-regex@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== @@ -4904,6 +8137,13 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" +is-typed-array@^1.1.10: + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== + dependencies: + which-typed-array "^1.1.11" + is-typed-array@^1.1.3, is-typed-array@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.9.tgz#246d77d2871e7d9f5aeb1d54b9f52c71329ece67" @@ -4925,6 +8165,16 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== + is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -4932,11 +8182,50 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^2.1.1, is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + isomorphic-fetch@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" @@ -4945,6 +8234,11 @@ isomorphic-fetch@2.2.1: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" +isomorphic-ws@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -5399,11 +8693,16 @@ js-sha3@^0.7.0: resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.7.0.tgz#0a5c57b36f79882573b2d84051f8bb85dd1bd63a" integrity sha512-Wpks3yBDm0UcL5qlVhwW9Jr9n9i4FfeWBFOOXP5puDS/SiudJGhw7DPyBqn3487qD4F0lsC0q3zxink37f7zeA== -js-tokens@^4.0.0: +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== + js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -5411,7 +8710,7 @@ js-yaml@4.1.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -js-yaml@^3.13.1: +js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -5419,16 +8718,31 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +jsbi@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-4.3.0.tgz#b54ee074fb6fcbc00619559305c8f7e912b04741" + integrity sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g== + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + integrity sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + json-buffer@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" @@ -5439,16 +8753,50 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" + integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== + dependencies: + async "^2.0.1" + babel-preset-env "^1.7.0" + babelify "^7.3.0" + json-rpc-error "^2.0.0" + promise-to-callback "^1.0.0" + safe-event-emitter "^1.0.1" + +json-rpc-error@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" + integrity sha512-EwUeWP+KgAZ/xqFpaP6YDAXMtCJi+o/QQpCQFIYyxr01AdADi2y413eM8hSqJcoQym9WMePAJWoaODEJufC4Ug== + dependencies: + inherits "^2.0.1" + +json-rpc-random-id@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" + integrity sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-schema@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" @@ -5459,11 +8807,23 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stable-stringify@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" + integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== + dependencies: + jsonify "^0.0.1" + json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw== + json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -5490,6 +8850,25 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" + integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== + jsprim@^1.2.2: version "1.4.2" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" @@ -5500,6 +8879,14 @@ jsprim@^1.2.2: json-schema "0.4.0" verror "1.10.0" +keccak@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff" + integrity sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + keccak@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" @@ -5532,6 +8919,37 @@ keyv@^3.0.0: dependencies: json-buffer "3.0.0" +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" @@ -5544,11 +8962,118 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw== + dependencies: + invert-kv "^1.0.0" + lens.ts@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/lens.ts/-/lens.ts-0.5.1.tgz#957cd81838ea7359b0c280f24f9478bc6e92bafc" integrity sha512-cxzQxbitr78SnkulxKsdPC6v/+1CHmB4j2sMt2KXcbiCXLHphYZtOWYNIB1PumO5hCHescODqwhURB/OH/j5VA== +level-codec@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" + integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== + dependencies: + buffer "^5.6.0" + +level-codec@~7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" + integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== + +level-errors@^1.0.3: + version "1.1.2" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" + integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== + dependencies: + errno "~0.1.1" + +level-errors@^2.0.0, level-errors@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" + integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== + dependencies: + errno "~0.1.1" + +level-errors@~1.0.3: + version "1.0.5" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" + integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== + dependencies: + errno "~0.1.1" + +level-iterator-stream@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz#ccfff7c046dcf47955ae9a86f46dfa06a31688b4" + integrity sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.5" + xtend "^4.0.0" + +level-iterator-stream@~1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" + integrity sha512-1qua0RHNtr4nrZBgYlpV0qHHeHpcRRWTxEZJ8xsemoHAXNL5tbooh4tPEEqIqsbWCAJBmUmkwYK/sW5OrFjWWw== + dependencies: + inherits "^2.0.1" + level-errors "^1.0.3" + readable-stream "^1.0.33" + xtend "^4.0.0" + +level-iterator-stream@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz#2c98a4f8820d87cdacab3132506815419077c730" + integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== + dependencies: + inherits "^2.0.1" + readable-stream "^2.3.6" + xtend "^4.0.0" + +level-mem@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-3.0.1.tgz#7ce8cf256eac40f716eb6489654726247f5a89e5" + integrity sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg== + dependencies: + level-packager "~4.0.0" + memdown "~3.0.0" + +level-packager@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-4.0.1.tgz#7e7d3016af005be0869bc5fa8de93d2a7f56ffe6" + integrity sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q== + dependencies: + encoding-down "~5.0.0" + levelup "^3.0.0" + +level-post@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/level-post/-/level-post-1.0.7.tgz#19ccca9441a7cc527879a0635000f06d5e8f27d0" + integrity sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew== + dependencies: + ltgt "^2.1.2" + +level-sublevel@6.6.4: + version "6.6.4" + resolved "https://registry.yarnpkg.com/level-sublevel/-/level-sublevel-6.6.4.tgz#f7844ae893919cd9d69ae19d7159499afd5352ba" + integrity sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA== + dependencies: + bytewise "~1.1.0" + level-codec "^9.0.0" + level-errors "^2.0.0" + level-iterator-stream "^2.0.3" + ltgt "~2.1.1" + pull-defer "^0.2.2" + pull-level "^2.0.3" + pull-stream "^3.6.8" + typewiselite "~1.0.0" + xtend "~4.0.0" + level-supports@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" @@ -5562,6 +9087,23 @@ level-transcoder@^1.0.1: buffer "^6.0.3" module-error "^1.0.1" +level-ws@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" + integrity sha512-XUTaO/+Db51Uiyp/t7fCMGVFOTdtLS/NIACxE/GHsij15mKzxksZifKVjlXDF41JMUP/oM1Oc4YNGdKnc3dVLw== + dependencies: + readable-stream "~1.0.15" + xtend "~2.1.1" + +level-ws@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-1.0.0.tgz#19a22d2d4ac57b18cc7c6ecc4bd23d899d8f603b" + integrity sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q== + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.8" + xtend "^4.0.1" + level@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/level/-/level-8.0.0.tgz#41b4c515dabe28212a3e881b61c161ffead14394" @@ -5570,11 +9112,42 @@ level@^8.0.0: browser-level "^1.0.1" classic-level "^1.2.0" +levelup@3.1.1, levelup@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" + integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== + dependencies: + deferred-leveldown "~4.0.0" + level-errors "~2.0.0" + level-iterator-stream "~3.0.0" + xtend "~4.0.0" + +levelup@^1.2.1: + version "1.3.9" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" + integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== + dependencies: + deferred-leveldown "~1.2.1" + level-codec "~7.0.0" + level-errors "~1.0.3" + level-iterator-stream "~1.3.0" + prr "~1.0.1" + semver "~5.4.1" + xtend "~4.0.0" + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -5588,6 +9161,17 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A== + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -5610,6 +9194,21 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.assign@^4.0.3, lodash.assign@^4.0.6: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + integrity sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw== + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.flatmap@4.5.0, lodash.flatmap@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e" + integrity sha512-/OcpcAGWlrZyoHGeHh3cAoa6nGdX6QYtmzNP84Jqol6UEQQ2gIaU3H+0eICcjcKGl0/XF8LWOujNn9lffsnaOg== + lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -5620,7 +9219,17 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.21: +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash@4.17.20: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5644,6 +9253,23 @@ log4js@6.6.1: rfdc "^1.3.0" streamroller "^3.1.2" +looper@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" + integrity sha512-6DzMHJcjbQX/UPHc1rRCBfKlLwDkvuGZ715cIR36wSdYqWXFT35uLXq5P/2orl3tz+t+VOVPxw4yPinQlUDGDQ== + +looper@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" + integrity sha512-LJ9wplN/uSn72oJRsXTx+snxPet5c8XiZmOKCm906NVYu+ag6SB6vUcnJcWxgnl2NfbIyeobAn7Bwv6xRj2XJg== + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + loupe@^2.3.1: version "2.3.6" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" @@ -5668,13 +9294,20 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== -lru-cache@^5.1.1: +lru-cache@5.1.1, lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" +lru-cache@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" + integrity sha512-91gyOKTc2k66UG6kHiH4h3S2eltcPwE1STVfMYC/NG+nZwf8IIuiamfmpGZjpbbxzSyEJaLC0tNSmhjlQUTJow== + dependencies: + pseudomap "^1.0.1" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -5687,6 +9320,16 @@ lru_map@^0.3.3: resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== +ltgt@^2.1.2, ltgt@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" + integrity sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA== + +ltgt@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" + integrity sha512-5VjHC5GsENtIi5rbJd+feEpDKhfr7j0odoUR2Uh978g+2p93nd5o34cTjQWohXsPsCZeqoDnIqEf88mPCe0Pfw== + make-dir@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -5706,6 +9349,23 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== + dependencies: + object-visit "^1.0.0" + +match-all@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" + integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== + mcl-wasm@^0.7.1: version "0.7.9" resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" @@ -5725,6 +9385,30 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== +memdown@^1.0.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" + integrity sha512-iVrGHZB8i4OQfM155xx8akvG9FIj+ht14DX5CQkCTG4EHzZ3d3sgckIf/Lm9ivZalEsFuEVnWv2B2WZvbrro2w== + dependencies: + abstract-leveldown "~2.7.1" + functional-red-black-tree "^1.0.1" + immediate "^3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + +memdown@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-3.0.0.tgz#93aca055d743b20efc37492e9e399784f2958309" + integrity sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA== + dependencies: + abstract-leveldown "~5.0.0" + functional-red-black-tree "~1.0.1" + immediate "~3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + memory-level@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" @@ -5754,6 +9438,33 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +merkle-patricia-tree@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz#448d85415565df72febc33ca362b8b614f5a58f8" + integrity sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ== + dependencies: + async "^2.6.1" + ethereumjs-util "^5.2.0" + level-mem "^3.0.1" + level-ws "^1.0.0" + readable-stream "^3.0.6" + rlp "^2.0.0" + semaphore ">=1.0.1" + +merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" + integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== + dependencies: + async "^1.4.2" + ethereumjs-util "^5.0.0" + level-ws "0.0.0" + levelup "^1.2.1" + memdown "^1.0.0" + readable-stream "^2.0.0" + rlp "^2.0.0" + semaphore ">=1.0.1" + merkletreejs@^0.2.27: version "0.2.32" resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.2.32.tgz#cf1c0760e2904e4a1cc269108d6009459fd06223" @@ -5770,7 +9481,31 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== -micromatch@^4.0.4: +micro-ftch@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" + integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== + +micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.2, micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -5803,6 +9538,11 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -5854,6 +9594,11 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== +minimist@~1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" @@ -5869,6 +9614,19 @@ minizlib@^1.3.3: dependencies: minipass "^2.9.0" +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" @@ -5876,12 +9634,12 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*: +mkdirp@*, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@^0.5.5: +mkdirp@^0.5.1, mkdirp@^0.5.5: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -6003,6 +9761,25 @@ multimatch@^4.0.0: arrify "^2.0.1" minimatch "^3.0.4" +murmur-128@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d" + integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg== + dependencies: + encode-utf8 "^1.0.2" + fmix "^0.1.0" + imul "^1.0.0" + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== + +nan@^2.17.0: + version "2.17.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" + integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== + nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" @@ -6013,6 +9790,23 @@ nanoid@3.3.3: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + napi-macros@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" @@ -6038,6 +9832,11 @@ next-tick@^1.1.0: resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -6058,6 +9857,13 @@ node-cache@^5.1.2: dependencies: clone "2.x" +node-fetch@2.6.6: + version "2.6.6" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89" + integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA== + dependencies: + whatwg-url "^5.0.0" + node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -6065,7 +9871,7 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@^1.0.1: +node-fetch@^1.0.1, node-fetch@~1.7.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== @@ -6073,6 +9879,13 @@ node-fetch@^1.0.1: encoding "^0.1.11" is-stream "^1.0.1" +node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40" @@ -6088,6 +9901,21 @@ node-releases@^2.0.6: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== +nofilter@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" + integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== + +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -6110,6 +9938,11 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== + number-to-bn@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" @@ -6123,21 +9956,55 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4, object-assign@^4.0.0, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + object-inspect@^1.12.2, object-inspect@^1.9.0: version "1.12.2" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== +object-inspect@^1.12.3, object-inspect@~1.12.3: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + integrity sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== + dependencies: + isobject "^3.0.0" + object.assign@^4.1.2, object.assign@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" @@ -6157,10 +10024,28 @@ object.entries@^1.1.5: define-properties "^1.1.4" es-abstract "^1.20.4" -object.values@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" - integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== +object.getownpropertydescriptors@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz#5e5c384dd209fa4efffead39e3a0512770ccc312" + integrity sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ== + dependencies: + array.prototype.reduce "^1.0.5" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.21.2" + safe-array-concat "^1.0.0" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== + dependencies: + isobject "^3.0.1" + +object.values@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" + integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" @@ -6171,6 +10056,13 @@ obliterator@^2.0.0: resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== +oboe@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" + integrity sha512-ymBJ4xSC6GBXLT9Y7lirj+xbqBLa+jADGJldGEYG7u8sZbS9GyG+u1Xk9c5cbriKwSpCg41qUhPjvU5xOpvIyQ== + dependencies: + http-https "^1.0.0" + oboe@2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" @@ -6192,6 +10084,13 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== + dependencies: + mimic-fn "^1.0.0" + onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -6199,6 +10098,35 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +open@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +open@^8.4.0: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +optionator@^0.8.2: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -6211,7 +10139,19 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -os-tmpdir@~1.0.2: +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g== + dependencies: + lcid "^1.0.0" + +os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== @@ -6316,6 +10256,21 @@ parse-headers@^2.0.0: resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9" integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA== +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -6339,6 +10294,54 @@ pascal-case@^3.1.2: no-case "^3.0.4" tslib "^2.0.3" +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== + +patch-package@6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.2.tgz#71d170d650c65c26556f0d0fbbb48d92b6cc5f39" + integrity sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^2.4.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^1.2.1" + fs-extra "^7.0.1" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.0" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + +patch-package@^6.2.2: + version "6.5.1" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" + integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^4.1.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^2.0.0" + fs-extra "^9.0.0" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.6" + open "^7.4.2" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + yaml "^1.10.2" + +path-browserify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + path-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/path-case/-/path-case-3.0.4.tgz#9168645334eb942658375c56f80b4c0cb5f82c6f" @@ -6347,6 +10350,13 @@ path-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ== + dependencies: + pinkie-promise "^2.0.0" + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -6357,11 +10367,21 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-is-absolute@^1.0.0: +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== +path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== + +path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -6377,6 +10397,15 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg== + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -6387,7 +10416,7 @@ pathval@^1.1.1: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -pbkdf2@^3.0.17, pbkdf2@^3.0.3: +pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -6413,6 +10442,23 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pify@^2.0.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== + pirates@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" @@ -6430,16 +10476,46 @@ popper.js@1.14.3: resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" integrity sha512-3lmujhsHXzb83+sI0PzfrE3O1XHZG8m8MXNMTupvA6LrM1/nnsiqYaacYc/RIente9VqnTDPztGEM8uvPAMGyg== +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== + +postinstall-postinstall@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" + integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== + +precond@0.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" + integrity sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + prepend-http@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== +prettier@^1.14.3: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== + +prettier@^2.1.2, prettier@^2.3.1: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + prettier@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc" @@ -6476,12 +10552,35 @@ pretty-quick@^3.1.3: mri "^1.1.5" multimatch "^4.0.0" +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -prompts@^2.0.1: +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +promise-to-callback@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" + integrity sha512-uhMIZmKM5ZteDMfLgJnoSq9GCwsNKrYau73Awf1jIy6/eUcuuZ3P+CD9zUv0kJsIUbU+x6uLNIhXhLHDs1pNPA== + dependencies: + is-fn "^1.0.0" + set-immediate-shim "^1.0.1" + +prompts@^2.0.1, prompts@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -6502,6 +10601,16 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== + +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== + psl@^1.1.28: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -6519,6 +10628,62 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" +pull-cat@^1.1.9: + version "1.1.11" + resolved "https://registry.yarnpkg.com/pull-cat/-/pull-cat-1.1.11.tgz#b642dd1255da376a706b6db4fa962f5fdb74c31b" + integrity sha512-i3w+xZ3DCtTVz8S62hBOuNLRHqVDsHMNZmgrZsjPnsxXUgbWtXEee84lo1XswE7W2a3WHyqsNuDJTjVLAQR8xg== + +pull-defer@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/pull-defer/-/pull-defer-0.2.3.tgz#4ee09c6d9e227bede9938db80391c3dac489d113" + integrity sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA== + +pull-level@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pull-level/-/pull-level-2.0.4.tgz#4822e61757c10bdcc7cf4a03af04c92734c9afac" + integrity sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg== + dependencies: + level-post "^1.0.7" + pull-cat "^1.1.9" + pull-live "^1.0.1" + pull-pushable "^2.0.0" + pull-stream "^3.4.0" + pull-window "^2.1.4" + stream-to-pull-stream "^1.7.1" + +pull-live@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pull-live/-/pull-live-1.0.1.tgz#a4ecee01e330155e9124bbbcf4761f21b38f51f5" + integrity sha512-tkNz1QT5gId8aPhV5+dmwoIiA1nmfDOzJDlOOUpU5DNusj6neNd3EePybJ5+sITr2FwyCs/FVpx74YMCfc8YeA== + dependencies: + pull-cat "^1.1.9" + pull-stream "^3.4.0" + +pull-pushable@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.2.0.tgz#5f2f3aed47ad86919f01b12a2e99d6f1bd776581" + integrity sha512-M7dp95enQ2kaHvfCt2+DJfyzgCSpWVR2h2kWYnVsW6ZpxQBx5wOu0QWOvQPVoPnBLUZYitYP2y7HyHkLQNeGXg== + +pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: + version "3.7.0" + resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.7.0.tgz#85de0e44ff38a4d2ad08cc43fc458e1922f9bf0b" + integrity sha512-Eco+/R004UaCK2qEDE8vGklcTG2OeZSVm1kTUQNrykEjDwcFXDZhygFDsW49DbXyJMEhHeRL3z5cRVqPAhXlIw== + +pull-window@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/pull-window/-/pull-window-2.1.4.tgz#fc3b86feebd1920c7ae297691e23f705f88552f0" + integrity sha512-cbDzN76BMlcGG46OImrgpkMf/VkCnupj8JhsrpBw3aWBM9ye345aYnqitmZCgauBkc0HbbRRn9hCnsa3k2FNUg== + dependencies: + looper "^2.0.0" + +pump@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" + integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -6532,6 +10697,11 @@ punycode@2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" integrity sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA== +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -6544,6 +10714,13 @@ qs@6.11.0, qs@^6.7.0: dependencies: side-channel "^1.0.4" +qs@^6.11.0, qs@^6.9.4: + version "6.11.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" + integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== + dependencies: + side-channel "^1.0.4" + qs@~6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" @@ -6568,7 +10745,7 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== @@ -6608,6 +10785,55 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A== + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ== + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +readable-stream@^1.0.33: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -6617,6 +10843,16 @@ readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@~1.0.15, readable-stream@~1.0.26-4: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -6624,6 +10860,47 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +reduce-flatten@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== + +regenerate@^1.2.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" + integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + functions-have-names "^1.2.3" + regexp.prototype.flags@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" @@ -6633,12 +10910,55 @@ regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== -request@^2.79.0: +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + integrity sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ== + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + integrity sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g== + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + integrity sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw== + dependencies: + jsesc "~0.5.0" + +repeat-element@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A== + dependencies: + is-finite "^1.0.0" + +request@^2.79.0, request@^2.85.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -6669,11 +10989,21 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -require-from-string@^2.0.0: +require-from-string@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + integrity sha512-H7AkJWMobeskkttHyhTVtS0fxpFLjxhbfMa6Bk3wimP7sdPRGL3EyCg3sAQenFfAe+xQ+oAc85Nmtvq0ROM83Q== + +require-from-string@^2.0.0, require-from-string@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== + resolve-alpn@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" @@ -6686,6 +11016,11 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -6696,6 +11031,11 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== + resolve.exports@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" @@ -6708,6 +11048,15 @@ resolve@1.17.0: dependencies: path-parse "^1.0.6" +resolve@^1.10.0, resolve@^1.8.1, resolve@~1.22.1: + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^1.20.0, resolve@^1.22.0: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" @@ -6731,6 +11080,26 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +resumer@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" + integrity sha512-Fn9X8rX8yYF4m81rZCK/5VmrmsSbqS/i3rDLl6ZZHAXgC2nTAx3dhwG8q8odP/RmdLa2YrybDJaAMg+X1ajY3w== + dependencies: + through "~2.3.4" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -6741,7 +11110,14 @@ rfdc@^1.3.0: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== -rimraf@^2.2.8: +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +rimraf@^2.2.8, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -6763,13 +11139,18 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rlp@^2.0.0, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.7: +rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.7: version "2.2.7" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== dependencies: bn.js "^5.2.0" +run-async@^2.2.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-parallel-limit@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" @@ -6789,16 +11170,40 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== +rxjs@^6.4.0: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + +safe-array-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" + integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + has-symbols "^1.0.3" + isarray "^2.0.5" + safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0: +safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-event-emitter@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" + integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== + dependencies: + events "^3.0.0" + safe-regex-test@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" @@ -6808,6 +11213,13 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== + dependencies: + ret "~0.1.10" + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -6823,6 +11235,13 @@ scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== +scryptsy@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" + integrity sha512-aldIRgMozSJ/Gl6K6qmJZysRP82lz83Wb42vl4PWN8SaLFHIaOzLPc9nUUW2jQN88CuGm5q5HefJ9jZ3nWSmTw== + dependencies: + pbkdf2 "^3.0.3" + secp256k1@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" @@ -6832,6 +11251,21 @@ secp256k1@^4.0.1: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" +seedrandom@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.1.tgz#eb3dde015bcf55df05a233514e5df44ef9dce083" + integrity sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg== + +semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" + integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.1, semver@^5.6.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + semver@7.x, semver@^7.3.5, semver@^7.3.7: version "7.3.8" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" @@ -6849,6 +11283,11 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@~5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== + send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -6905,6 +11344,26 @@ servify@^0.1.12: request "^2.79.0" xhr "^2.3.3" +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + integrity sha512-Li5AOqrZWCVA2n5kryzEmqai6bKSIvpz5oUJHPVj6+dsbD3X1ixtsY5tEnsaNpH3pFAHmG8eIHUrtEtohrg+UQ== + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + setimmediate@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" @@ -6928,6 +11387,13 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -6935,6 +11401,11 @@ shebang-command@^2.0.0: dependencies: shebang-regex "^3.0.0" +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + shebang-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" @@ -6973,11 +11444,39 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg== + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + snake-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" @@ -6986,6 +11485,36 @@ snake-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + solc@0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" @@ -7001,6 +11530,70 @@ solc@0.7.3: semver "^5.5.0" tmp "0.0.33" +solc@^0.4.20: + version "0.4.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.26.tgz#5390a62a99f40806b86258c737c1cf653cc35cb5" + integrity sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA== + dependencies: + fs-extra "^0.30.0" + memorystream "^0.3.1" + require-from-string "^1.1.0" + semver "^5.3.0" + yargs "^4.7.1" + +solc@^0.6.3: + version "0.6.12" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.6.12.tgz#48ac854e0c729361b22a7483645077f58cba080e" + integrity sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +solhint@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-2.3.1.tgz#6fee8fc2635112bf5812f7cba8359c14e9d9a491" + integrity sha512-wP/G+Dqj8LNWlCI9Mt6XiQRWQfZwv1rkZe/V+HKtip5SAZJVvp144PdH28KE45ZvR99Hhrp/Mujt74fSmXsFiw== + dependencies: + ajv "^6.6.1" + antlr4 "4.7.1" + chalk "^2.4.2" + commander "2.18.0" + cosmiconfig "^5.0.7" + eslint "^5.6.0" + fast-diff "^1.1.2" + glob "^7.1.3" + ignore "^4.0.6" + js-yaml "^3.12.0" + lodash "^4.17.11" + semver "^6.3.0" + optionalDependencies: + prettier "^1.14.3" + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@0.5.12: + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -7009,6 +11602,13 @@ source-map-support@0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + source-map-support@^0.5.13: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -7017,16 +11617,75 @@ source-map-support@^0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + +source-map@^0.5.6, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +spdx-correct@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.13" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz#7189a474c46f8d47c7b0da4b987bb45e908bd2d5" + integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w== + +split-ca@^1.0.0, split-ca@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" + integrity sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +ssh2@^1.11.0: + version "1.14.0" + resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-1.14.0.tgz#8f68440e1b768b66942c9e4e4620b2725b3555bb" + integrity sha512-AqzD1UCqit8tbOKoj6ztDDi1ffJZ2rV2SwlgrVVrHPkV5vWqGJOVp5pmtj18PunkPJAuKQsnInyKV+/Nb2bUnA== + dependencies: + asn1 "^0.2.6" + bcrypt-pbkdf "^1.0.2" + optionalDependencies: + cpu-features "~0.0.8" + nan "^2.17.0" + sshpk@^1.7.0: version "1.17.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" @@ -7056,11 +11715,27 @@ stacktrace-parser@^0.1.10: dependencies: type-fest "^0.7.1" +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +stream-to-pull-stream@^1.7.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz#4161aa2d2eb9964de60bfa1af7feaf917e874ece" + integrity sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg== + dependencies: + looper "^3.0.0" + pull-stream "^3.2.3" + streamroller@^3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.1.3.tgz#d95689a8c29b30d093525d0baffe6616fd62ca7e" @@ -7080,6 +11755,11 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== +string-format@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" + integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -7088,6 +11768,32 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -7097,6 +11803,15 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string.prototype.trim@^1.2.7, string.prototype.trim@~1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string.prototype.trimend@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" @@ -7140,6 +11855,39 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -7147,6 +11895,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== + dependencies: + is-utf8 "^0.2.0" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -7174,6 +11929,11 @@ strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1. resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + supports-color@8.1.1, supports-color@^8.0.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -7181,6 +11941,11 @@ supports-color@8.1.1, supports-color@^8.0.0: dependencies: has-flag "^4.0.0" +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -7217,6 +11982,102 @@ swarm-js@^0.1.40: tar "^4.0.2" xhr-request "^1.0.1" +table-layout@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + +table@^6.8.0: + version "6.8.1" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" + integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +tape@^4.6.3: + version "4.16.2" + resolved "https://registry.yarnpkg.com/tape/-/tape-4.16.2.tgz#7565e6af20426565557266e9dda7215869b297b6" + integrity sha512-TUChV+q0GxBBCEbfCYkGLkv8hDJYjMdSWdE0/Lr331sB389dsvFUHNV9ph5iQqKzt8Ss9drzcda/YeexclBFqg== + dependencies: + call-bind "~1.0.2" + deep-equal "~1.1.1" + defined "~1.0.1" + dotignore "~0.1.2" + for-each "~0.3.3" + glob "~7.2.3" + has "~1.0.3" + inherits "~2.0.4" + is-regex "~1.1.4" + minimist "~1.2.7" + object-inspect "~1.12.3" + resolve "~1.22.1" + resumer "~0.0.0" + string.prototype.trim "~1.2.7" + through "~2.3.8" + +tar-fs@~1.16.3: + version "1.16.3" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" + integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw== + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + +tar-fs@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" + integrity sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.0.0" + +tar-stream@^1.1.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + +tar-stream@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + tar@^4.0.2: version "4.4.19" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" @@ -7230,6 +12091,20 @@ tar@^4.0.2: safe-buffer "^5.2.1" yallist "^3.1.1" +tenderly@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tenderly/-/tenderly-0.0.3.tgz#8c85e287e080073502420d5c6f13f4762d0f59cd" + integrity sha512-dVf2uxrIOeLDRNDEXcQlV2xJt50TIx8zGQKlNj1deYTV3FYu2L0zheHBHaDU12GqAff2iiGYk+fKqFkK0bB0+w== + dependencies: + axios "^0.27.2" + cli-table3 "^0.6.2" + commander "^9.4.0" + express "^4.18.1" + hyperlinker "^1.0.0" + js-yaml "^4.1.0" + open "^8.4.0" + prompts "^2.4.2" + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -7239,38 +12114,106 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +test-value@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" + integrity sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w== + dependencies: + array-back "^1.0.3" + typical "^2.6.0" + +testrpc@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/testrpc/-/testrpc-0.0.1.tgz#83e2195b1f5873aec7be1af8cbe6dcf39edb7aed" + integrity sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA== + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +through2@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +"through@>=2.2.7 <3", through@^2.3.6, through@~2.3.4, through@~2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== -tmp@0.0.33: +tiny-invariant@1.3.1, tiny-invariant@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" + integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== + +tiny-warning@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + +tmp@0.0.33, tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" +tmp@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" + integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== + dependencies: + rimraf "^2.6.3" + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== + dependencies: + kind-of "^3.0.2" + to-readable-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -7278,6 +12221,21 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toformat@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/toformat/-/toformat-2.0.0.tgz#7a043fd2dfbe9021a4e36e508835ba32056739d8" + integrity sha512-03SWBVop6nU8bpyZCx7SodpYznbZF5R4ljwNLBcTQzKOD9xuihRo/psX58llS1BMFhhAI08H3luot5GoXJz2pQ== + toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -7301,16 +12259,61 @@ treeify@^1.1.0: resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== + +ts-command-line-args@^2.2.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz#e64456b580d1d4f6d948824c274cf6fa5f45f7f0" + integrity sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw== + dependencies: + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.0" + string-format "^2.0.0" + ts-essentials@9.1.2: version "9.1.2" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-9.1.2.tgz#46db6944b73b4cd603f3d959ef1123c16ba56f59" integrity sha512-EaSmXsAhEiirrTY1Oaa7TSpei9dzuCuFPmjKRJRPamERYtfaGS8/KpOSbjergLz/Y76/aZlV9i/krgzsuWEBbg== +ts-essentials@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" + integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== + +ts-essentials@^6.0.3: + version "6.0.7" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.7.tgz#5f4880911b7581a873783740ce8b94da163d18a6" + integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== + +ts-essentials@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== + ts-essentials@^9.1.2: version "9.3.0" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-9.3.0.tgz#7e639c1a76b1805c3c60d6e1b5178da2e70aea02" integrity sha512-XeiCboEyBG8UqXZtXl59bWEi4ZgOqRsogFDI6WDGIF1LmzbYiAkIwjkXN6zZWWl4re/lsOqMlYfe8KA0XiiEPw== +ts-generator@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" + integrity sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ== + dependencies: + "@types/mkdirp" "^0.5.2" + "@types/prettier" "^2.1.1" + "@types/resolve" "^0.0.8" + chalk "^2.4.1" + glob "^7.1.2" + mkdirp "^0.5.1" + prettier "^2.1.2" + resolve "^1.8.1" + ts-essentials "^1.0.0" + ts-jest@^29.0.3: version "29.0.3" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.0.3.tgz#63ea93c5401ab73595440733cefdba31fcf9cb77" @@ -7354,7 +12357,7 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1, tslib@^1.9.3: +tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -7383,7 +12386,7 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -tweetnacl-util@^0.15.1: +tweetnacl-util@^0.15.0, tweetnacl-util@^0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== @@ -7393,7 +12396,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== -tweetnacl@^1.0.3: +tweetnacl@^1.0.0, tweetnacl@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== @@ -7405,6 +12408,13 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== + dependencies: + prelude-ls "~1.1.2" + type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -7443,6 +12453,74 @@ type@^2.7.2: resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== +typechain@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.1.1.tgz#9c2e8012c2c4c586536fc18402dcd7034c4ff0bd" + integrity sha512-uF/sUvnXTOVF2FHKhQYnxHk4su4JjZR8vr4mA2mBaRwHTbwh0jIlqARz9XJr1tA0l7afJGvEa1dTSi4zt039LQ== + dependencies: + "@types/prettier" "^2.1.1" + debug "^4.3.1" + fs-extra "^7.0.0" + glob "7.1.7" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.3.1" + ts-command-line-args "^2.2.0" + ts-essentials "^7.0.1" + +typechain@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-3.0.0.tgz#d5a47700831f238e43f7429b987b4bb54849b92e" + integrity sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg== + dependencies: + command-line-args "^4.0.7" + debug "^4.1.1" + fs-extra "^7.0.0" + js-sha3 "^0.8.0" + lodash "^4.17.15" + ts-essentials "^6.0.3" + ts-generator "^0.1.1" + +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" + integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -7450,11 +12528,48 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + typescript@4.6.4: version "4.6.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg== +typewise-core@^1.2, typewise-core@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" + integrity sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg== + +typewise@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" + integrity sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ== + dependencies: + typewise-core "^1.2.0" + +typewiselite@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typewiselite/-/typewiselite-1.0.0.tgz#c8882fa1bb1092c06005a97f34ef5c8508e3664e" + integrity sha512-J9alhjVHupW3Wfz6qFRGgQw0N3gr8hOkw6zm7FZ6UR1Cse/oD9/JVok7DNE9TT9IbciDHX2Ex9+ksE6cRmtymw== + +typical@^2.6.0, typical@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" + integrity sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg== + +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + +typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== + ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" @@ -7475,6 +12590,11 @@ underscore@1.12.1: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== +underscore@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== + undici@^5.14.0: version "5.16.0" resolved "https://registry.yarnpkg.com/undici/-/undici-5.16.0.tgz#6b64f9b890de85489ac6332bd45ca67e4f7d9943" @@ -7482,16 +12602,51 @@ undici@^5.14.0: dependencies: busboy "^1.6.0" +undici@^5.4.0: + version "5.23.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.23.0.tgz#e7bdb0ed42cebe7b7aca87ced53e6eaafb8f8ca0" + integrity sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg== + dependencies: + busboy "^1.6.0" + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unorm@^1.3.3: + version "1.6.0" + resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" + integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + update-browserslist-db@^1.0.9: version "1.0.10" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" @@ -7521,6 +12676,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== + url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -7533,6 +12693,19 @@ url-set-query@^1.0.0: resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" integrity sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg== +url@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.1.tgz#26f90f615427eca1b9f4d6a28288c147e2302a32" + integrity sha512-rWS3H04/+mzzJkv0eZ7vEDGiQbgquI1fGfOad6zKvgYQi1SzMmhl7c/DdRGxhaWrVH6z0qWITo8rpnxK/RfEhA== + dependencies: + punycode "^1.4.1" + qs "^6.11.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + utf-8-validate@^5.0.2: version "5.0.10" resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" @@ -7540,16 +12713,29 @@ utf-8-validate@^5.0.2: dependencies: node-gyp-build "^4.3.0" -utf8@3.0.0: +utf8@3.0.0, utf8@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== -util-deprecate@^1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +util.promisify@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.2.tgz#02b3dbadbb80071eee4c43aed58747afdfc516db" + integrity sha512-PBdZ03m1kBnQ5cjjO0ZvJMJS+QsbyIcFwi4hY4U76OQsCO9JrOYjbCFgIF76ccFg9xnJo7ZHPkqyj1GqmdS7MA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + for-each "^0.3.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + object.getownpropertydescriptors "^2.1.6" + safe-array-concat "^1.0.0" + util@^0.12.0: version "0.12.5" resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" @@ -7605,6 +12791,14 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + varint@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" @@ -7624,6 +12818,21 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +viem@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/viem/-/viem-1.0.2.tgz#0798c80598daddc05b7132b642ae2f60811c4fbe" + integrity sha512-3Bn+CuInU8zsdKqqzFDWL018x4B9HDjPIISztReGcBjikY+04tP7CrQQCf1lbinK3wWrEoFU9VDiptCciNjUQA== + dependencies: + "@adraffy/ens-normalize" "1.9.0" + "@noble/curves" "1.0.0" + "@noble/hashes" "1.3.0" + "@scure/bip32" "1.3.0" + "@scure/bip39" "1.2.0" + "@wagmi/chains" "1.1.0" + abitype "0.8.7" + isomorphic-ws "5.0.0" + ws "8.12.0" + walker@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -7631,6 +12840,16 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" +web3-bzz@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" + integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== + dependencies: + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + underscore "1.9.1" + web3-bzz@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.6.0.tgz#584b51339f21eedff159abc9239b4b7ef6ded840" @@ -7640,6 +12859,15 @@ web3-bzz@1.6.0: got "9.6.0" swarm-js "^0.1.40" +web3-core-helpers@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" + integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== + dependencies: + underscore "1.9.1" + web3-eth-iban "1.2.11" + web3-utils "1.2.11" + web3-core-helpers@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.6.0.tgz#77e161b6ba930a4008a0df804ab379e0aa7e1e7f" @@ -7648,6 +12876,18 @@ web3-core-helpers@1.6.0: web3-eth-iban "1.6.0" web3-utils "1.6.0" +web3-core-method@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" + integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== + dependencies: + "@ethersproject/transactions" "^5.0.0-beta.135" + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-utils "1.2.11" + web3-core-method@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.6.0.tgz#ebe4ea51f5a4fa809bb68185576186359d3982e9" @@ -7660,6 +12900,13 @@ web3-core-method@1.6.0: web3-core-subscriptions "1.6.0" web3-utils "1.6.0" +web3-core-promievent@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" + integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== + dependencies: + eventemitter3 "4.0.4" + web3-core-promievent@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.6.0.tgz#8b6053ae83cb47164540167fc361469fc604d2dd" @@ -7667,6 +12914,17 @@ web3-core-promievent@1.6.0: dependencies: eventemitter3 "4.0.4" +web3-core-requestmanager@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" + integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== + dependencies: + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-providers-http "1.2.11" + web3-providers-ipc "1.2.11" + web3-providers-ws "1.2.11" + web3-core-requestmanager@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.6.0.tgz#8ef3a3b89cd08983bd94574f9c5893f70a8a6aea" @@ -7678,6 +12936,15 @@ web3-core-requestmanager@1.6.0: web3-providers-ipc "1.6.0" web3-providers-ws "1.6.0" +web3-core-subscriptions@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" + integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-core-subscriptions@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.6.0.tgz#8c23b15b434a7c9f937652ecca45d7108e2c54df" @@ -7686,6 +12953,19 @@ web3-core-subscriptions@1.6.0: eventemitter3 "4.0.4" web3-core-helpers "1.6.0" +web3-core@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" + integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== + dependencies: + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-requestmanager "1.2.11" + web3-utils "1.2.11" + web3-core@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.6.0.tgz#144eb00f651c9812faf7176abd7ee99d5f45e212" @@ -7699,6 +12979,15 @@ web3-core@1.6.0: web3-core-requestmanager "1.6.0" web3-utils "1.6.0" +web3-eth-abi@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" + integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== + dependencies: + "@ethersproject/abi" "5.0.0-beta.153" + underscore "1.9.1" + web3-utils "1.2.11" + web3-eth-abi@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.4.0.tgz#83f9f0ce48fd6d6b233a30a33bd674b3518e472b" @@ -7716,6 +13005,23 @@ web3-eth-abi@1.6.0: "@ethersproject/abi" "5.0.7" web3-utils "1.6.0" +web3-eth-accounts@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" + integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== + dependencies: + crypto-browserify "3.12.0" + eth-lib "0.2.8" + ethereumjs-common "^1.3.2" + ethereumjs-tx "^2.1.1" + scrypt-js "^3.0.1" + underscore "1.9.1" + uuid "3.3.2" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + web3-eth-accounts@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.6.0.tgz#530927f4c5b78df93b3ea1203abbb467de29cd04" @@ -7733,6 +13039,21 @@ web3-eth-accounts@1.6.0: web3-core-method "1.6.0" web3-utils "1.6.0" +web3-eth-contract@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" + integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== + dependencies: + "@types/bn.js" "^4.11.5" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-utils "1.2.11" + web3-eth-contract@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.6.0.tgz#deb946867ad86d32bcbba899d733b681b25ea674" @@ -7747,6 +13068,21 @@ web3-eth-contract@1.6.0: web3-eth-abi "1.6.0" web3-utils "1.6.0" +web3-eth-ens@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" + integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-contract "1.2.11" + web3-utils "1.2.11" + web3-eth-ens@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.6.0.tgz#af13852168d56fa71b9198eb097e96fb93831c2a" @@ -7761,6 +13097,14 @@ web3-eth-ens@1.6.0: web3-eth-contract "1.6.0" web3-utils "1.6.0" +web3-eth-iban@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" + integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== + dependencies: + bn.js "^4.11.9" + web3-utils "1.2.11" + web3-eth-iban@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.6.0.tgz#edbe46cedc5b148d53fa455edea6b4eef53b2be7" @@ -7769,6 +13113,18 @@ web3-eth-iban@1.6.0: bn.js "^4.11.9" web3-utils "1.6.0" +web3-eth-personal@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" + integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + web3-eth-personal@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.6.0.tgz#b75a61c0737b8b8bcc11d05db2ed7bfce7e4b262" @@ -7781,6 +13137,25 @@ web3-eth-personal@1.6.0: web3-net "1.6.0" web3-utils "1.6.0" +web3-eth@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" + integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== + dependencies: + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-accounts "1.2.11" + web3-eth-contract "1.2.11" + web3-eth-ens "1.2.11" + web3-eth-iban "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + web3-eth@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.6.0.tgz#4c9d5fb4eccf9f8744828281757e6ea76af58cbd" @@ -7799,6 +13174,15 @@ web3-eth@1.6.0: web3-net "1.6.0" web3-utils "1.6.0" +web3-net@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" + integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + web3-net@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.6.0.tgz#2c28f8787073110a7c2310336889d2dad647e500" @@ -7808,6 +13192,40 @@ web3-net@1.6.0: web3-core-method "1.6.0" web3-utils "1.6.0" +web3-provider-engine@14.2.1: + version "14.2.1" + resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz#ef351578797bf170e08d529cb5b02f8751329b95" + integrity sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw== + dependencies: + async "^2.5.0" + backoff "^2.5.0" + clone "^2.0.0" + cross-fetch "^2.1.0" + eth-block-tracker "^3.0.0" + eth-json-rpc-infura "^3.1.0" + eth-sig-util "^1.4.2" + ethereumjs-block "^1.2.2" + ethereumjs-tx "^1.2.0" + ethereumjs-util "^5.1.5" + ethereumjs-vm "^2.3.4" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + readable-stream "^2.2.9" + request "^2.85.0" + semaphore "^1.0.3" + ws "^5.1.1" + xhr "^2.2.0" + xtend "^4.0.1" + +web3-providers-http@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" + integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== + dependencies: + web3-core-helpers "1.2.11" + xhr2-cookies "1.1.0" + web3-providers-http@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.6.0.tgz#8db4e589abf7197f5d65b12af1bf9726c45f4160" @@ -7816,6 +13234,15 @@ web3-providers-http@1.6.0: web3-core-helpers "1.6.0" xhr2-cookies "1.1.0" +web3-providers-ipc@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" + integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== + dependencies: + oboe "2.1.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-providers-ipc@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.6.0.tgz#6a3410fd47a67c4a36719fb97f99534ae12aac98" @@ -7824,6 +13251,16 @@ web3-providers-ipc@1.6.0: oboe "2.1.5" web3-core-helpers "1.6.0" +web3-providers-ws@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" + integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + websocket "^1.0.31" + web3-providers-ws@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.6.0.tgz#dc15dc18c30089efda992015fd5254bd2b77af5f" @@ -7833,6 +13270,16 @@ web3-providers-ws@1.6.0: web3-core-helpers "1.6.0" websocket "^1.0.32" +web3-shh@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" + integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-net "1.2.11" + web3-shh@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.6.0.tgz#838a3435dce1039f669a48e53e948062de197931" @@ -7843,6 +13290,20 @@ web3-shh@1.6.0: web3-core-subscriptions "1.6.0" web3-net "1.6.0" +web3-utils@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" + integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== + dependencies: + bn.js "^4.11.9" + eth-lib "0.2.8" + ethereum-bloom-filters "^1.0.6" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + underscore "1.9.1" + utf8 "3.0.0" + web3-utils@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.4.0.tgz#e8cb381c81b242dc1d4ecb397200356d404410e6" @@ -7870,6 +13331,20 @@ web3-utils@1.6.0: randombytes "^2.1.0" utf8 "3.0.0" +web3-utils@^1.0.0-beta.31: + version "1.10.1" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.1.tgz#97532130d85358628bc0ff14d94b7e9449786983" + integrity sha512-r6iUUw/uMnNcWXjhRv33Nyrhxq3VGOPBXeSzxhOXIci4SvC/LPTpROY0uTrMX7ztKyODYrHp8WhTkEf+ZnHssw== + dependencies: + "@ethereumjs/util" "^8.1.0" + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereum-cryptography "^2.1.2" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + web3-utils@^1.3.4: version "1.8.1" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.8.1.tgz#f2f7ca7eb65e6feb9f3d61056d0de6bbd57125ff" @@ -7883,6 +13358,19 @@ web3-utils@^1.3.4: randombytes "^2.1.0" utf8 "3.0.0" +web3@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" + integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== + dependencies: + web3-bzz "1.2.11" + web3-core "1.2.11" + web3-eth "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-shh "1.2.11" + web3-utils "1.2.11" + web3@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3/-/web3-1.6.0.tgz#d8fa0cd9e7bf252f9fe43bb77dc42bc6671affde" @@ -7901,7 +13389,19 @@ webidl-conversions@^3.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== -websocket@^1.0.32: +websocket@1.0.32: + version "1.0.32" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.32.tgz#1f16ddab3a21a2d929dec1687ab21cfdc6d3dbb1" + integrity sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +websocket@^1.0.31, websocket@^1.0.32: version "1.0.34" resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== @@ -7918,6 +13418,11 @@ whatwg-fetch@>=0.10.0: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== +whatwg-fetch@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -7937,6 +13442,22 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ== + +which-typed-array@^1.1.10, which-typed-array@^1.1.11: + version "1.1.11" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" + integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + which-typed-array@^1.1.2: version "1.1.8" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.8.tgz#0cfd53401a6f334d90ed1125754a42ed663eb01f" @@ -7949,6 +13470,13 @@ which-typed-array@^1.1.2: has-tostringtag "^1.0.0" is-typed-array "^1.1.9" +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -7956,16 +13484,42 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +window-size@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" + integrity sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw== + word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +word-wrap@~1.2.3: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +wordwrapjs@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.2.0" + workerpool@6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw== + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -7988,11 +13542,23 @@ write-file-atomic@^4.0.1: imurmurhash "^0.1.4" signal-exit "^3.0.7" +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + ws@7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@8.12.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" + integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== + ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" @@ -8002,6 +13568,13 @@ ws@^3.0.0: safe-buffer "~5.1.0" ultron "~1.1.0" +ws@^5.1.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" + integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== + dependencies: + async-limiter "~1.0.0" + ws@^7.4.6: version "7.5.9" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" @@ -8034,7 +13607,7 @@ xhr2-cookies@1.1.0: dependencies: cookiejar "^2.1.1" -xhr@^2.0.4, xhr@^2.3.3: +xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: version "2.6.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== @@ -8049,11 +13622,23 @@ xmlhttprequest@1.8.0: resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA== -xtend@^4.0.0: +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + integrity sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ== + dependencies: + object-keys "~0.4.0" + +y18n@^3.2.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -8074,11 +13659,24 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== +yargs-parser@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" + integrity sha512-9pIKIJhnI5tonzG6OnCFlz/yln8xHYcGl+pn3xR0Vzff0vzN1PbNRaelgfgRUwZ3s4i3jvxT9WhmUGL4whnasA== + dependencies: + camelcase "^3.0.0" + lodash.assign "^4.0.6" + yargs-parser@^20.2.2: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" @@ -8125,6 +13723,26 @@ yargs@^17.0.1, yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.0.0" +yargs@^4.7.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" + integrity sha512-LqodLrnIDM3IFT+Hf/5sxBnEGECrfdC1uIbgZeJmESCSo4HoCAaKEus8MylXHAkdacGc0ye+Qa+dpkuom8uVYA== + dependencies: + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + lodash.assign "^4.0.3" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.1" + which-module "^1.0.0" + window-size "^0.2.0" + y18n "^3.2.1" + yargs-parser "^2.4.1" + yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" @@ -8134,3 +13752,18 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zksync-web3@^0.14.3: + version "0.14.3" + resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.14.3.tgz#64ac2a16d597464c3fc4ae07447a8007631c57c9" + integrity sha512-hT72th4AnqyLW1d5Jlv8N2B/qhEnl2NePK2A3org7tAa24niem/UAaHMkEvmWI3SF9waYUPtqAtjpf+yvQ9zvQ== + +zksync-web3@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.8.1.tgz#db289d8f6caf61f4d5ddc471fa3448d93208dc14" + integrity sha512-1A4aHPQ3MyuGjpv5X/8pVEN+MdZqMjfVmiweQSRjOlklXYu65wT9BGEOtCmMs5d3gIvLp4ssfTeuR5OCKOD2kw== + +zod@3.21.4: + version "3.21.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db" + integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw== From eec0c52c891ab43ed43386ca49d22c846283ff87 Mon Sep 17 00:00:00 2001 From: Verisana Date: Mon, 28 Aug 2023 12:44:54 +0100 Subject: [PATCH 159/833] fix: optimize manual state requests --- src/dex/algebra/algebra-integration.test.ts | 14 ++- src/dex/algebra/algebra-pool-v1_1.ts | 132 ++++++++++++-------- src/lib/decoders.ts | 13 +- 3 files changed, 101 insertions(+), 58 deletions(-) diff --git a/src/dex/algebra/algebra-integration.test.ts b/src/dex/algebra/algebra-integration.test.ts index 20b8ef98a..d345ef8a8 100644 --- a/src/dex/algebra/algebra-integration.test.ts +++ b/src/dex/algebra/algebra-integration.test.ts @@ -497,7 +497,7 @@ describe('Algebra', function () { } }); - it('both generate state result match', async function () { + it('generate state is working for problematic pool', async function () { const pool = (await algebra.getPool( '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9', '0xc5015b9d9161dca7e18e32f6f25c4ad850731fd4', @@ -505,6 +505,18 @@ describe('Algebra', function () { )) as AlgebraEventPoolV1_1; const stateManually = await pool.fetchStateManually(blockNumber); + // We can not compare with usual way, because this pool can not be requested normally + expect(Array.isArray(stateManually)).toBeTruthy(); + }); + + it('recognize pool does not exist error', async function () { + const pool = (await algebra.getPool( + '0x8aaebb46e1742f4623e6e1621f909f01846ca5e2', + '0xf9ed88937b2d82707d0eabd8c3d9aa4870b714d3', + blockNumber, + )) as AlgebraEventPoolV1_1; + + expect(pool).toBeNull(); }); }); }); diff --git a/src/dex/algebra/algebra-pool-v1_1.ts b/src/dex/algebra/algebra-pool-v1_1.ts index 0f9e3ccb1..8690b1785 100644 --- a/src/dex/algebra/algebra-pool-v1_1.ts +++ b/src/dex/algebra/algebra-pool-v1_1.ts @@ -2,7 +2,7 @@ import _ from 'lodash'; import { Interface } from '@ethersproject/abi'; import { DeepReadonly, assert } from 'ts-essentials'; import { Address, BlockHeader, Log, Logger } from '../../types'; -import { bigIntify, catchParseLogError, int16, uint128 } from '../../utils'; +import { bigIntify, catchParseLogError, int16 } from '../../utils'; import { InitializeStateOptions, StatefulEventSubscriber, @@ -28,8 +28,8 @@ import { import { addressDecode, uint256ToBigInt, - uint128ToBigInt, - int24ToBigInt, + uint128ToBigNumber, + int24ToNumber, } from '../../lib/decoders'; import { MultiCallParams } from '../../lib/multi-wrapper'; import { @@ -43,9 +43,12 @@ import { _reduceTicks, } from '../uniswap-v3/contract-math/utils'; import { Constants } from './lib/Constants'; -import { Network } from '../../constants'; +import { Network, NULL_ADDRESS } from '../../constants'; import { TickTable } from './lib/TickTable'; +const BN_ZERO = BigNumber.from(0); +const MAX_BATCH_SIZE = 100; + export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber { handlers: { [event: string]: ( @@ -67,6 +70,10 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber public readonly poolIface = new Interface(AlgebraABI); public readonly factoryIface = new Interface(FactoryABI); + private readonly cachedStateMultiCalls: MultiCallParams< + string | bigint | BigNumber | number | DecodedGlobalStateV1_1 + >[]; + public initFailed = false; public initRetryAttemptCount = 0; @@ -98,6 +105,8 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber this.handlers['Flash'] = this.handleFlashEvent.bind(this); this.handlers['Collect'] = this.handleCollectEvent.bind(this); this.handlers['CommunityFee'] = this.handleCommunityFee.bind(this); + + this.cachedStateMultiCalls = this._getStateMulticall(); } get poolAddress() { @@ -344,7 +353,6 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber return [balance0, balance1, _state]; } - // FIXME: Here happens double conversion in types, but for prototyping and to check if this approach helps, it is nor very important async _fetchInitStateMultiStrategies( blockNumber: number, ): Promise< @@ -362,13 +370,10 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber } } - async fetchStateManually( - blockNumber: number, - ): Promise< - [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmapsV1_1] - > { - // FIXME: If this approach works, need to add caching of multicalls - const [poolAddress] = await this.dexHelper.multiWrapper.aggregate([ + private _getStateMulticall(): MultiCallParams< + string | bigint | BigNumber | number | DecodedGlobalStateV1_1 + >[] { + return [ { target: this.factoryAddress, callData: this.factoryIface.encodeFunctionData('poolByPair', [ @@ -377,22 +382,6 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber ]), decodeFunction: addressDecode, }, - ]); - assert( - poolAddress.toLowerCase() === this.poolAddress.toLowerCase(), - `Pool address mismatch: ${poolAddress.toLowerCase()} != ${this.poolAddress.toLowerCase()}`, - ); - - const [ - balance0, - balance1, - liquidity, - tickSpacing, - maxLiquidityPerTick, - globalState, - ] = (await this.dexHelper.multiWrapper.aggregate< - bigint | number | DecodedGlobalStateV1_1 - >([ { target: this.token0, callData: this.erc20Interface.encodeFunctionData('balanceOf', [ @@ -408,26 +397,68 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber decodeFunction: uint256ToBigInt, }, { - target: poolAddress, + target: this.poolAddress, callData: this.poolIface.encodeFunctionData('liquidity', []), - decodeFunction: uint128ToBigInt, + decodeFunction: uint128ToBigNumber, }, { - target: poolAddress, + target: this.poolAddress, callData: this.poolIface.encodeFunctionData('tickSpacing', []), - decodeFunction: int24ToBigInt, + decodeFunction: int24ToNumber, }, { - target: poolAddress, + target: this.poolAddress, callData: this.poolIface.encodeFunctionData('maxLiquidityPerTick', []), - decodeFunction: uint128ToBigInt, + decodeFunction: uint128ToBigNumber, }, { - target: poolAddress, + target: this.poolAddress, callData: this.poolIface.encodeFunctionData('globalState', []), decodeFunction: decodeGlobalStateV1_1, }, - ])) as [bigint, bigint, bigint, bigint, bigint, DecodedGlobalStateV1_1]; + ]; + } + + async fetchStateManually( + blockNumber: number, + ): Promise< + [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmapsV1_1] + > { + // Unfortunately I can not unite this call with the next one. For some reason even if pool does not exist + // call succeeds and makes decoding function to throw. Otherwise, I should rewrite decoders in different which + // require some time + const [poolAddress] = (await this.dexHelper.multiWrapper.aggregate< + string | bigint | BigNumber | number | DecodedGlobalStateV1_1 + >(this.cachedStateMultiCalls.slice(0, 1), blockNumber, MAX_BATCH_SIZE)) as [ + string, + ]; + + if (poolAddress === NULL_ADDRESS) { + throw new Error('Pool does not exist'); + } + + const [ + balance0, + balance1, + liquidity, + tickSpacing, + maxLiquidityPerTick, + globalState, + ] = (await this.dexHelper.multiWrapper.aggregate< + string | bigint | BigNumber | number | DecodedGlobalStateV1_1 + >(this.cachedStateMultiCalls.slice(1), blockNumber, MAX_BATCH_SIZE)) as [ + bigint, + bigint, + BigNumber, + number, + BigNumber, + DecodedGlobalStateV1_1, + ]; + + assert( + poolAddress.toLowerCase() === this.poolAddress.toLowerCase(), + `Pool address mismatch: ${poolAddress.toLowerCase()} != ${this.poolAddress.toLowerCase()}`, + ); const currentBitMapIndex = TickTable.position( BigInt(BigInt(globalState.tick) / BigInt(tickSpacing)), @@ -449,14 +480,15 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber }; }, ), + blockNumber, + MAX_BATCH_SIZE, ); const tickBitmap: TickBitMapMappingsWithBigNumber[] = []; let globalIndex = 0; - for (let i = leftBitMapIndex; i <= rightBitMapIndex; i++) { - const index = int16(i); + const index = Number(int16(i)); const bitmap = allTickBitMaps[globalIndex]; globalIndex++; if (bitmap == 0n) continue; @@ -468,13 +500,13 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber const tickRequests = tickBitmap .map(tb => { const allBits: MultiCallParams[] = []; - if (tb.value === BigNumber.from(0)) return allBits; + if (tb.value === BN_ZERO) return allBits; _.range(0, 256).forEach(j => { if ((tb.value.toBigInt() & (1n << BigInt(j))) > 0n) { const populatedTick = (BigInt.asIntN(16, BigInt(tb.index) << 8n) + BigInt(j)) * - tickSpacing; + BigInt(tickSpacing); tickIndexes.push(populatedTick); allBits.push({ @@ -490,13 +522,12 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber }) .flat(); - const ticksValues = ( - await Promise.all( - _.chunk(tickRequests, 100).map(tickRequestChunk => - this.dexHelper.multiWrapper.aggregate(tickRequestChunk), - ), - ) - ).flat(); + const ticksValues = await this.dexHelper.multiWrapper.aggregate( + tickRequests, + blockNumber, + MAX_BATCH_SIZE, + ); + assert( tickIndexes.length === ticksValues.length, `Tick indexes mismatch: ${tickIndexes.length} != ${ticksValues.length}`, @@ -516,14 +547,13 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber return [ balance0, balance1, - // FIXME: If we validate that this is working, remove redundant conversions { pool: poolAddress, blockTimestamp: BigNumber.from(Date.now()), globalState, - liquidity: BigNumber.from(liquidity), - tickSpacing: Number(tickSpacing), - maxLiquidityPerTick: BigNumber.from(maxLiquidityPerTick), + liquidity, + tickSpacing, + maxLiquidityPerTick, tickBitmap, ticks, }, diff --git a/src/lib/decoders.ts b/src/lib/decoders.ts index 6c2453b0c..fd48cd5c1 100644 --- a/src/lib/decoders.ts +++ b/src/lib/decoders.ts @@ -1,5 +1,6 @@ import { Result } from '@ethersproject/abi'; import BigNumber from 'bignumber.js'; +import { BigNumber as EthersBigNumber } from 'ethers'; import { BytesLike, defaultAbiCoder } from 'ethers/lib/utils'; import _, { parseInt } from 'lodash'; import { BN_0 } from '../bignumber-constants'; @@ -50,16 +51,16 @@ export const uint256ToBigInt = ( return generalDecoder(result, ['uint256'], 0n, value => value[0].toBigInt()); }; -export const uint128ToBigInt = ( +export const uint128ToBigNumber = ( result: MultiResult | BytesLike, -): bigint => { - return generalDecoder(result, ['uint128'], 0n, value => value[0].toBigInt()); +): EthersBigNumber => { + return generalDecoder(result, ['uint128'], 0n, value => value[0]); }; -export const int24ToBigInt = ( +export const int24ToNumber = ( result: MultiResult | BytesLike, -): bigint => { - return generalDecoder(result, ['int24'], 0n, value => BigInt(value[0])); +): number => { + return generalDecoder(result, ['int24'], 0n, value => value[0]); }; export const uint256ArrayDecode = ( From 103ea97dc69f7175c3794115f0a2b6005425499a Mon Sep 17 00:00:00 2001 From: Verisana Date: Mon, 28 Aug 2023 12:46:13 +0100 Subject: [PATCH 160/833] 2.31.4-zkevm-revive.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 32f20b96a..b1782b7e6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.7", + "version": "2.31.4-zkevm-revive.8", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From acd0906717fde01fbd76c0cec1f9f0e1ea294a7b Mon Sep 17 00:00:00 2001 From: Verisana Date: Mon, 28 Aug 2023 13:40:33 +0100 Subject: [PATCH 161/833] fix: try search fo optimal batch size split --- src/dex/algebra/algebra-integration.test.ts | 14 +++++++- src/dex/algebra/algebra-pool-v1_1.ts | 40 ++++++++++++++++++--- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/dex/algebra/algebra-integration.test.ts b/src/dex/algebra/algebra-integration.test.ts index d345ef8a8..a244391d6 100644 --- a/src/dex/algebra/algebra-integration.test.ts +++ b/src/dex/algebra/algebra-integration.test.ts @@ -497,7 +497,7 @@ describe('Algebra', function () { } }); - it('generate state is working for problematic pool', async function () { + it('WETH/DAI generate state is working for problematic pool', async function () { const pool = (await algebra.getPool( '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9', '0xc5015b9d9161dca7e18e32f6f25c4ad850731fd4', @@ -509,6 +509,18 @@ describe('Algebra', function () { expect(Array.isArray(stateManually)).toBeTruthy(); }); + it('WETH/MATIC generate state is working for problematic pool', async function () { + const pool = (await algebra.getPool( + '0x4f9a0e7fd2bf6067db6994cf12e4495df938e6e9', + '0xa2036f0538221a77a3937f1379699f44945018d0', + blockNumber, + )) as AlgebraEventPoolV1_1; + + const stateManually = await pool.fetchStateManually(blockNumber); + // We can not compare with usual way, because this pool can not be requested normally + expect(Array.isArray(stateManually)).toBeTruthy(); + }); + it('recognize pool does not exist error', async function () { const pool = (await algebra.getPool( '0x8aaebb46e1742f4623e6e1621f909f01846ca5e2', diff --git a/src/dex/algebra/algebra-pool-v1_1.ts b/src/dex/algebra/algebra-pool-v1_1.ts index 8690b1785..41b3737b6 100644 --- a/src/dex/algebra/algebra-pool-v1_1.ts +++ b/src/dex/algebra/algebra-pool-v1_1.ts @@ -48,6 +48,7 @@ import { TickTable } from './lib/TickTable'; const BN_ZERO = BigNumber.from(0); const MAX_BATCH_SIZE = 100; +const MAX_NUMBER_OF_BATCH_REQUEST_HALVING = 3; export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber { handlers: { @@ -74,6 +75,8 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber string | bigint | BigNumber | number | DecodedGlobalStateV1_1 >[]; + private optimalTickRequestBatchSize?: number; + public initFailed = false; public initRetryAttemptCount = 0; @@ -522,11 +525,38 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber }) .flat(); - const ticksValues = await this.dexHelper.multiWrapper.aggregate( - tickRequests, - blockNumber, - MAX_BATCH_SIZE, - ); + let ticksValues: TickInfoWithBigNumber[] = []; + if (this.optimalTickRequestBatchSize) { + ticksValues = await this.dexHelper.multiWrapper.aggregate( + tickRequests, + blockNumber, + this.optimalTickRequestBatchSize, + ); + // If we don't know what is optimal number of requests for this pool, we want to try it experimentally and save it + // Maybe later to consider distant caching + } else { + for (const i of _.range(0, MAX_NUMBER_OF_BATCH_REQUEST_HALVING)) { + const currentBatchSize = MAX_BATCH_SIZE / (+i + 1); + try { + // Some of the pools fails with 100 batch size, for them we want to try additionally with reduced batch size + ticksValues = await this.dexHelper.multiWrapper.aggregate( + tickRequests, + blockNumber, + currentBatchSize, + ); + this.optimalTickRequestBatchSize = currentBatchSize; + break; + } catch (e) { + if (+i + 1 === MAX_NUMBER_OF_BATCH_REQUEST_HALVING) { + this.logger.warn( + `Failed to fetch ticks for pool ${poolAddress} (${this.token0}_${this.token1}) with batch size ${currentBatchSize}`, + e, + ); + throw e; + } + } + } + } assert( tickIndexes.length === ticksValues.length, From d1edcb2faee36b5bfea8998fb4314259e37918b9 Mon Sep 17 00:00:00 2001 From: Verisana Date: Mon, 28 Aug 2023 13:41:49 +0100 Subject: [PATCH 162/833] 2.31.4-zkevm-revive.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b1782b7e6..4dbd325ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.8", + "version": "2.31.4-zkevm-revive.9", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From d83682cf91036b3a50ab8a493e522050842a93dd Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 28 Aug 2023 17:26:37 +0300 Subject: [PATCH 163/833] update --- src/config.ts | 4 +- src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts | 21 +- .../sushiswap-v3-integration.test.ts | 114 ++++++++-- src/dex/sushiswap-v3/sushiswap-v3.ts | 211 ++++++++++++------ src/dex/sushiswap-v3/types.ts | 12 - src/dex/uniswap-v3/types.ts | 2 +- tests/utils-e2e.ts | 2 + 7 files changed, 246 insertions(+), 120 deletions(-) delete mode 100644 src/dex/sushiswap-v3/types.ts diff --git a/src/config.ts b/src/config.ts index 32e10ee75..ee352e017 100644 --- a/src/config.ts +++ b/src/config.ts @@ -277,8 +277,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], adapterAddresses: { ArbitrumAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9', - ArbitrumAdapter02: '0x68be90b86BC3A8f1d958A179043Ce6C3bae4aA27', - ArbitrumBuyAdapter: '0x2880C3971CCaE35a9609DC2397AdeE4AA9dFdF35', + ArbitrumAdapter02: '0x902A1f552776D1f6D0614A902F6ba7bb608EDd2C', + ArbitrumBuyAdapter: '0xAFad34619549AD69f2e2e5266cbBe2eF0EbA6C49', }, uniswapV2ExchangeRouterAddress: '0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC', diff --git a/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts b/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts index 81b071757..65cf67023 100644 --- a/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts +++ b/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts @@ -34,17 +34,15 @@ function testForNetwork( SwapSide.SELL, [ ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - // ContractMethod.directUniV3Swap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, ], ], [ SwapSide.BUY, [ ContractMethod.simpleBuy, - // ContractMethod.buy, - // ContractMethod.directUniV3Buy, + ContractMethod.buy, ], ], ]); @@ -133,18 +131,17 @@ describe('SushiSwapV3 E2E', () => { tokenAAmount, tokenBAmount, nativeTokenAmount, - 500, // 5% ); }); describe('ARBITRUM', () => { const network = Network.ARBITRUM; - const tokenASymbol: string = 'USDCe'; - const tokenBSymbol: string = 'USDT'; + const tokenASymbol: string = 'USDT'; + const tokenBSymbol: string = 'USDCe'; - const tokenAAmount: string = '11111000'; - const tokenBAmount: string = '10000000'; + const tokenAAmount: string = '11111000000'; + const tokenBAmount: string = '10000000000'; const nativeTokenAmount = '11000000000000000'; testForNetwork( @@ -155,7 +152,6 @@ describe('SushiSwapV3 E2E', () => { tokenAAmount, tokenBAmount, nativeTokenAmount, - 500, // 5% ); }); @@ -177,7 +173,6 @@ describe('SushiSwapV3 E2E', () => { tokenAAmount, tokenBAmount, nativeTokenAmount, - 500, // 5% ); }); @@ -297,7 +292,6 @@ describe('SushiSwapV3 E2E', () => { tokenAAmount, tokenBAmount, nativeTokenAmount, - 500, // 5% ); }); @@ -413,7 +407,6 @@ describe('SushiSwapV3 E2E', () => { tokenAAmount, tokenBAmount, nativeTokenAmount, - 500, // 5% ); }); }); diff --git a/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts b/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts index 998271fad..5f386bc60 100644 --- a/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts +++ b/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts @@ -1,14 +1,17 @@ -import { UniswapV3 } from '../uniswap-v3/uniswap-v3'; +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); +import { SushiSwapV3 } from '../sushiswap-v3/sushiswap-v3'; import { Network, SwapSide } from '../../constants'; import { DummyDexHelper, IDexHelper } from '../../dex-helper'; import { Tokens } from '../../../tests/constants-e2e'; import { BI_POWS } from '../../bigint-constants'; import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; import { Interface, Result } from '@ethersproject/abi'; -import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; +import SushiswapV3QuoterV2ABI from '../../abi/sushiswap-v3/QuoterV2.json'; import { Address } from '@paraswap/core'; -const quoterIface = new Interface(UniswapV3QuoterV2ABI); +const quoterIface = new Interface(SushiswapV3QuoterV2ABI); function getReaderCalldata( exchangeAddress: string, @@ -40,7 +43,7 @@ function decodeReaderResult( async function checkOnChainPricing( dexHelper: IDexHelper, - uniswapV3: UniswapV3, + sushiSwapV3: SushiSwapV3, funcName: string, blockNumber: number, exchangeAddress: string, @@ -111,8 +114,8 @@ describe('SushiSwapV3', () => { describe('Mainnet', () => { let blockNumber: number; - let uniswapV3: UniswapV3; - let uniswapV3Mainnet: UniswapV3; + let sushiSwapV3: SushiSwapV3; + let sushiSwapV3Mainnet: SushiSwapV3; const network = Network.MAINNET; const dexHelper = new DummyDexHelper(network); @@ -124,14 +127,14 @@ describe('SushiSwapV3', () => { beforeEach(async () => { blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - uniswapV3 = new UniswapV3(network, dexKey, dexHelper); - uniswapV3Mainnet = new UniswapV3(Network.MAINNET, dexKey, dexHelper); + sushiSwapV3 = new SushiSwapV3(network, dexKey, dexHelper); + sushiSwapV3Mainnet = new SushiSwapV3(Network.MAINNET, dexKey, dexHelper); }); it('getPoolIdentifiers and getPricesVolume SELL', async function () { const amounts = [0n, BI_POWS[6], 2000000n]; - const pools = await uniswapV3.getPoolIdentifiers( + const pools = await sushiSwapV3.getPoolIdentifiers( TokenA, TokenB, SwapSide.SELL, @@ -144,7 +147,7 @@ describe('SushiSwapV3', () => { expect(pools.length).toBeGreaterThan(0); - const poolPrices = await uniswapV3.getPricesVolume( + const poolPrices = await sushiSwapV3.getPricesVolume( TokenA, TokenB, amounts, @@ -163,10 +166,10 @@ describe('SushiSwapV3', () => { let falseChecksCounter = 0; await Promise.all( poolPrices!.map(async price => { - const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const fee = sushiSwapV3.eventPools[price.poolIdentifier!]!.feeCode; const res = await checkOnChainPricing( dexHelper, - uniswapV3, + sushiSwapV3, 'quoteExactInputSingle', blockNumber, '0x64e8802FE490fa7cc61d3463958199161Bb608A7', @@ -186,7 +189,7 @@ describe('SushiSwapV3', () => { it('getPoolIdentifiers and getPricesVolume BUY', async function () { const amounts = [0n, BI_POWS[6], 2000000n]; - const pools = await uniswapV3.getPoolIdentifiers( + const pools = await sushiSwapV3.getPoolIdentifiers( TokenA, TokenB, SwapSide.BUY, @@ -199,7 +202,7 @@ describe('SushiSwapV3', () => { expect(pools.length).toBeGreaterThan(0); - const poolPrices = await uniswapV3.getPricesVolume( + const poolPrices = await sushiSwapV3.getPricesVolume( TokenA, TokenB, amounts, @@ -218,10 +221,10 @@ describe('SushiSwapV3', () => { let falseChecksCounter = 0; await Promise.all( poolPrices!.map(async price => { - const fee = uniswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const fee = sushiSwapV3.eventPools[price.poolIdentifier!]!.feeCode; const res = await checkOnChainPricing( dexHelper, - uniswapV3, + sushiSwapV3, 'quoteExactOutputSingle', blockNumber, '0x64e8802FE490fa7cc61d3463958199161Bb608A7', @@ -239,7 +242,7 @@ describe('SushiSwapV3', () => { }); it('getTopPoolsForToken', async function () { - const poolLiquidity = await uniswapV3.getTopPoolsForToken( + const poolLiquidity = await sushiSwapV3.getTopPoolsForToken( TokenB.address, 10, ); @@ -248,4 +251,81 @@ describe('SushiSwapV3', () => { checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); }); }); + + describe('Arbitrum', () => { + let blockNumber: number; + let sushiSwapV3: SushiSwapV3; + let sushiSwapV3Mainnet: SushiSwapV3; + + const network = Network.ARBITRUM; + const dexHelper = new DummyDexHelper(network); + const TokenASymbol = 'USDCe'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDT'; + const TokenB = Tokens[network][TokenBSymbol]; + + beforeEach(async () => { + // blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + blockNumber = 125789437; + sushiSwapV3 = new SushiSwapV3(network, dexKey, dexHelper); + sushiSwapV3Mainnet = new SushiSwapV3(Network.ARBITRUM, dexKey, dexHelper); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + const amounts = [0n, 100000000n, 200000000n]; + + const pools = await sushiSwapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await sushiSwapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = sushiSwapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + sushiSwapV3, + 'quoteExactOutputSingle', + blockNumber, + '0x0524E833cCD057e4d7A296e3aaAb9f7675964Ce1', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + }); }); diff --git a/src/dex/sushiswap-v3/sushiswap-v3.ts b/src/dex/sushiswap-v3/sushiswap-v3.ts index 9423fe345..098fcf21f 100644 --- a/src/dex/sushiswap-v3/sushiswap-v3.ts +++ b/src/dex/sushiswap-v3/sushiswap-v3.ts @@ -1,12 +1,12 @@ import _ from 'lodash'; import { createPublicClient, http } from 'viem'; -import { DataFetcher, LiquidityProviders, Router, RPParams } from '@sushiswap/router'; +import { DataFetcher, LiquidityProviders, Router, RPParams, } from '@sushiswap/router'; import { Token as SushiToken } from '@sushiswap/currency'; import { SushiSwapV3Config, Adapters } from './config'; import { UniswapV3 } from '../uniswap-v3/uniswap-v3'; import { getViemChain } from './constants'; import { Network, SwapSide } from '../../constants'; -import { getDexKeysWithNetwork } from '../../utils'; +import { getDexKeysWithNetwork, Utils } from '../../utils'; import SushiswapV3RouterABI from '../../abi/sushiswap-v3/RouterProcessor3.json'; import SushiswapV3QuoterV2ABI from '../../abi/sushiswap-v3/QuoterV2.json'; import { IDexHelper } from '../../dex-helper'; @@ -20,10 +20,9 @@ import { } from '../../types'; import { generateConfig } from '../../config'; import { BigNumber } from 'ethers'; -import { getLocalDeadlineAsFriendlyPlaceholder, SimpleExchange } from '../simple-exchange'; +import { getLocalDeadlineAsFriendlyPlaceholder } from '../simple-exchange'; import { OptimalSwapExchange } from '@paraswap/core'; import { assert } from 'ts-essentials'; -import { SushiSwapV3Data } from './types'; import { UniswapV3Data} from '../uniswap-v3/types'; import { MultiCallParams } from '../../lib/multi-wrapper'; import { uint256DecodeToNumber } from '../../lib/decoders'; @@ -62,65 +61,53 @@ export class SushiSwapV3 extends UniswapV3 { side: SwapSide, options: PreprocessTransactionOptions, ): Promise<[OptimalSwapExchange, ExchangeTxInfo]> { - if (!options.isDirectMethod) { - return [ - optimalSwapExchange, - { - deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), - }, - ]; - } assert( optimalSwapExchange.data !== undefined, `preProcessTransaction: data field is missing`, ); - let isApproved: boolean | undefined; - - try { - this.erc20Contract.options.address = - this.dexHelper.config.wrapETH(srcToken).address; - const allowance = await this.erc20Contract.methods - .allowance(this.augustusAddress, this.config.router) - .call(undefined, 'latest'); - isApproved = - BigInt(allowance.toString()) >= BigInt(optimalSwapExchange.srcAmount); - } catch (e) { - this.logger.error( - `preProcessTransaction failed to retrieve allowance info: `, - e, - ); + if(options.isDirectMethod) { + let isApproved: boolean | undefined; + + try { + this.erc20Contract.options.address = + this.dexHelper.config.wrapETH(srcToken).address; + const allowance = await this.erc20Contract.methods + .allowance(this.augustusAddress, this.config.router) + .call(undefined, 'latest'); + isApproved = + BigInt(allowance.toString()) >= BigInt(optimalSwapExchange.srcAmount); + } catch (e) { + this.logger.error( + `preProcessTransaction failed to retrieve allowance info: `, + e, + ); + } + + return [ + { + ...optimalSwapExchange, + data: { + ...optimalSwapExchange.data, + isApproved, + }, + }, + { + deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), + }, + ]; } - const rpParams = await this.getSushiV3Params( - srcToken.address, - destToken.address, - optimalSwapExchange.srcAmount, - ); + const _srcToken = this.dexHelper.config.wrapETH(srcToken); + const _destToken = this.dexHelper.config.wrapETH(destToken); - console.log('preprocess tx: ', rpParams); + console.log('DATA: ', options); - return [ - { - ...optimalSwapExchange, - data: { - ...optimalSwapExchange.data, - isApproved, - rpParams, - }, - }, - { - deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), - }, - ]; - } + console.log('_src token: ', _srcToken); + console.log('_dest token: ', _destToken); + console.log('side: ', side); - async getSushiV3Params( - srcToken: string, - destToken: string, - srcAmount: string, - ): Promise { const web3Client = createPublicClient({ transport: http(generateConfig(this.network).privateHttpProvider), chain: getViemChain(this.network), @@ -131,14 +118,16 @@ export class SushiSwapV3 extends UniswapV3 { web3Client, ); + dataFetcher.startDataFetching([LiquidityProviders.SushiSwapV3]); + const callData: MultiCallParams[] = [ { - target: srcToken, + target: _srcToken.address, callData: this.erc20Interface.encodeFunctionData('decimals'), decodeFunction: uint256DecodeToNumber, }, { - target: destToken, + target: _destToken.address, callData: this.erc20Interface.encodeFunctionData('decimals'), decodeFunction: uint256DecodeToNumber, } @@ -153,16 +142,14 @@ export class SushiSwapV3 extends UniswapV3 { false, ); - dataFetcher.startDataFetching([LiquidityProviders.SushiSwapV3]); - const fromToken = new SushiToken({ - address: srcToken, + address: _srcToken.address, decimals: decimals0.returnData, chainId: this.network, }); const toToken = new SushiToken({ - address: destToken, + address: _destToken.address, decimals: decimals1.returnData, chainId: this.network, }); @@ -175,7 +162,7 @@ export class SushiSwapV3 extends UniswapV3 { pcMap, this.network, fromToken, - BigNumber.from(srcAmount), + BigNumber.from(optimalSwapExchange.srcAmount), toToken, 50e9, [LiquidityProviders.SushiSwapV3], @@ -183,7 +170,7 @@ export class SushiSwapV3 extends UniswapV3 { console.log('ROUTE: ', route); - const rpParams = Router.routeProcessor2Params( + const routerParams = Router.routeProcessor2Params( pcMap, route, fromToken, @@ -192,9 +179,18 @@ export class SushiSwapV3 extends UniswapV3 { this.config.router, ); - dataFetcher.stopDataFetching(); - - return rpParams; + return [ + { + ...optimalSwapExchange, + data: { + ...optimalSwapExchange.data, + routerParams, + }, + }, + { + deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), + }, + ]; } getAdapterParam( @@ -202,10 +198,11 @@ export class SushiSwapV3 extends UniswapV3 { destToken: string, srcAmount: string, destAmount: string, - data: SushiSwapV3Data, + data: UniswapV3Data, side: SwapSide, ): AdapterExchangeParam { - console.log('getAdapterParam: ', data.rpParams); + + console.log('DATA ROUTE PARAMS: ', data.routerParams); const payload = this.abiCoder.encodeParameter( { @@ -219,12 +216,12 @@ export class SushiSwapV3 extends UniswapV3 { }, }, { - tokenIn: data.rpParams!.tokenIn, - amountIn: data.rpParams!.amountIn, - tokenOut: data.rpParams!.tokenOut, - amountOutMin: data.rpParams!.amountOutMin, - to: data.rpParams!.to, - route: data.rpParams!.routeCode, + tokenIn: data.routerParams!.tokenIn, + amountIn: data.routerParams!.amountIn, + tokenOut: data.routerParams!.tokenOut, + amountOutMin: data.routerParams!.amountOutMin, + to: data.routerParams!.to, + route: data.routerParams!.routeCode, }, ); @@ -240,12 +237,76 @@ export class SushiSwapV3 extends UniswapV3 { destToken: string, srcAmount: string, destAmount: string, - data: SushiSwapV3Data, + data: UniswapV3Data, ): Promise { + const web3Client = createPublicClient({ + transport: http(generateConfig(this.network).privateHttpProvider), + chain: getViemChain(this.network), + }); + + const dataFetcher = new DataFetcher( + this.network, + web3Client, + ); - const routerParams = await this.getSushiV3Params(srcToken, destToken, destAmount); + dataFetcher.startDataFetching([LiquidityProviders.SushiSwapV3]); - console.log('getSimpleParam: ', routerParams); + const callData: MultiCallParams[] = [ + { + target: srcToken, + callData: this.erc20Interface.encodeFunctionData('decimals'), + decodeFunction: uint256DecodeToNumber, + }, + { + target: destToken, + callData: this.erc20Interface.encodeFunctionData('decimals'), + decodeFunction: uint256DecodeToNumber, + } + ]; + + const [decimals0, decimals1] = + await this.dexHelper.multiWrapper.tryAggregate( + false, + callData, + undefined, + this.dexHelper.multiWrapper.defaultBatchSize, + false, + ); + + const fromToken = new SushiToken({ + address: srcToken, + decimals: decimals0.returnData, + chainId: this.network, + }); + + const toToken = new SushiToken({ + address: destToken, + decimals: decimals1.returnData, + chainId: this.network, + }); + + await dataFetcher.fetchPoolsForToken(fromToken, toToken); + + const pcMap = dataFetcher.getCurrentPoolCodeMap(fromToken, toToken); + + const route = Router.findBestRoute( + pcMap, + this.network, + fromToken, + BigNumber.from(srcAmount), + toToken, + 50e9, + [LiquidityProviders.SushiSwapV3], + ); + + const routerParams = Router.routeProcessor2Params( + pcMap, + route, + fromToken, + toToken, + this.augustusAddress, + this.config.router, + ); const swapData = this.routerIface.encodeFunctionData('processRoute', [ routerParams.tokenIn, @@ -256,6 +317,8 @@ export class SushiSwapV3 extends UniswapV3 { routerParams.routeCode, ]); + dataFetcher.stopDataFetching(); + return this.buildSimpleParamWithoutWETHConversion( srcToken, srcAmount, diff --git a/src/dex/sushiswap-v3/types.ts b/src/dex/sushiswap-v3/types.ts deleted file mode 100644 index 347136af5..000000000 --- a/src/dex/sushiswap-v3/types.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Address, NumberAsString } from '../../types'; -import { RPParams } from '@sushiswap/router'; - -export type SushiSwapV3Data = { - path: { - tokenIn: Address; - tokenOut: Address; - fee: NumberAsString; - }[]; - isApproved?: boolean; - rpParams?: RPParams; -}; diff --git a/src/dex/uniswap-v3/types.ts b/src/dex/uniswap-v3/types.ts index a06a8cd66..381ece50f 100644 --- a/src/dex/uniswap-v3/types.ts +++ b/src/dex/uniswap-v3/types.ts @@ -61,7 +61,7 @@ export type UniswapV3Data = { fee: NumberAsString; }[]; isApproved?: boolean; - rpParams?: RPParams; + routerParams?: RPParams; }; export type DecodeStateMultiCallFunc = ( diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index 12143c4dc..34323fa65 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -31,6 +31,7 @@ import { SmartToken, StateOverrides } from './smart-tokens'; import { GIFTER_ADDRESS } from './constants-e2e'; import { generateDeployBytecode, sleep } from './utils'; import { assert } from 'ts-essentials'; +import * as util from 'util'; export const testingEndpoint = process.env.E2E_TEST_ENDPOINT; @@ -368,6 +369,7 @@ export async function testE2E( poolIdentifiers, transferFees, ); + console.log('PRICE ROUTE: ', util.inspect(priceRoute, false, null, true)); expect(parseFloat(priceRoute.destAmount)).toBeGreaterThan(0); // Calculate slippage. Default is 1% From 7bc84ff9f8dee0786fb4d00e419213dc970ef063 Mon Sep 17 00:00:00 2001 From: Verisana Date: Mon, 28 Aug 2023 18:07:41 +0100 Subject: [PATCH 164/833] test: add more tests for states --- src/dex/algebra/algebra-integration.test.ts | 24 +++++++++++++++++++++ src/dex/algebra/algebra.ts | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/dex/algebra/algebra-integration.test.ts b/src/dex/algebra/algebra-integration.test.ts index a244391d6..002b4292f 100644 --- a/src/dex/algebra/algebra-integration.test.ts +++ b/src/dex/algebra/algebra-integration.test.ts @@ -521,6 +521,30 @@ describe('Algebra', function () { expect(Array.isArray(stateManually)).toBeTruthy(); }); + it('stMATIC/WETH generate state is working for problematic pool', async function () { + const pool = (await algebra.getPool( + '0x83b874c1e09d316059d929da402dcb1a98e92082', + '0x4f9a0e7fd2bf6067db6994cf12e4495df938e6e9', + blockNumber, + )) as AlgebraEventPoolV1_1; + + const stateManually = await pool.fetchStateManually(blockNumber); + // We can not compare with usual way, because this pool can not be requested normally + expect(Array.isArray(stateManually)).toBeTruthy(); + }); + + it('WETH/USDC generate state is working for problematic pool', async function () { + const pool = (await algebra.getPool( + '0x4f9a0e7fd2bf6067db6994cf12e4495df938e6e9', + '0xa8ce8aee21bc2a48a5ef670afcc9274c7bbbc035', + blockNumber, + )) as AlgebraEventPoolV1_1; + + const stateManually = await pool.fetchStateManually(blockNumber); + // We can not compare with usual way, because this pool can not be requested normally + expect(Array.isArray(stateManually)).toBeTruthy(); + }); + it('recognize pool does not exist error', async function () { const pool = (await algebra.getPool( '0x8aaebb46e1742f4623e6e1621f909f01846ca5e2', diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 0178f2307..3b1f55ae5 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -257,7 +257,7 @@ export class Algebra extends SimpleExchange implements IDex { e, ); } else { - // on unkown error mark as failed and increase retryCount for retry init strategy + // on unknown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, From 2ba99c0f1de03c0f880d77dca24d7e1f90bf8345 Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 29 Aug 2023 11:01:11 +0100 Subject: [PATCH 165/833] style: rename files to dash --- src/dex/{QuickPerps => quick-perps}/config.ts | 0 src/dex/{QuickPerps => quick-perps}/fast-price-feed.ts | 0 src/dex/{QuickPerps => quick-perps}/pool.ts | 0 .../quick-perps-e2e.test.ts} | 0 .../quick-perps-events.test.ts} | 0 .../quick-perps-integration.test.ts} | 0 src/dex/{QuickPerps/quickPerps.ts => quick-perps/quick-perps.ts} | 0 src/dex/{QuickPerps => quick-perps}/types.ts | 0 src/dex/{QuickPerps => quick-perps}/usdq.ts | 0 src/dex/{QuickPerps => quick-perps}/vault-price-feed.ts | 0 src/dex/{QuickPerps => quick-perps}/vault-utils.ts | 0 src/dex/{QuickPerps => quick-perps}/vault.ts | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename src/dex/{QuickPerps => quick-perps}/config.ts (100%) rename src/dex/{QuickPerps => quick-perps}/fast-price-feed.ts (100%) rename src/dex/{QuickPerps => quick-perps}/pool.ts (100%) rename src/dex/{QuickPerps/quickPerps-e2e.test.ts => quick-perps/quick-perps-e2e.test.ts} (100%) rename src/dex/{QuickPerps/quickPerps-events.test.ts => quick-perps/quick-perps-events.test.ts} (100%) rename src/dex/{QuickPerps/quickPerps-integration.test.ts => quick-perps/quick-perps-integration.test.ts} (100%) rename src/dex/{QuickPerps/quickPerps.ts => quick-perps/quick-perps.ts} (100%) rename src/dex/{QuickPerps => quick-perps}/types.ts (100%) rename src/dex/{QuickPerps => quick-perps}/usdq.ts (100%) rename src/dex/{QuickPerps => quick-perps}/vault-price-feed.ts (100%) rename src/dex/{QuickPerps => quick-perps}/vault-utils.ts (100%) rename src/dex/{QuickPerps => quick-perps}/vault.ts (100%) diff --git a/src/dex/QuickPerps/config.ts b/src/dex/quick-perps/config.ts similarity index 100% rename from src/dex/QuickPerps/config.ts rename to src/dex/quick-perps/config.ts diff --git a/src/dex/QuickPerps/fast-price-feed.ts b/src/dex/quick-perps/fast-price-feed.ts similarity index 100% rename from src/dex/QuickPerps/fast-price-feed.ts rename to src/dex/quick-perps/fast-price-feed.ts diff --git a/src/dex/QuickPerps/pool.ts b/src/dex/quick-perps/pool.ts similarity index 100% rename from src/dex/QuickPerps/pool.ts rename to src/dex/quick-perps/pool.ts diff --git a/src/dex/QuickPerps/quickPerps-e2e.test.ts b/src/dex/quick-perps/quick-perps-e2e.test.ts similarity index 100% rename from src/dex/QuickPerps/quickPerps-e2e.test.ts rename to src/dex/quick-perps/quick-perps-e2e.test.ts diff --git a/src/dex/QuickPerps/quickPerps-events.test.ts b/src/dex/quick-perps/quick-perps-events.test.ts similarity index 100% rename from src/dex/QuickPerps/quickPerps-events.test.ts rename to src/dex/quick-perps/quick-perps-events.test.ts diff --git a/src/dex/QuickPerps/quickPerps-integration.test.ts b/src/dex/quick-perps/quick-perps-integration.test.ts similarity index 100% rename from src/dex/QuickPerps/quickPerps-integration.test.ts rename to src/dex/quick-perps/quick-perps-integration.test.ts diff --git a/src/dex/QuickPerps/quickPerps.ts b/src/dex/quick-perps/quick-perps.ts similarity index 100% rename from src/dex/QuickPerps/quickPerps.ts rename to src/dex/quick-perps/quick-perps.ts diff --git a/src/dex/QuickPerps/types.ts b/src/dex/quick-perps/types.ts similarity index 100% rename from src/dex/QuickPerps/types.ts rename to src/dex/quick-perps/types.ts diff --git a/src/dex/QuickPerps/usdq.ts b/src/dex/quick-perps/usdq.ts similarity index 100% rename from src/dex/QuickPerps/usdq.ts rename to src/dex/quick-perps/usdq.ts diff --git a/src/dex/QuickPerps/vault-price-feed.ts b/src/dex/quick-perps/vault-price-feed.ts similarity index 100% rename from src/dex/QuickPerps/vault-price-feed.ts rename to src/dex/quick-perps/vault-price-feed.ts diff --git a/src/dex/QuickPerps/vault-utils.ts b/src/dex/quick-perps/vault-utils.ts similarity index 100% rename from src/dex/QuickPerps/vault-utils.ts rename to src/dex/quick-perps/vault-utils.ts diff --git a/src/dex/QuickPerps/vault.ts b/src/dex/quick-perps/vault.ts similarity index 100% rename from src/dex/QuickPerps/vault.ts rename to src/dex/quick-perps/vault.ts From 50e9077d92b3862ce14afe42b7b685bf6486f5c5 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 29 Aug 2023 13:09:29 +0300 Subject: [PATCH 166/833] re-implement as one to one univ3 fork --- package.json | 2 - src/abi/sushiswap-v3/QuoterV2.json | 267 - src/abi/sushiswap-v3/RouterProcessor3.json | 289 - src/config.ts | 4 +- src/dex/index.ts | 2 - src/dex/sushiswap-v3/config.ts | 137 - src/dex/sushiswap-v3/constants.ts | 32 - src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts | 412 -- .../sushiswap-v3-integration.test.ts | 331 - src/dex/sushiswap-v3/sushiswap-v3-original.ts | 1017 --- src/dex/sushiswap-v3/sushiswap-v3.ts | 331 - src/dex/uniswap-v3/config.ts | 93 +- .../sushiswap-v3-integration.test.ts | 111 + src/dex/uniswap-v3/types.ts | 2 - src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 403 ++ .../uniswap-v3/uniswap-v3-integration.test.ts | 222 + src/dex/uniswap-v3/uniswap-v3.ts | 8 +- tests/utils-e2e.ts | 2 - yarn.lock | 5867 +---------------- 19 files changed, 951 insertions(+), 8581 deletions(-) delete mode 100644 src/abi/sushiswap-v3/QuoterV2.json delete mode 100644 src/abi/sushiswap-v3/RouterProcessor3.json delete mode 100644 src/dex/sushiswap-v3/config.ts delete mode 100644 src/dex/sushiswap-v3/constants.ts delete mode 100644 src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts delete mode 100644 src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts delete mode 100644 src/dex/sushiswap-v3/sushiswap-v3-original.ts delete mode 100644 src/dex/sushiswap-v3/sushiswap-v3.ts create mode 100644 src/dex/uniswap-v3/sushiswap-v3-integration.test.ts diff --git a/package.json b/package.json index de49a2b36..8609a6a0e 100644 --- a/package.json +++ b/package.json @@ -54,8 +54,6 @@ "@hashflow/sdk": "1.2.4", "@hashflow/taker-js": "0.0.2", "@paraswap/core": "1.1.0", - "@sushiswap/router": "^0.0.12", - "@sushiswap/viem-config": "^1.0.2", "async": "^3.2.4", "axios": "0.26.0", "bignumber.js": "9.1.0", diff --git a/src/abi/sushiswap-v3/QuoterV2.json b/src/abi/sushiswap-v3/QuoterV2.json deleted file mode 100644 index ce1374e69..000000000 --- a/src/abi/sushiswap-v3/QuoterV2.json +++ /dev/null @@ -1,267 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_factory", - "type": "address" - }, - { - "internalType": "address", - "name": "_WETH9", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "WETH9", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "factory", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "path", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - } - ], - "name": "quoteExactInput", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint160[]", - "name": "sqrtPriceX96AfterList", - "type": "uint160[]" - }, - { - "internalType": "uint32[]", - "name": "initializedTicksCrossedList", - "type": "uint32[]" - }, - { - "internalType": "uint256", - "name": "gasEstimate", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint24", - "name": "fee", - "type": "uint24" - }, - { - "internalType": "uint160", - "name": "sqrtPriceLimitX96", - "type": "uint160" - } - ], - "internalType": "struct IQuoterV2.QuoteExactInputSingleParams", - "name": "params", - "type": "tuple" - } - ], - "name": "quoteExactInputSingle", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - }, - { - "internalType": "uint160", - "name": "sqrtPriceX96After", - "type": "uint160" - }, - { - "internalType": "uint32", - "name": "initializedTicksCrossed", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "gasEstimate", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "path", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "name": "quoteExactOutput", - "outputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint160[]", - "name": "sqrtPriceX96AfterList", - "type": "uint160[]" - }, - { - "internalType": "uint32[]", - "name": "initializedTicksCrossedList", - "type": "uint32[]" - }, - { - "internalType": "uint256", - "name": "gasEstimate", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint24", - "name": "fee", - "type": "uint24" - }, - { - "internalType": "uint160", - "name": "sqrtPriceLimitX96", - "type": "uint160" - } - ], - "internalType": "struct IQuoterV2.QuoteExactOutputSingleParams", - "name": "params", - "type": "tuple" - } - ], - "name": "quoteExactOutputSingle", - "outputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "uint160", - "name": "sqrtPriceX96After", - "type": "uint160" - }, - { - "internalType": "uint32", - "name": "initializedTicksCrossed", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "gasEstimate", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "amount0Delta", - "type": "int256" - }, - { - "internalType": "int256", - "name": "amount1Delta", - "type": "int256" - }, - { - "internalType": "bytes", - "name": "path", - "type": "bytes" - } - ], - "name": "uniswapV3SwapCallback", - "outputs": [], - "stateMutability": "view", - "type": "function" - } -] diff --git a/src/abi/sushiswap-v3/RouterProcessor3.json b/src/abi/sushiswap-v3/RouterProcessor3.json deleted file mode 100644 index d8959084f..000000000 --- a/src/abi/sushiswap-v3/RouterProcessor3.json +++ /dev/null @@ -1,289 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_bentoBox", - "type": "address" - }, - { - "internalType": "address[]", - "name": "priviledgedUserList", - "type": "address[]" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "name": "Route", - "type": "event" - }, - { - "inputs": [], - "name": "bentoBox", - "outputs": [ - { - "internalType": "contract IBentoBoxMinimal", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "route", - "type": "bytes" - } - ], - "name": "processRoute", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "resume", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "bool", - "name": "priviledge", - "type": "bool" - } - ], - "name": "setPriviledge", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "transferValueTo", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountValueTransfer", - "type": "uint256" - }, - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountOutMin", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "route", - "type": "bytes" - } - ], - "name": "transferValueAndprocessRoute", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "amount0Delta", - "type": "int256" - }, - { - "internalType": "int256", - "name": "amount1Delta", - "type": "int256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "uniswapV3SwapCallback", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/src/config.ts b/src/config.ts index ee352e017..45b466f84 100644 --- a/src/config.ts +++ b/src/config.ts @@ -277,8 +277,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], adapterAddresses: { ArbitrumAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9', - ArbitrumAdapter02: '0x902A1f552776D1f6D0614A902F6ba7bb608EDd2C', - ArbitrumBuyAdapter: '0xAFad34619549AD69f2e2e5266cbBe2eF0EbA6C49', + ArbitrumAdapter02: '0x3ad7f275E27AC579cA88e0b4765828242A9E8C49', + ArbitrumBuyAdapter: '0x6c33C7f6CBB4a428fe9ee31ca500a787c9f1525b', }, uniswapV2ExchangeRouterAddress: '0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC', diff --git a/src/dex/index.ts b/src/dex/index.ts index ffbbaf018..11302d4c3 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -70,7 +70,6 @@ import { SwaapV2 } from './swaap-v2/swaap-v2'; import { SpiritSwapV3 } from './quickswap/spiritswap-v3'; import { TraderJoeV21 } from './trader-joe-v2.1'; import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3'; -import { SushiSwapV3 } from './sushiswap-v3/sushiswap-v3'; import { Algebra } from './algebra/algebra'; const LegacyDexes = [ @@ -107,7 +106,6 @@ const Dexes = [ UniswapV3, Algebra, PancakeswapV3, - SushiSwapV3, BiSwap, MDEX, Dfyn, diff --git a/src/dex/sushiswap-v3/config.ts b/src/dex/sushiswap-v3/config.ts deleted file mode 100644 index 8421b9194..000000000 --- a/src/dex/sushiswap-v3/config.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { Network, SwapSide } from '../../constants'; -import { DexParams } from '../uniswap-v3/types'; -import { DexConfigMap, AdapterMappings } from '../../types'; -import { SUPPORTED_FEES } from '../uniswap-v3/config'; - -export const SushiSwapV3Config: DexConfigMap = { - SushiSwapV3: { - [Network.MAINNET]: { - factory: '0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F', - quoter: '0x64e8802FE490fa7cc61d3463958199161Bb608A7', - router: '0x827179dD56d07A7eeA32e3873493835da2866976', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-ethereum', - }, - [Network.POLYGON]: { - factory: '0x917933899c6a5f8e37f31e19f92cdbff7e8ff0e2', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-polygon', - }, - [Network.BSC]: { - factory: '0x126555dd55a39328F69400d6aE4F782Bd4C34ABb', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x400d75dAb26bBc18D163AEA3e83D9Ea68F6c1804', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x593F39A4Ba26A9c8ed2128ac95D109E8e403C485', - uniswapMulticall: '0x963Df249eD09c358A4819E39d9Cd5736c3087184', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-bsc', - }, - [Network.AVALANCHE]: { - factory: '0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x717b7948AA264DeCf4D780aa6914482e5F46Da3e', - supportedFees: SUPPORTED_FEES, - stateMulticall: '', - uniswapMulticall: '0x8C0F842791F03C095b6c633759224FcC9ACe68ea', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-avalanche', - }, - [Network.FANTOM]: { - factory: '0x7770978eED668a3ba661d51a773d3a992Fc9DDCB', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x2214A42d8e2A1d20635c2cb0664422c528B6A432', - supportedFees: SUPPORTED_FEES, - stateMulticall: '', - uniswapMulticall: '0xB1395e098c0a847CC719Bcf1Fc8114421a9F8232', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-fantom', - }, - [Network.ARBITRUM]: { - factory: '0x1af415a1eba07a4986a52b6f2e7de7003d82231e', - quoter: '0x0524E833cCD057e4d7A296e3aaAb9f7675964Ce1', - router: '0xfc506AaA1340b4dedFfd88bE278bEe058952D674', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-arbitrum', - }, - [Network.OPTIMISM]: { - factory: '0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x4C5D5234f232BD2D76B96aA33F5AE4FCF0E4BFAb', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x4FF0dEC5f9a763Aa1E5C2a962aa6f4eDFeE4f9eA', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-optimism', - }, - }, -}; - -export const Adapters: Record = { - [Network.MAINNET]: { - [SwapSide.SELL]: [{ name: 'Adapter01', index: 6 }], - [SwapSide.BUY]: [{ name: 'BuyAdapter', index: 2 }], - }, - [Network.BSC]: { - [SwapSide.SELL]: [{ name: 'BscAdapter02', index: 4 }], - [SwapSide.BUY]: [{ name: 'BscBuyAdapter', index: 5 }], - }, - [Network.POLYGON]: { - [SwapSide.SELL]: [{ name: 'PolygonAdapter01', index: 13 }], - [SwapSide.BUY]: [{ name: 'PolygonBuyAdapter', index: 2 }], - }, - [Network.ARBITRUM]: { - [SwapSide.SELL]: [{ name: 'ArbitrumAdapter02', index: 6 }], - [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 8 }], - }, - [Network.OPTIMISM]: { - [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 3 }], - [SwapSide.BUY]: [{ name: 'OptimismBuyAdapter', index: 2 }], - }, - [Network.FANTOM]: { - [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 11 }], - [SwapSide.BUY]: [{ name: 'FantomBuyAdapter', index: 3 }], - }, - [Network.ZKEVM]: { - [SwapSide.SELL]: [{ name: 'PolygonZkEvmAdapter01', index: 1 }], - [SwapSide.BUY]: [{ name: 'PolygonZkEvmBuyAdapter', index: 1 }], - }, - [Network.AVALANCHE]: { - [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 5 }], - [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 6 }], - }, - [Network.FANTOM]: { - [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 11 }], - [SwapSide.BUY]: [{ name: 'FantomBuyAdapter', index: 3 }], - }, -}; diff --git a/src/dex/sushiswap-v3/constants.ts b/src/dex/sushiswap-v3/constants.ts deleted file mode 100644 index e61b75fe3..000000000 --- a/src/dex/sushiswap-v3/constants.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { - arbitrum, - avalanche, - bsc, - fantom, - mainnet, - optimism, - polygon, -} from '@sushiswap/viem-config'; -import { Network } from '../../constants'; -import { Chain } from 'viem'; - -export function getViemChain(network: Network): Chain { - switch (network) { - case Network.ARBITRUM: - return arbitrum; - case Network.AVALANCHE: - return avalanche; - case Network.BSC: - return bsc; - case Network.FANTOM: - return fantom; - case Network.MAINNET: - return mainnet; - case Network.OPTIMISM: - return optimism; - case Network.POLYGON: - return polygon; - default: - throw new Error(`Chain with id ${network} is not supported`); - } -} diff --git a/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts b/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts deleted file mode 100644 index 65cf67023..000000000 --- a/src/dex/sushiswap-v3/sushiswap-v3-e2e.test.ts +++ /dev/null @@ -1,412 +0,0 @@ -import dotenv from 'dotenv'; -dotenv.config(); - -import { ContractMethod, Network, SwapSide } from '../../constants'; -import { - Holders, - NativeTokenSymbols, - Tokens, -} from '../../../tests/constants-e2e'; -import { StaticJsonRpcProvider } from '@ethersproject/providers'; -import { generateConfig } from '../../config'; -import { testE2E } from '../../../tests/utils-e2e'; - -function testForNetwork( - network: Network, - dexKey: string, - tokenASymbol: string, - tokenBSymbol: string, - tokenAAmount: string, - tokenBAmount: string, - nativeTokenAmount: string, - slippage?: number | undefined, -) { - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - const tokens = Tokens[network]; - const holders = Holders[network]; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ], - ], - [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - ContractMethod.buy, - ], - ], - ]); - - describe(`${network}`, () => { - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - 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, - 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, - 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, - network, - provider, - undefined, - undefined, - undefined, - slippage, - ); - }); - }); - }); - }), - ); - }); -} - -describe('SushiSwapV3 E2E', () => { - const dexKey = 'SushiSwapV3'; - - describe('MAINNET', () => { - const network = Network.MAINNET; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; - - const tokenAAmount: string = '111110000'; - const tokenBAmount: string = '1100000000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); - - describe('ARBITRUM', () => { - const network = Network.ARBITRUM; - - const tokenASymbol: string = 'USDT'; - const tokenBSymbol: string = 'USDCe'; - - const tokenAAmount: string = '11111000000'; - const tokenBAmount: string = '10000000000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); - - describe('POLYGON', () => { - const network = Network.POLYGON; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; - - const tokenAAmount: string = '21111000'; - const tokenBAmount: string = '200000000'; - const nativeTokenAmount = '110000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); - - describe('BSC', () => { - const network = Network.BSC; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ContractMethod.directUniV3Swap, - ], - ], - [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - ContractMethod.buy, - ContractMethod.directUniV3Buy, - ], - ], - ]); - - const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ - [ - { - name: 'USDC', - sellAmount: '100000000000000000000', - buyAmount: '100000000000000000000', - }, - { - name: 'USDT', - sellAmount: '100000000000000000000', - buyAmount: '100000000000000000000', - }, - ], - [ - { - name: 'BNB', - sellAmount: '1000000000000000000', - buyAmount: '10000000000000000000', - }, - { - name: 'USDT', - sellAmount: '1000000000000000000000', - buyAmount: '20000000000000000', - }, - ], - ]; - - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - contractMethods.forEach((contractMethod: ContractMethod) => { - pairs.forEach(pair => { - describe(`${contractMethod}`, () => { - it(`${pair[0].name} -> ${pair[1].name}`, async () => { - await testE2E( - tokens[pair[0].name], - tokens[pair[1].name], - holders[pair[0].name], - side === SwapSide.SELL - ? pair[0].sellAmount - : pair[0].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${pair[1].name} -> ${pair[0].name}`, async () => { - await testE2E( - tokens[pair[1].name], - tokens[pair[0].name], - holders[pair[1].name], - side === SwapSide.SELL - ? pair[1].sellAmount - : pair[1].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }); - }); - }), - ); - }); - - describe('AVALANCHE', () => { - const network = Network.AVALANCHE; - - const tokenASymbol: string = 'USDT'; - const tokenBSymbol: string = 'USDC'; - - const tokenAAmount: string = '111110'; - const tokenBAmount: string = '100000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); - - describe('FANTOM', () => { - const network = Network.FANTOM; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ContractMethod.directUniV3Swap, - ], - ], - [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - ContractMethod.buy, - ContractMethod.directUniV3Buy, - ], - ], - ]); - - const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ - [ - { - name: 'USDC', - sellAmount: '111110', - buyAmount: '111110', - }, - { - name: 'FUSDT', - sellAmount: '111110', - buyAmount: '111110', - }, - ], - // [ - // { - // name: 'BNB', - // sellAmount: '1000000000000000000', - // buyAmount: '10000000000000000000', - // }, - // { name: 'USDT', sellAmount: '1000000000000000000000', buyAmount: '20000000000000000' }, - // ], - ]; - - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - contractMethods.forEach((contractMethod: ContractMethod) => { - pairs.forEach(pair => { - describe(`${contractMethod}`, () => { - it(`${pair[0].name} -> ${pair[1].name}`, async () => { - await testE2E( - tokens[pair[0].name], - tokens[pair[1].name], - holders[pair[0].name], - side === SwapSide.SELL - ? pair[0].sellAmount - : pair[0].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${pair[1].name} -> ${pair[0].name}`, async () => { - await testE2E( - tokens[pair[1].name], - tokens[pair[0].name], - holders[pair[1].name], - side === SwapSide.SELL - ? pair[1].sellAmount - : pair[1].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }); - }); - }), - ); - }); - - describe('OPTIMISM', () => { - const network = Network.OPTIMISM; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; - - const tokenAAmount: string = '111110000'; - const tokenBAmount: string = '10000000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); -}); diff --git a/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts b/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts deleted file mode 100644 index 5f386bc60..000000000 --- a/src/dex/sushiswap-v3/sushiswap-v3-integration.test.ts +++ /dev/null @@ -1,331 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); -import { SushiSwapV3 } from '../sushiswap-v3/sushiswap-v3'; -import { Network, SwapSide } from '../../constants'; -import { DummyDexHelper, IDexHelper } from '../../dex-helper'; -import { Tokens } from '../../../tests/constants-e2e'; -import { BI_POWS } from '../../bigint-constants'; -import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; -import { Interface, Result } from '@ethersproject/abi'; -import SushiswapV3QuoterV2ABI from '../../abi/sushiswap-v3/QuoterV2.json'; -import { Address } from '@paraswap/core'; - -const quoterIface = new Interface(SushiswapV3QuoterV2ABI); - -function getReaderCalldata( - exchangeAddress: string, - readerIface: Interface, - amounts: bigint[], - funcName: string, - tokenIn: Address, - tokenOut: Address, - fee: bigint, -) { - return amounts.map(amount => ({ - target: exchangeAddress, - callData: readerIface.encodeFunctionData(funcName, [ - [tokenIn, tokenOut, amount.toString(), fee.toString(), 0], - ]), - })); -} - -function decodeReaderResult( - results: Result, - readerIface: Interface, - funcName: string, -) { - return results.map(result => { - const parsed = readerIface.decodeFunctionResult(funcName, result); - return BigInt(parsed[0]._hex); - }); -} - -async function checkOnChainPricing( - dexHelper: IDexHelper, - sushiSwapV3: SushiSwapV3, - funcName: string, - blockNumber: number, - exchangeAddress: string, - prices: bigint[], - tokenIn: Address, - tokenOut: Address, - fee: bigint, - _amounts: bigint[], -) { - // Quoter address - // const exchangeAddress = '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'; - const readerIface = quoterIface; - - // const sum = prices.reduce((acc, curr) => (acc += curr), 0n); - // - // if (sum === 0n) { - // console.log( - // `Prices were not calculated for tokenIn=${tokenIn}, tokenOut=${tokenOut}, fee=${fee.toString()}. Most likely price impact is too big for requested amount`, - // ); - // return false; - // } - - const readerCallData = getReaderCalldata( - exchangeAddress, - readerIface, - _amounts.slice(1), - funcName, - tokenIn, - tokenOut, - fee, - ); - - let readerResult; - try { - readerResult = ( - await dexHelper.multiContract.methods - .aggregate(readerCallData) - .call({}, blockNumber) - ).returnData; - } catch (e) { - console.log( - `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, - e, - ); - return false; - } - - const expectedPrices = [0n].concat( - decodeReaderResult(readerResult, readerIface, funcName), - ); - - console.log('EXPECTED PRICES: ', expectedPrices); - - let firstZeroIndex = prices.slice(1).indexOf(0n); - - // we skipped first, so add +1 on result - firstZeroIndex = firstZeroIndex === -1 ? prices.length : firstZeroIndex; - - // Compare only the ones for which we were able to calculate prices - expect(prices.slice(0, firstZeroIndex)).toEqual( - expectedPrices.slice(0, firstZeroIndex), - ); - return true; -} - -describe('SushiSwapV3', () => { - const dexKey = 'SushiSwapV3'; - - describe('Mainnet', () => { - let blockNumber: number; - let sushiSwapV3: SushiSwapV3; - let sushiSwapV3Mainnet: SushiSwapV3; - - const network = Network.MAINNET; - const dexHelper = new DummyDexHelper(network); - const TokenASymbol = 'USDC'; - const TokenA = Tokens[network][TokenASymbol]; - - const TokenBSymbol = 'USDT'; - const TokenB = Tokens[network][TokenBSymbol]; - - beforeEach(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - sushiSwapV3 = new SushiSwapV3(network, dexKey, dexHelper); - sushiSwapV3Mainnet = new SushiSwapV3(Network.MAINNET, dexKey, dexHelper); - }); - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - const amounts = [0n, BI_POWS[6], 2000000n]; - - const pools = await sushiSwapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.SELL, - blockNumber, - ); - console.log( - `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, - pools, - ); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await sushiSwapV3.getPricesVolume( - TokenA, - TokenB, - amounts, - SwapSide.SELL, - blockNumber, - pools, - ); - console.log( - `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, - poolPrices, - ); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); - - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = sushiSwapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - dexHelper, - sushiSwapV3, - 'quoteExactInputSingle', - blockNumber, - '0x64e8802FE490fa7cc61d3463958199161Bb608A7', - price.prices, - TokenA.address, - TokenB.address, - fee, - amounts, - ); - if (res === false) falseChecksCounter++; - }), - ); - - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - const amounts = [0n, BI_POWS[6], 2000000n]; - - const pools = await sushiSwapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.BUY, - blockNumber, - ); - console.log( - `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, - pools, - ); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await sushiSwapV3.getPricesVolume( - TokenA, - TokenB, - amounts, - SwapSide.BUY, - blockNumber, - pools, - ); - console.log( - `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, - poolPrices, - ); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); - - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = sushiSwapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - dexHelper, - sushiSwapV3, - 'quoteExactOutputSingle', - blockNumber, - '0x64e8802FE490fa7cc61d3463958199161Bb608A7', - price.prices, - TokenA.address, - TokenB.address, - fee, - amounts, - ); - if (res === false) falseChecksCounter++; - }), - ); - - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - it('getTopPoolsForToken', async function () { - const poolLiquidity = await sushiSwapV3.getTopPoolsForToken( - TokenB.address, - 10, - ); - console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); - - checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); - }); - }); - - describe('Arbitrum', () => { - let blockNumber: number; - let sushiSwapV3: SushiSwapV3; - let sushiSwapV3Mainnet: SushiSwapV3; - - const network = Network.ARBITRUM; - const dexHelper = new DummyDexHelper(network); - const TokenASymbol = 'USDCe'; - const TokenA = Tokens[network][TokenASymbol]; - - const TokenBSymbol = 'USDT'; - const TokenB = Tokens[network][TokenBSymbol]; - - beforeEach(async () => { - // blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - blockNumber = 125789437; - sushiSwapV3 = new SushiSwapV3(network, dexKey, dexHelper); - sushiSwapV3Mainnet = new SushiSwapV3(Network.ARBITRUM, dexKey, dexHelper); - }); - - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - const amounts = [0n, 100000000n, 200000000n]; - - const pools = await sushiSwapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.BUY, - blockNumber, - ); - console.log( - `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, - pools, - ); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await sushiSwapV3.getPricesVolume( - TokenA, - TokenB, - amounts, - SwapSide.BUY, - blockNumber, - pools, - ); - console.log( - `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, - poolPrices, - ); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); - - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = sushiSwapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - dexHelper, - sushiSwapV3, - 'quoteExactOutputSingle', - blockNumber, - '0x0524E833cCD057e4d7A296e3aaAb9f7675964Ce1', - price.prices, - TokenA.address, - TokenB.address, - fee, - amounts, - ); - if (res === false) falseChecksCounter++; - }), - ); - - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - }); -}); diff --git a/src/dex/sushiswap-v3/sushiswap-v3-original.ts b/src/dex/sushiswap-v3/sushiswap-v3-original.ts deleted file mode 100644 index 19ef285d4..000000000 --- a/src/dex/sushiswap-v3/sushiswap-v3-original.ts +++ /dev/null @@ -1,1017 +0,0 @@ -import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; -import { - Token, - Address, - ExchangePrices, - PoolPrices, - AdapterExchangeParam, - SimpleExchangeParam, - PoolLiquidity, - Logger, - NumberAsString, -} from '../../types'; -import { SwapSide, Network, CACHE_PREFIX } from '../../constants'; -import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { - getBigIntPow, - getDexKeysWithNetwork, - interpolate, - isTruthy, -} from '../../utils'; -import { IDex } from '../../dex/idex'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { - DexParams, - OutputResult, - PoolState, - QuoteExactInputSingleParams, - QuoteExactOutputSingleParams, - UniswapV3Data as SushiswapV3Data, -} from './types'; -import { - SimpleExchange, - getLocalDeadlineAsFriendlyPlaceholder, -} from '../simple-exchange'; -import { SushiswapV3Config, Adapters } from './config'; -import { SushiswapV3EventPool } from './sushiswap-v3-pool'; -import { Interface, defaultAbiCoder } from 'ethers/lib/utils'; -import { AbiItem } from 'web3-utils'; -import { Contract } from 'web3-eth-contract'; -import { pack } from '@ethersproject/solidity'; -import { - UNISWAPV3_EFFICIENCY_FACTOR, - UNISWAPV3_POOL_SEARCH_OVERHEAD, - UNISWAPV3_TICK_BASE_OVERHEAD, - UNISWAPV3_TICK_GAS_COST, - ViemChain, -} from './constants'; -import { uniswapV3Math } from '../uniswap-v3/contract-math/uniswap-v3-math'; -import { BalanceRequest, getBalances } from '../../lib/tokens/balancer-fetcher'; -import { - AssetType, - DEFAULT_ID_ERC20, - DEFAULT_ID_ERC20_AS_STRING, -} from '../../lib/tokens/types'; -import { DataFetcher, LiquidityProviders, Router } from '@sushiswap/router'; -import { ChainId } from '@sushiswap/chain'; -import { createPublicClient, http } from 'viem'; - -import SushiswapV3RouterABI from '../../abi/sushiswap-v3/RouterProcessor3.json'; -import SushiswapV3QuoterV2ABI from '../../abi/sushiswap-v3/QuoterV2.json'; -import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; -import UniswapV3StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; -import { generateConfig } from '../../config'; -import { BigNumber } from 'ethers'; -import { getToken } from './token'; -import _ from 'lodash'; -import { UniswapV3Config } from '../uniswap-v3/config'; - -const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 60 * 60 * 24 * 1000; // 24 hours -const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 30 * 60 * 1000; // Once in 30 minutes -const UNISWAPV3_QUOTE_GASLIMIT = 200_000; - -export class SushiswapV3 - extends SimpleExchange - implements IDex -{ - readonly eventPools: Record = {}; - - readonly hasConstantPriceLargeAmounts = false; - readonly needWrapNative = true; - - intervalTask?: NodeJS.Timeout; - - readonly isFeeOnTransferSupported = false; - - public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(SushiswapV3Config); - - logger: Logger; - - private uniswapMulti: Contract; - private stateMultiContract: Contract; - - private notExistingPoolSetKey: string; - - constructor( - readonly network: Network, - readonly dexKey: string, - readonly dexHelper: IDexHelper, - protected adapters = Adapters[network] || {}, - readonly routerIface = new Interface(SushiswapV3RouterABI), - readonly quoterIface = new Interface(SushiswapV3QuoterV2ABI), - readonly config = SushiswapV3Config[dexKey][network], - ) { - super(dexHelper, dexKey); - this.logger = dexHelper.getLogger(dexKey + '-' + network); - - this.uniswapMulti = new this.dexHelper.web3Provider.eth.Contract( - UniswapV3MultiABI as AbiItem[], - this.config.uniswapMulticall, - ); - this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( - UniswapV3StateMulticallABI as AbiItem[], - this.config.stateMulticall, - ); - - // To receive revert reasons - this.dexHelper.web3Provider.eth.handleRevert = false; - - // Normalise once all config addresses and use across all scenarios - this.config = this._toLowerForAllConfigAddresses(); - - this.notExistingPoolSetKey = - `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); - } - - // Initialize pricing is called once in the start of - // pricing service. It is intended to setup the integration - // for pricing requests. It is optional for a DEX to - // implement this function - async initializePricing(blockNumber: number) { - if (!this.dexHelper.config.isSlave) { - const cleanExpiredNotExistingPoolsKeys = async () => { - const maxTimestamp = - Date.now() - UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS; - await this.dexHelper.cache.zremrangebyscore( - this.notExistingPoolSetKey, - 0, - maxTimestamp, - ); - }; - - this.intervalTask = setInterval( - cleanExpiredNotExistingPoolsKeys.bind(this), - UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS, - ); - } - } - - get supportedFees() { - return this.config.supportedFees; - } - - // Returns the list of contract adapters (name and index) - // for a buy/sell. Return null if there are no adapters. - getAdapters(side: SwapSide): { name: string; index: number }[] | null { - return this.adapters[side] ? this.adapters[side] : null; - } - - getPoolIdentifier(srcAddress: Address, destAddress: Address, fee: bigint) { - const tokenAddresses = this._sortTokens(srcAddress, destAddress).join('_'); - return `${this.dexKey}_${tokenAddresses}_${fee}`; - } - - // Returns pool prices for amounts. - // If limitPools is defined only pools in limitPools - // should be used. If limitPools is undefined then - // any pools can be used. - async getPricesVolume( - srcToken: Token, - destToken: Token, - amounts: bigint[], - side: SwapSide, - blockNumber: number, - limitPools?: string[], - ): Promise> { - try { - const _srcToken = this.dexHelper.config.wrapETH(srcToken); - const _destToken = this.dexHelper.config.wrapETH(destToken); - - const [_srcAddress, _destAddress] = this._getLoweredAddresses( - _srcToken, - _destToken, - ); - - if (_srcAddress === _destAddress) return null; - - let selectedPools: SushiswapV3EventPool[] = []; - - if (!limitPools) { - selectedPools = ( - await Promise.all( - this.supportedFees.map(async fee => { - const locallyFoundPool = - this.eventPools[ - this.getPoolIdentifier(_srcAddress, _destAddress, fee) - ]; - if (locallyFoundPool) return locallyFoundPool; - - const newlyFetchedPool = await this.getPool( - _srcAddress, - _destAddress, - fee, - blockNumber, - ); - return newlyFetchedPool; - }), - ) - ).filter(isTruthy); - } else { - const pairIdentifierWithoutFee = this.getPoolIdentifier( - _srcAddress, - _destAddress, - 0n, - // Trim from 0 fee postfix, so it become comparable - ).slice(0, -1); - - const poolIdentifiers = limitPools.filter(identifier => - identifier.startsWith(pairIdentifierWithoutFee), - ); - - selectedPools = ( - await Promise.all( - poolIdentifiers.map(async identifier => { - let locallyFoundPool = this.eventPools[identifier]; - if (locallyFoundPool) return locallyFoundPool; - - const [, srcAddress, destAddress, fee] = identifier.split('_'); - const newlyFetchedPool = await this.getPool( - srcAddress, - destAddress, - BigInt(fee), - blockNumber, - ); - return newlyFetchedPool; - }), - ) - ).filter(isTruthy); - } - - if (selectedPools.length === 0) return null; - - const poolsToUse = selectedPools.reduce( - (acc, pool) => { - let state = pool.getState(blockNumber); - if (state === null) { - this.logger.trace( - `${this.dexKey}: State === null. Fallback to rpc ${pool.name}`, - ); - acc.poolWithoutState.push(pool); - } else { - acc.poolWithState.push(pool); - } - return acc; - }, - { - poolWithState: [] as SushiswapV3EventPool[], - poolWithoutState: [] as SushiswapV3EventPool[], - }, - ); - - const rpcResultsPromise = this.getPricingFromRpc( - _srcToken, - _destToken, - amounts, - side, - poolsToUse.poolWithoutState, - ); - - const states = poolsToUse.poolWithState.map( - p => p.getState(blockNumber)!, - ); - - const unitAmount = getBigIntPow( - side == SwapSide.SELL ? _srcToken.decimals : _destToken.decimals, - ); - - const _amounts = [...amounts.slice(1)]; - - const [token0] = this._sortTokens(_srcAddress, _destAddress); - - const zeroForOne = token0 === _srcAddress ? true : false; - - const result = await Promise.all( - poolsToUse.poolWithState.map(async (pool, i) => { - const state = states[i]; - - if (state.liquidity <= 0n) { - this.logger.trace(`pool have 0 liquidity`); - return null; - } - - const balanceDestToken = - _destAddress === pool.token0 ? state.balance0 : state.balance1; - - const unitResult = this._getOutputs( - state, - [unitAmount], - zeroForOne, - side, - balanceDestToken, - ); - const pricesResult = this._getOutputs( - state, - _amounts, - zeroForOne, - side, - balanceDestToken, - ); - - if (!unitResult || !pricesResult) { - this.logger.debug('Prices or unit is not calculated'); - return null; - } - - const prices = [0n, ...pricesResult.outputs]; - const gasCost = [ - 0, - ...pricesResult.outputs.map((p, index) => { - if (p == 0n) { - return 0; - } else { - return ( - UNISWAPV3_POOL_SEARCH_OVERHEAD + - UNISWAPV3_TICK_BASE_OVERHEAD + - pricesResult.tickCounts[index] * UNISWAPV3_TICK_GAS_COST - ); - } - }), - ]; - return { - unit: unitResult.outputs[0], - prices, - data: { - path: [ - { - tokenIn: _srcAddress, - tokenOut: _destAddress, - fee: pool.feeCode.toString(), - }, - ], - }, - poolIdentifier: this.getPoolIdentifier( - pool.token0, - pool.token1, - pool.feeCode, - ), - exchange: this.dexKey, - gasCost: gasCost, - poolAddresses: [pool.poolAddress], - }; - }), - ); - const rpcResults = await rpcResultsPromise; - - const notNullResult = result.filter( - res => res !== null, - ) as ExchangePrices; - - if (rpcResults) { - rpcResults.forEach(r => { - if (r) { - notNullResult.push(r); - } - }); - } - - return notNullResult; - } catch (e) { - this.logger.error( - `Error_getPricesVolume ${srcToken.symbol || srcToken.address}, ${ - destToken.symbol || destToken.address - }, ${side}:`, - e, - ); - return null; - } - } - - private getQuoterV2CallData( - funcName: string, - tokenIn: Address, - tokenOut: Address, - amount: bigint, - fee: bigint, - ): QuoteExactInputSingleParams | QuoteExactOutputSingleParams { - return funcName === 'quoteExactInputSingle' - ? { tokenIn, tokenOut, fee, sqrtPriceLimitX96: 0n, amountIn: amount } - : { tokenIn, tokenOut, fee, sqrtPriceLimitX96: 0n, amount }; - } - - async getPricingFromRpc( - from: Token, - to: Token, - amounts: bigint[], - side: SwapSide, - pools: SushiswapV3EventPool[], - ): Promise | null> { - if (pools.length === 0) { - return null; - } - this.logger.warn(`fallback to rpc for ${pools.length} pool(s)`); - - const requests = pools.map( - pool => ({ - owner: pool.poolAddress, - asset: side == SwapSide.SELL ? from.address : to.address, - assetType: AssetType.ERC20, - ids: [ - { - id: DEFAULT_ID_ERC20, - spenders: [], - }, - ], - }), - [], - ); - - const balances = await getBalances(this.dexHelper.multiWrapper, requests); - - pools = pools.filter((pool, index) => { - const balance = balances[index].amounts[DEFAULT_ID_ERC20_AS_STRING]; - if (balance >= amounts[amounts.length - 1]) { - return true; - } - this.logger.warn( - `[${this.network}][${pool.parentName}] have no balance ${pool.poolAddress} ${from.address} ${to.address}. (Balance: ${balance})`, - ); - return false; - }); - - pools.forEach(pool => { - this.logger.warn( - `[${this.network}][${pool.parentName}] fallback to rpc for ${pool.name}`, - ); - }); - - const unitVolume = getBigIntPow( - (side === SwapSide.SELL ? from : to).decimals, - ); - - const chunks = amounts.length - 1; - - const _width = Math.floor(chunks / this.config.chunksCount); - - const _amounts = [unitVolume].concat( - Array.from(Array(this.config.chunksCount).keys()).map( - i => amounts[(i + 1) * _width], - ), - ); - - const funcName = - side === SwapSide.SELL - ? 'quoteExactInputSingle' - : 'quoteExactOutputSingle'; - - const calldata = pools.map(pool => - _amounts.map(_amount => ({ - target: this.config.quoter, - gasLimit: UNISWAPV3_QUOTE_GASLIMIT, - callData: this.quoterIface.encodeFunctionData(funcName, [ - this.getQuoterV2CallData( - funcName, - from.address, - to.address, - _amount, - pool.feeCode, - ), - ]), - })), - ); - - const data = await new this.dexHelper.web3Provider.eth.Contract( - UniswapV3MultiABI as AbiItem[], - this.config.uniswapMulticall, - ).methods - .multicall(calldata.flat()) - .call(); - - const decode = (j: number): bigint => { - if (!data.returnData[j].success) { - return 0n; - } - const decoded = defaultAbiCoder.decode( - ['uint256'], - data.returnData[j].returnData, - ); - return BigInt(decoded[0].toString()); - }; - - let i = 0; - const result = pools.map(pool => { - const _rates = _amounts.map(() => decode(i++)); - const unit: bigint = _rates[0]; - - const prices = interpolate( - _amounts.slice(1), - _rates.slice(1), - amounts, - side, - ); - - return { - prices, - unit, - data: { - path: [ - { - tokenIn: from.address, - tokenOut: to.address, - fee: pool.feeCodeAsString, - }, - ], - }, - poolIdentifier: this.getPoolIdentifier( - pool.token0, - pool.token1, - pool.feeCode, - ), - exchange: this.dexKey, - gasCost: prices.map(p => (p === 0n ? 0 : UNISWAPV3_QUOTE_GASLIMIT)), - poolAddresses: [pool.poolAddress], - }; - }); - - return result; - } - - // Returns estimated gas cost of calldata for this DEX in multiSwap - getCalldataGasCost( - poolPrices: PoolPrices, - ): number | number[] { - const gasCost = - CALLDATA_GAS_COST.DEX_OVERHEAD + - CALLDATA_GAS_COST.LENGTH_SMALL + - // ParentStruct header - CALLDATA_GAS_COST.OFFSET_SMALL + - // ParentStruct -> path header - CALLDATA_GAS_COST.OFFSET_SMALL + - // ParentStruct -> deadline - CALLDATA_GAS_COST.TIMESTAMP + - // ParentStruct -> path (20+3+20 = 43 = 32+11 bytes) - CALLDATA_GAS_COST.LENGTH_SMALL + - CALLDATA_GAS_COST.FULL_WORD + - CALLDATA_GAS_COST.wordNonZeroBytes(11); - const arr = new Array(poolPrices.prices.length); - poolPrices.prices.forEach((p, index) => { - if (p == 0n) { - arr[index] = 0; - } else { - arr[index] = gasCost; - } - }); - return arr; - } - - // Encode params required by the exchange adapter - // Used for multiSwap, buy & megaSwap - getAdapterParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, - data: SushiswapV3Data, - side: SwapSide, - ): AdapterExchangeParam { - const { path: rawPath } = data; - const path = this._encodePath(rawPath, side); - - const payload = this.abiCoder.encodeParameter( - { - ParentStruct: { - path: 'bytes', - deadline: 'uint256', - }, - }, - { - path, - deadline: getLocalDeadlineAsFriendlyPlaceholder(), // FIXME: more gas efficient to pass block.timestamp in adapter - }, - ); - - return { - targetExchange: UniswapV3Config['UniswapV3'][this.network].router, - payload, - networkFee: '0', - }; - } - - // Encode call data used by simpleSwap like routers - // Used for simpleSwap & simpleBuy - async getSimpleParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, - data: SushiswapV3Data, - ): Promise { - const web3Client = createPublicClient({ - chain: ViemChain[this.network], - transport: http(generateConfig(this.network).privateHttpProvider), - }); - - const dataFetcher = new DataFetcher( - web3Client.chain.id as ChainId, - web3Client, - ); - - dataFetcher.startDataFetching([LiquidityProviders.SushiSwapV3]); - - const fromToken = await getToken({ web3Client, address: srcToken }); - - const toToken = await getToken({ web3Client, address: destToken }); - - await dataFetcher.fetchPoolsForToken(fromToken, toToken); - - const pcMap = dataFetcher.getCurrentPoolCodeMap(fromToken, toToken); - - const route = Router.findBestRoute( - pcMap, - this.network as unknown as ChainId, - fromToken, - BigNumber.from(srcAmount), - toToken, - 50e9, - [LiquidityProviders.SushiSwapV3], - ); - - const rpParams = Router.routeProcessor2Params( - pcMap, - route, - fromToken, - toToken, - this.augustusAddress, - this.config.router, - ); - - const swapData = this.routerIface.encodeFunctionData('processRoute', [ - rpParams.tokenIn, - rpParams.amountIn, - rpParams.tokenOut, - rpParams.amountOutMin, - rpParams.to, - rpParams.routeCode, - ]); - - dataFetcher.stopDataFetching(); - - return this.buildSimpleParamWithoutWETHConversion( - srcToken, - srcAmount, - destToken, - destAmount, - swapData, - this.config.router, - ); - } - - async getTopPoolsForToken( - tokenAddress: Address, - limit: number, - ): Promise { - const _tokenAddress = tokenAddress.toLowerCase(); - - const res = await this._querySubgraph( - `query ($token: Bytes!, $count: Int) { - pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token}) { - id - token0 { - id - decimals - } - token1 { - id - decimals - } - totalValueLockedUSD - } - pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token}) { - id - token0 { - id - decimals - } - token1 { - id - decimals - } - totalValueLockedUSD - } - }`, - { - token: _tokenAddress, - count: limit, - }, - ); - - if (!(res && res.pools0 && res.pools1)) { - this.logger.error( - `Error_${this.dexKey}_Subgraph: couldn't fetch the pools from the subgraph`, - ); - return []; - } - - const pools0 = _.map(res.pools0, pool => ({ - exchange: this.dexKey, - address: pool.id.toLowerCase(), - connectorTokens: [ - { - address: pool.token1.id.toLowerCase(), - decimals: parseInt(pool.token1.decimals), - }, - ], - liquidityUSD: - parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, - })); - - const pools1 = _.map(res.pools1, pool => ({ - exchange: this.dexKey, - address: pool.id.toLowerCase(), - connectorTokens: [ - { - address: pool.token0.id.toLowerCase(), - decimals: parseInt(pool.token0.decimals), - }, - ], - liquidityUSD: - parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, - })); - - const pools = _.slice( - _.sortBy(_.concat(pools0, pools1), [pool => -1 * pool.liquidityUSD]), - 0, - limit, - ); - return pools; - } - - private _encodePath( - path: { - tokenIn: Address; - tokenOut: Address; - fee: NumberAsString; - }[], - side: SwapSide, - ): string { - if (path.length === 0) { - this.logger.error( - `${this.dexKey}: Received invalid path=${path} for side=${side} to encode`, - ); - return '0x'; - } - - const { _path, types } = path.reduce( - ( - { _path, types }: { _path: string[]; types: string[] }, - curr, - index, - ): { _path: string[]; types: string[] } => { - if (index === 0) { - return { - types: ['address', 'uint24', 'address'], - _path: [curr.tokenIn, curr.fee, curr.tokenOut], - }; - } else { - return { - types: [...types, 'uint24', 'address'], - _path: [..._path, curr.fee, curr.tokenOut], - }; - } - }, - { _path: [], types: [] }, - ); - - return side === SwapSide.BUY - ? pack(types.reverse(), _path.reverse()) - : pack(types, _path); - } - - async getPoolIdentifiers( - srcToken: Token, - destToken: Token, - side: SwapSide, - blockNumber: number, - ): Promise { - const _srcToken = this.dexHelper.config.wrapETH(srcToken); - const _destToken = this.dexHelper.config.wrapETH(destToken); - - const [_srcAddress, _destAddress] = this._getLoweredAddresses( - _srcToken, - _destToken, - ); - - if (_srcAddress === _destAddress) return []; - - const pools = ( - await Promise.all( - this.supportedFees.map(async fee => - this.getPool(_srcAddress, _destAddress, fee, blockNumber), - ), - ) - ).filter(pool => pool); - - if (pools.length === 0) return []; - - return pools.map(pool => - this.getPoolIdentifier(_srcAddress, _destAddress, pool!.feeCode), - ); - } - - async getPool( - srcAddress: Address, - destAddress: Address, - fee: bigint, - blockNumber: number, - ): Promise { - let pool = - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)]; - - if (pool === undefined) { - const [token0, token1] = this._sortTokens(srcAddress, destAddress); - - const key = `${token0}_${token1}_${fee}`.toLowerCase(); - - const notExistingPoolScore = await this.dexHelper.cache.zscore( - this.notExistingPoolSetKey, - key, - ); - - const poolDoesNotExist = notExistingPoolScore !== null; - - if (poolDoesNotExist) { - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - null; - return null; - } - - await this.dexHelper.cache.hset( - this.dexmapKey, - key, - JSON.stringify({ - token0, - token1, - fee: fee.toString(), - }), - ); - - this.logger.trace(`starting to listen to new pool: ${key}`); - pool = new SushiswapV3EventPool( - this.dexHelper, - this.dexKey, - this.stateMultiContract, - this.erc20Interface, - this.config.factory, - fee, - token0, - token1, - this.logger, - this.cacheStateKey, - this.config.initHash, - ); - - try { - await pool.initialize(blockNumber, { - initCallback: (state: DeepReadonly) => { - //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber - pool!.addressesSubscribed[0] = state.pool; - pool!.poolAddress = state.pool; - }, - }); - } catch (e) { - if (e instanceof Error && e.message.endsWith('Pool does not exist')) { - // no need to await we want the set to have the pool key but it's not blocking - this.dexHelper.cache.zadd( - this.notExistingPoolSetKey, - [Date.now(), key], - 'NX', - ); - - // Pool does not exist for this feeCode, so we can set it to null - // to prevent more requests for this pool - pool = null; - this.logger.trace( - `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, - e, - ); - } else { - // Unexpected Error. Break execution. Do not save the pool in this.eventPools - this.logger.error( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool`, - e, - ); - throw new Error('Cannot generate pool state'); - } - } - - if (pool !== null) { - const allEventPools = Object.values(this.eventPools); - this.logger.info( - `starting to listen to new non-null pool: ${key}. Already following ${allEventPools - // Not that I like this reduce, but since it is done only on initialization, expect this to be ok - .reduce( - (acc, curr) => (curr !== null ? ++acc : acc), - 0, - )} non-null pools or ${allEventPools.length} total pools`, - ); - } - - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - pool; - } - return pool; - } - - private _getLoweredAddresses(srcToken: Token, destToken: Token) { - return [srcToken.address.toLowerCase(), destToken.address.toLowerCase()]; - } - - private _sortTokens(srcAddress: Address, destAddress: Address) { - return [srcAddress, destAddress].sort((a, b) => (a < b ? -1 : 1)); - } - - private _toLowerForAllConfigAddresses() { - // If new config property will be added, the TS will throw compile error - const newConfig: DexParams = { - router: this.config.router.toLowerCase(), - quoter: this.config.quoter.toLowerCase(), - factory: this.config.factory.toLowerCase(), - supportedFees: this.config.supportedFees, - stateMulticall: this.config.stateMulticall.toLowerCase(), - chunksCount: this.config.chunksCount, - uniswapMulticall: this.config.uniswapMulticall, - deployer: this.config.deployer?.toLowerCase(), - initHash: this.config.initHash, - subgraphURL: this.config.subgraphURL, - }; - return newConfig; - } - - private async _querySubgraph( - query: string, - variables: Object, - timeout = 30000, - ) { - try { - const res = await this.dexHelper.httpRequest.post( - this.config.subgraphURL, - { query, variables }, - undefined, - { timeout: timeout }, - ); - return res.data; - } catch (e) { - this.logger.error(`${this.dexKey}: can not query subgraph: `, e); - return {}; - } - } - - private _getOutputs( - state: DeepReadonly, - amounts: bigint[], - zeroForOne: boolean, - side: SwapSide, - destTokenBalance: bigint, - ): OutputResult | null { - try { - const outputsResult = uniswapV3Math.queryOutputs( - state, - amounts, - zeroForOne, - side, - ); - - if (side === SwapSide.SELL) { - if (outputsResult.outputs[0] > destTokenBalance) { - return null; - } - - for (let i = 0; i < outputsResult.outputs.length; i++) { - if (outputsResult.outputs[i] > destTokenBalance) { - outputsResult.outputs[i] = 0n; - outputsResult.tickCounts[i] = 0; - } - } - } else { - if (amounts[0] > destTokenBalance) { - return null; - } - - // This may be improved by first checking outputs and requesting outputs - // only for amounts that makes more sense, but I don't think this is really - // important now - for (let i = 0; i < amounts.length; i++) { - if (amounts[i] > destTokenBalance) { - outputsResult.outputs[i] = 0n; - outputsResult.tickCounts[i] = 0; - } - } - } - - return outputsResult; - } catch (e) { - this.logger.debug( - `${this.dexKey}: received error in _getOutputs while calculating outputs`, - e, - ); - return null; - } - } - - releaseResources(): AsyncOrSync { - if (this.intervalTask !== undefined) { - clearInterval(this.intervalTask); - this.intervalTask = undefined; - } - } -} diff --git a/src/dex/sushiswap-v3/sushiswap-v3.ts b/src/dex/sushiswap-v3/sushiswap-v3.ts deleted file mode 100644 index 098fcf21f..000000000 --- a/src/dex/sushiswap-v3/sushiswap-v3.ts +++ /dev/null @@ -1,331 +0,0 @@ -import _ from 'lodash'; -import { createPublicClient, http } from 'viem'; -import { DataFetcher, LiquidityProviders, Router, RPParams, } from '@sushiswap/router'; -import { Token as SushiToken } from '@sushiswap/currency'; -import { SushiSwapV3Config, Adapters } from './config'; -import { UniswapV3 } from '../uniswap-v3/uniswap-v3'; -import { getViemChain } from './constants'; -import { Network, SwapSide } from '../../constants'; -import { getDexKeysWithNetwork, Utils } from '../../utils'; -import SushiswapV3RouterABI from '../../abi/sushiswap-v3/RouterProcessor3.json'; -import SushiswapV3QuoterV2ABI from '../../abi/sushiswap-v3/QuoterV2.json'; -import { IDexHelper } from '../../dex-helper'; -import { Interface } from '@ethersproject/abi'; -import { - AdapterExchangeParam, - ExchangeTxInfo, - PreprocessTransactionOptions, - SimpleExchangeParam, - Token, -} from '../../types'; -import { generateConfig } from '../../config'; -import { BigNumber } from 'ethers'; -import { getLocalDeadlineAsFriendlyPlaceholder } from '../simple-exchange'; -import { OptimalSwapExchange } from '@paraswap/core'; -import { assert } from 'ts-essentials'; -import { UniswapV3Data} from '../uniswap-v3/types'; -import { MultiCallParams } from '../../lib/multi-wrapper'; -import { uint256DecodeToNumber } from '../../lib/decoders'; - -export class SushiSwapV3 extends UniswapV3 { - - constructor( - protected network: Network, - dexKey: string, - protected dexHelper: IDexHelper, - protected adapters = Adapters[network] || {}, - readonly routerIface = new Interface(SushiswapV3RouterABI), - readonly quoterIface = new Interface(SushiswapV3QuoterV2ABI), - protected config = SushiSwapV3Config[dexKey][network], - protected poolsToPreload = [], - ) { - super( - network, - dexKey, - dexHelper, - adapters, - routerIface, - quoterIface, - config, - poolsToPreload, - ); - } - - public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(_.pick(SushiSwapV3Config, ['SushiSwapV3'])); - - async preProcessTransaction( - optimalSwapExchange: OptimalSwapExchange, - srcToken: Token, - destToken: Token, - side: SwapSide, - options: PreprocessTransactionOptions, - ): Promise<[OptimalSwapExchange, ExchangeTxInfo]> { - - assert( - optimalSwapExchange.data !== undefined, - `preProcessTransaction: data field is missing`, - ); - - if(options.isDirectMethod) { - let isApproved: boolean | undefined; - - try { - this.erc20Contract.options.address = - this.dexHelper.config.wrapETH(srcToken).address; - const allowance = await this.erc20Contract.methods - .allowance(this.augustusAddress, this.config.router) - .call(undefined, 'latest'); - isApproved = - BigInt(allowance.toString()) >= BigInt(optimalSwapExchange.srcAmount); - } catch (e) { - this.logger.error( - `preProcessTransaction failed to retrieve allowance info: `, - e, - ); - } - - return [ - { - ...optimalSwapExchange, - data: { - ...optimalSwapExchange.data, - isApproved, - }, - }, - { - deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), - }, - ]; - } - - const _srcToken = this.dexHelper.config.wrapETH(srcToken); - const _destToken = this.dexHelper.config.wrapETH(destToken); - - console.log('DATA: ', options); - - console.log('_src token: ', _srcToken); - console.log('_dest token: ', _destToken); - console.log('side: ', side); - - const web3Client = createPublicClient({ - transport: http(generateConfig(this.network).privateHttpProvider), - chain: getViemChain(this.network), - }); - - const dataFetcher = new DataFetcher( - this.network, - web3Client, - ); - - dataFetcher.startDataFetching([LiquidityProviders.SushiSwapV3]); - - const callData: MultiCallParams[] = [ - { - target: _srcToken.address, - callData: this.erc20Interface.encodeFunctionData('decimals'), - decodeFunction: uint256DecodeToNumber, - }, - { - target: _destToken.address, - callData: this.erc20Interface.encodeFunctionData('decimals'), - decodeFunction: uint256DecodeToNumber, - } - ]; - - const [decimals0, decimals1] = - await this.dexHelper.multiWrapper.tryAggregate( - false, - callData, - undefined, - this.dexHelper.multiWrapper.defaultBatchSize, - false, - ); - - const fromToken = new SushiToken({ - address: _srcToken.address, - decimals: decimals0.returnData, - chainId: this.network, - }); - - const toToken = new SushiToken({ - address: _destToken.address, - decimals: decimals1.returnData, - chainId: this.network, - }); - - await dataFetcher.fetchPoolsForToken(fromToken, toToken); - - const pcMap = dataFetcher.getCurrentPoolCodeMap(fromToken, toToken); - - const route = Router.findBestRoute( - pcMap, - this.network, - fromToken, - BigNumber.from(optimalSwapExchange.srcAmount), - toToken, - 50e9, - [LiquidityProviders.SushiSwapV3], - ); - - console.log('ROUTE: ', route); - - const routerParams = Router.routeProcessor2Params( - pcMap, - route, - fromToken, - toToken, - this.augustusAddress, - this.config.router, - ); - - return [ - { - ...optimalSwapExchange, - data: { - ...optimalSwapExchange.data, - routerParams, - }, - }, - { - deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), - }, - ]; - } - - getAdapterParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, - data: UniswapV3Data, - side: SwapSide, - ): AdapterExchangeParam { - - console.log('DATA ROUTE PARAMS: ', data.routerParams); - - const payload = this.abiCoder.encodeParameter( - { - ParentStruct: { - tokenIn: 'address', - amountIn: 'uint256', - tokenOut: 'address', - amountOutMin: 'uint256', - to: 'address', - route: 'bytes', - }, - }, - { - tokenIn: data.routerParams!.tokenIn, - amountIn: data.routerParams!.amountIn, - tokenOut: data.routerParams!.tokenOut, - amountOutMin: data.routerParams!.amountOutMin, - to: data.routerParams!.to, - route: data.routerParams!.routeCode, - }, - ); - - return { - targetExchange: this.config.router, - payload, - networkFee: '0', - }; - } - - async getSimpleParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, - data: UniswapV3Data, - ): Promise { - const web3Client = createPublicClient({ - transport: http(generateConfig(this.network).privateHttpProvider), - chain: getViemChain(this.network), - }); - - const dataFetcher = new DataFetcher( - this.network, - web3Client, - ); - - dataFetcher.startDataFetching([LiquidityProviders.SushiSwapV3]); - - const callData: MultiCallParams[] = [ - { - target: srcToken, - callData: this.erc20Interface.encodeFunctionData('decimals'), - decodeFunction: uint256DecodeToNumber, - }, - { - target: destToken, - callData: this.erc20Interface.encodeFunctionData('decimals'), - decodeFunction: uint256DecodeToNumber, - } - ]; - - const [decimals0, decimals1] = - await this.dexHelper.multiWrapper.tryAggregate( - false, - callData, - undefined, - this.dexHelper.multiWrapper.defaultBatchSize, - false, - ); - - const fromToken = new SushiToken({ - address: srcToken, - decimals: decimals0.returnData, - chainId: this.network, - }); - - const toToken = new SushiToken({ - address: destToken, - decimals: decimals1.returnData, - chainId: this.network, - }); - - await dataFetcher.fetchPoolsForToken(fromToken, toToken); - - const pcMap = dataFetcher.getCurrentPoolCodeMap(fromToken, toToken); - - const route = Router.findBestRoute( - pcMap, - this.network, - fromToken, - BigNumber.from(srcAmount), - toToken, - 50e9, - [LiquidityProviders.SushiSwapV3], - ); - - const routerParams = Router.routeProcessor2Params( - pcMap, - route, - fromToken, - toToken, - this.augustusAddress, - this.config.router, - ); - - const swapData = this.routerIface.encodeFunctionData('processRoute', [ - routerParams.tokenIn, - routerParams.amountIn, - routerParams.tokenOut, - routerParams.amountOutMin, - routerParams.to, - routerParams.routeCode, - ]); - - dataFetcher.stopDataFetching(); - - return this.buildSimpleParamWithoutWETHConversion( - srcToken, - srcAmount, - destToken, - destAmount, - swapData, - this.config.router, - ); - } -} diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index 7cf4ad24d..96bfa27bb 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -6,7 +6,7 @@ import RamsesV2StateMulticallABI from '../../abi/RamsesV2StateMulticall.abi.json import { AbiItem } from 'web3-utils'; import { decodeStateMultiCallResultWithRelativeBitmaps } from './forks/ramses-v2/utils'; -export const SUPPORTED_FEES = [10000n, 3000n, 500n, 100n]; +const SUPPORTED_FEES = [10000n, 3000n, 500n, 100n]; // Pools that will be initialized on app startup // They are added for testing @@ -107,6 +107,97 @@ export const UniswapV3Config: DexConfigMap = { 'https://api.thegraph.com/subgraphs/name/lynnshaoyu/uniswap-v3-avax', }, }, + SushiSwapV3: { + [Network.MAINNET]: { + factory: '0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F', + quoter: '0x64e8802FE490fa7cc61d3463958199161Bb608A7', + router: '0xFDF9EE3Cc6CA79263F6904aA03F1b071Becb1165', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-ethereum', + }, + [Network.POLYGON]: { + factory: '0x917933899c6a5f8e37f31e19f92cdbff7e8ff0e2', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-polygon', + }, + [Network.BSC]: { + factory: '0x126555dd55a39328F69400d6aE4F782Bd4C34ABb', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x400d75dAb26bBc18D163AEA3e83D9Ea68F6c1804', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x593F39A4Ba26A9c8ed2128ac95D109E8e403C485', + uniswapMulticall: '0x963Df249eD09c358A4819E39d9Cd5736c3087184', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-bsc', + }, + [Network.AVALANCHE]: { + factory: '0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0xDcCa1db4016BE1f3879aB033A7776e3998ef7968', + supportedFees: SUPPORTED_FEES, + stateMulticall: '', + uniswapMulticall: '0x8C0F842791F03C095b6c633759224FcC9ACe68ea', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-avalanche', + }, + [Network.FANTOM]: { + factory: '0x7770978eED668a3ba661d51a773d3a992Fc9DDCB', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x2214A42d8e2A1d20635c2cb0664422c528B6A432', + supportedFees: SUPPORTED_FEES, + stateMulticall: '', + uniswapMulticall: '0xB1395e098c0a847CC719Bcf1Fc8114421a9F8232', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-fantom', + }, + [Network.ARBITRUM]: { + factory: '0x1af415a1eba07a4986a52b6f2e7de7003d82231e', + quoter: '0x0524E833cCD057e4d7A296e3aaAb9f7675964Ce1', + router: '0x08d08eF6e715e00351CC2FCF8501C04642c37EB4', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-arbitrum', + }, + [Network.OPTIMISM]: { + factory: '0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x4C5D5234f232BD2D76B96aA33F5AE4FCF0E4BFAb', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x4FF0dEC5f9a763Aa1E5C2a962aa6f4eDFeE4f9eA', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-optimism', + }, + }, ChronosV3: { [Network.ARBITRUM]: { factory: '0x4Db9D624F67E00dbF8ef7AE0e0e8eE54aF1dee49', diff --git a/src/dex/uniswap-v3/sushiswap-v3-integration.test.ts b/src/dex/uniswap-v3/sushiswap-v3-integration.test.ts new file mode 100644 index 000000000..a1366f98a --- /dev/null +++ b/src/dex/uniswap-v3/sushiswap-v3-integration.test.ts @@ -0,0 +1,111 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); +import { SushiSwapV3 } from '../sushiswap-v3/sushiswap-v3'; +import { Network, SwapSide } from '../../constants'; +import { DummyDexHelper, IDexHelper } from '../../dex-helper'; +import { Tokens } from '../../../tests/constants-e2e'; +import { BI_POWS } from '../../bigint-constants'; +import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; +import { Interface, Result } from '@ethersproject/abi'; +import SushiswapV3QuoterV2ABI from '../../abi/sushiswap-v3/QuoterV2.json'; +import { Address } from '@paraswap/core'; + +const quoterIface = new Interface(SushiswapV3QuoterV2ABI); + +function getReaderCalldata( + exchangeAddress: string, + readerIface: Interface, + amounts: bigint[], + funcName: string, + tokenIn: Address, + tokenOut: Address, + fee: bigint, +) { + return amounts.map(amount => ({ + target: exchangeAddress, + callData: readerIface.encodeFunctionData(funcName, [ + [tokenIn, tokenOut, amount.toString(), fee.toString(), 0], + ]), + })); +} + +function decodeReaderResult( + results: Result, + readerIface: Interface, + funcName: string, +) { + return results.map(result => { + const parsed = readerIface.decodeFunctionResult(funcName, result); + return BigInt(parsed[0]._hex); + }); +} + +async function checkOnChainPricing( + dexHelper: IDexHelper, + sushiSwapV3: SushiSwapV3, + funcName: string, + blockNumber: number, + exchangeAddress: string, + prices: bigint[], + tokenIn: Address, + tokenOut: Address, + fee: bigint, + _amounts: bigint[], +) { + // Quoter address + // const exchangeAddress = '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'; + const readerIface = quoterIface; + + // const sum = prices.reduce((acc, curr) => (acc += curr), 0n); + // + // if (sum === 0n) { + // console.log( + // `Prices were not calculated for tokenIn=${tokenIn}, tokenOut=${tokenOut}, fee=${fee.toString()}. Most likely price impact is too big for requested amount`, + // ); + // return false; + // } + + const readerCallData = getReaderCalldata( + exchangeAddress, + readerIface, + _amounts.slice(1), + funcName, + tokenIn, + tokenOut, + fee, + ); + + let readerResult; + try { + readerResult = ( + await dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blockNumber) + ).returnData; + } catch (e) { + console.log( + `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, + e, + ); + return false; + } + + const expectedPrices = [0n].concat( + decodeReaderResult(readerResult, readerIface, funcName), + ); + + console.log('EXPECTED PRICES: ', expectedPrices); + + let firstZeroIndex = prices.slice(1).indexOf(0n); + + // we skipped first, so add +1 on result + firstZeroIndex = firstZeroIndex === -1 ? prices.length : firstZeroIndex; + + // Compare only the ones for which we were able to calculate prices + expect(prices.slice(0, firstZeroIndex)).toEqual( + expectedPrices.slice(0, firstZeroIndex), + ); + return true; +} + diff --git a/src/dex/uniswap-v3/types.ts b/src/dex/uniswap-v3/types.ts index 381ece50f..b7c314500 100644 --- a/src/dex/uniswap-v3/types.ts +++ b/src/dex/uniswap-v3/types.ts @@ -3,7 +3,6 @@ import { NumberAsString } from '../../types'; import { Address } from '../../types'; import { AbiItem } from 'web3-utils'; import { MultiResult } from '../../lib/multi-wrapper'; -import { RPParams } from '@sushiswap/router'; export type OracleObservation = { blockTimestamp: bigint; @@ -61,7 +60,6 @@ export type UniswapV3Data = { fee: NumberAsString; }[]; isApproved?: boolean; - routerParams?: RPParams; }; export type DecodeStateMultiCallFunc = ( diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index 294251034..88940447c 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -11,6 +11,108 @@ import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, + slippage?: number | undefined, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, + ], + ], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + 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, + 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, + network, + provider, + undefined, + undefined, + undefined, + slippage, + ); + }); + }); + }); + }), + ); + }); +} + + describe('UniswapV3 E2E', () => { describe('UniswapV3', () => { @@ -593,4 +695,305 @@ describe('UniswapV3 E2E', () => { ); }); }); + + describe('SushiSwapV3 E2E', () => { + const dexKey = 'SushiSwapV3'; + + describe('MAINNET', () => { + const network = Network.MAINNET; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '1100000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + + describe('ARBITRUM', () => { + const network = Network.ARBITRUM; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDCe'; + + const tokenAAmount: string = '10000000'; + const tokenBAmount: string = '10000000'; + const nativeTokenAmount = '900000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + + describe('POLYGON', () => { + const network = Network.POLYGON; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '21111000'; + const tokenBAmount: string = '200000000'; + const nativeTokenAmount = '110000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + + describe('BSC', () => { + const network = Network.BSC; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, + ], + ], + ]); + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ + [ + { + name: 'USDC', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + { + name: 'USDT', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + ], + [ + { + name: 'BNB', + sellAmount: '1000000000000000000', + buyAmount: '10000000000000000000', + }, + { + name: 'USDT', + sellAmount: '1000000000000000000000', + buyAmount: '20000000000000000', + }, + ], + ]; + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }); + }), + ); + }); + + describe('AVALANCHE', () => { + const network = Network.AVALANCHE; + + const tokenASymbol: string = 'USDT'; + const tokenBSymbol: string = 'USDC'; + + const tokenAAmount: string = '111110'; + const tokenBAmount: string = '100000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + + describe('FANTOM', () => { + const network = Network.FANTOM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, + ], + ], + ]); + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ + [ + { + name: 'USDC', + sellAmount: '111110', + buyAmount: '111110', + }, + { + name: 'FUSDT', + sellAmount: '111110', + buyAmount: '111110', + }, + ], + // [ + // { + // name: 'BNB', + // sellAmount: '1000000000000000000', + // buyAmount: '10000000000000000000', + // }, + // { name: 'USDT', sellAmount: '1000000000000000000000', buyAmount: '20000000000000000' }, + // ], + ]; + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }); + }), + ); + }); + + describe('OPTIMISM', () => { + const network = Network.OPTIMISM; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '10000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + }); }); diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index 6df249331..1896e15c7 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -746,3 +746,225 @@ describe('ChronosV3', () => { checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); }); }); + +describe('SushiSwapV3', () => { + const dexKey = 'SushiSwapV3'; + + describe('Mainnet', () => { + let blockNumber: number; + let sushiSwapV3: UniswapV3; + let sushiSwapV3Mainnet: UniswapV3; + + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + const TokenASymbol = 'USDC'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDT'; + const TokenB = Tokens[network][TokenBSymbol]; + + beforeEach(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + sushiSwapV3 = new UniswapV3(network, dexKey, dexHelper); + sushiSwapV3Mainnet = new UniswapV3(Network.MAINNET, dexKey, dexHelper); + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + const amounts = [0n, BI_POWS[6], 2000000n]; + + const pools = await sushiSwapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await sushiSwapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = sushiSwapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + sushiSwapV3, + 'quoteExactInputSingle', + blockNumber, + '0x64e8802FE490fa7cc61d3463958199161Bb608A7', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + const amounts = [0n, BI_POWS[6], 2000000n]; + + const pools = await sushiSwapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await sushiSwapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = sushiSwapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + sushiSwapV3, + 'quoteExactOutputSingle', + blockNumber, + '0x64e8802FE490fa7cc61d3463958199161Bb608A7', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getTopPoolsForToken', async function () { + const poolLiquidity = await sushiSwapV3.getTopPoolsForToken( + TokenB.address, + 10, + ); + console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); + }); + }); + + describe('Arbitrum', () => { + let blockNumber: number; + let sushiSwapV3: UniswapV3; + let sushiSwapV3Mainnet: UniswapV3; + + const network = Network.ARBITRUM; + const dexHelper = new DummyDexHelper(network); + const TokenASymbol = 'USDCe'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDT'; + const TokenB = Tokens[network][TokenBSymbol]; + + beforeEach(async () => { + // blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + blockNumber = 125789437; + sushiSwapV3 = new UniswapV3(network, dexKey, dexHelper); + sushiSwapV3Mainnet = new UniswapV3(Network.ARBITRUM, dexKey, dexHelper); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + const amounts = [0n, 100000000n, 200000000n]; + + const pools = await sushiSwapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await sushiSwapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = sushiSwapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + sushiSwapV3, + 'quoteExactOutputSingle', + blockNumber, + '0x0524E833cCD057e4d7A296e3aaAb9f7675964Ce1', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + }); +}); + diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 478f8e0bf..7ef42c117 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -91,15 +91,15 @@ export class UniswapV3 public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork( - _.pick(UniswapV3Config, ['UniswapV3', 'QuickSwapV3.1', 'RamsesV2', 'ChronosV3']), + _.pick(UniswapV3Config, ['UniswapV3', 'SushiSwapV3', 'QuickSwapV3.1', 'RamsesV2', 'ChronosV3']), ); logger: Logger; - protected uniswapMulti: Contract; - protected stateMultiContract: Contract; + private uniswapMulti: Contract; + private stateMultiContract: Contract; - protected notExistingPoolSetKey: string; + private notExistingPoolSetKey: string; constructor( protected network: Network, diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index 34323fa65..12143c4dc 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -31,7 +31,6 @@ import { SmartToken, StateOverrides } from './smart-tokens'; import { GIFTER_ADDRESS } from './constants-e2e'; import { generateDeployBytecode, sleep } from './utils'; import { assert } from 'ts-essentials'; -import * as util from 'util'; export const testingEndpoint = process.env.E2E_TEST_ENDPOINT; @@ -369,7 +368,6 @@ export async function testE2E( poolIdentifiers, transferFees, ); - console.log('PRICE ROUTE: ', util.inspect(priceRoute, false, null, true)); expect(parseFloat(priceRoute.destAmount)).toBeGreaterThan(0); // Calculate slippage. Default is 1% diff --git a/yarn.lock b/yarn.lock index 1b6079b1a..eb77e24a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -41,11 +41,6 @@ js-sha3 "^0.7.0" lodash "^4.17.11" -"@adraffy/ens-normalize@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.9.0.tgz#223572538f6bea336750039bb43a4016dcc8182d" - integrity sha512-iowxq3U30sghZotgl4s/oJRci6WPBfNO5YYgk2cIOMCHr3LeGPcsZjCEr+33Q4N+oV3OABDAtA+pyvWjbvBifQ== - "@ampproject/remapping@^2.1.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" @@ -336,57 +331,11 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" -"@balena/dockerignore@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d" - integrity sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q== - "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@chainsafe/as-sha256@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz#3639df0e1435cab03f4d9870cc3ac079e57a6fc9" - integrity sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg== - -"@chainsafe/persistent-merkle-tree@^0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz#4c9ee80cc57cd3be7208d98c40014ad38f36f7ff" - integrity sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - -"@chainsafe/persistent-merkle-tree@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz#2b4a62c9489a5739dedd197250d8d2f5427e9f63" - integrity sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - -"@chainsafe/ssz@^0.10.0": - version "0.10.2" - resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.10.2.tgz#c782929e1bb25fec66ba72e75934b31fd087579e" - integrity sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - "@chainsafe/persistent-merkle-tree" "^0.5.0" - -"@chainsafe/ssz@^0.9.2": - version "0.9.4" - resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.9.4.tgz#696a8db46d6975b600f8309ad3a12f7c0e310497" - integrity sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - "@chainsafe/persistent-merkle-tree" "^0.4.2" - case "^1.6.3" - -"@colors/colors@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" - integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== - "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -394,22 +343,6 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@ensdomains/ens@^0.4.4": - version "0.4.5" - resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" - integrity sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw== - dependencies: - bluebird "^3.5.2" - eth-ens-namehash "^2.0.8" - solc "^0.4.20" - testrpc "0.0.1" - web3-utils "^1.0.0-beta.31" - -"@ensdomains/resolver@^0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" - integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== - "@eslint/eslintrc@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.0.tgz#8ec64e0df3e7a1971ee1ff5158da87389f167a63" @@ -479,59 +412,6 @@ merkletreejs "^0.2.27" rlp "^2.2.7" -"@ethereum-waffle/chai@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.4.tgz#16c4cc877df31b035d6d92486dfdf983df9138ff" - integrity sha512-/K8czydBtXXkcM9X6q29EqEkc5dN3oYenyH2a9hF7rGAApAJUpH8QBtojxOY/xQ2up5W332jqgxwp0yPiYug1g== - dependencies: - "@ethereum-waffle/provider" "^3.4.4" - ethers "^5.5.2" - -"@ethereum-waffle/compiler@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.4.tgz#d568ee0f6029e68b5c645506079fbf67d0dfcf19" - integrity sha512-RUK3axJ8IkD5xpWjWoJgyHclOeEzDLQFga6gKpeGxiS/zBu+HB0W2FvsrrLalTFIaPw/CGYACRBSIxqiCqwqTQ== - dependencies: - "@resolver-engine/imports" "^0.3.3" - "@resolver-engine/imports-fs" "^0.3.3" - "@typechain/ethers-v5" "^2.0.0" - "@types/mkdirp" "^0.5.2" - "@types/node-fetch" "^2.5.5" - ethers "^5.0.1" - mkdirp "^0.5.1" - node-fetch "^2.6.1" - solc "^0.6.3" - ts-generator "^0.1.1" - typechain "^3.0.0" - -"@ethereum-waffle/ens@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.4.4.tgz#db97ea2c9decbb70b9205d53de2ccbd6f3182ba1" - integrity sha512-0m4NdwWxliy3heBYva1Wr4WbJKLnwXizmy5FfSSr5PMbjI7SIGCdCB59U7/ZzY773/hY3bLnzLwvG5mggVjJWg== - dependencies: - "@ensdomains/ens" "^0.4.4" - "@ensdomains/resolver" "^0.2.4" - ethers "^5.5.2" - -"@ethereum-waffle/mock-contract@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.4.4.tgz#fc6ffa18813546f4950a69f5892d4dd54b2c685a" - integrity sha512-Mp0iB2YNWYGUV+VMl5tjPsaXKbKo8MDH9wSJ702l9EBjdxFf/vBvnMBAC1Fub1lLtmD0JHtp1pq+mWzg/xlLnA== - dependencies: - "@ethersproject/abi" "^5.5.0" - ethers "^5.5.2" - -"@ethereum-waffle/provider@^3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.4.tgz#398fc1f7eb91cc2df7d011272eacba8af0c7fffb" - integrity sha512-GK8oKJAM8+PKy2nK08yDgl4A80mFuI8zBkE0C9GqTRYQqvuxIyXoLmJ5NZU9lIwyWVv5/KsoA11BgAv2jXE82g== - dependencies: - "@ethereum-waffle/ens" "^3.4.4" - ethers "^5.5.2" - ganache-core "^2.13.2" - patch-package "^6.2.2" - postinstall-postinstall "^2.1.0" - "@ethereumjs/common@^2.3.0", "@ethereumjs/common@^2.4.0", "@ethereumjs/common@^2.6.4": version "2.6.5" resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30" @@ -540,11 +420,6 @@ crc-32 "^1.2.0" ethereumjs-util "^7.1.5" -"@ethereumjs/rlp@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" - integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== - "@ethereumjs/tx@^3.2.1": version "3.5.2" resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.2.tgz#197b9b6299582ad84f9527ca961466fce2296c1c" @@ -553,30 +428,6 @@ "@ethereumjs/common" "^2.6.4" ethereumjs-util "^7.1.5" -"@ethereumjs/util@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4" - integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA== - dependencies: - "@ethereumjs/rlp" "^4.0.1" - ethereum-cryptography "^2.0.0" - micro-ftch "^0.3.1" - -"@ethersproject/abi@5.0.0-beta.153": - version "5.0.0-beta.153" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" - integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg== - dependencies: - "@ethersproject/address" ">=5.0.0-beta.128" - "@ethersproject/bignumber" ">=5.0.0-beta.130" - "@ethersproject/bytes" ">=5.0.0-beta.129" - "@ethersproject/constants" ">=5.0.0-beta.128" - "@ethersproject/hash" ">=5.0.0-beta.128" - "@ethersproject/keccak256" ">=5.0.0-beta.127" - "@ethersproject/logger" ">=5.0.0-beta.129" - "@ethersproject/properties" ">=5.0.0-beta.131" - "@ethersproject/strings" ">=5.0.0-beta.130" - "@ethersproject/abi@5.0.7": version "5.0.7" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" @@ -592,7 +443,7 @@ "@ethersproject/properties" "^5.0.3" "@ethersproject/strings" "^5.0.4" -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.5.0", "@ethersproject/abi@^5.7.0": +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== @@ -631,7 +482,7 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/address@5.7.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.7.0": +"@ethersproject/address@5.7.0", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== @@ -657,7 +508,7 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.7.0": +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== @@ -666,14 +517,14 @@ "@ethersproject/logger" "^5.7.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.7.0": +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/constants@5.7.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.7.0": +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== @@ -696,7 +547,7 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/transactions" "^5.7.0" -"@ethersproject/hash@5.7.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.7.0": +"@ethersproject/hash@5.7.0", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== @@ -748,7 +599,7 @@ aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.7.0": +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== @@ -756,7 +607,7 @@ "@ethersproject/bytes" "^5.7.0" js-sha3 "0.8.0" -"@ethersproject/logger@5.7.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.7.0": +"@ethersproject/logger@5.7.0", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== @@ -776,14 +627,14 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/sha2" "^5.7.0" -"@ethersproject/properties@5.7.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.7.0": +"@ethersproject/properties@5.7.0", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.0", "@ethersproject/providers@^5.7.1", "@ethersproject/providers@^5.7.2": +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.0": version "5.7.2" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== @@ -846,7 +697,7 @@ elliptic "6.5.4" hash.js "1.1.7" -"@ethersproject/solidity@5.7.0", "@ethersproject/solidity@^5.7.0": +"@ethersproject/solidity@5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== @@ -858,7 +709,7 @@ "@ethersproject/sha2" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@ethersproject/strings@5.7.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.7.0": +"@ethersproject/strings@5.7.0", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== @@ -882,7 +733,7 @@ "@ethersproject/rlp" "^5.7.0" "@ethersproject/signing-key" "^5.7.0" -"@ethersproject/units@5.7.0", "@ethersproject/units@^5.7.0": +"@ethersproject/units@5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== @@ -891,7 +742,7 @@ "@ethersproject/constants" "^5.7.0" "@ethersproject/logger" "^5.7.0" -"@ethersproject/wallet@5.7.0", "@ethersproject/wallet@^5.7.0": +"@ethersproject/wallet@5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== @@ -1274,22 +1125,6 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@matterlabs/hardhat-zksync-deploy@0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-deploy/-/hardhat-zksync-deploy-0.6.2.tgz#077beeaadc28af5afc469c0a94f394bbc9d96ad4" - integrity sha512-TRGbYXqFdLspaGRjNRWFcej0i8+OgYodDPFVRMg/3KJvC0QLViEEcBZ2cpBqC/R5fydsIql5KXe8ZVMz22AeqA== - dependencies: - chalk "4.1.2" - -"@matterlabs/hardhat-zksync-solc@0.3.14": - version "0.3.14" - resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-solc/-/hardhat-zksync-solc-0.3.14.tgz#0a32f01b4cd8631ecd8dfe0547e3ac49ab8290d5" - integrity sha512-iKuQ+vvnpv3K2lkFO41xpJcNWH0KHJ/5JbOboTlPZATVR7F3GJeHfJL+GG4wkxKXnxZczpxyQqC4rAfMKvRaDg== - dependencies: - "@nomiclabs/hardhat-docker" "^2.0.0" - chalk "4.1.2" - dockerode "^3.3.4" - "@metamask/eth-sig-util@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" @@ -1301,45 +1136,16 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" -"@noble/curves@1.0.0", "@noble/curves@~1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.0.0.tgz#e40be8c7daf088aaf291887cbc73f43464a92932" - integrity sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw== - dependencies: - "@noble/hashes" "1.3.0" - -"@noble/curves@1.1.0", "@noble/curves@~1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" - integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA== - dependencies: - "@noble/hashes" "1.3.1" - "@noble/hashes@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== -"@noble/hashes@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" - integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== - -"@noble/hashes@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" - integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== - "@noble/hashes@~1.1.1": version "1.1.5" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.5.tgz#1a0377f3b9020efe2fae03290bd2a12140c95c11" integrity sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ== -"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" - integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== - "@noble/secp256k1@1.6.3", "@noble/secp256k1@~1.6.0": version "1.6.3" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.6.3.tgz#7eed12d9f4404b416999d0c87686836c4c5c9b94" @@ -1366,19 +1172,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@nomicfoundation/ethereumjs-block@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.1.tgz#6f89664f55febbd723195b6d0974773d29ee133d" - integrity sha512-u1Yioemi6Ckj3xspygu/SfFvm8vZEO8/Yx5a1QLzi6nVU0jz3Pg2OmHKJ5w+D9Ogk1vhwRiqEBAqcb0GVhCyHw== - dependencies: - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - ethereum-cryptography "0.1.3" - ethers "^5.7.1" - "@nomicfoundation/ethereumjs-block@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.0.0.tgz#fdd5c045e7baa5169abeed0e1202bf94e4481c49" @@ -1391,25 +1184,6 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-blockchain@7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.1.tgz#80e0bd3535bfeb9baa29836b6f25123dab06a726" - integrity sha512-NhzndlGg829XXbqJEYrF1VeZhAwSPgsK/OB7TVrdzft3y918hW5KNd7gIZ85sn6peDZOdjBsAXIpXZ38oBYE5A== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-ethash" "3.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - abstract-level "^1.0.3" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - level "^8.0.0" - lru-cache "^5.1.1" - memory-level "^1.0.0" - "@nomicfoundation/ethereumjs-blockchain@^6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.0.0.tgz#1a8c243a46d4d3691631f139bfb3a4a157187b0c" @@ -1428,14 +1202,6 @@ lru-cache "^5.1.1" memory-level "^1.0.0" -"@nomicfoundation/ethereumjs-common@4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.1.tgz#4702d82df35b07b5407583b54a45bf728e46a2f0" - integrity sha512-OBErlkfp54GpeiE06brBW/TTbtbuBJV5YI5Nz/aB2evTDo+KawyEzPjBlSr84z/8MFfj8wS2wxzQX1o32cev5g== - dependencies: - "@nomicfoundation/ethereumjs-util" "9.0.1" - crc-32 "^1.2.0" - "@nomicfoundation/ethereumjs-common@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.0.0.tgz#f6bcc7753994555e49ab3aa517fc8bcf89c280b9" @@ -1444,18 +1210,6 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" crc-32 "^1.2.0" -"@nomicfoundation/ethereumjs-ethash@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.1.tgz#65ca494d53e71e8415c9a49ef48bc921c538fc41" - integrity sha512-KDjGIB5igzWOp8Ik5I6QiRH5DH+XgILlplsHR7TEuWANZA759G6krQ6o8bvj+tRUz08YygMQu/sGd9mJ1DYT8w== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - abstract-level "^1.0.3" - bigint-crypto-utils "^3.0.23" - ethereum-cryptography "0.1.3" - "@nomicfoundation/ethereumjs-ethash@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.0.tgz#11539c32fe0990e1122ff987d1b84cfa34774e81" @@ -1468,20 +1222,6 @@ bigint-crypto-utils "^3.0.23" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-evm@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.1.tgz#f35681e203363f69ce2b3d3bf9f44d4e883ca1f1" - integrity sha512-oL8vJcnk0Bx/onl+TgQOQ1t/534GKFaEG17fZmwtPFeH8S5soiBYPCLUrvANOl4sCp9elYxIMzIiTtMtNNN8EQ== - dependencies: - "@ethersproject/providers" "^5.7.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - "@nomicfoundation/ethereumjs-evm@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.0.0.tgz#99cd173c03b59107c156a69c5e215409098a370b" @@ -1496,28 +1236,11 @@ mcl-wasm "^0.7.1" rustbn.js "~0.2.0" -"@nomicfoundation/ethereumjs-rlp@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.1.tgz#0b30c1cf77d125d390408e391c4bb5291ef43c28" - integrity sha512-xtxrMGa8kP4zF5ApBQBtjlSbN5E2HI8m8FYgVSYAnO6ssUoY5pVPGy2H8+xdf/bmMa22Ce8nWMH3aEW8CcqMeQ== - "@nomicfoundation/ethereumjs-rlp@^4.0.0", "@nomicfoundation/ethereumjs-rlp@^4.0.0-beta.2": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.0.tgz#d9a9c5f0f10310c8849b6525101de455a53e771d" integrity sha512-GaSOGk5QbUk4eBP5qFbpXoZoZUj/NrW7MRa0tKY4Ew4c2HAS0GXArEMAamtFrkazp0BO4K5p2ZCG3b2FmbShmw== -"@nomicfoundation/ethereumjs-statemanager@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.1.tgz#8824a97938db4471911e2d2f140f79195def5935" - integrity sha512-B5ApMOnlruVOR7gisBaYwFX+L/AP7i/2oAahatssjPIBVDF6wTX1K7Qpa39E/nzsH8iYuL3krkYeUFIdO3EMUQ== - dependencies: - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - ethers "^5.7.1" - js-sdsl "^4.1.4" - "@nomicfoundation/ethereumjs-statemanager@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.0.tgz#14a9d4e1c828230368f7ab520c144c34d8721e4b" @@ -1531,17 +1254,6 @@ ethereum-cryptography "0.1.3" functional-red-black-tree "^1.0.1" -"@nomicfoundation/ethereumjs-trie@6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.1.tgz#662c55f6b50659fd4b22ea9f806a7401cafb7717" - integrity sha512-A64It/IMpDVODzCgxDgAAla8jNjNtsoQZIzZUfIV5AY6Coi4nvn7+VReBn5itlxMiL2yaTlQr9TRWp3CSI6VoA== - dependencies: - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - "@types/readable-stream" "^2.3.13" - ethereum-cryptography "0.1.3" - readable-stream "^3.6.0" - "@nomicfoundation/ethereumjs-trie@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.0.tgz#dcfbe3be53a94bc061c9767a396c16702bc2f5b7" @@ -1552,18 +1264,6 @@ ethereum-cryptography "0.1.3" readable-stream "^3.6.0" -"@nomicfoundation/ethereumjs-tx@5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.1.tgz#7629dc2036b4a33c34e9f0a592b43227ef4f0c7d" - integrity sha512-0HwxUF2u2hrsIM1fsasjXvlbDOq1ZHFV2dd1yGq8CA+MEYhaxZr8OTScpVkkxqMwBcc5y83FyPl0J9MZn3kY0w== - dependencies: - "@chainsafe/ssz" "^0.9.2" - "@ethersproject/providers" "^5.7.2" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - ethereum-cryptography "0.1.3" - "@nomicfoundation/ethereumjs-tx@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.0.0.tgz#59dc7452b0862b30342966f7052ab9a1f7802f52" @@ -1574,15 +1274,6 @@ "@nomicfoundation/ethereumjs-util" "^8.0.0" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-util@9.0.1": - version "9.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.1.tgz#530cda8bae33f8b5020a8f199ed1d0a2ce48ec89" - integrity sha512-TwbhOWQ8QoSCFhV/DDfSmyfFIHjPjFBj957219+V3jTZYZ2rf9PmDtNOeZWAE3p3vlp8xb02XGpd0v6nTUPbsA== - dependencies: - "@chainsafe/ssz" "^0.10.0" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - ethereum-cryptography "0.1.3" - "@nomicfoundation/ethereumjs-util@^8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.0.tgz#deb2b15d2c308a731e82977aefc4e61ca0ece6c5" @@ -1591,25 +1282,6 @@ "@nomicfoundation/ethereumjs-rlp" "^4.0.0-beta.2" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-vm@7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.1.tgz#7d035e0993bcad10716c8b36e61dfb87fa3ca05f" - integrity sha512-rArhyn0jPsS/D+ApFsz3yVJMQ29+pVzNZ0VJgkzAZ+7FqXSRtThl1C1prhmlVr3YNUlfpZ69Ak+RUT4g7VoOuQ== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-blockchain" "7.0.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-evm" "2.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-statemanager" "2.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - "@nomicfoundation/ethereumjs-vm@^6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.0.0.tgz#2bb50d332bf41790b01a3767ffec3987585d1de6" @@ -1698,57 +1370,6 @@ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.0" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.0" -"@nomiclabs/hardhat-docker@^2.0.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-docker/-/hardhat-docker-2.0.2.tgz#ae964be17951275a55859ff7358e9e7c77448846" - integrity sha512-XgGEpRT3wlA1VslyB57zyAHV+oll8KnV1TjwnxxC1tpAL04/lbdwpdO5KxInVN8irMSepqFpsiSkqlcnvbE7Ng== - dependencies: - dockerode "^2.5.8" - fs-extra "^7.0.1" - node-fetch "^2.6.0" - -"@nomiclabs/hardhat-ethers@^2.1.1": - version "2.2.3" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz#b41053e360c31a32c2640c9a45ee981a7e603fe0" - integrity sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg== - -"@nomiclabs/hardhat-ethers@npm:hardhat-deploy-ethers@0.3.0-beta.13", hardhat-deploy-ethers@0.3.0-beta.13: - name "@nomiclabs/hardhat-ethers" - version "0.3.0-beta.13" - resolved "https://registry.yarnpkg.com/hardhat-deploy-ethers/-/hardhat-deploy-ethers-0.3.0-beta.13.tgz#b96086ff768ddf69928984d5eb0a8d78cfca9366" - integrity sha512-PdWVcKB9coqWV1L7JTpfXRCI91Cgwsm7KLmBcwZ8f0COSm1xtABHZTyz3fvF6p42cTnz1VM0QnfDvMFlIRkSNw== - -"@nomiclabs/hardhat-etherscan@3.1.3": - version "3.1.3" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.3.tgz#c9dbaa4174edfa075a464a0e9142bc8710a2c4e2" - integrity sha512-UeNO97j0lwOHqX7mrH6SfQQBdXq1Ng6eFr7uJKuQOrq2UVTWGD70lE5QO4fAFVPz9ao+xlNpMyIqSR7+OaDR+Q== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@ethersproject/address" "^5.0.2" - cbor "^8.1.0" - chalk "^2.4.2" - debug "^4.1.1" - fs-extra "^7.0.1" - lodash "^4.17.11" - semver "^6.3.0" - table "^6.8.0" - undici "^5.4.0" - -"@nomiclabs/hardhat-solhint@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-solhint/-/hardhat-solhint-2.0.1.tgz#62896569d10c95a17cefab0229701cfffd19246f" - integrity sha512-SrTLufY21t78KLpJL5fS6gHIsCwVv0yWsHp1aQOPL1qwRWpe0Mnh5wb2YzBHd3Dbr/KzUYys+j2ui0PsSVU9pg== - dependencies: - solhint "^2.0.0" - -"@nomiclabs/hardhat-waffle@2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.3.tgz#9c538a09c5ed89f68f5fd2dc3f78f16ed1d6e0b1" - integrity sha512-049PHSnI1CZq6+XTbrMbMv5NaL7cednTfPenx02k3cEh8wBMLa6ys++dBETJa6JjfwgA9nBhhHQ173LJv6k2Pg== - dependencies: - "@types/sinon-chai" "^3.2.3" - "@types/web3" "1.0.19" - "@openzeppelin/contracts-upgradeable@4.7.3": version "4.7.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.7.3.tgz#f1d606e2827d409053f3e908ba4eb8adb1dd6995" @@ -1759,16 +1380,6 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.1.tgz#363f7dd08f25f8f77e16d374350c3d6b43340a7a" integrity sha512-1wTv+20lNiC0R07jyIAbHU7TNHKRwGiTGRfiNnA8jOWjKT98g5OgLpYWOi40Vgpk8SPLA9EvfJAbAeIyVn+7Bw== -"@openzeppelin/contracts@3.4.1-solc-0.7-2": - version "3.4.1-solc-0.7-2" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.1-solc-0.7-2.tgz#371c67ebffe50f551c3146a9eec5fe6ffe862e92" - integrity sha512-tAG9LWg8+M2CMu7hIsqHPaTyG4uDzjr6mhvH96LvOpLZZj6tgzTluBt+LsCf1/QaYrlis6pITvpIaIhE+iZB+Q== - -"@openzeppelin/contracts@3.4.2-solc-0.7": - version "3.4.2-solc-0.7" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.4.2-solc-0.7.tgz#38f4dbab672631034076ccdf2f3201fab1726635" - integrity sha512-W6QmqgkADuFcTLzHL8vVoNBtkwjvQRpYIAom7KiUNoLKghyx3FgH0GBjt8NRvigV1ZmMOBllvE1By1C+bi8WpA== - "@openzeppelin/contracts@4.7.3": version "4.7.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.3.tgz#939534757a81f8d69cc854c7692805684ff3111e" @@ -1793,48 +1404,6 @@ bignumber.js "^9.0.2" ts-essentials "^9.1.2" -"@rari-capital/solmate@6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@rari-capital/solmate/-/solmate-6.2.0.tgz#4f70dc236606c27ec2cb1b4261dd830235d01fe4" - integrity sha512-g94F+Ra9ixyJyNgvnOIufNjUz488uEG0nxIEEtJ7+g+tA1XGUupRB2kB5b+VO7WYO26RNOVD2fW6xE4e14iWpg== - -"@resolver-engine/core@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" - integrity sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ== - dependencies: - debug "^3.1.0" - is-url "^1.2.4" - request "^2.85.0" - -"@resolver-engine/fs@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.3.3.tgz#fbf83fa0c4f60154a82c817d2fe3f3b0c049a973" - integrity sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ== - dependencies: - "@resolver-engine/core" "^0.3.3" - debug "^3.1.0" - -"@resolver-engine/imports-fs@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz#4085db4b8d3c03feb7a425fbfcf5325c0d1e6c1b" - integrity sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA== - dependencies: - "@resolver-engine/fs" "^0.3.3" - "@resolver-engine/imports" "^0.3.3" - debug "^3.1.0" - -"@resolver-engine/imports@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.3.3.tgz#badfb513bb3ff3c1ee9fd56073e3144245588bcc" - integrity sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q== - dependencies: - "@resolver-engine/core" "^0.3.3" - debug "^3.1.0" - hosted-git-info "^2.6.0" - path-browserify "^1.0.0" - url "^0.11.0" - "@scure/base@~1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" @@ -1849,24 +1418,6 @@ "@noble/secp256k1" "~1.6.0" "@scure/base" "~1.1.0" -"@scure/bip32@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.0.tgz#6c8d980ef3f290987736acd0ee2e0f0d50068d87" - integrity sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q== - dependencies: - "@noble/curves" "~1.0.0" - "@noble/hashes" "~1.3.0" - "@scure/base" "~1.1.0" - -"@scure/bip32@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10" - integrity sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A== - dependencies: - "@noble/curves" "~1.1.0" - "@noble/hashes" "~1.3.1" - "@scure/base" "~1.1.0" - "@scure/bip39@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.0.tgz#92f11d095bae025f166bef3defcc5bf4945d419a" @@ -1875,22 +1426,6 @@ "@noble/hashes" "~1.1.1" "@scure/base" "~1.1.0" -"@scure/bip39@1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.0.tgz#a207e2ef96de354de7d0002292ba1503538fc77b" - integrity sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg== - dependencies: - "@noble/hashes" "~1.3.0" - "@scure/base" "~1.1.0" - -"@scure/bip39@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" - integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== - dependencies: - "@noble/hashes" "~1.3.0" - "@scure/base" "~1.1.0" - "@sentry/core@5.30.0": version "5.30.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" @@ -2005,191 +1540,6 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@sushiswap/abi@0.0.1": - version "0.0.1" - resolved "https://registry.yarnpkg.com/@sushiswap/abi/-/abi-0.0.1.tgz#2bb8ab632e4a95ec2152603c489f88fcc8ffdf7d" - integrity sha512-J4zWyfZdFiDIBa28MV/yYmr9nmWDqX8CXVfUoLfg48RVUyqPsu57dKtEKiBqAO/xpl7d9ZciNcya0d09NXvm8w== - -"@sushiswap/amm@0.1.12": - version "0.1.12" - resolved "https://registry.yarnpkg.com/@sushiswap/amm/-/amm-0.1.12.tgz#e4ddd4e8dfc6eccb3b6dbd203557333db1d3d655" - integrity sha512-SvgRfKZnNxSUwocuUbQFfHi2VYysrgPVxGnDC7iOTVU+4mS27XcNUmWXeJ/qciQe/f6x7z/GNbbeXjM2ZdehVg== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@sushiswap/chain" "0.1.2" - "@sushiswap/currency" "0.1.1" - "@sushiswap/math" "0.1.0" - "@sushiswap/tines" "1.0.8" - "@sushiswap/trident-core" "1.0.7" - "@sushiswap/types" "0.0.2" - "@sushiswap/v2-sdk" "0.0.8" - tiny-invariant "1.3.1" - tiny-warning "1.0.3" - zod "3.21.4" - -"@sushiswap/bentobox@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@sushiswap/bentobox/-/bentobox-1.0.1.tgz#a3fb265d66b28e4ddba290182ccf2f3e565a7da7" - integrity sha512-Wg3QVWie0YIVHch0oE0y6Dy+qpX/e5fsiF0MSaXgYNhTki1Uc5IPTcJ2wCISbkMjDpEP+HiLWivftNdc7gc+aw== - -"@sushiswap/chain@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@sushiswap/chain/-/chain-0.1.2.tgz#dc164887ace62edd781a8d9afac1054cbdefd582" - integrity sha512-A0S5fYxYxUZu3UQj3AwekCRgjDQ8hzLRjc1p9XwV9i+0r9ZxAdXafWFrpQufDoXS0lfKd/4XiFh50LsbhvWA8A== - -"@sushiswap/currency@0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@sushiswap/currency/-/currency-0.1.1.tgz#627b20155fbf40d76f4a930251c4bf088e3d93b3" - integrity sha512-AjzrYYUvpYabel13CmGBpDk+NHNkBIExTcLyZl1QBtDKkhWl/1239NU8WgEF04Pxx0UD1wK/FTCput2n5yK50Q== - dependencies: - "@ethersproject/address" "5.7.0" - "@ethersproject/units" "^5.7.0" - "@sushiswap/chain" "0.1.2" - "@sushiswap/math" "0.1.0" - lodash.flatmap "4.5.0" - tiny-invariant "1.3.1" - zod "3.21.4" - -"@sushiswap/hardhat-config@0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@sushiswap/hardhat-config/-/hardhat-config-0.1.3.tgz#33e7a457be3094716be7cffc3e5a37f8280f200b" - integrity sha512-lc+tPdmin2j3C/KtquoqsUZdQCIh7ibWThqfx0BMqixFwyBR3REp48JzN6hWmODKwQE8PKnYmldZ1GmZczKOMw== - dependencies: - "@matterlabs/hardhat-zksync-deploy" "0.6.2" - "@matterlabs/hardhat-zksync-solc" "0.3.14" - "@nomiclabs/hardhat-ethers" "npm:hardhat-deploy-ethers@0.3.0-beta.13" - "@nomiclabs/hardhat-etherscan" "3.1.3" - "@nomiclabs/hardhat-solhint" "2.0.1" - "@nomiclabs/hardhat-waffle" "2.0.3" - "@sushiswap/types" "0.0.2" - "@tenderly/hardhat-tenderly" "1.3.2" - "@typechain/ethers-v5" "10.1.1" - "@typechain/hardhat" "6.1.4" - dotenv "16.0.3" - ethereum-waffle "3.4.4" - hardhat-deploy "0.11.22" - hardhat-deploy-ethers "0.3.0-beta.13" - typechain "8.1.1" - -"@sushiswap/math@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@sushiswap/math/-/math-0.1.0.tgz#e4821e81997a8acfcc11fdd55eccdd160cb308fe" - integrity sha512-bchOAQo7vWPHufXJQuk7+sWGxjhlbdlaI+kin3m3cLkUzKPPHqZxMwND4G9IpXsqEbko/DFrQL/M6a25gs7InA== - dependencies: - big.js "^6.1.1" - decimal.js-light "^2.5.1" - jsbi "^4.1.0" - tiny-invariant "^1.2.0" - toformat "^2.0.0" - -"@sushiswap/router-config@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sushiswap/router-config/-/router-config-2.0.0.tgz#5052f57472f1c9e72153995927ee4c72089c3b79" - integrity sha512-cVN20sur3EbC4GTxywuCVPovhXcuBh7hUMSFyhYhOQxhQGbvlPYot/+PX77UpYviTsJOTdo+ov2LyMT5AGdTHA== - -"@sushiswap/router@^0.0.12": - version "0.0.12" - resolved "https://registry.yarnpkg.com/@sushiswap/router/-/router-0.0.12.tgz#89d65dc04bfb971c5c9a987078cf8ee4ec92165c" - integrity sha512-53cPuNmZPDnt7u9l7q9CpoiJQHnOdtPMjnq1EsHKDh7Meb1pFav9zYrAFgCbn/5Np9Qs83/xxn77JtlGSh0ypw== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@sushiswap/abi" "0.0.1" - "@sushiswap/amm" "0.1.12" - "@sushiswap/bentobox" "1.0.1" - "@sushiswap/chain" "0.1.2" - "@sushiswap/currency" "0.1.1" - "@sushiswap/math" "0.1.0" - "@sushiswap/router-config" "2.0.0" - "@sushiswap/tines" "1.0.8" - "@sushiswap/trident-core" "1.0.7" - "@sushiswap/v2-sdk" "0.0.8" - "@sushiswap/v3-sdk" "1.0.9" - "@sushiswap/viem-config" "1.0.2" - date-fns "2.29.3" - ethers "5.7.2" - lodash.flatmap "^4.5.0" - node-fetch "2.6.6" - tiny-invariant "1.3.1" - tiny-warning "1.0.3" - viem "1.0.2" - zod "3.21.4" - -"@sushiswap/tines@1.0.8": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@sushiswap/tines/-/tines-1.0.8.tgz#11e7a0ed3bffe7fb0dea4141811b44294f09f95a" - integrity sha512-se9CnYcjnsuDqf7pbEXfo7FYaLgjSrBjaEc/TvEd0r8bO/goQSHUwNqklA+i9DpzYSki72GT2G5+4r6OxnActA== - dependencies: - "@ethersproject/bignumber" "5.7.0" - "@sushiswap/currency" "0.1.1" - -"@sushiswap/trident-core@1.0.7": - version "1.0.7" - resolved "https://registry.yarnpkg.com/@sushiswap/trident-core/-/trident-core-1.0.7.tgz#20c7691374332a0601e13fe1045189ae063d49b9" - integrity sha512-u2Z22726Y2hC8sx0jDj/lGMf2egFZ/uTctGUWrlUDb3KyT/LtxFVQOSYgaFw6GnRhunSfE0oOpHlYJNHEVYBpA== - dependencies: - "@openzeppelin/contracts" "4.7.3" - "@rari-capital/solmate" "6.2.0" - "@sushiswap/bentobox" "1.0.1" - "@sushiswap/currency" "0.1.1" - "@sushiswap/hardhat-config" "0.1.3" - "@sushiswap/types" "0.0.2" - -"@sushiswap/types@0.0.2": - version "0.0.2" - resolved "https://registry.yarnpkg.com/@sushiswap/types/-/types-0.0.2.tgz#9088674d01afede9c3738f6a62a908976f8bc639" - integrity sha512-Aa4MnBFq/SK/F4zZlRXNpLcqza2RsE0mLxxv4+8an1Dtr7l26lyWd+3PbVrtv1bA7OVmBXoqJhTrQKA8w3zEPA== - -"@sushiswap/v2-sdk@0.0.8": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@sushiswap/v2-sdk/-/v2-sdk-0.0.8.tgz#14c0460c8f3164314cd9d9b574815e1d365e7c06" - integrity sha512-o1h7uDkUOauNiVh2DUFZEfp5ASqt7muOs25VQxRV966YHYwDPs9SZEI9fVXn6a04jTWWOVbPP8BnDLYH+MRh8Q== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@sushiswap/chain" "0.1.2" - "@sushiswap/currency" "0.1.1" - "@sushiswap/math" "0.1.0" - tiny-invariant "1.3.1" - tiny-warning "1.0.3" - zod "3.21.4" - -"@sushiswap/v3-sdk@1.0.9": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@sushiswap/v3-sdk/-/v3-sdk-1.0.9.tgz#79d280a00b100886d8dee52dcfd0b9c2a115b32c" - integrity sha512-Lb5aJTy4atLUd8vtCQH3ZgAxFFefeZ26JqEeYlCrH2ayh73bs2CPET7E3ZKvKEOD1g2l67bvHfWesbueCyurVg== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@sushiswap/amm" "0.1.12" - "@sushiswap/chain" "0.1.2" - "@sushiswap/currency" "0.1.1" - "@sushiswap/math" "0.1.0" - "@sushiswap/tines" "1.0.8" - "@uniswap/swap-router-contracts" "1.3.0" - "@uniswap/v3-core" "1.0.1" - "@uniswap/v3-periphery" "1.4.3" - "@uniswap/v3-staker" "1.0.2" - tiny-invariant "1.3.1" - tiny-warning "1.0.3" - zod "3.21.4" - -"@sushiswap/viem-config@1.0.2", "@sushiswap/viem-config@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@sushiswap/viem-config/-/viem-config-1.0.2.tgz#82112a2cdddc63fa902f6d568d899423402200b8" - integrity sha512-IpZ/vmgs67LeR4eqrfIF/Og/taFGD9NW3E12kzS2sFyJJ0uZQP/hpqLNtNmXTPg9oV6/JCtnTGL+6Ic0EUd+gA== - dependencies: - "@sushiswap/chain" "0.1.2" - "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -2204,21 +1554,6 @@ dependencies: defer-to-connect "^2.0.0" -"@tenderly/hardhat-tenderly@1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@tenderly/hardhat-tenderly/-/hardhat-tenderly-1.3.2.tgz#9ee69ba1fb8650d18160c637e8e487d938f6dcea" - integrity sha512-0kE0gv8RIu0N5JXKCCfYcydsMgGgj8z3qCvbeD/ynBKwOBvbFB+NZFRyTHNopbeaUKO7Q3bGFau8vS1B0EWS0g== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@nomiclabs/hardhat-ethers" "^2.1.1" - axios "^0.27.2" - ethers "^5.7.0" - fs-extra "^10.1.0" - hardhat "^2.10.2" - hardhat-deploy "^0.11.14" - js-yaml "^4.1.0" - tenderly "^0.0.3" - "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -2239,28 +1574,6 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== -"@typechain/ethers-v5@10.1.1": - version "10.1.1" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-10.1.1.tgz#fdb527d8854129cea5f139d76c6c6e1c9bb040ec" - integrity sha512-o6nffJBxwmeX1ZiZpdnP/tqGd/7M7iYvQC88ZXaFFoyAGh7eYncynzVjOJV0XmaKzAc6puqyqZrnva+gJbk4sw== - dependencies: - lodash "^4.17.15" - ts-essentials "^7.0.1" - -"@typechain/ethers-v5@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" - integrity sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw== - dependencies: - ethers "^5.0.2" - -"@typechain/hardhat@6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-6.1.4.tgz#da930bf17bdae5e0996b86d37992c6c58b8a49c8" - integrity sha512-S8k5d1Rjc+plwKpkorlifmh72M7Ki0XNUOVVLtdbcA/vLaEkuqZSJFdddpBgS5QxiJP+6CbRa/yO6EVTE2+fMQ== - dependencies: - fs-extra "^9.1.0" - "@types/async-eventemitter@^0.2.1": version "0.2.1" resolved "https://registry.yarnpkg.com/@types/async-eventemitter/-/async-eventemitter-0.2.1.tgz#f8e6280e87e8c60b2b938624b0a3530fb3e24712" @@ -2311,13 +1624,6 @@ dependencies: "@babel/types" "^7.3.0" -"@types/bn.js@*", "@types/bn.js@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" - integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== - dependencies: - "@types/node" "*" - "@types/bn.js@^4.11.0", "@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": version "4.11.6" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" @@ -2325,6 +1631,13 @@ dependencies: "@types/node" "*" +"@types/bn.js@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== + dependencies: + "@types/node" "*" + "@types/body-parser@*": version "1.19.2" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" @@ -2343,11 +1656,6 @@ "@types/node" "*" "@types/responselike" "*" -"@types/chai@*": - version "4.3.5" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b" - integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== - "@types/connect@*": version "3.4.35" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" @@ -2450,21 +1758,6 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== -"@types/mkdirp@^0.5.2": - version "0.5.2" - resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" - integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== - dependencies: - "@types/node" "*" - -"@types/node-fetch@^2.5.5": - version "2.6.4" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" - integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg== - dependencies: - "@types/node" "*" - form-data "^3.0.0" - "@types/node@*": version "18.11.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.3.tgz#78a6d7ec962b596fc2d2ec102c4dd3ef073fea6a" @@ -2487,11 +1780,6 @@ dependencies: "@types/node" "*" -"@types/prettier@^2.1.1": - version "2.7.3" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" - integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== - "@types/prettier@^2.1.5": version "2.7.1" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e" @@ -2502,7 +1790,7 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== -"@types/qs@*", "@types/qs@^6.9.7": +"@types/qs@*": version "6.9.7" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== @@ -2521,21 +1809,6 @@ "@types/scheduler" "*" csstype "^3.0.2" -"@types/readable-stream@^2.3.13": - version "2.3.15" - resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.15.tgz#3d79c9ceb1b6a57d5f6e6976f489b9b5384321ae" - integrity sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ== - dependencies: - "@types/node" "*" - safe-buffer "~5.1.1" - -"@types/resolve@^0.0.8": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" - integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== - dependencies: - "@types/node" "*" - "@types/responselike@*", "@types/responselike@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" @@ -2568,49 +1841,16 @@ "@types/mime" "*" "@types/node" "*" -"@types/sinon-chai@^3.2.3": - version "3.2.9" - resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.9.tgz#71feb938574bbadcb176c68e5ff1a6014c5e69d4" - integrity sha512-/19t63pFYU0ikrdbXKBWj9PCdnKyTd0Qkz0X91Ta081cYsq90OxYdcWwK/dwEoDa6dtXgj2HJfmzgq+QZTHdmQ== - dependencies: - "@types/chai" "*" - "@types/sinon" "*" - -"@types/sinon@*": - version "10.0.16" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.16.tgz#4bf10313bd9aa8eef1e50ec9f4decd3dd455b4d3" - integrity sha512-j2Du5SYpXZjJVJtXBokASpPRj+e2z+VUhCPHmM6WMfe3dpHu6iVKJMU6AiBcMp/XTAYnEj6Wc1trJUWwZ0QaAQ== - dependencies: - "@types/sinonjs__fake-timers" "*" - -"@types/sinonjs__fake-timers@*": - version "8.1.2" - resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz#bf2e02a3dbd4aecaf95942ecd99b7402e03fad5e" - integrity sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA== - "@types/stack-utils@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== -"@types/underscore@*": - version "1.11.7" - resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.7.tgz#fa644dd948a34b4e102e6d31c30823ecba6ba9c7" - integrity sha512-uXFrH3+/R8AkckdYPJdmJm537rAOWOUt4DW3ni2l2GdXe1YrdREqab6lqsq1hm76xEihV39/qTxKIevNpZw2Zg== - "@types/uuid@^9.0.1": version "9.0.2" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.2.tgz#ede1d1b1e451548d44919dc226253e32a6952c4b" integrity sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ== -"@types/web3@1.0.19": - version "1.0.19" - resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.0.19.tgz#46b85d91d398ded9ab7c85a5dd57cb33ac558924" - integrity sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A== - dependencies: - "@types/bn.js" "*" - "@types/underscore" "*" - "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" @@ -2713,99 +1953,12 @@ "@typescript-eslint/types" "5.47.0" eslint-visitor-keys "^3.3.0" -"@uniswap/lib@^4.0.1-alpha": - version "4.0.1-alpha" - resolved "https://registry.yarnpkg.com/@uniswap/lib/-/lib-4.0.1-alpha.tgz#2881008e55f075344675b3bca93f020b028fbd02" - integrity sha512-f6UIliwBbRsgVLxIaBANF6w09tYqc6Y/qXdsrbEmXHyFA7ILiKrIwRFXe1yOg8M3cksgVsO9N7yuL2DdCGQKBA== - -"@uniswap/swap-router-contracts@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@uniswap/swap-router-contracts/-/swap-router-contracts-1.3.0.tgz#8d555ca6d74b888d6e02a26ebb806ce315605f1f" - integrity sha512-iKvCuRkHXEe0EMjOf8HFUISTIhlxI57kKFllf3C3PUIE0HmwxrayyoflwAz5u/TRsFGYqJ9IjX2UgzLCsrNa5A== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== dependencies: - "@openzeppelin/contracts" "3.4.2-solc-0.7" - "@uniswap/v2-core" "1.0.1" - "@uniswap/v3-core" "1.0.0" - "@uniswap/v3-periphery" "1.4.1" - dotenv "^14.2.0" - hardhat-watcher "^2.1.1" - -"@uniswap/v2-core@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@uniswap/v2-core/-/v2-core-1.0.1.tgz#af8f508bf183204779938969e2e54043e147d425" - integrity sha512-MtybtkUPSyysqLY2U210NBDeCHX+ltHt3oADGdjqoThZaFRDKwM6k1Nb3F0A3hk5hwuQvytFWhrWHOEq6nVJ8Q== - -"@uniswap/v3-core@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.0.tgz#6c24adacc4c25dceee0ba3ca142b35adbd7e359d" - integrity sha512-kSC4djMGKMHj7sLMYVnn61k9nu+lHjMIxgg9CDQT+s2QYLoA56GbSK9Oxr+qJXzzygbkrmuY6cwgP6cW2JXPFA== - -"@uniswap/v3-core@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@uniswap/v3-core/-/v3-core-1.0.1.tgz#b6d2bdc6ba3c3fbd610bdc502395d86cd35264a0" - integrity sha512-7pVk4hEm00j9tc71Y9+ssYpO6ytkeI0y7WE9P6UcmNzhxPePwyAxImuhVsTqWK9YFvzgtvzJHi64pBl4jUzKMQ== - -"@uniswap/v3-periphery@1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.4.1.tgz#b90f08b7386163c0abfd7258831caef6339c7862" - integrity sha512-Ab0ZCKOQrQMKIcpBTezTsEhWfQjItd0TtkCG8mPhoQu+wC67nPaf4hYUhM6wGHeFUmDiYY5MpEQuokB0ENvoTg== - dependencies: - "@openzeppelin/contracts" "3.4.2-solc-0.7" - "@uniswap/lib" "^4.0.1-alpha" - "@uniswap/v2-core" "1.0.1" - "@uniswap/v3-core" "1.0.0" - base64-sol "1.0.1" - hardhat-watcher "^2.1.1" - -"@uniswap/v3-periphery@1.4.3", "@uniswap/v3-periphery@^1.0.1": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@uniswap/v3-periphery/-/v3-periphery-1.4.3.tgz#a6da4632dbd46b139cc13a410e4ec09ad22bd19f" - integrity sha512-80c+wtVzl5JJT8UQskxVYYG3oZb4pkhY0zDe0ab/RX4+8f9+W5d8wI4BT0wLB0wFQTSnbW+QdBSpkHA/vRyGBA== - dependencies: - "@openzeppelin/contracts" "3.4.2-solc-0.7" - "@uniswap/lib" "^4.0.1-alpha" - "@uniswap/v2-core" "1.0.1" - "@uniswap/v3-core" "1.0.0" - base64-sol "1.0.1" - -"@uniswap/v3-staker@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@uniswap/v3-staker/-/v3-staker-1.0.2.tgz#febad4905903032bb114ab58138c2d5200c87a3c" - integrity sha512-+swIh/yhY9GQGyQxT4Gz54aXYLK+uc3qsmIvaAX+FjvhcL9TGOvS9tXbQsCZM4AJW63vj6TLsmHIjGMIePL1BQ== - dependencies: - "@openzeppelin/contracts" "3.4.1-solc-0.7-2" - "@uniswap/v3-core" "1.0.0" - "@uniswap/v3-periphery" "^1.0.1" - -"@wagmi/chains@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-1.1.0.tgz#d351b3dc6f472b167f180721f46f6098b6c1585b" - integrity sha512-pWZlxBk0Ql8E7DV8DwqlbBpOyUdaG9UDlQPBxJNALuEK1I0tbQ3AVvSDnlsEIt06UPmPo5o27gzs3hwPQ/A+UA== - -"@yarnpkg/lockfile@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" - integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== - -JSONStream@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" - integrity sha512-mn0KSip7N4e0UDPZHnqDsHECo5uGQrixQKnAskOM1BIB8hd7QKbd6il8IPRPudPHOeHiECoCFqhyMaRO9+nWyA== - dependencies: - jsonparse "^1.2.0" - through ">=2.2.7 <3" - -abitype@0.8.7: - version "0.8.7" - resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.8.7.tgz#e4b3f051febd08111f486c0cc6a98fa72d033622" - integrity sha512-wQ7hV8Yg/yKmGyFpqrNZufCxbszDe5es4AZGYPBitocfSqXtjrTG9JMWFcc4N30ukl2ve48aBTwt7NJxVQdU3w== - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" + event-target-shim "^5.0.0" abortcontroller-polyfill@^1.1.9: version "1.7.5" @@ -2825,34 +1978,6 @@ abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: module-error "^1.0.1" queue-microtask "^1.2.3" -abstract-leveldown@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" - integrity sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@^2.4.1, abstract-leveldown@~2.7.1: - version "2.7.2" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" - integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz#f7128e1f86ccabf7d2893077ce5d06d798e386c6" - integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@~2.6.0: - version "2.6.3" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" - integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== - dependencies: - xtend "~4.0.0" - accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -2861,7 +1986,7 @@ accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-jsx@^5.0.0, acorn-jsx@^5.3.2: +acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== @@ -2871,11 +1996,6 @@ acorn-walk@^8.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^6.0.7: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - acorn@^8.4.1: version "8.8.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" @@ -2896,11 +2016,6 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== -aes-js@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" - integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== - agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -2916,7 +2031,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.6.1, ajv@^6.9.1: +ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2926,16 +2041,6 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.6.1, ajv@^6.9.1: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.1: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -2946,11 +2051,6 @@ ansi-colors@^4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== -ansi-escapes@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== - ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -2958,32 +2058,12 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: dependencies: type-fest "^0.21.3" -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== - -ansi-regex@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" - integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== - -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - ansi-regex@^5.0.0, ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: +ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -3002,11 +2082,6 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -antlr4@4.7.1: - version "4.7.1" - resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.7.1.tgz#69984014f096e9e775f53dd9744bf994d8959773" - integrity sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ== - anymatch@^3.0.3: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" @@ -3040,53 +2115,6 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== - -array-back@^1.0.3, array-back@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" - integrity sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw== - dependencies: - typical "^2.6.0" - -array-back@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" - integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== - dependencies: - typical "^2.6.1" - -array-back@^3.0.1, array-back@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" - integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== - -array-back@^4.0.1, array-back@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" - integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== - -array-buffer-byte-length@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" - integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== - dependencies: - call-bind "^1.0.2" - is-array-buffer "^3.0.1" - array-differ@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" @@ -3113,11 +2141,6 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== - array.prototype.flat@^1.2.5: version "1.3.1" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" @@ -3128,29 +2151,6 @@ array.prototype.flat@^1.2.5: es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" -array.prototype.reduce@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" - integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - es-array-method-boxes-properly "^1.0.0" - is-string "^1.0.7" - -arraybuffer.prototype.slice@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz#9b5ea3868a6eebc30273da577eb888381c0044bb" - integrity sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw== - dependencies: - array-buffer-byte-length "^1.0.0" - call-bind "^1.0.2" - define-properties "^1.2.0" - get-intrinsic "^1.2.1" - is-array-buffer "^3.0.2" - is-shared-array-buffer "^1.0.2" - arrify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" @@ -3166,7 +2166,7 @@ asn1.js@^5.2.0: minimalistic-assert "^1.0.0" safer-buffer "^2.1.0" -asn1@^0.2.6, asn1@~0.2.3: +asn1@~0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== @@ -3183,22 +2183,7 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== - -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - -async-eventemitter@^0.2.2, async-eventemitter@^0.2.4: +async-eventemitter@^0.2.4: version "0.2.4" resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== @@ -3210,19 +2195,7 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async@2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" - integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== - dependencies: - lodash "^4.17.11" - -async@^1.4.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== - -async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: +async@^2.4.0: version "2.6.4" resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== @@ -3239,16 +2212,6 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - -atob@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - available-typed-arrays@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" @@ -3280,13 +2243,6 @@ axios@0.26.0: dependencies: follow-redirects "^1.14.8" -axios@^0.21.1: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - axios@^0.27.2: version "0.27.2" resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" @@ -3295,167 +2251,6 @@ axios@^0.27.2: follow-redirects "^1.14.9" form-data "^4.0.0" -babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g== - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-core@^6.0.14, babel-core@^6.26.0: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - -babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - integrity sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q== - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - integrity sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ== - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - integrity sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA== - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - integrity sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ== - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - integrity sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q== - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - integrity sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - integrity sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - integrity sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - integrity sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg== - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - integrity sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg== - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - integrity sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw== - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ== - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-jest@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.2.1.tgz#213c47e28072de11bdb98c9d29b89f2ab99664f1" @@ -3469,20 +2264,6 @@ babel-jest@^29.2.1: graceful-fs "^4.2.9" slash "^3.0.0" -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-check-es2015-constants@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - integrity sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA== - dependencies: - babel-runtime "^6.22.0" - babel-plugin-istanbul@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" @@ -3504,244 +2285,6 @@ babel-plugin-jest-hoist@^29.2.0: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - integrity sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw== - -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - integrity sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ== - -babel-plugin-syntax-trailing-function-commas@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - integrity sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ== - -babel-plugin-transform-async-to-generator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - integrity sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw== - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-arrow-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - integrity sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - integrity sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.23.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - integrity sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw== - dependencies: - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-plugin-transform-es2015-classes@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - integrity sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag== - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - integrity sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw== - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - integrity sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - integrity sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - integrity sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - integrity sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg== - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - integrity sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - integrity sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA== - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: - version "6.26.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" - integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-types "^6.26.0" - -babel-plugin-transform-es2015-modules-systemjs@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - integrity sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg== - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - integrity sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw== - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - integrity sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA== - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - integrity sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ== - dependencies: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - integrity sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - integrity sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-sticky-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - integrity sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ== - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - integrity sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - integrity sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw== - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - integrity sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ== - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - integrity sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ== - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-regenerator@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - integrity sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg== - dependencies: - regenerator-transform "^0.10.0" - -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - integrity sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -3760,42 +2303,6 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-env@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" - integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.23.0" - babel-plugin-transform-es2015-classes "^6.23.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.23.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.23.0" - babel-plugin-transform-es2015-function-name "^6.22.0" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.23.0" - babel-plugin-transform-es2015-modules-systemjs "^6.23.0" - babel-plugin-transform-es2015-modules-umd "^6.23.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.23.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.23.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-exponentiation-operator "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - browserslist "^3.2.6" - invariant "^2.2.2" - semver "^5.3.0" - babel-preset-jest@^29.2.0: version "29.2.0" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz#3048bea3a1af222e3505e4a767a974c95a7620dc" @@ -3804,83 +2311,6 @@ babel-preset-jest@^29.2.0: babel-plugin-jest-hoist "^29.2.0" babel-preset-current-node-syntax "^1.0.0" -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A== - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.24.1, babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg== - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.24.1, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA== - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g== - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babelify@^7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" - integrity sha512-vID8Fz6pPN5pJMdlUnNFSfrlcx5MUule4k9aKs/zbZPyXxMTcRrB0M4Tarw22L8afr8eYSWxDPYCob3TdrqtlA== - dependencies: - babel-core "^6.0.14" - object-assign "^4.0.0" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - -backoff@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" - integrity sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA== - dependencies: - precond "0.2" - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -3898,25 +2328,7 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base64-sol@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/base64-sol/-/base64-sol-1.0.1.tgz#91317aa341f0bc763811783c5729f1c2574600f6" - integrity sha512-ld3cCNMeXt4uJXmLZBHFGMvVpK9KsLVEhPpFRXnvSVAqABKbuNZg/+dsq3NuM+wxFLb/UrVkz7m1ciWmkMfTbg== - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2: +bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== @@ -3928,11 +2340,6 @@ bech32@1.1.4: resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== -big.js@^6.1.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.2.1.tgz#7205ce763efb17c2e41f26f121c420c6a7c2744f" - integrity sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ== - bigint-crypto-utils@^3.0.23: version "3.1.8" resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.1.8.tgz#e2e0f40cf45488f9d7f0e32ff84152aa73819d5d" @@ -3965,40 +2372,12 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bip39@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" - integrity sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA== - dependencies: - create-hash "^1.1.0" - pbkdf2 "^3.0.9" - randombytes "^2.0.1" - safe-buffer "^5.0.1" - unorm "^1.3.3" - -bl@^1.0.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" - integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== - dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" - -bl@^4.0.3: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" - integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - blakejs@^1.1.0: version "1.2.1" resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== -bluebird@^3.5.0, bluebird@^3.5.2: +bluebird@^3.5.0: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -4008,7 +2387,7 @@ bn.js@4.11.6: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.8.0: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== @@ -4051,22 +2430,6 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -4148,14 +2511,6 @@ browserify-sign@^4.0.0: readable-stream "^3.6.0" safe-buffer "^5.2.0" -browserslist@^3.2.6: - version "3.2.8" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" - integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== - dependencies: - caniuse-lite "^1.0.30000844" - electron-to-chromium "^1.3.47" - browserslist@^4.21.3: version "4.21.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" @@ -4196,24 +2551,6 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== - buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -4234,14 +2571,7 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== -buffer-xor@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" - integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== - dependencies: - safe-buffer "^5.1.1" - -buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: +buffer@^5.0.5, buffer@^5.5.0, buffer@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -4269,11 +2599,6 @@ bufio@^1.0.7: resolved "https://registry.yarnpkg.com/bufio/-/bufio-1.2.0.tgz#b9ad1c06b0d9010363c387c39d2810a7086d143f" integrity sha512-UlFk8z/PwdhYQTXSQQagwGAdtRI83gib2n4uy4rQnenxUM2yQi8lBDzF230BNk+3wAoZDxYRoBwVVUPgHa9MCA== -buildcheck@~0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.6.tgz#89aa6e417cfd1e2196e3f8fe915eb709d2fe4238" - integrity sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A== - busboy@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -4286,36 +2611,6 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -bytewise-core@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" - integrity sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA== - dependencies: - typewise-core "^1.2" - -bytewise@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" - integrity sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ== - dependencies: - bytewise-core "^1.2.2" - typewise "^1.0.3" - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - cacheable-lookup@^5.0.3: version "5.0.4" resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" @@ -4347,15 +2642,7 @@ cacheable-request@^7.0.2: normalize-url "^6.0.1" responselike "^2.0.0" -cachedown@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cachedown/-/cachedown-1.0.0.tgz#d43f036e4510696b31246d7db31ebf0f7ac32d15" - integrity sha512-t+yVk82vQWCJF3PsWHMld+jhhjkkWjcAzz8NbFx1iULOXWl8Tm/FdM4smZNVw3MRr0X+lVTx9PKzvEn4Ng19RQ== - dependencies: - abstract-leveldown "^2.4.1" - lru-cache "^3.2.0" - -call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: +call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== @@ -4363,25 +2650,6 @@ call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== - callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -4395,11 +2663,6 @@ camel-case@^4.1.2: pascal-case "^3.1.2" tslib "^2.0.3" -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg== - camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -4410,11 +2673,6 @@ camelcase@^6.0.0, camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30000844: - version "1.0.30001522" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001522.tgz#44b87a406c901269adcdb834713e23582dd71856" - integrity sha512-TKiyTVZxJGhsTszLuzb+6vUZSjVOAhClszBr2Ta2k9IwtNBT/4dzmL6aywt0HCgEZlmwJzXJd8yNiob6HgwTRg== - caniuse-lite@^1.0.30001400: version "1.0.30001423" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001423.tgz#57176d460aa8cd85ee1a72016b961eb9aca55d91" @@ -4429,11 +2687,6 @@ capital-case@^1.0.4: tslib "^2.0.3" upper-case-first "^2.0.2" -case@^1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" - integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== - caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -4444,13 +2697,6 @@ catering@^2.1.0, catering@^2.1.1: resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== -cbor@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" - integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== - dependencies: - nofilter "^3.1.0" - chai@^4.3.4: version "4.3.7" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" @@ -4464,26 +2710,7 @@ chai@^4.3.4: pathval "^1.1.1" type-detect "^4.0.5" -chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -4500,6 +2727,14 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + change-case@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" @@ -4523,24 +2758,12 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== -checkpoint-store@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" - integrity sha512-J/NdY2WvIx654cc6LWSq/IYFFCUf75fFTgwzFnmbqyORH4MwgiQCgswLLKBGzmsyTI5V7i5bp/So6sMbDWhedg== - dependencies: - functional-red-black-tree "^1.0.1" - -chokidar@3.5.3, chokidar@^3.4.0, chokidar@^3.5.2, chokidar@^3.5.3: +chokidar@3.5.3, chokidar@^3.4.0: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -4555,7 +2778,7 @@ chokidar@3.5.3, chokidar@^3.4.0, chokidar@^3.5.2, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" -chownr@^1.0.1, chownr@^1.1.1, chownr@^1.1.4: +chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== @@ -4599,16 +2822,6 @@ class-is@^1.1.0: resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - classic-level@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.2.0.tgz#2d52bdec8e7a27f534e67fdeb890abef3e643c27" @@ -4625,36 +2838,6 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== - dependencies: - restore-cursor "^2.0.0" - -cli-table3@^0.6.2: - version "0.6.3" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" - integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== - dependencies: - string-width "^4.2.0" - optionalDependencies: - "@colors/colors" "1.5.0" - -cli-width@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" - integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== - -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w== - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -4680,7 +2863,7 @@ clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" -clone@2.1.2, clone@2.x, clone@^2.0.0: +clone@2.x: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== @@ -4690,24 +2873,11 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== - collect-v8-coverage@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -4744,70 +2914,16 @@ command-exists@^1.2.8: resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== -command-line-args@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46" - integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== - dependencies: - array-back "^2.0.0" - find-replace "^1.0.3" - typical "^2.6.1" - -command-line-args@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" - integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== - dependencies: - array-back "^3.1.0" - find-replace "^3.0.0" - lodash.camelcase "^4.3.0" - typical "^4.0.0" - -command-line-usage@^6.1.0: - version "6.1.3" - resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.3.tgz#428fa5acde6a838779dfa30e44686f4b6761d957" - integrity sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw== - dependencies: - array-back "^4.0.2" - chalk "^2.4.2" - table-layout "^1.0.2" - typical "^5.2.0" - -commander@2.18.0: - version "2.18.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" - integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== - commander@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== -commander@^9.4.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" - integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== - -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -concat-stream@^1.5.1, concat-stream@~1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - confusing-browser-globals@^1.0.10: version "1.0.11" resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" @@ -4843,7 +2959,7 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== -convert-source-map@^1.4.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== @@ -4868,31 +2984,11 @@ cookiejar@^2.1.1: resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== - -core-js-pure@^3.0.1: - version "3.32.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.32.1.tgz#5775b88f9062885f67b6d7edce59984e89d276f3" - integrity sha512-f52QZwkFVDPf7UEQZGHKx6NYxsxmVGJe5DIvbzOdRMJlmT6yv0KDjR8rmy3ngr/t5wU54c7Sp/qIJH0ppbhVpQ== - -core-js@^2.4.0, core-js@^2.5.0: - version "2.6.12" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" - integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== - core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - cors@^2.8.1: version "2.8.5" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" @@ -4901,24 +2997,6 @@ cors@^2.8.1: object-assign "^4" vary "^1" -cosmiconfig@^5.0.7: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - -cpu-features@~0.0.8: - version "0.0.9" - resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.9.tgz#5226b92f0f1c63122b0a3eb84cb8335a4de499fc" - integrity sha512-AKjgn2rP2yJyfbepsmLfiYcmtNn/2eUvocUyM/09yB0YDiz39HteK/5/T4Onf0pmdYDMgkBoGvRLvEguzyL7wQ== - dependencies: - buildcheck "~0.0.6" - nan "^2.17.0" - crc-32@^1.2.0: version "1.2.2" resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" @@ -4960,14 +3038,6 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-fetch@^2.1.0, cross-fetch@^2.1.1: - version "2.2.6" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.6.tgz#2ef0bb39a24ac034787965c457368a28730e220a" - integrity sha512-9JZz+vXCmfKUZ68zAptS7k4Nu8e2qcibe7WVZYps7sAgk5R8GYTc+T1WR0v1rlP9HxgARmOX1UTIJZFytajpNA== - dependencies: - node-fetch "^2.6.7" - whatwg-fetch "^2.0.4" - cross-fetch@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" @@ -4975,17 +3045,6 @@ cross-fetch@^3.1.5: dependencies: node-fetch "2.6.7" -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -5037,59 +3096,37 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -date-fns@2.29.3: - version "2.29.3" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" - integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== - date-format@^4.0.13, date-format@^4.0.14: version "4.0.14" resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.14.tgz#7a8e584434fb169a521c8b7aa481f355810d9400" integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -debug@4, debug@4.3.4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: +debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" -decamelize@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - decamelize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== -decimal.js-light@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" - integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== - decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -5121,24 +3158,7 @@ deep-eql@^4.1.2: dependencies: type-detect "^4.0.0" -deep-equal@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - -deep-extend@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deep-is@^0.1.3, deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -5158,26 +3178,6 @@ defer-to-connect@^2.0.0: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== -deferred-leveldown@~1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" - integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== - dependencies: - abstract-leveldown "~2.6.0" - -deferred-leveldown@~4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz#0b0570087827bf480a23494b398f04c128c19a20" - integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== - dependencies: - abstract-leveldown "~5.0.0" - inherits "^2.0.3" - -define-lazy-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" - integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== - define-properties@^1.1.3, define-properties@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" @@ -5186,41 +3186,6 @@ define-properties@^1.1.3, define-properties@^1.1.4: has-property-descriptors "^1.0.0" object-keys "^1.1.1" -define-properties@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" - integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -defined@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" - integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -5244,13 +3209,6 @@ destroy@1.2.0: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A== - dependencies: - repeating "^2.0.0" - detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -5297,44 +3255,6 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -docker-modem@^1.0.8: - version "1.0.9" - resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-1.0.9.tgz#a1f13e50e6afb6cf3431b2d5e7aac589db6aaba8" - integrity sha512-lVjqCSCIAUDZPAZIeyM125HXfNvOmYYInciphNrLrylUtKyW66meAjSPXWchKVzoIYZx69TPnAepVSSkeawoIw== - dependencies: - JSONStream "1.3.2" - debug "^3.2.6" - readable-stream "~1.0.26-4" - split-ca "^1.0.0" - -docker-modem@^3.0.0: - version "3.0.8" - resolved "https://registry.yarnpkg.com/docker-modem/-/docker-modem-3.0.8.tgz#ef62c8bdff6e8a7d12f0160988c295ea8705e77a" - integrity sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ== - dependencies: - debug "^4.1.1" - readable-stream "^3.5.0" - split-ca "^1.0.1" - ssh2 "^1.11.0" - -dockerode@^2.5.8: - version "2.5.8" - resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-2.5.8.tgz#1b661e36e1e4f860e25f56e0deabe9f87f1d0acc" - integrity sha512-+7iOUYBeDTScmOmQqpUYQaE7F4vvIt6+gIZNHWhqAQEI887tiPFB9OvXI/HzQYqfUNvukMK+9myLW63oTJPZpw== - dependencies: - concat-stream "~1.6.2" - docker-modem "^1.0.8" - tar-fs "~1.16.3" - -dockerode@^3.3.4: - version "3.3.5" - resolved "https://registry.yarnpkg.com/dockerode/-/dockerode-3.3.5.tgz#7ae3f40f2bec53ae5e9a741ce655fff459745629" - integrity sha512-/0YNa3ZDNeLr/tSckmD69+Gq+qVNhvKfAHNeZJBnp7EOP6RGKV8ORrJHkUn20So5wU+xxT7+1n5u8PjHbfjbSA== - dependencies: - "@balena/dockerignore" "^1.0.2" - docker-modem "^3.0.0" - tar-fs "~2.0.1" - doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -5367,23 +3287,6 @@ dotenv@16.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411" integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q== -dotenv@16.0.3: - version "16.0.3" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" - integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== - -dotenv@^14.2.0: - version "14.3.2" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-14.3.2.tgz#7c30b3a5f777c79a3429cb2db358eef6751e8369" - integrity sha512-vwEppIphpFdvaMCaHfCEv9IgwcxMljMw2TnAQBB4VWPvzXQLTb82jwmdOKzlEVUL3gNFT4l4TPKO+Bn+sqcrVQ== - -dotignore@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" - integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== - dependencies: - minimatch "^3.0.4" - duplexer3@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" @@ -5402,11 +3305,6 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.3.47: - version "1.4.500" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.500.tgz#7dd05fdfbe02ed34b9f6099cfe01407b473d5af7" - integrity sha512-P38NO8eOuWOKY1sQk5yE0crNtrjgjJj6r3NrbIKtG18KzCHmHE2Bt+aQA7/y0w3uYsHWxDa6icOohzjLJ4vJ4A== - electron-to-chromium@^1.4.251: version "1.4.284" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" @@ -5430,37 +3328,16 @@ emittery@^0.10.2: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933" integrity sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw== -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -encode-utf8@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" - integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -encoding-down@5.0.4, encoding-down@~5.0.0: - version "5.0.4" - resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-5.0.4.tgz#1e477da8e9e9d0f7c8293d320044f8b2cd8e9614" - integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== - dependencies: - abstract-leveldown "^5.0.0" - inherits "^2.0.3" - level-codec "^9.0.0" - level-errors "^2.0.0" - xtend "^4.0.1" - encoding@^0.1.11: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" @@ -5468,7 +3345,7 @@ encoding@^0.1.11: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: +end-of-stream@^1.1.0: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -5482,27 +3359,12 @@ enquirer@^2.3.0: dependencies: ansi-colors "^4.1.1" -enquirer@^2.3.6: - version "2.4.1" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" - integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== - dependencies: - ansi-colors "^4.1.1" - strip-ansi "^6.0.1" - env-paths@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== -errno@~0.1.1: - version "0.1.8" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" - integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== - dependencies: - prr "~1.0.1" - -error-ex@^1.2.0, error-ex@^1.3.1: +error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -5570,65 +3432,6 @@ es-abstract@^1.20.4: string.prototype.trimstart "^1.0.6" unbox-primitive "^1.0.2" -es-abstract@^1.21.2: - version "1.22.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc" - integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw== - dependencies: - array-buffer-byte-length "^1.0.0" - arraybuffer.prototype.slice "^1.0.1" - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-set-tostringtag "^2.0.1" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.2.1" - get-symbol-description "^1.0.0" - globalthis "^1.0.3" - gopd "^1.0.1" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.5" - is-array-buffer "^3.0.2" - is-callable "^1.2.7" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-typed-array "^1.1.10" - is-weakref "^1.0.2" - object-inspect "^1.12.3" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.5.0" - safe-array-concat "^1.0.0" - safe-regex-test "^1.0.0" - string.prototype.trim "^1.2.7" - string.prototype.trimend "^1.0.6" - string.prototype.trimstart "^1.0.6" - typed-array-buffer "^1.0.0" - typed-array-byte-length "^1.0.0" - typed-array-byte-offset "^1.0.0" - typed-array-length "^1.0.4" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.10" - -es-array-method-boxes-properly@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" - integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== - -es-set-tostringtag@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" - integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== - dependencies: - get-intrinsic "^1.1.3" - has "^1.0.3" - has-tostringtag "^1.0.0" - es-shim-unscopables@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" @@ -5691,7 +3494,7 @@ escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== @@ -5750,14 +3553,6 @@ eslint-plugin-import@^2.26.0: resolve "^1.22.0" tsconfig-paths "^3.14.1" -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -5774,13 +3569,6 @@ eslint-scope@^7.1.1: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-utils@^1.3.1: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" - eslint-utils@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" @@ -5788,11 +3576,6 @@ eslint-utils@^3.0.0: dependencies: eslint-visitor-keys "^2.0.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - eslint-visitor-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" @@ -5803,48 +3586,6 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@^5.6.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^4.0.3" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.7.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.13.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.11" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" - table "^5.2.3" - text-table "^0.2.0" - eslint@^8.30.0: version "8.30.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.30.0.tgz#83a506125d089eef7c5b5910eeea824273a33f50" @@ -5890,15 +3631,6 @@ eslint@^8.30.0: strip-json-comments "^3.1.0" text-table "^0.2.0" -espree@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" - integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== - dependencies: - acorn "^6.0.7" - acorn-jsx "^5.0.0" - eslint-visitor-keys "^1.0.0" - espree@^9.4.0: version "9.4.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" @@ -5913,13 +3645,6 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - esquery@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" @@ -5927,7 +3652,7 @@ esquery@^1.4.0: dependencies: estraverse "^5.1.0" -esrecurse@^4.1.0, esrecurse@^4.3.0: +esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== @@ -5954,20 +3679,7 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -eth-block-tracker@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz#95cd5e763c7293e0b1b2790a2a39ac2ac188a5e1" - integrity sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug== - dependencies: - eth-query "^2.1.0" - ethereumjs-tx "^1.3.3" - ethereumjs-util "^5.1.3" - ethjs-util "^0.1.3" - json-rpc-engine "^3.6.0" - pify "^2.3.0" - tape "^4.6.3" - -eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: +eth-ens-namehash@2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" integrity sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw== @@ -5975,35 +3687,6 @@ eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: idna-uts46-hx "^2.3.1" js-sha3 "^0.5.7" -eth-json-rpc-infura@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz#26702a821067862b72d979c016fd611502c6057f" - integrity sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw== - dependencies: - cross-fetch "^2.1.1" - eth-json-rpc-middleware "^1.5.0" - json-rpc-engine "^3.4.0" - json-rpc-error "^2.0.0" - -eth-json-rpc-middleware@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" - integrity sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q== - dependencies: - async "^2.5.0" - eth-query "^2.1.2" - eth-tx-summary "^3.1.2" - ethereumjs-block "^1.6.0" - ethereumjs-tx "^1.3.3" - ethereumjs-util "^5.1.2" - ethereumjs-vm "^2.1.0" - fetch-ponyfill "^4.0.0" - json-rpc-engine "^3.6.0" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - tape "^4.6.3" - eth-lib@0.2.8: version "0.2.8" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" @@ -6025,60 +3708,6 @@ eth-lib@^0.1.26: ws "^3.0.0" xhr-request-promise "^0.1.2" -eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" - integrity sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA== - dependencies: - json-rpc-random-id "^1.0.0" - xtend "^4.0.1" - -eth-sig-util@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.0.tgz#75133b3d7c20a5731af0690c385e184ab942b97e" - integrity sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ== - dependencies: - buffer "^5.2.1" - elliptic "^6.4.0" - ethereumjs-abi "0.6.5" - ethereumjs-util "^5.1.1" - tweetnacl "^1.0.0" - tweetnacl-util "^0.15.0" - -eth-sig-util@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" - integrity sha512-iNZ576iTOGcfllftB73cPB5AN+XUQAT/T8xzsILsghXC1o8gJUqe3RHlcDqagu+biFpYQ61KQrZZJza8eRSYqw== - dependencies: - ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" - ethereumjs-util "^5.1.1" - -eth-tx-summary@^3.1.2: - version "3.2.4" - resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" - integrity sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg== - dependencies: - async "^2.1.2" - clone "^2.0.0" - concat-stream "^1.5.1" - end-of-stream "^1.1.0" - eth-query "^2.0.2" - ethereumjs-block "^1.4.1" - ethereumjs-tx "^1.1.1" - ethereumjs-util "^5.0.1" - ethereumjs-vm "^2.6.0" - through2 "^2.0.3" - -ethashjs@~0.0.7: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.8.tgz#227442f1bdee409a548fb04136e24c874f3aa6f9" - integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw== - dependencies: - async "^2.1.2" - buffer-xor "^2.0.1" - ethereumjs-util "^7.0.2" - miller-rabin "^4.0.0" - ethereum-bloom-filters@^1.0.6: version "1.0.10" resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" @@ -6086,16 +3715,6 @@ ethereum-bloom-filters@^1.0.6: dependencies: js-sha3 "^0.8.0" -ethereum-common@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" - integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== - -ethereum-common@^0.0.18: - version "0.0.18" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" - integrity sha512-EoltVQTRNg2Uy4o84qpa2aXymXDJhxm7eos/ACOg0DG4baAbMjhbdAEsx9GeE8sC3XCxnYvrrzZDH8D8MtA2iQ== - ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" @@ -6127,16 +3746,6 @@ ethereum-cryptography@^1.0.3: "@scure/bip32" "1.1.0" "@scure/bip39" "1.1.0" -ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz#18fa7108622e56481157a5cb7c01c0c6a672eb67" - integrity sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug== - dependencies: - "@noble/curves" "1.1.0" - "@noble/hashes" "1.3.1" - "@scure/bip32" "1.3.1" - "@scure/bip39" "1.2.1" - ethereum-types@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/ethereum-types/-/ethereum-types-2.1.6.tgz#57d9d515fad86ab987c0f6962c4203be37da8579" @@ -6145,26 +3754,7 @@ ethereum-types@^2.1.6: "@types/node" "*" bignumber.js "~8.0.2" -ethereum-waffle@3.4.4: - version "3.4.4" - resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.4.tgz#1378b72040697857b7f5e8f473ca8f97a37b5840" - integrity sha512-PA9+jCjw4WC3Oc5ocSMBj5sXvueWQeAbvCA+hUlb6oFgwwKyq5ka3bWQ7QZcjzIX+TdFkxP4IbFmoY2D8Dkj9Q== - dependencies: - "@ethereum-waffle/chai" "^3.4.4" - "@ethereum-waffle/compiler" "^3.4.4" - "@ethereum-waffle/mock-contract" "^3.4.4" - "@ethereum-waffle/provider" "^3.4.4" - ethers "^5.0.1" - -ethereumjs-abi@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" - integrity sha512-rCjJZ/AE96c/AAZc6O3kaog4FhOsAViaysBxqJNy2+LHP0ttH0zkZ7nXdVHOAyt6lFwLO0nlCwWszysG/ao1+g== - dependencies: - bn.js "^4.10.0" - ethereumjs-util "^4.3.0" - -ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: +ethereumjs-abi@^0.6.8: version "0.6.8" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== @@ -6172,96 +3762,20 @@ ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.8: bn.js "^4.11.8" ethereumjs-util "^6.0.0" -"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": - version "0.6.8" - resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0" - dependencies: - bn.js "^4.11.8" - ethereumjs-util "^6.0.0" - -ethereumjs-account@3.0.0, ethereumjs-account@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz#728f060c8e0c6e87f1e987f751d3da25422570a9" - integrity sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA== - dependencies: - ethereumjs-util "^6.0.0" - rlp "^2.2.1" - safe-buffer "^5.1.1" - -ethereumjs-account@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" - integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== +ethereumjs-util@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" + integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== dependencies: - ethereumjs-util "^5.0.0" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "^0.1.3" rlp "^2.0.0" safe-buffer "^5.1.1" -ethereumjs-block@2.2.2, ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.0, ethereumjs-block@~2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" - integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== - dependencies: - async "^2.0.1" - ethereumjs-common "^1.5.0" - ethereumjs-tx "^2.1.1" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0: - version "1.7.1" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" - integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== - dependencies: - async "^2.0.1" - ethereum-common "0.2.0" - ethereumjs-tx "^1.2.2" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-blockchain@^4.0.3: - version "4.0.4" - resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz#30f2228dc35f6dcf94423692a6902604ae34960f" - integrity sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ== - dependencies: - async "^2.6.1" - ethashjs "~0.0.7" - ethereumjs-block "~2.2.2" - ethereumjs-common "^1.5.0" - ethereumjs-util "^6.1.0" - flow-stoplight "^1.0.0" - level-mem "^3.0.1" - lru-cache "^5.1.1" - rlp "^2.2.2" - semaphore "^1.1.0" - -ethereumjs-common@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd" - integrity sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ== - -ethereumjs-common@^1.1.0, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" - integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== - -ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" - integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== - dependencies: - ethereumjs-common "^1.5.0" - ethereumjs-util "^6.0.0" - -ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3: - version "1.3.7" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" - integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== - dependencies: - ethereum-common "^0.0.18" - ethereumjs-util "^5.0.0" - -ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0, ethereumjs-util@^6.2.1: +ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== @@ -6274,31 +3788,7 @@ ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumj ethjs-util "0.1.6" rlp "^2.2.3" -ethereumjs-util@^4.3.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz#f4bf9b3b515a484e3cc8781d61d9d980f7c83bd0" - integrity sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w== - dependencies: - bn.js "^4.8.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - rlp "^2.0.0" - -ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" - integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== - dependencies: - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "^0.1.3" - rlp "^2.0.0" - safe-buffer "^5.1.1" - -ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: +ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== @@ -6309,60 +3799,7 @@ ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0, ethereu ethereum-cryptography "^0.1.3" rlp "^2.2.4" -ethereumjs-vm@4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz#e885e861424e373dbc556278f7259ff3fca5edab" - integrity sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA== - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - core-js-pure "^3.0.1" - ethereumjs-account "^3.0.0" - ethereumjs-block "^2.2.2" - ethereumjs-blockchain "^4.0.3" - ethereumjs-common "^1.5.0" - ethereumjs-tx "^2.1.2" - ethereumjs-util "^6.2.0" - fake-merkle-patricia-tree "^1.0.1" - functional-red-black-tree "^1.0.1" - merkle-patricia-tree "^2.3.2" - rustbn.js "~0.2.0" - safe-buffer "^5.1.1" - util.promisify "^1.0.0" - -ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" - integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - ethereumjs-account "^2.0.3" - ethereumjs-block "~2.2.0" - ethereumjs-common "^1.1.0" - ethereumjs-util "^6.0.0" - fake-merkle-patricia-tree "^1.0.1" - functional-red-black-tree "^1.0.1" - merkle-patricia-tree "^2.3.2" - rustbn.js "~0.2.0" - safe-buffer "^5.1.1" - -ethereumjs-wallet@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz#685e9091645cee230ad125c007658833991ed474" - integrity sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA== - dependencies: - aes-js "^3.1.1" - bs58check "^2.1.2" - ethereum-cryptography "^0.1.3" - ethereumjs-util "^6.0.0" - randombytes "^2.0.6" - safe-buffer "^5.1.2" - scryptsy "^1.2.1" - utf8 "^3.0.0" - uuid "^3.3.2" - -ethers@5.7.2, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.5.2, ethers@^5.5.3, ethers@^5.6.5, ethers@^5.7.0, ethers@^5.7.1: +ethers@^5.6.5, ethers@^5.7.0: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -6439,11 +3876,6 @@ eventemitter3@4.0.4: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== -events@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" @@ -6487,19 +3919,6 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - expect@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/expect/-/expect-29.2.1.tgz#25752d0df92d3daa5188dc8804de1f30759658cf" @@ -6511,7 +3930,7 @@ expect@^29.2.1: jest-message-util "^29.2.1" jest-util "^29.2.1" -express@^4.14.0, express@^4.18.1, express@^4.18.2: +express@^4.14.0, express@^4.18.2: version "4.18.2" resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== @@ -6555,49 +3974,11 @@ ext@^1.1.2: dependencies: type "^2.7.2" -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -6608,23 +3989,11 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== -fake-merkle-patricia-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" - integrity sha512-Tgq37lkc9pUIgIKw5uitNUKcgcYL3R6JvXtKQbOf/ZSavXbidsksgp/pAY6p//uhw0I4yoMsvTSovvVIsk/qxA== - dependencies: - checkpoint-store "^1.1.0" - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" - integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== - fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" @@ -6641,7 +4010,7 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-sta resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== @@ -6660,27 +4029,6 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -fetch-ponyfill@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" - integrity sha512-knK9sGskIg2T7OnYLdZ2hZXn0CtDrAIBxYQLpmEf0BqfdWnwmM1weccUl5+4EdA44tzNSFAuxITPbXtPehUB3g== - dependencies: - node-fetch "~1.7.1" - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -6688,16 +4036,6 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -6718,21 +4056,6 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" -find-replace@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" - integrity sha512-KrUnjzDCD9426YnCP56zGYy/eieTnhtK6Vn++j+JJzmlsWWwEkDnsyVF575spT6HJ6Ow9tlbT3TQTDsa+O4UWA== - dependencies: - array-back "^1.0.4" - test-value "^2.1.0" - -find-replace@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" - integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== - dependencies: - array-back "^3.0.1" - find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -6741,14 +4064,6 @@ find-up@5.0.0, find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA== - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -6764,30 +4079,6 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -find-yarn-workspace-root@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" - integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== - dependencies: - fs-extra "^4.0.3" - micromatch "^3.1.4" - -find-yarn-workspace-root@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" - integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== - dependencies: - micromatch "^4.0.2" - -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -6801,59 +4092,28 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== - flatted@^3.1.0, flatted@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== -flow-stoplight@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" - integrity sha512-rDjbZUKpN8OYhB0IE/vY/I8UWO/602IIJEU/76Tv4LvYnwHCk0BCsvz4eRr9n+FQcri7L5cyaXOo0+/Kh4HisA== - -fmix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c" - integrity sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w== - dependencies: - imul "^1.0.0" - -follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.14.8, follow-redirects@^1.14.9, follow-redirects@^1.15.0: +follow-redirects@^1.12.1, follow-redirects@^1.14.8, follow-redirects@^1.14.9, follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== -for-each@^0.3.3, for-each@~0.3.3: +for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== dependencies: is-callable "^1.1.3" -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== -form-data@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -6887,23 +4147,11 @@ fp-ts@^1.0.0: resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== - dependencies: - map-cache "^0.2.2" - fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" @@ -6915,16 +4163,7 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^10.0.0, fs-extra@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" - integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - -fs-extra@^4.0.2, fs-extra@^4.0.3: +fs-extra@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== @@ -6933,7 +4172,7 @@ fs-extra@^4.0.2, fs-extra@^4.0.3: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^7.0.0, fs-extra@^7.0.1: +fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== @@ -6951,16 +4190,6 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.0, fs-extra@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" - integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - fs-minipass@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" @@ -6993,63 +4222,21 @@ function.prototype.name@^1.1.5: es-abstract "^1.19.0" functions-have-names "^1.2.2" -functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: +functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== -functions-have-names@^1.2.2, functions-have-names@^1.2.3: +functions-have-names@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -ganache-core@^2.13.2: - version "2.13.2" - resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.13.2.tgz#27e6fc5417c10e6e76e2e646671869d7665814a3" - integrity sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw== - dependencies: - abstract-leveldown "3.0.0" - async "2.6.2" - bip39 "2.5.0" - cachedown "1.0.0" - clone "2.1.2" - debug "3.2.6" - encoding-down "5.0.4" - eth-sig-util "3.0.0" - ethereumjs-abi "0.6.8" - ethereumjs-account "3.0.0" - ethereumjs-block "2.2.2" - ethereumjs-common "1.5.0" - ethereumjs-tx "2.1.2" - ethereumjs-util "6.2.1" - ethereumjs-vm "4.2.0" - heap "0.2.6" - keccak "3.0.1" - level-sublevel "6.6.4" - levelup "3.1.1" - lodash "4.17.20" - lru-cache "5.1.1" - merkle-patricia-tree "3.0.0" - patch-package "6.2.2" - seedrandom "3.0.1" - source-map-support "0.5.12" - tmp "0.1.0" - web3-provider-engine "14.2.1" - websocket "1.0.32" - optionalDependencies: - ethereumjs-wallet "0.6.5" - web3 "1.2.11" - gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -7069,16 +4256,6 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@ has "^1.0.3" has-symbols "^1.0.3" -get-intrinsic@^1.2.0, get-intrinsic@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" - integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-proto "^1.0.1" - has-symbols "^1.0.3" - get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -7111,11 +4288,6 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== - getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -7137,18 +4309,6 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@7.1.7: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" @@ -7161,7 +4321,7 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.2.3: +glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -7181,7 +4341,7 @@ global@~4.4.0: min-document "^2.19.0" process "^0.11.10" -globals@^11.1.0, globals@^11.7.0: +globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== @@ -7193,18 +4353,6 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== - -globalthis@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" - integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== - dependencies: - define-properties "^1.1.3" - globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" @@ -7258,11 +4406,6 @@ got@^11.8.5: p-cancelable "^2.0.0" responselike "^2.0.0" -graceful-fs@^4.1.11: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" @@ -7286,116 +4429,6 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" -hardhat-deploy@0.11.22: - version "0.11.22" - resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.22.tgz#9799c0266a0fc40c84690de54760f1b4dae5e487" - integrity sha512-ZhHVNB7Jo2l8Is+KIAk9F8Q3d7pptyiX+nsNbIFXztCz81kaP+6kxNODRBqRCy7SOD3It4+iKCL6tWsPAA/jVQ== - dependencies: - "@types/qs" "^6.9.7" - axios "^0.21.1" - chalk "^4.1.2" - chokidar "^3.5.2" - debug "^4.3.2" - enquirer "^2.3.6" - ethers "^5.5.3" - form-data "^4.0.0" - fs-extra "^10.0.0" - match-all "^1.2.6" - murmur-128 "^0.2.1" - qs "^6.9.4" - zksync-web3 "^0.8.1" - -hardhat-deploy@^0.11.14: - version "0.11.37" - resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.37.tgz#6a771b859c82ae25292321a6d510d7c0eda09d2b" - integrity sha512-pohPSEEo/X9Yfv0Fc0kXBQW6JO0LNOILBGCP69Ci1COJvLht1hLjAtXt/hccyvD9qY/uwJAM75fmsf41Y9N7lg== - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/contracts" "^5.7.0" - "@ethersproject/providers" "^5.7.2" - "@ethersproject/solidity" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wallet" "^5.7.0" - "@types/qs" "^6.9.7" - axios "^0.21.1" - chalk "^4.1.2" - chokidar "^3.5.2" - debug "^4.3.2" - enquirer "^2.3.6" - ethers "^5.5.3" - form-data "^4.0.0" - fs-extra "^10.0.0" - match-all "^1.2.6" - murmur-128 "^0.2.1" - qs "^6.9.4" - zksync-web3 "^0.14.3" - -hardhat-watcher@^2.1.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/hardhat-watcher/-/hardhat-watcher-2.5.0.tgz#3ee76c3cb5b99f2875b78d176207745aa484ed4a" - integrity sha512-Su2qcSMIo2YO2PrmJ0/tdkf+6pSt8zf9+4URR5edMVti6+ShI8T3xhPrwugdyTOFuyj8lKHrcTZNKUFYowYiyA== - dependencies: - chokidar "^3.5.3" - -hardhat@^2.10.2: - version "2.17.1" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.17.1.tgz#4b6c8c8f624fd23d9f40185a4af24815d05a486a" - integrity sha512-1PxRkfjhEzXs/wDxI5YgzYBxNmvzifBTjYzuopwel+vXpAhCudplusJthN5eig0FTs4qbi828DBIITEDh8x9LA== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/ethereumjs-block" "5.0.1" - "@nomicfoundation/ethereumjs-blockchain" "7.0.1" - "@nomicfoundation/ethereumjs-common" "4.0.1" - "@nomicfoundation/ethereumjs-evm" "2.0.1" - "@nomicfoundation/ethereumjs-rlp" "5.0.1" - "@nomicfoundation/ethereumjs-statemanager" "2.0.1" - "@nomicfoundation/ethereumjs-trie" "6.0.1" - "@nomicfoundation/ethereumjs-tx" "5.0.1" - "@nomicfoundation/ethereumjs-util" "9.0.1" - "@nomicfoundation/ethereumjs-vm" "7.0.1" - "@nomicfoundation/solidity-analyzer" "^0.1.0" - "@sentry/node" "^5.18.1" - "@types/bn.js" "^5.1.0" - "@types/lru-cache" "^5.1.0" - adm-zip "^0.4.16" - aggregate-error "^3.0.0" - ansi-escapes "^4.3.0" - chalk "^2.4.2" - chokidar "^3.4.0" - ci-info "^2.0.0" - debug "^4.1.1" - enquirer "^2.3.0" - env-paths "^2.2.0" - ethereum-cryptography "^1.0.3" - ethereumjs-abi "^0.6.8" - find-up "^2.1.0" - fp-ts "1.19.3" - fs-extra "^7.0.1" - glob "7.2.0" - immutable "^4.0.0-rc.12" - io-ts "1.10.4" - keccak "^3.0.2" - lodash "^4.17.11" - mnemonist "^0.38.0" - mocha "^10.0.0" - p-map "^4.0.0" - raw-body "^2.4.1" - resolve "1.17.0" - semver "^6.3.0" - solc "0.7.3" - source-map-support "^0.5.13" - stacktrace-parser "^0.1.10" - tsort "0.0.1" - undici "^5.14.0" - uuid "^8.3.2" - ws "^7.4.6" - hardhat@^2.9.6: version "2.12.6" resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.6.tgz#ea3c058bbd81850867389d10f76037cfa52a0019" @@ -7452,13 +4485,6 @@ hardhat@^2.9.6: uuid "^8.3.2" ws "^7.4.6" -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== - dependencies: - ansi-regex "^2.0.0" - has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -7481,11 +4507,6 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" @@ -7498,38 +4519,7 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has@^1.0.3, has@~1.0.3: +has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -7574,11 +4564,6 @@ header-case@^2.0.4: capital-case "^1.0.4" tslib "^2.0.3" -heap@0.2.6: - version "0.2.6" - resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" - integrity sha512-MzzWcnfB1e4EG2vHi3dXHoBupmuXNZzx6pY6HldVS55JKKBoq3xOyzfSaZRkJp37HIhEYC78knabHff3zc4dQQ== - hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -7588,19 +4573,6 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - -hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -7667,12 +4639,7 @@ husky@^8.0.2: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.2.tgz#5816a60db02650f1f22c8b69b928fd6bcd77a236" integrity sha512-Tkv80jtvbnkK3mYWxPZePGFpQ/tT3HNSs/sasF9P2YfkMezDl3ON37YN6jUUI4eTg5LcyVynlb6r4eyvOmspvg== -hyperlinker@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e" - integrity sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ== - -iconv-lite@0.4.24, iconv-lite@^0.4.24: +iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -7698,11 +4665,6 @@ ieee754@^1.1.13, ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - ignore@^5.1.4: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" @@ -7713,29 +4675,11 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== -immediate@^3.2.3: - version "3.3.0" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" - integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== - -immediate@~3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== - immutable@^4.0.0-rc.12: version "4.2.2" resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.2.tgz#2da9ff4384a4330c36d4d1bc88e90f9e0b0ccd16" integrity sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og== -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -7752,11 +4696,6 @@ import-local@^3.0.2: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" -imul@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9" - integrity sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA== - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -7775,30 +4714,11 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -inquirer@^6.2.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" - integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== - dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.12" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" - internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -7808,27 +4728,6 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" -internal-slot@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" - integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== - dependencies: - get-intrinsic "^1.2.0" - has "^1.0.3" - side-channel "^1.0.4" - -invariant@^2.2.2: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ== - io-ts@1.10.4: version "1.10.4" resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" @@ -7841,20 +4740,6 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - is-arguments@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -7863,15 +4748,6 @@ is-arguments@^1.0.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" - integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.0" - is-typed-array "^1.1.10" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -7899,11 +4775,6 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -7914,20 +4785,6 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-core-module@^2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" - integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== - dependencies: - has "^1.0.3" - is-core-module@^2.8.1, is-core-module@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" @@ -7935,20 +4792,6 @@ is-core-module@^2.8.1, is-core-module@^2.9.0: dependencies: has "^1.0.3" -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - is-date-object@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" @@ -7956,73 +4799,11 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== - -is-docker@^2.0.0, is-docker@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-finite@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" - integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== - -is-fn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" - integrity sha512-XoFPJQmsAShb3jEQRfzf2rqXavq7fIqF/jOekp308JlThqrODnMpweVSGilKTCXELfLhltGP2AGgbQGVP8F1dg== - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== - is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -8069,13 +4850,6 @@ is-number-object@^1.0.4: dependencies: has-tostringtag "^1.0.0" -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== - dependencies: - kind-of "^3.0.2" - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -8091,14 +4865,7 @@ is-plain-obj@^2.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-regex@^1.0.4, is-regex@^1.1.4, is-regex@~1.1.4: +is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== @@ -8137,13 +4904,6 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.10: - version "1.1.12" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" - integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== - dependencies: - which-typed-array "^1.1.11" - is-typed-array@^1.1.3, is-typed-array@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.9.tgz#246d77d2871e7d9f5aeb1d54b9f52c71329ece67" @@ -8165,16 +4925,6 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -is-url@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" - integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== - is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -8182,50 +4932,11 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-wsl@^2.1.1, is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== - isomorphic-fetch@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" @@ -8234,11 +4945,6 @@ isomorphic-fetch@2.2.1: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" -isomorphic-ws@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" - integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== - isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -8693,16 +5399,11 @@ js-sha3@^0.7.0: resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.7.0.tgz#0a5c57b36f79882573b2d84051f8bb85dd1bd63a" integrity sha512-Wpks3yBDm0UcL5qlVhwW9Jr9n9i4FfeWBFOOXP5puDS/SiudJGhw7DPyBqn3487qD4F0lsC0q3zxink37f7zeA== -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: +js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== - js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -8710,7 +5411,7 @@ js-yaml@4.1.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: +js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -8718,31 +5419,16 @@ js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -jsbi@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-4.3.0.tgz#b54ee074fb6fcbc00619559305c8f7e912b04741" - integrity sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g== - jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA== - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== - json-buffer@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" @@ -8753,50 +5439,16 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== -json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" - integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== - dependencies: - async "^2.0.1" - babel-preset-env "^1.7.0" - babelify "^7.3.0" - json-rpc-error "^2.0.0" - promise-to-callback "^1.0.0" - safe-event-emitter "^1.0.1" - -json-rpc-error@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" - integrity sha512-EwUeWP+KgAZ/xqFpaP6YDAXMtCJi+o/QQpCQFIYyxr01AdADi2y413eM8hSqJcoQym9WMePAJWoaODEJufC4Ug== - dependencies: - inherits "^2.0.1" - -json-rpc-random-id@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" - integrity sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA== - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - json-schema@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" @@ -8807,23 +5459,11 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json-stable-stringify@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" - integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== - dependencies: - jsonify "^0.0.1" - json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw== - json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -8850,25 +5490,6 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - -jsonify@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" - integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== - -jsonparse@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== - jsprim@^1.2.2: version "1.4.2" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" @@ -8879,14 +5500,6 @@ jsprim@^1.2.2: json-schema "0.4.0" verror "1.10.0" -keccak@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff" - integrity sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA== - dependencies: - node-addon-api "^2.0.0" - node-gyp-build "^4.2.0" - keccak@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" @@ -8919,37 +5532,6 @@ keyv@^3.0.0: dependencies: json-buffer "3.0.0" -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -klaw-sync@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" - integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== - dependencies: - graceful-fs "^4.1.11" - klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" @@ -8962,118 +5544,11 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw== - dependencies: - invert-kv "^1.0.0" - lens.ts@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/lens.ts/-/lens.ts-0.5.1.tgz#957cd81838ea7359b0c280f24f9478bc6e92bafc" integrity sha512-cxzQxbitr78SnkulxKsdPC6v/+1CHmB4j2sMt2KXcbiCXLHphYZtOWYNIB1PumO5hCHescODqwhURB/OH/j5VA== -level-codec@^9.0.0: - version "9.0.2" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" - integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== - dependencies: - buffer "^5.6.0" - -level-codec@~7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" - integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== - -level-errors@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" - integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== - dependencies: - errno "~0.1.1" - -level-errors@^2.0.0, level-errors@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" - integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== - dependencies: - errno "~0.1.1" - -level-errors@~1.0.3: - version "1.0.5" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" - integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== - dependencies: - errno "~0.1.1" - -level-iterator-stream@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz#ccfff7c046dcf47955ae9a86f46dfa06a31688b4" - integrity sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig== - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.5" - xtend "^4.0.0" - -level-iterator-stream@~1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" - integrity sha512-1qua0RHNtr4nrZBgYlpV0qHHeHpcRRWTxEZJ8xsemoHAXNL5tbooh4tPEEqIqsbWCAJBmUmkwYK/sW5OrFjWWw== - dependencies: - inherits "^2.0.1" - level-errors "^1.0.3" - readable-stream "^1.0.33" - xtend "^4.0.0" - -level-iterator-stream@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz#2c98a4f8820d87cdacab3132506815419077c730" - integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== - dependencies: - inherits "^2.0.1" - readable-stream "^2.3.6" - xtend "^4.0.0" - -level-mem@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-3.0.1.tgz#7ce8cf256eac40f716eb6489654726247f5a89e5" - integrity sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg== - dependencies: - level-packager "~4.0.0" - memdown "~3.0.0" - -level-packager@~4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-4.0.1.tgz#7e7d3016af005be0869bc5fa8de93d2a7f56ffe6" - integrity sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q== - dependencies: - encoding-down "~5.0.0" - levelup "^3.0.0" - -level-post@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/level-post/-/level-post-1.0.7.tgz#19ccca9441a7cc527879a0635000f06d5e8f27d0" - integrity sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew== - dependencies: - ltgt "^2.1.2" - -level-sublevel@6.6.4: - version "6.6.4" - resolved "https://registry.yarnpkg.com/level-sublevel/-/level-sublevel-6.6.4.tgz#f7844ae893919cd9d69ae19d7159499afd5352ba" - integrity sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA== - dependencies: - bytewise "~1.1.0" - level-codec "^9.0.0" - level-errors "^2.0.0" - level-iterator-stream "^2.0.3" - ltgt "~2.1.1" - pull-defer "^0.2.2" - pull-level "^2.0.3" - pull-stream "^3.6.8" - typewiselite "~1.0.0" - xtend "~4.0.0" - level-supports@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" @@ -9087,23 +5562,6 @@ level-transcoder@^1.0.1: buffer "^6.0.3" module-error "^1.0.1" -level-ws@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" - integrity sha512-XUTaO/+Db51Uiyp/t7fCMGVFOTdtLS/NIACxE/GHsij15mKzxksZifKVjlXDF41JMUP/oM1Oc4YNGdKnc3dVLw== - dependencies: - readable-stream "~1.0.15" - xtend "~2.1.1" - -level-ws@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-1.0.0.tgz#19a22d2d4ac57b18cc7c6ecc4bd23d899d8f603b" - integrity sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q== - dependencies: - inherits "^2.0.3" - readable-stream "^2.2.8" - xtend "^4.0.1" - level@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/level/-/level-8.0.0.tgz#41b4c515dabe28212a3e881b61c161ffead14394" @@ -9112,42 +5570,11 @@ level@^8.0.0: browser-level "^1.0.1" classic-level "^1.2.0" -levelup@3.1.1, levelup@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" - integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== - dependencies: - deferred-leveldown "~4.0.0" - level-errors "~2.0.0" - level-iterator-stream "~3.0.0" - xtend "~4.0.0" - -levelup@^1.2.1: - version "1.3.9" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" - integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== - dependencies: - deferred-leveldown "~1.2.1" - level-codec "~7.0.0" - level-errors "~1.0.3" - level-iterator-stream "~1.3.0" - prr "~1.0.1" - semver "~5.4.1" - xtend "~4.0.0" - leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -9161,17 +5588,6 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A== - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -9194,21 +5610,6 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash.assign@^4.0.3, lodash.assign@^4.0.6: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - integrity sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw== - -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== - -lodash.flatmap@4.5.0, lodash.flatmap@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e" - integrity sha512-/OcpcAGWlrZyoHGeHh3cAoa6nGdX6QYtmzNP84Jqol6UEQQ2gIaU3H+0eICcjcKGl0/XF8LWOujNn9lffsnaOg== - lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -9219,17 +5620,7 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.truncate@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" - integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== - -lodash@4.17.20: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== - -lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.4: +lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -9253,23 +5644,6 @@ log4js@6.6.1: rfdc "^1.3.0" streamroller "^3.1.2" -looper@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" - integrity sha512-6DzMHJcjbQX/UPHc1rRCBfKlLwDkvuGZ715cIR36wSdYqWXFT35uLXq5P/2orl3tz+t+VOVPxw4yPinQlUDGDQ== - -looper@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" - integrity sha512-LJ9wplN/uSn72oJRsXTx+snxPet5c8XiZmOKCm906NVYu+ag6SB6vUcnJcWxgnl2NfbIyeobAn7Bwv6xRj2XJg== - -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - loupe@^2.3.1: version "2.3.6" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" @@ -9294,20 +5668,13 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== -lru-cache@5.1.1, lru-cache@^5.1.1: +lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" -lru-cache@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" - integrity sha512-91gyOKTc2k66UG6kHiH4h3S2eltcPwE1STVfMYC/NG+nZwf8IIuiamfmpGZjpbbxzSyEJaLC0tNSmhjlQUTJow== - dependencies: - pseudomap "^1.0.1" - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -9320,16 +5687,6 @@ lru_map@^0.3.3: resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== -ltgt@^2.1.2, ltgt@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" - integrity sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA== - -ltgt@~2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" - integrity sha512-5VjHC5GsENtIi5rbJd+feEpDKhfr7j0odoUR2Uh978g+2p93nd5o34cTjQWohXsPsCZeqoDnIqEf88mPCe0Pfw== - make-dir@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -9349,23 +5706,6 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== - dependencies: - object-visit "^1.0.0" - -match-all@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" - integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== - mcl-wasm@^0.7.1: version "0.7.9" resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" @@ -9385,30 +5725,6 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -memdown@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" - integrity sha512-iVrGHZB8i4OQfM155xx8akvG9FIj+ht14DX5CQkCTG4EHzZ3d3sgckIf/Lm9ivZalEsFuEVnWv2B2WZvbrro2w== - dependencies: - abstract-leveldown "~2.7.1" - functional-red-black-tree "^1.0.1" - immediate "^3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.1.1" - -memdown@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-3.0.0.tgz#93aca055d743b20efc37492e9e399784f2958309" - integrity sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA== - dependencies: - abstract-leveldown "~5.0.0" - functional-red-black-tree "~1.0.1" - immediate "~3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.1.1" - memory-level@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" @@ -9438,33 +5754,6 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -merkle-patricia-tree@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz#448d85415565df72febc33ca362b8b614f5a58f8" - integrity sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ== - dependencies: - async "^2.6.1" - ethereumjs-util "^5.2.0" - level-mem "^3.0.1" - level-ws "^1.0.0" - readable-stream "^3.0.6" - rlp "^2.0.0" - semaphore ">=1.0.1" - -merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" - integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== - dependencies: - async "^1.4.2" - ethereumjs-util "^5.0.0" - level-ws "0.0.0" - levelup "^1.2.1" - memdown "^1.0.0" - readable-stream "^2.0.0" - rlp "^2.0.0" - semaphore ">=1.0.1" - merkletreejs@^0.2.27: version "0.2.32" resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.2.32.tgz#cf1c0760e2904e4a1cc269108d6009459fd06223" @@ -9481,31 +5770,7 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== -micro-ftch@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" - integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== - -micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -micromatch@^4.0.2, micromatch@^4.0.4: +micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -9538,11 +5803,6 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -9594,11 +5854,6 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== -minimist@~1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" @@ -9614,19 +5869,6 @@ minizlib@^1.3.3: dependencies: minipass "^2.9.0" -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp-classic@^0.5.2: - version "0.5.3" - resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" - integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== - mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" @@ -9634,12 +5876,12 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@^1.0.4: +mkdirp@*: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@^0.5.1, mkdirp@^0.5.5: +mkdirp@^0.5.5: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -9761,25 +6003,6 @@ multimatch@^4.0.0: arrify "^2.0.1" minimatch "^3.0.4" -murmur-128@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d" - integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg== - dependencies: - encode-utf8 "^1.0.2" - fmix "^0.1.0" - imul "^1.0.0" - -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== - -nan@^2.17.0: - version "2.17.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" - integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== - nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" @@ -9790,23 +6013,6 @@ nanoid@3.3.3: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - napi-macros@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" @@ -9832,11 +6038,6 @@ next-tick@^1.1.0: resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -9857,13 +6058,6 @@ node-cache@^5.1.2: dependencies: clone "2.x" -node-fetch@2.6.6: - version "2.6.6" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89" - integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA== - dependencies: - whatwg-url "^5.0.0" - node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -9871,7 +6065,7 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@^1.0.1, node-fetch@~1.7.1: +node-fetch@^1.0.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== @@ -9879,13 +6073,6 @@ node-fetch@^1.0.1, node-fetch@~1.7.1: encoding "^0.1.11" is-stream "^1.0.1" -node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40" @@ -9901,21 +6088,6 @@ node-releases@^2.0.6: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== -nofilter@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66" - integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== - -normalize-package-data@^2.3.2: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -9938,11 +6110,6 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== - number-to-bn@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" @@ -9956,55 +6123,21 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4, object-assign@^4.0.0, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - object-inspect@^1.12.2, object-inspect@^1.9.0: version "1.12.2" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== -object-inspect@^1.12.3, object-inspect@~1.12.3: - version "1.12.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" - integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== - -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-keys@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw== - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== - dependencies: - isobject "^3.0.0" - object.assign@^4.1.2, object.assign@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" @@ -10024,24 +6157,6 @@ object.entries@^1.1.5: define-properties "^1.1.4" es-abstract "^1.20.4" -object.getownpropertydescriptors@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz#5e5c384dd209fa4efffead39e3a0512770ccc312" - integrity sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ== - dependencies: - array.prototype.reduce "^1.0.5" - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.21.2" - safe-array-concat "^1.0.0" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== - dependencies: - isobject "^3.0.1" - object.values@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" @@ -10056,13 +6171,6 @@ obliterator@^2.0.0: resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== -oboe@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" - integrity sha512-ymBJ4xSC6GBXLT9Y7lirj+xbqBLa+jADGJldGEYG7u8sZbS9GyG+u1Xk9c5cbriKwSpCg41qUhPjvU5xOpvIyQ== - dependencies: - http-https "^1.0.0" - oboe@2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" @@ -10084,13 +6192,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== - dependencies: - mimic-fn "^1.0.0" - onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -10098,35 +6199,6 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -open@^7.4.2: - version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" - integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - -open@^8.4.0: - version "8.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" - integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== - dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" - -optionator@^0.8.2: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -10139,19 +6211,7 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== - -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g== - dependencies: - lcid "^1.0.0" - -os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: +os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== @@ -10256,21 +6316,6 @@ parse-headers@^2.0.0: resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.5.tgz#069793f9356a54008571eb7f9761153e6c770da9" integrity sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA== -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== - dependencies: - error-ex "^1.2.0" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -10294,54 +6339,6 @@ pascal-case@^3.1.2: no-case "^3.0.4" tslib "^2.0.3" -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== - -patch-package@6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.2.tgz#71d170d650c65c26556f0d0fbbb48d92b6cc5f39" - integrity sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg== - dependencies: - "@yarnpkg/lockfile" "^1.1.0" - chalk "^2.4.2" - cross-spawn "^6.0.5" - find-yarn-workspace-root "^1.2.1" - fs-extra "^7.0.1" - is-ci "^2.0.0" - klaw-sync "^6.0.0" - minimist "^1.2.0" - rimraf "^2.6.3" - semver "^5.6.0" - slash "^2.0.0" - tmp "^0.0.33" - -patch-package@^6.2.2: - version "6.5.1" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" - integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== - dependencies: - "@yarnpkg/lockfile" "^1.1.0" - chalk "^4.1.2" - cross-spawn "^6.0.5" - find-yarn-workspace-root "^2.0.0" - fs-extra "^9.0.0" - is-ci "^2.0.0" - klaw-sync "^6.0.0" - minimist "^1.2.6" - open "^7.4.2" - rimraf "^2.6.3" - semver "^5.6.0" - slash "^2.0.0" - tmp "^0.0.33" - yaml "^1.10.2" - -path-browserify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" - integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== - path-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/path-case/-/path-case-3.0.4.tgz#9168645334eb942658375c56f80b4c0cb5f82c6f" @@ -10350,13 +6347,6 @@ path-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ== - dependencies: - pinkie-promise "^2.0.0" - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -10367,21 +6357,11 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: +path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== - -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== - path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -10397,15 +6377,6 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg== - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -10416,7 +6387,7 @@ pathval@^1.1.1: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: +pbkdf2@^3.0.17, pbkdf2@^3.0.3: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -10442,23 +6413,6 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pify@^2.0.0, pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== - pirates@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" @@ -10476,46 +6430,16 @@ popper.js@1.14.3: resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" integrity sha512-3lmujhsHXzb83+sI0PzfrE3O1XHZG8m8MXNMTupvA6LrM1/nnsiqYaacYc/RIente9VqnTDPztGEM8uvPAMGyg== -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== - -postinstall-postinstall@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" - integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== - -precond@0.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" - integrity sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ== - prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== - prepend-http@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== -prettier@^1.14.3: - version "1.19.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" - integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== - -prettier@^2.1.2, prettier@^2.3.1: - version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== - prettier@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc" @@ -10552,35 +6476,12 @@ pretty-quick@^3.1.3: mri "^1.1.5" multimatch "^4.0.0" -private@^0.1.6, private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -promise-to-callback@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" - integrity sha512-uhMIZmKM5ZteDMfLgJnoSq9GCwsNKrYau73Awf1jIy6/eUcuuZ3P+CD9zUv0kJsIUbU+x6uLNIhXhLHDs1pNPA== - dependencies: - is-fn "^1.0.0" - set-immediate-shim "^1.0.1" - -prompts@^2.0.1, prompts@^2.4.2: +prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -10601,16 +6502,6 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== - -pseudomap@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== - psl@^1.1.28: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -10628,62 +6519,6 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" -pull-cat@^1.1.9: - version "1.1.11" - resolved "https://registry.yarnpkg.com/pull-cat/-/pull-cat-1.1.11.tgz#b642dd1255da376a706b6db4fa962f5fdb74c31b" - integrity sha512-i3w+xZ3DCtTVz8S62hBOuNLRHqVDsHMNZmgrZsjPnsxXUgbWtXEee84lo1XswE7W2a3WHyqsNuDJTjVLAQR8xg== - -pull-defer@^0.2.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/pull-defer/-/pull-defer-0.2.3.tgz#4ee09c6d9e227bede9938db80391c3dac489d113" - integrity sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA== - -pull-level@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pull-level/-/pull-level-2.0.4.tgz#4822e61757c10bdcc7cf4a03af04c92734c9afac" - integrity sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg== - dependencies: - level-post "^1.0.7" - pull-cat "^1.1.9" - pull-live "^1.0.1" - pull-pushable "^2.0.0" - pull-stream "^3.4.0" - pull-window "^2.1.4" - stream-to-pull-stream "^1.7.1" - -pull-live@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pull-live/-/pull-live-1.0.1.tgz#a4ecee01e330155e9124bbbcf4761f21b38f51f5" - integrity sha512-tkNz1QT5gId8aPhV5+dmwoIiA1nmfDOzJDlOOUpU5DNusj6neNd3EePybJ5+sITr2FwyCs/FVpx74YMCfc8YeA== - dependencies: - pull-cat "^1.1.9" - pull-stream "^3.4.0" - -pull-pushable@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.2.0.tgz#5f2f3aed47ad86919f01b12a2e99d6f1bd776581" - integrity sha512-M7dp95enQ2kaHvfCt2+DJfyzgCSpWVR2h2kWYnVsW6ZpxQBx5wOu0QWOvQPVoPnBLUZYitYP2y7HyHkLQNeGXg== - -pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: - version "3.7.0" - resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.7.0.tgz#85de0e44ff38a4d2ad08cc43fc458e1922f9bf0b" - integrity sha512-Eco+/R004UaCK2qEDE8vGklcTG2OeZSVm1kTUQNrykEjDwcFXDZhygFDsW49DbXyJMEhHeRL3z5cRVqPAhXlIw== - -pull-window@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/pull-window/-/pull-window-2.1.4.tgz#fc3b86feebd1920c7ae297691e23f705f88552f0" - integrity sha512-cbDzN76BMlcGG46OImrgpkMf/VkCnupj8JhsrpBw3aWBM9ye345aYnqitmZCgauBkc0HbbRRn9hCnsa3k2FNUg== - dependencies: - looper "^2.0.0" - -pump@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" - integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -10697,11 +6532,6 @@ punycode@2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" integrity sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA== -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== - punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -10714,13 +6544,6 @@ qs@6.11.0, qs@^6.7.0: dependencies: side-channel "^1.0.4" -qs@^6.11.0, qs@^6.9.4: - version "6.11.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" - integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== - dependencies: - side-channel "^1.0.4" - qs@~6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" @@ -10745,7 +6568,7 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== @@ -10785,55 +6608,6 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A== - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ== - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -readable-stream@^1.0.33: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -10843,16 +6617,6 @@ readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@~1.0.15, readable-stream@~1.0.26-4: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -10860,47 +6624,6 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -reduce-flatten@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" - integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== - -regenerate@^1.2.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - -regenerator-transform@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== - dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" - private "^0.1.6" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" - integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - functions-have-names "^1.2.3" - regexp.prototype.flags@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" @@ -10910,55 +6633,12 @@ regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - integrity sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ== - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - integrity sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g== - -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - integrity sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw== - dependencies: - jsesc "~0.5.0" - -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A== - dependencies: - is-finite "^1.0.0" - -request@^2.79.0, request@^2.85.0: +request@^2.79.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -10989,21 +6669,11 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -require-from-string@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" - integrity sha512-H7AkJWMobeskkttHyhTVtS0fxpFLjxhbfMa6Bk3wimP7sdPRGL3EyCg3sAQenFfAe+xQ+oAc85Nmtvq0ROM83Q== - -require-from-string@^2.0.0, require-from-string@^2.0.2: +require-from-string@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== - resolve-alpn@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" @@ -11016,11 +6686,6 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -11031,11 +6696,6 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== - resolve.exports@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" @@ -11048,15 +6708,6 @@ resolve@1.17.0: dependencies: path-parse "^1.0.6" -resolve@^1.10.0, resolve@^1.8.1, resolve@~1.22.1: - version "1.22.4" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" - integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - resolve@^1.20.0, resolve@^1.22.0: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" @@ -11080,26 +6731,6 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -resumer@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" - integrity sha512-Fn9X8rX8yYF4m81rZCK/5VmrmsSbqS/i3rDLl6ZZHAXgC2nTAx3dhwG8q8odP/RmdLa2YrybDJaAMg+X1ajY3w== - dependencies: - through "~2.3.4" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -11110,14 +6741,7 @@ rfdc@^1.3.0: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -rimraf@^2.2.8, rimraf@^2.6.3: +rimraf@^2.2.8: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -11139,18 +6763,13 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.7: +rlp@^2.0.0, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.7: version "2.2.7" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== dependencies: bn.js "^5.2.0" -run-async@^2.2.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - run-parallel-limit@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" @@ -11170,40 +6789,16 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== -rxjs@^6.4.0: - version "6.6.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" - integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== - dependencies: - tslib "^1.9.0" - -safe-array-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" - integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.0" - has-symbols "^1.0.3" - isarray "^2.0.5" - safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@~5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-event-emitter@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" - integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== - dependencies: - events "^3.0.0" - safe-regex-test@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" @@ -11213,13 +6808,6 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== - dependencies: - ret "~0.1.10" - "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -11235,13 +6823,6 @@ scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== -scryptsy@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" - integrity sha512-aldIRgMozSJ/Gl6K6qmJZysRP82lz83Wb42vl4PWN8SaLFHIaOzLPc9nUUW2jQN88CuGm5q5HefJ9jZ3nWSmTw== - dependencies: - pbkdf2 "^3.0.3" - secp256k1@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" @@ -11251,21 +6832,6 @@ secp256k1@^4.0.1: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" -seedrandom@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.1.tgz#eb3dde015bcf55df05a233514e5df44ef9dce083" - integrity sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg== - -semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" - integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== - -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.1, semver@^5.6.0: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - semver@7.x, semver@^7.3.5, semver@^7.3.7: version "7.3.8" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" @@ -11283,11 +6849,6 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@~5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== - send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -11344,26 +6905,6 @@ servify@^0.1.12: request "^2.79.0" xhr "^2.3.3" -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - integrity sha512-Li5AOqrZWCVA2n5kryzEmqai6bKSIvpz5oUJHPVj6+dsbD3X1ixtsY5tEnsaNpH3pFAHmG8eIHUrtEtohrg+UQ== - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - setimmediate@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" @@ -11387,13 +6928,6 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== - dependencies: - shebang-regex "^1.0.0" - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -11401,11 +6935,6 @@ shebang-command@^2.0.0: dependencies: shebang-regex "^3.0.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== - shebang-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" @@ -11444,39 +6973,11 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg== - -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== - slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - snake-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" @@ -11485,36 +6986,6 @@ snake-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - solc@0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" @@ -11530,70 +7001,6 @@ solc@0.7.3: semver "^5.5.0" tmp "0.0.33" -solc@^0.4.20: - version "0.4.26" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.26.tgz#5390a62a99f40806b86258c737c1cf653cc35cb5" - integrity sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA== - dependencies: - fs-extra "^0.30.0" - memorystream "^0.3.1" - require-from-string "^1.1.0" - semver "^5.3.0" - yargs "^4.7.1" - -solc@^0.6.3: - version "0.6.12" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.6.12.tgz#48ac854e0c729361b22a7483645077f58cba080e" - integrity sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g== - dependencies: - command-exists "^1.2.8" - commander "3.0.2" - fs-extra "^0.30.0" - js-sha3 "0.8.0" - memorystream "^0.3.1" - require-from-string "^2.0.0" - semver "^5.5.0" - tmp "0.0.33" - -solhint@^2.0.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/solhint/-/solhint-2.3.1.tgz#6fee8fc2635112bf5812f7cba8359c14e9d9a491" - integrity sha512-wP/G+Dqj8LNWlCI9Mt6XiQRWQfZwv1rkZe/V+HKtip5SAZJVvp144PdH28KE45ZvR99Hhrp/Mujt74fSmXsFiw== - dependencies: - ajv "^6.6.1" - antlr4 "4.7.1" - chalk "^2.4.2" - commander "2.18.0" - cosmiconfig "^5.0.7" - eslint "^5.6.0" - fast-diff "^1.1.2" - glob "^7.1.3" - ignore "^4.0.6" - js-yaml "^3.12.0" - lodash "^4.17.11" - semver "^6.3.0" - optionalDependencies: - prettier "^1.14.3" - -source-map-resolve@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@0.5.12: - version "0.5.12" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" - integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -11602,13 +7009,6 @@ source-map-support@0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - source-map-support@^0.5.13: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -11617,75 +7017,16 @@ source-map-support@^0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - -source-map@^0.5.6, source-map@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== - source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -spdx-correct@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" - integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.13" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz#7189a474c46f8d47c7b0da4b987bb45e908bd2d5" - integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w== - -split-ca@^1.0.0, split-ca@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" - integrity sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ== - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -ssh2@^1.11.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-1.14.0.tgz#8f68440e1b768b66942c9e4e4620b2725b3555bb" - integrity sha512-AqzD1UCqit8tbOKoj6ztDDi1ffJZ2rV2SwlgrVVrHPkV5vWqGJOVp5pmtj18PunkPJAuKQsnInyKV+/Nb2bUnA== - dependencies: - asn1 "^0.2.6" - bcrypt-pbkdf "^1.0.2" - optionalDependencies: - cpu-features "~0.0.8" - nan "^2.17.0" - sshpk@^1.7.0: version "1.17.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" @@ -11715,27 +7056,11 @@ stacktrace-parser@^0.1.10: dependencies: type-fest "^0.7.1" -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -stream-to-pull-stream@^1.7.1: - version "1.7.3" - resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz#4161aa2d2eb9964de60bfa1af7feaf917e874ece" - integrity sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg== - dependencies: - looper "^3.0.0" - pull-stream "^3.2.3" - streamroller@^3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.1.3.tgz#d95689a8c29b30d093525d0baffe6616fd62ca7e" @@ -11755,11 +7080,6 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== -string-format@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" - integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== - string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -11768,32 +7088,6 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string-width@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -11803,15 +7097,6 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.trim@^1.2.7, string.prototype.trim@~1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" - integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - string.prototype.trimend@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" @@ -11855,39 +7140,6 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -11895,13 +7147,6 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== - dependencies: - is-utf8 "^0.2.0" - strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -11929,11 +7174,6 @@ strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1. resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strip-json-comments@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - supports-color@8.1.1, supports-color@^8.0.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -11941,11 +7181,6 @@ supports-color@8.1.1, supports-color@^8.0.0: dependencies: has-flag "^4.0.0" -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -11982,102 +7217,6 @@ swarm-js@^0.1.40: tar "^4.0.2" xhr-request "^1.0.1" -table-layout@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" - integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== - dependencies: - array-back "^4.0.1" - deep-extend "~0.6.0" - typical "^5.2.0" - wordwrapjs "^4.0.0" - -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== - dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" - -table@^6.8.0: - version "6.8.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" - integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== - dependencies: - ajv "^8.0.1" - lodash.truncate "^4.4.2" - slice-ansi "^4.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" - -tape@^4.6.3: - version "4.16.2" - resolved "https://registry.yarnpkg.com/tape/-/tape-4.16.2.tgz#7565e6af20426565557266e9dda7215869b297b6" - integrity sha512-TUChV+q0GxBBCEbfCYkGLkv8hDJYjMdSWdE0/Lr331sB389dsvFUHNV9ph5iQqKzt8Ss9drzcda/YeexclBFqg== - dependencies: - call-bind "~1.0.2" - deep-equal "~1.1.1" - defined "~1.0.1" - dotignore "~0.1.2" - for-each "~0.3.3" - glob "~7.2.3" - has "~1.0.3" - inherits "~2.0.4" - is-regex "~1.1.4" - minimist "~1.2.7" - object-inspect "~1.12.3" - resolve "~1.22.1" - resumer "~0.0.0" - string.prototype.trim "~1.2.7" - through "~2.3.8" - -tar-fs@~1.16.3: - version "1.16.3" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" - integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw== - dependencies: - chownr "^1.0.1" - mkdirp "^0.5.1" - pump "^1.0.0" - tar-stream "^1.1.2" - -tar-fs@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" - integrity sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA== - dependencies: - chownr "^1.1.1" - mkdirp-classic "^0.5.2" - pump "^3.0.0" - tar-stream "^2.0.0" - -tar-stream@^1.1.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== - dependencies: - bl "^1.0.0" - buffer-alloc "^1.2.0" - end-of-stream "^1.0.0" - fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.1" - xtend "^4.0.0" - -tar-stream@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" - integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== - dependencies: - bl "^4.0.3" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - tar@^4.0.2: version "4.4.19" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" @@ -12088,22 +7227,8 @@ tar@^4.0.2: minipass "^2.9.0" minizlib "^1.3.3" mkdirp "^0.5.5" - safe-buffer "^5.2.1" - yallist "^3.1.1" - -tenderly@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tenderly/-/tenderly-0.0.3.tgz#8c85e287e080073502420d5c6f13f4762d0f59cd" - integrity sha512-dVf2uxrIOeLDRNDEXcQlV2xJt50TIx8zGQKlNj1deYTV3FYu2L0zheHBHaDU12GqAff2iiGYk+fKqFkK0bB0+w== - dependencies: - axios "^0.27.2" - cli-table3 "^0.6.2" - commander "^9.4.0" - express "^4.18.1" - hyperlinker "^1.0.0" - js-yaml "^4.1.0" - open "^8.4.0" - prompts "^2.4.2" + safe-buffer "^5.2.1" + yallist "^3.1.1" test-exclude@^6.0.0: version "6.0.0" @@ -12114,106 +7239,38 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -test-value@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" - integrity sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w== - dependencies: - array-back "^1.0.3" - typical "^2.6.0" - -testrpc@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/testrpc/-/testrpc-0.0.1.tgz#83e2195b1f5873aec7be1af8cbe6dcf39edb7aed" - integrity sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA== - text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -through2@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -"through@>=2.2.7 <3", through@^2.3.6, through@~2.3.4, through@~2.3.8: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== - timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== -tiny-invariant@1.3.1, tiny-invariant@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" - integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== - -tiny-warning@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" - integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== - -tmp@0.0.33, tmp@^0.0.33: +tmp@0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" -tmp@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" - integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== - dependencies: - rimraf "^2.6.3" - tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== -to-buffer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== - dependencies: - kind-of "^3.0.2" - to-readable-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -12221,21 +7278,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -toformat@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/toformat/-/toformat-2.0.0.tgz#7a043fd2dfbe9021a4e36e508835ba32056739d8" - integrity sha512-03SWBVop6nU8bpyZCx7SodpYznbZF5R4ljwNLBcTQzKOD9xuihRo/psX58llS1BMFhhAI08H3luot5GoXJz2pQ== - toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -12259,61 +7301,16 @@ treeify@^1.1.0: resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== - -ts-command-line-args@^2.2.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz#e64456b580d1d4f6d948824c274cf6fa5f45f7f0" - integrity sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw== - dependencies: - chalk "^4.1.0" - command-line-args "^5.1.1" - command-line-usage "^6.1.0" - string-format "^2.0.0" - ts-essentials@9.1.2: version "9.1.2" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-9.1.2.tgz#46db6944b73b4cd603f3d959ef1123c16ba56f59" integrity sha512-EaSmXsAhEiirrTY1Oaa7TSpei9dzuCuFPmjKRJRPamERYtfaGS8/KpOSbjergLz/Y76/aZlV9i/krgzsuWEBbg== -ts-essentials@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" - integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== - -ts-essentials@^6.0.3: - version "6.0.7" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.7.tgz#5f4880911b7581a873783740ce8b94da163d18a6" - integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== - -ts-essentials@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" - integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== - ts-essentials@^9.1.2: version "9.3.0" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-9.3.0.tgz#7e639c1a76b1805c3c60d6e1b5178da2e70aea02" integrity sha512-XeiCboEyBG8UqXZtXl59bWEi4ZgOqRsogFDI6WDGIF1LmzbYiAkIwjkXN6zZWWl4re/lsOqMlYfe8KA0XiiEPw== -ts-generator@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" - integrity sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ== - dependencies: - "@types/mkdirp" "^0.5.2" - "@types/prettier" "^2.1.1" - "@types/resolve" "^0.0.8" - chalk "^2.4.1" - glob "^7.1.2" - mkdirp "^0.5.1" - prettier "^2.1.2" - resolve "^1.8.1" - ts-essentials "^1.0.0" - ts-jest@^29.0.3: version "29.0.3" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.0.3.tgz#63ea93c5401ab73595440733cefdba31fcf9cb77" @@ -12357,7 +7354,7 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.8.1, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -12386,7 +7383,7 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -tweetnacl-util@^0.15.0, tweetnacl-util@^0.15.1: +tweetnacl-util@^0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== @@ -12396,7 +7393,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== -tweetnacl@^1.0.0, tweetnacl@^1.0.3: +tweetnacl@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== @@ -12408,13 +7405,6 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== - dependencies: - prelude-ls "~1.1.2" - type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -12453,74 +7443,6 @@ type@^2.7.2: resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== -typechain@8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.1.1.tgz#9c2e8012c2c4c586536fc18402dcd7034c4ff0bd" - integrity sha512-uF/sUvnXTOVF2FHKhQYnxHk4su4JjZR8vr4mA2mBaRwHTbwh0jIlqARz9XJr1tA0l7afJGvEa1dTSi4zt039LQ== - dependencies: - "@types/prettier" "^2.1.1" - debug "^4.3.1" - fs-extra "^7.0.0" - glob "7.1.7" - js-sha3 "^0.8.0" - lodash "^4.17.15" - mkdirp "^1.0.4" - prettier "^2.3.1" - ts-command-line-args "^2.2.0" - ts-essentials "^7.0.1" - -typechain@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-3.0.0.tgz#d5a47700831f238e43f7429b987b4bb54849b92e" - integrity sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg== - dependencies: - command-line-args "^4.0.7" - debug "^4.1.1" - fs-extra "^7.0.0" - js-sha3 "^0.8.0" - lodash "^4.17.15" - ts-essentials "^6.0.3" - ts-generator "^0.1.1" - -typed-array-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" - integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" - is-typed-array "^1.1.10" - -typed-array-byte-length@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" - integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== - dependencies: - call-bind "^1.0.2" - for-each "^0.3.3" - has-proto "^1.0.1" - is-typed-array "^1.1.10" - -typed-array-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" - integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - has-proto "^1.0.1" - is-typed-array "^1.1.10" - -typed-array-length@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" - integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== - dependencies: - call-bind "^1.0.2" - for-each "^0.3.3" - is-typed-array "^1.1.9" - typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -12528,48 +7450,11 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== - typescript@4.6.4: version "4.6.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg== -typewise-core@^1.2, typewise-core@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" - integrity sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg== - -typewise@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" - integrity sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ== - dependencies: - typewise-core "^1.2.0" - -typewiselite@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typewiselite/-/typewiselite-1.0.0.tgz#c8882fa1bb1092c06005a97f34ef5c8508e3664e" - integrity sha512-J9alhjVHupW3Wfz6qFRGgQw0N3gr8hOkw6zm7FZ6UR1Cse/oD9/JVok7DNE9TT9IbciDHX2Ex9+ksE6cRmtymw== - -typical@^2.6.0, typical@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" - integrity sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg== - -typical@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" - integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== - -typical@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" - integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== - ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" @@ -12590,11 +7475,6 @@ underscore@1.12.1: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== -underscore@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== - undici@^5.14.0: version "5.16.0" resolved "https://registry.yarnpkg.com/undici/-/undici-5.16.0.tgz#6b64f9b890de85489ac6332bd45ca67e4f7d9943" @@ -12602,51 +7482,16 @@ undici@^5.14.0: dependencies: busboy "^1.6.0" -undici@^5.4.0: - version "5.23.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.23.0.tgz#e7bdb0ed42cebe7b7aca87ced53e6eaafb8f8ca0" - integrity sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg== - dependencies: - busboy "^1.6.0" - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - -unorm@^1.3.3: - version "1.6.0" - resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" - integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== - unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - update-browserslist-db@^1.0.9: version "1.0.10" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" @@ -12676,11 +7521,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== - url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -12693,19 +7533,6 @@ url-set-query@^1.0.0: resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" integrity sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg== -url@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.1.tgz#26f90f615427eca1b9f4d6a28288c147e2302a32" - integrity sha512-rWS3H04/+mzzJkv0eZ7vEDGiQbgquI1fGfOad6zKvgYQi1SzMmhl7c/DdRGxhaWrVH6z0qWITo8rpnxK/RfEhA== - dependencies: - punycode "^1.4.1" - qs "^6.11.0" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - utf-8-validate@^5.0.2: version "5.0.10" resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" @@ -12713,29 +7540,16 @@ utf-8-validate@^5.0.2: dependencies: node-gyp-build "^4.3.0" -utf8@3.0.0, utf8@^3.0.0: +utf8@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -util.promisify@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.2.tgz#02b3dbadbb80071eee4c43aed58747afdfc516db" - integrity sha512-PBdZ03m1kBnQ5cjjO0ZvJMJS+QsbyIcFwi4hY4U76OQsCO9JrOYjbCFgIF76ccFg9xnJo7ZHPkqyj1GqmdS7MA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - for-each "^0.3.3" - has-proto "^1.0.1" - has-symbols "^1.0.3" - object.getownpropertydescriptors "^2.1.6" - safe-array-concat "^1.0.0" - util@^0.12.0: version "0.12.5" resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" @@ -12791,14 +7605,6 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - varint@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" @@ -12818,21 +7624,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -viem@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/viem/-/viem-1.0.2.tgz#0798c80598daddc05b7132b642ae2f60811c4fbe" - integrity sha512-3Bn+CuInU8zsdKqqzFDWL018x4B9HDjPIISztReGcBjikY+04tP7CrQQCf1lbinK3wWrEoFU9VDiptCciNjUQA== - dependencies: - "@adraffy/ens-normalize" "1.9.0" - "@noble/curves" "1.0.0" - "@noble/hashes" "1.3.0" - "@scure/bip32" "1.3.0" - "@scure/bip39" "1.2.0" - "@wagmi/chains" "1.1.0" - abitype "0.8.7" - isomorphic-ws "5.0.0" - ws "8.12.0" - walker@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -12840,16 +7631,6 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" -web3-bzz@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" - integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== - dependencies: - "@types/node" "^12.12.6" - got "9.6.0" - swarm-js "^0.1.40" - underscore "1.9.1" - web3-bzz@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.6.0.tgz#584b51339f21eedff159abc9239b4b7ef6ded840" @@ -12859,15 +7640,6 @@ web3-bzz@1.6.0: got "9.6.0" swarm-js "^0.1.40" -web3-core-helpers@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" - integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== - dependencies: - underscore "1.9.1" - web3-eth-iban "1.2.11" - web3-utils "1.2.11" - web3-core-helpers@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.6.0.tgz#77e161b6ba930a4008a0df804ab379e0aa7e1e7f" @@ -12876,18 +7648,6 @@ web3-core-helpers@1.6.0: web3-eth-iban "1.6.0" web3-utils "1.6.0" -web3-core-method@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" - integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== - dependencies: - "@ethersproject/transactions" "^5.0.0-beta.135" - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-core-promievent "1.2.11" - web3-core-subscriptions "1.2.11" - web3-utils "1.2.11" - web3-core-method@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.6.0.tgz#ebe4ea51f5a4fa809bb68185576186359d3982e9" @@ -12900,13 +7660,6 @@ web3-core-method@1.6.0: web3-core-subscriptions "1.6.0" web3-utils "1.6.0" -web3-core-promievent@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" - integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== - dependencies: - eventemitter3 "4.0.4" - web3-core-promievent@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.6.0.tgz#8b6053ae83cb47164540167fc361469fc604d2dd" @@ -12914,17 +7667,6 @@ web3-core-promievent@1.6.0: dependencies: eventemitter3 "4.0.4" -web3-core-requestmanager@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" - integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== - dependencies: - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-providers-http "1.2.11" - web3-providers-ipc "1.2.11" - web3-providers-ws "1.2.11" - web3-core-requestmanager@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.6.0.tgz#8ef3a3b89cd08983bd94574f9c5893f70a8a6aea" @@ -12936,15 +7678,6 @@ web3-core-requestmanager@1.6.0: web3-providers-ipc "1.6.0" web3-providers-ws "1.6.0" -web3-core-subscriptions@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" - integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== - dependencies: - eventemitter3 "4.0.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-core-subscriptions@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.6.0.tgz#8c23b15b434a7c9f937652ecca45d7108e2c54df" @@ -12953,19 +7686,6 @@ web3-core-subscriptions@1.6.0: eventemitter3 "4.0.4" web3-core-helpers "1.6.0" -web3-core@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" - integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== - dependencies: - "@types/bn.js" "^4.11.5" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-requestmanager "1.2.11" - web3-utils "1.2.11" - web3-core@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.6.0.tgz#144eb00f651c9812faf7176abd7ee99d5f45e212" @@ -12979,15 +7699,6 @@ web3-core@1.6.0: web3-core-requestmanager "1.6.0" web3-utils "1.6.0" -web3-eth-abi@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" - integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== - dependencies: - "@ethersproject/abi" "5.0.0-beta.153" - underscore "1.9.1" - web3-utils "1.2.11" - web3-eth-abi@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.4.0.tgz#83f9f0ce48fd6d6b233a30a33bd674b3518e472b" @@ -13005,23 +7716,6 @@ web3-eth-abi@1.6.0: "@ethersproject/abi" "5.0.7" web3-utils "1.6.0" -web3-eth-accounts@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" - integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== - dependencies: - crypto-browserify "3.12.0" - eth-lib "0.2.8" - ethereumjs-common "^1.3.2" - ethereumjs-tx "^2.1.1" - scrypt-js "^3.0.1" - underscore "1.9.1" - uuid "3.3.2" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" - web3-eth-accounts@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.6.0.tgz#530927f4c5b78df93b3ea1203abbb467de29cd04" @@ -13039,21 +7733,6 @@ web3-eth-accounts@1.6.0: web3-core-method "1.6.0" web3-utils "1.6.0" -web3-eth-contract@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" - integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== - dependencies: - "@types/bn.js" "^4.11.5" - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-promievent "1.2.11" - web3-core-subscriptions "1.2.11" - web3-eth-abi "1.2.11" - web3-utils "1.2.11" - web3-eth-contract@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.6.0.tgz#deb946867ad86d32bcbba899d733b681b25ea674" @@ -13068,21 +7747,6 @@ web3-eth-contract@1.6.0: web3-eth-abi "1.6.0" web3-utils "1.6.0" -web3-eth-ens@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" - integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== - dependencies: - content-hash "^2.5.2" - eth-ens-namehash "2.0.8" - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-promievent "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-contract "1.2.11" - web3-utils "1.2.11" - web3-eth-ens@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.6.0.tgz#af13852168d56fa71b9198eb097e96fb93831c2a" @@ -13097,14 +7761,6 @@ web3-eth-ens@1.6.0: web3-eth-contract "1.6.0" web3-utils "1.6.0" -web3-eth-iban@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" - integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== - dependencies: - bn.js "^4.11.9" - web3-utils "1.2.11" - web3-eth-iban@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.6.0.tgz#edbe46cedc5b148d53fa455edea6b4eef53b2be7" @@ -13113,18 +7769,6 @@ web3-eth-iban@1.6.0: bn.js "^4.11.9" web3-utils "1.6.0" -web3-eth-personal@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" - integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== - dependencies: - "@types/node" "^12.12.6" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" - web3-eth-personal@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.6.0.tgz#b75a61c0737b8b8bcc11d05db2ed7bfce7e4b262" @@ -13137,25 +7781,6 @@ web3-eth-personal@1.6.0: web3-net "1.6.0" web3-utils "1.6.0" -web3-eth@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" - integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== - dependencies: - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-accounts "1.2.11" - web3-eth-contract "1.2.11" - web3-eth-ens "1.2.11" - web3-eth-iban "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" - web3-eth@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.6.0.tgz#4c9d5fb4eccf9f8744828281757e6ea76af58cbd" @@ -13174,15 +7799,6 @@ web3-eth@1.6.0: web3-net "1.6.0" web3-utils "1.6.0" -web3-net@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" - integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== - dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" - web3-net@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.6.0.tgz#2c28f8787073110a7c2310336889d2dad647e500" @@ -13192,40 +7808,6 @@ web3-net@1.6.0: web3-core-method "1.6.0" web3-utils "1.6.0" -web3-provider-engine@14.2.1: - version "14.2.1" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz#ef351578797bf170e08d529cb5b02f8751329b95" - integrity sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw== - dependencies: - async "^2.5.0" - backoff "^2.5.0" - clone "^2.0.0" - cross-fetch "^2.1.0" - eth-block-tracker "^3.0.0" - eth-json-rpc-infura "^3.1.0" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.1.5" - ethereumjs-vm "^2.3.4" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.85.0" - semaphore "^1.0.3" - ws "^5.1.1" - xhr "^2.2.0" - xtend "^4.0.1" - -web3-providers-http@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" - integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== - dependencies: - web3-core-helpers "1.2.11" - xhr2-cookies "1.1.0" - web3-providers-http@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.6.0.tgz#8db4e589abf7197f5d65b12af1bf9726c45f4160" @@ -13234,15 +7816,6 @@ web3-providers-http@1.6.0: web3-core-helpers "1.6.0" xhr2-cookies "1.1.0" -web3-providers-ipc@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" - integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== - dependencies: - oboe "2.1.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-providers-ipc@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.6.0.tgz#6a3410fd47a67c4a36719fb97f99534ae12aac98" @@ -13251,16 +7824,6 @@ web3-providers-ipc@1.6.0: oboe "2.1.5" web3-core-helpers "1.6.0" -web3-providers-ws@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" - integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== - dependencies: - eventemitter3 "4.0.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - websocket "^1.0.31" - web3-providers-ws@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.6.0.tgz#dc15dc18c30089efda992015fd5254bd2b77af5f" @@ -13270,16 +7833,6 @@ web3-providers-ws@1.6.0: web3-core-helpers "1.6.0" websocket "^1.0.32" -web3-shh@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" - integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== - dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-net "1.2.11" - web3-shh@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.6.0.tgz#838a3435dce1039f669a48e53e948062de197931" @@ -13290,20 +7843,6 @@ web3-shh@1.6.0: web3-core-subscriptions "1.6.0" web3-net "1.6.0" -web3-utils@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" - integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== - dependencies: - bn.js "^4.11.9" - eth-lib "0.2.8" - ethereum-bloom-filters "^1.0.6" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - underscore "1.9.1" - utf8 "3.0.0" - web3-utils@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.4.0.tgz#e8cb381c81b242dc1d4ecb397200356d404410e6" @@ -13331,20 +7870,6 @@ web3-utils@1.6.0: randombytes "^2.1.0" utf8 "3.0.0" -web3-utils@^1.0.0-beta.31: - version "1.10.1" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.1.tgz#97532130d85358628bc0ff14d94b7e9449786983" - integrity sha512-r6iUUw/uMnNcWXjhRv33Nyrhxq3VGOPBXeSzxhOXIci4SvC/LPTpROY0uTrMX7ztKyODYrHp8WhTkEf+ZnHssw== - dependencies: - "@ethereumjs/util" "^8.1.0" - bn.js "^5.2.1" - ethereum-bloom-filters "^1.0.6" - ethereum-cryptography "^2.1.2" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - utf8 "3.0.0" - web3-utils@^1.3.4: version "1.8.1" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.8.1.tgz#f2f7ca7eb65e6feb9f3d61056d0de6bbd57125ff" @@ -13358,19 +7883,6 @@ web3-utils@^1.3.4: randombytes "^2.1.0" utf8 "3.0.0" -web3@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" - integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== - dependencies: - web3-bzz "1.2.11" - web3-core "1.2.11" - web3-eth "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-shh "1.2.11" - web3-utils "1.2.11" - web3@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/web3/-/web3-1.6.0.tgz#d8fa0cd9e7bf252f9fe43bb77dc42bc6671affde" @@ -13389,19 +7901,7 @@ webidl-conversions@^3.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== -websocket@1.0.32: - version "1.0.32" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.32.tgz#1f16ddab3a21a2d929dec1687ab21cfdc6d3dbb1" - integrity sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q== - dependencies: - bufferutil "^4.0.1" - debug "^2.2.0" - es5-ext "^0.10.50" - typedarray-to-buffer "^3.1.5" - utf-8-validate "^5.0.2" - yaeti "^0.0.6" - -websocket@^1.0.31, websocket@^1.0.32: +websocket@^1.0.32: version "1.0.34" resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== @@ -13418,11 +7918,6 @@ whatwg-fetch@>=0.10.0: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== -whatwg-fetch@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" - integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== - whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -13442,22 +7937,6 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ== - -which-typed-array@^1.1.10, which-typed-array@^1.1.11: - version "1.1.11" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" - integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - which-typed-array@^1.1.2: version "1.1.8" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.8.tgz#0cfd53401a6f334d90ed1125754a42ed663eb01f" @@ -13470,13 +7949,6 @@ which-typed-array@^1.1.2: has-tostringtag "^1.0.0" is-typed-array "^1.1.9" -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -13484,42 +7956,16 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -window-size@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - integrity sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw== - word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -word-wrap@~1.2.3: - version "1.2.5" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" - integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== - -wordwrapjs@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" - integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== - dependencies: - reduce-flatten "^2.0.0" - typical "^5.2.0" - workerpool@6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw== - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -13542,23 +7988,11 @@ write-file-atomic@^4.0.1: imurmurhash "^0.1.4" signal-exit "^3.0.7" -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - ws@7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== -ws@8.12.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" - integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== - ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" @@ -13568,13 +8002,6 @@ ws@^3.0.0: safe-buffer "~5.1.0" ultron "~1.1.0" -ws@^5.1.1: - version "5.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" - integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== - dependencies: - async-limiter "~1.0.0" - ws@^7.4.6: version "7.5.9" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" @@ -13607,7 +8034,7 @@ xhr2-cookies@1.1.0: dependencies: cookiejar "^2.1.1" -xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: +xhr@^2.0.4, xhr@^2.3.3: version "2.6.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== @@ -13622,23 +8049,11 @@ xmlhttprequest@1.8.0: resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA== -xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: +xtend@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -xtend@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ== - dependencies: - object-keys "~0.4.0" - -y18n@^3.2.1: - version "3.2.2" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" - integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== - y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -13659,24 +8074,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== -yargs-parser@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" - integrity sha512-9pIKIJhnI5tonzG6OnCFlz/yln8xHYcGl+pn3xR0Vzff0vzN1PbNRaelgfgRUwZ3s4i3jvxT9WhmUGL4whnasA== - dependencies: - camelcase "^3.0.0" - lodash.assign "^4.0.6" - yargs-parser@^20.2.2: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" @@ -13723,26 +8125,6 @@ yargs@^17.0.1, yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.0.0" -yargs@^4.7.1: - version "4.8.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" - integrity sha512-LqodLrnIDM3IFT+Hf/5sxBnEGECrfdC1uIbgZeJmESCSo4HoCAaKEus8MylXHAkdacGc0ye+Qa+dpkuom8uVYA== - dependencies: - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - lodash.assign "^4.0.3" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.1" - which-module "^1.0.0" - window-size "^0.2.0" - y18n "^3.2.1" - yargs-parser "^2.4.1" - yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" @@ -13752,18 +8134,3 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zksync-web3@^0.14.3: - version "0.14.3" - resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.14.3.tgz#64ac2a16d597464c3fc4ae07447a8007631c57c9" - integrity sha512-hT72th4AnqyLW1d5Jlv8N2B/qhEnl2NePK2A3org7tAa24niem/UAaHMkEvmWI3SF9waYUPtqAtjpf+yvQ9zvQ== - -zksync-web3@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.8.1.tgz#db289d8f6caf61f4d5ddc471fa3448d93208dc14" - integrity sha512-1A4aHPQ3MyuGjpv5X/8pVEN+MdZqMjfVmiweQSRjOlklXYu65wT9BGEOtCmMs5d3gIvLp4ssfTeuR5OCKOD2kw== - -zod@3.21.4: - version "3.21.4" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db" - integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw== From 935d72c2d3f02c154653b8c0eed8e424d99c43c9 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 29 Aug 2023 13:10:27 +0300 Subject: [PATCH 167/833] remove old integration tests --- .../sushiswap-v3-integration.test.ts | 111 ------------------ 1 file changed, 111 deletions(-) delete mode 100644 src/dex/uniswap-v3/sushiswap-v3-integration.test.ts diff --git a/src/dex/uniswap-v3/sushiswap-v3-integration.test.ts b/src/dex/uniswap-v3/sushiswap-v3-integration.test.ts deleted file mode 100644 index a1366f98a..000000000 --- a/src/dex/uniswap-v3/sushiswap-v3-integration.test.ts +++ /dev/null @@ -1,111 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); -import { SushiSwapV3 } from '../sushiswap-v3/sushiswap-v3'; -import { Network, SwapSide } from '../../constants'; -import { DummyDexHelper, IDexHelper } from '../../dex-helper'; -import { Tokens } from '../../../tests/constants-e2e'; -import { BI_POWS } from '../../bigint-constants'; -import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; -import { Interface, Result } from '@ethersproject/abi'; -import SushiswapV3QuoterV2ABI from '../../abi/sushiswap-v3/QuoterV2.json'; -import { Address } from '@paraswap/core'; - -const quoterIface = new Interface(SushiswapV3QuoterV2ABI); - -function getReaderCalldata( - exchangeAddress: string, - readerIface: Interface, - amounts: bigint[], - funcName: string, - tokenIn: Address, - tokenOut: Address, - fee: bigint, -) { - return amounts.map(amount => ({ - target: exchangeAddress, - callData: readerIface.encodeFunctionData(funcName, [ - [tokenIn, tokenOut, amount.toString(), fee.toString(), 0], - ]), - })); -} - -function decodeReaderResult( - results: Result, - readerIface: Interface, - funcName: string, -) { - return results.map(result => { - const parsed = readerIface.decodeFunctionResult(funcName, result); - return BigInt(parsed[0]._hex); - }); -} - -async function checkOnChainPricing( - dexHelper: IDexHelper, - sushiSwapV3: SushiSwapV3, - funcName: string, - blockNumber: number, - exchangeAddress: string, - prices: bigint[], - tokenIn: Address, - tokenOut: Address, - fee: bigint, - _amounts: bigint[], -) { - // Quoter address - // const exchangeAddress = '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'; - const readerIface = quoterIface; - - // const sum = prices.reduce((acc, curr) => (acc += curr), 0n); - // - // if (sum === 0n) { - // console.log( - // `Prices were not calculated for tokenIn=${tokenIn}, tokenOut=${tokenOut}, fee=${fee.toString()}. Most likely price impact is too big for requested amount`, - // ); - // return false; - // } - - const readerCallData = getReaderCalldata( - exchangeAddress, - readerIface, - _amounts.slice(1), - funcName, - tokenIn, - tokenOut, - fee, - ); - - let readerResult; - try { - readerResult = ( - await dexHelper.multiContract.methods - .aggregate(readerCallData) - .call({}, blockNumber) - ).returnData; - } catch (e) { - console.log( - `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, - e, - ); - return false; - } - - const expectedPrices = [0n].concat( - decodeReaderResult(readerResult, readerIface, funcName), - ); - - console.log('EXPECTED PRICES: ', expectedPrices); - - let firstZeroIndex = prices.slice(1).indexOf(0n); - - // we skipped first, so add +1 on result - firstZeroIndex = firstZeroIndex === -1 ? prices.length : firstZeroIndex; - - // Compare only the ones for which we were able to calculate prices - expect(prices.slice(0, firstZeroIndex)).toEqual( - expectedPrices.slice(0, firstZeroIndex), - ); - return true; -} - From 7721832210c33d863c78975727868d946e502c57 Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 29 Aug 2023 12:05:20 +0100 Subject: [PATCH 168/833] style: abi rename and update imports --- .../fast-price-events.json | 0 .../fast-price-feed.json | 0 .../{quickPerps => quick-perps}/reader.json | 0 .../vault-price-feed.json | 0 .../{quickPerps => quick-perps}/vault.json | 0 src/dex/quick-perps/fast-price-feed.ts | 4 +-- src/dex/quick-perps/pool.ts | 2 +- .../quick-perps-integration.test.ts | 29 +++++++++++-------- src/dex/quick-perps/vault-price-feed.ts | 2 +- src/dex/quick-perps/vault.ts | 2 +- 10 files changed, 22 insertions(+), 17 deletions(-) rename src/abi/{quickPerps => quick-perps}/fast-price-events.json (100%) rename src/abi/{quickPerps => quick-perps}/fast-price-feed.json (100%) rename src/abi/{quickPerps => quick-perps}/reader.json (100%) rename src/abi/{quickPerps => quick-perps}/vault-price-feed.json (100%) rename src/abi/{quickPerps => quick-perps}/vault.json (100%) diff --git a/src/abi/quickPerps/fast-price-events.json b/src/abi/quick-perps/fast-price-events.json similarity index 100% rename from src/abi/quickPerps/fast-price-events.json rename to src/abi/quick-perps/fast-price-events.json diff --git a/src/abi/quickPerps/fast-price-feed.json b/src/abi/quick-perps/fast-price-feed.json similarity index 100% rename from src/abi/quickPerps/fast-price-feed.json rename to src/abi/quick-perps/fast-price-feed.json diff --git a/src/abi/quickPerps/reader.json b/src/abi/quick-perps/reader.json similarity index 100% rename from src/abi/quickPerps/reader.json rename to src/abi/quick-perps/reader.json diff --git a/src/abi/quickPerps/vault-price-feed.json b/src/abi/quick-perps/vault-price-feed.json similarity index 100% rename from src/abi/quickPerps/vault-price-feed.json rename to src/abi/quick-perps/vault-price-feed.json diff --git a/src/abi/quickPerps/vault.json b/src/abi/quick-perps/vault.json similarity index 100% rename from src/abi/quickPerps/vault.json rename to src/abi/quick-perps/vault.json diff --git a/src/dex/quick-perps/fast-price-feed.ts b/src/dex/quick-perps/fast-price-feed.ts index 7140ddf70..8af150067 100644 --- a/src/dex/quick-perps/fast-price-feed.ts +++ b/src/dex/quick-perps/fast-price-feed.ts @@ -11,8 +11,8 @@ import { BlockHeader, } from '../../types'; import { FastPriceFeedConfig, FastPriceFeedState } from './types'; -import FastPriceFeedAbi from '../../abi/quickPerps/fast-price-feed.json'; -import FastPriceEventsAbi from '../../abi/quickPerps/fast-price-events.json'; +import FastPriceFeedAbi from '../../abi/quick-perps/fast-price-feed.json'; +import FastPriceEventsAbi from '../../abi/quick-perps/fast-price-events.json'; import { Lens } from '../../lens'; export class FastPriceFeed extends PartialEventSubscriber< diff --git a/src/dex/quick-perps/pool.ts b/src/dex/quick-perps/pool.ts index 20d2fbb92..da81d0f82 100644 --- a/src/dex/quick-perps/pool.ts +++ b/src/dex/quick-perps/pool.ts @@ -10,7 +10,7 @@ import { VaultPriceFeed } from './vault-price-feed'; import { Vault } from './vault'; import { USDQ } from './usdq'; import { Contract } from 'web3-eth-contract'; -import ReaderABI from '../../abi/quickPerps/reader.json'; +import ReaderABI from '../../abi/quick-perps/reader.json'; const MAX_AMOUNT_IN_CACHE_TTL = 5 * 60; diff --git a/src/dex/quick-perps/quick-perps-integration.test.ts b/src/dex/quick-perps/quick-perps-integration.test.ts index 5c488326f..28e243a78 100644 --- a/src/dex/quick-perps/quick-perps-integration.test.ts +++ b/src/dex/quick-perps/quick-perps-integration.test.ts @@ -1,11 +1,11 @@ +/* eslint-disable no-console */ import dotenv from 'dotenv'; dotenv.config(); import { Interface } from '@ethersproject/abi'; import { DummyDexHelper } from '../../dex-helper/index'; import { Network, SwapSide } from '../../constants'; -import { BI_POWS } from '../../bigint-constants'; -import { QuickPerps } from './quickPerps'; +import { QuickPerps } from './quick-perps'; import { QuickPerpsConfig } from './config'; import { checkPoolPrices, @@ -13,28 +13,33 @@ import { checkConstantPoolPrices, } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; -import ReaderABI from '../../abi/quickPerps/reader.json'; +import ReaderABI from '../../abi/quick-perps/reader.json'; -const network = Network.AVALANCHE; -const TokenASymbol = 'USDCe'; +const network = Network.ZKEVM; +const TokenASymbol = 'WETH'; const TokenA = Tokens[network][TokenASymbol]; -const TokenBSymbol = 'WAVAX'; +const TokenBSymbol = 'MATIC'; const TokenB = Tokens[network][TokenBSymbol]; const amounts = [ 0n, - 1000000000n, - 2000000000n, - 3000000000n, - 4000000000n, - 5000000000n, + 100000000000000000n, + 200000000000000000n, + 300000000000000000n, + 400000000000000000n, + 500000000000000000n, + 600000000000000000n, + 700000000000000000n, + 800000000000000000n, + 900000000000000000n, + 1000000000000000000n, ]; const dexKey = 'QuickPerps'; const params = QuickPerpsConfig[dexKey][network]; const readerInterface = new Interface(ReaderABI); -const readerAddress = '0x67b789D48c926006F5132BFCe4e976F0A7A63d5D'; +const readerAddress = '0xf1CFB75854DE535475B88Bb6FBad317eea98c0F9'; describe('QuickPerps', function () { it('getPoolIdentifiers and getPricesVolume SELL', async function () { diff --git a/src/dex/quick-perps/vault-price-feed.ts b/src/dex/quick-perps/vault-price-feed.ts index 5071cb135..43a96e7e2 100644 --- a/src/dex/quick-perps/vault-price-feed.ts +++ b/src/dex/quick-perps/vault-price-feed.ts @@ -2,7 +2,7 @@ import { Interface } from '@ethersproject/abi'; import { Address, MultiCallInput, MultiCallOutput } from '../../types'; import { PoolState, VaultPriceFeedConfig } from './types'; import { FastPriceFeed } from './fast-price-feed'; -import VaultPriceFeedAbi from '../../abi/quickPerps/vault-price-feed.json'; +import VaultPriceFeedAbi from '../../abi/quick-perps/vault-price-feed.json'; import { ChainLinkSubscriber } from '../../lib/chainlink'; import { DeepReadonly } from 'ts-essentials'; diff --git a/src/dex/quick-perps/vault.ts b/src/dex/quick-perps/vault.ts index 725d3f27f..a5832c76c 100644 --- a/src/dex/quick-perps/vault.ts +++ b/src/dex/quick-perps/vault.ts @@ -3,7 +3,7 @@ import { Interface } from '@ethersproject/abi'; import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; import { PartialEventSubscriber } from '../../composed-event-subscriber'; import { Lens } from '../../lens'; -import VaultABI from '../../abi/quickPerps/vault.json'; +import VaultABI from '../../abi/quick-perps/vault.json'; import { VaultUtils } from './vault-utils'; import { VaultConfig, From c1bfaf4a4c10b367a3b0a0534a146e5f9dd8e1c8 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 29 Aug 2023 15:54:01 +0300 Subject: [PATCH 169/833] update router addresses --- src/dex/uniswap-v3/config.ts | 16 +++++++------- src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 26 +++++++++++------------ tests/constants-e2e.ts | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index 96bfa27bb..c4d58d165 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -111,7 +111,7 @@ export const UniswapV3Config: DexConfigMap = { [Network.MAINNET]: { factory: '0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F', quoter: '0x64e8802FE490fa7cc61d3463958199161Bb608A7', - router: '0xFDF9EE3Cc6CA79263F6904aA03F1b071Becb1165', + router: '0x00F23572b16c5e9e58e7b965DEF51Ff8Ff546E34', supportedFees: SUPPORTED_FEES, stateMulticall: '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63', uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', @@ -124,7 +124,7 @@ export const UniswapV3Config: DexConfigMap = { [Network.POLYGON]: { factory: '0x917933899c6a5f8e37f31e19f92cdbff7e8ff0e2', quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6', + router: '0x34D41cE301257a4615D4F5AD260FA91D03925243', supportedFees: SUPPORTED_FEES, stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', @@ -137,7 +137,7 @@ export const UniswapV3Config: DexConfigMap = { [Network.BSC]: { factory: '0x126555dd55a39328F69400d6aE4F782Bd4C34ABb', quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x400d75dAb26bBc18D163AEA3e83D9Ea68F6c1804', + router: '0xDCf4EE5B700e2a5Fec458e06B763A4a3E3004494', supportedFees: SUPPORTED_FEES, stateMulticall: '0x593F39A4Ba26A9c8ed2128ac95D109E8e403C485', uniswapMulticall: '0x963Df249eD09c358A4819E39d9Cd5736c3087184', @@ -149,7 +149,7 @@ export const UniswapV3Config: DexConfigMap = { [Network.AVALANCHE]: { factory: '0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715', quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0xDcCa1db4016BE1f3879aB033A7776e3998ef7968', + router: '0x24c90C7d8fb463722e304A71255341610Fa7589b', supportedFees: SUPPORTED_FEES, stateMulticall: '', uniswapMulticall: '0x8C0F842791F03C095b6c633759224FcC9ACe68ea', @@ -162,9 +162,9 @@ export const UniswapV3Config: DexConfigMap = { [Network.FANTOM]: { factory: '0x7770978eED668a3ba661d51a773d3a992Fc9DDCB', quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x2214A42d8e2A1d20635c2cb0664422c528B6A432', + router: '0xDCf4EE5B700e2a5Fec458e06B763A4a3E3004494', supportedFees: SUPPORTED_FEES, - stateMulticall: '', + stateMulticall: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', uniswapMulticall: '0xB1395e098c0a847CC719Bcf1Fc8114421a9F8232', chunksCount: 10, initRetryFrequency: 10, @@ -174,7 +174,7 @@ export const UniswapV3Config: DexConfigMap = { [Network.ARBITRUM]: { factory: '0x1af415a1eba07a4986a52b6f2e7de7003d82231e', quoter: '0x0524E833cCD057e4d7A296e3aaAb9f7675964Ce1', - router: '0x08d08eF6e715e00351CC2FCF8501C04642c37EB4', + router: '0xbDa4176fD98b47018aF673805d069b9dbd49373D', supportedFees: SUPPORTED_FEES, stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', @@ -187,7 +187,7 @@ export const UniswapV3Config: DexConfigMap = { [Network.OPTIMISM]: { factory: '0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0', quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x4C5D5234f232BD2D76B96aA33F5AE4FCF0E4BFAb', + router: '0xa05d8C3F278fC7b20b39Ea7A3035E3aD8D808c78', supportedFees: SUPPORTED_FEES, stateMulticall: '0x4FF0dEC5f9a763Aa1E5C2a962aa6f4eDFeE4f9eA', uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index 88940447c..57d0ed3a4 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -912,25 +912,25 @@ describe('UniswapV3 E2E', () => { const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ [ + { + name: 'FTM', + sellAmount: '100000000000000000', + buyAmount: '100000000', + }, { name: 'USDC', - sellAmount: '111110', - buyAmount: '111110', + sellAmount: '100000000', + buyAmount: '100000000000000000', }, + ], + [ { - name: 'FUSDT', - sellAmount: '111110', - buyAmount: '111110', + name: 'WFTM', + sellAmount: '100000000000000', + buyAmount: '1000000000000000', }, + { name: 'WETH', sellAmount: '1000000000000000', buyAmount: '100000000000000' }, ], - // [ - // { - // name: 'BNB', - // sellAmount: '1000000000000000000', - // buyAmount: '10000000000000000000', - // }, - // { name: 'USDT', sellAmount: '1000000000000000000000', buyAmount: '20000000000000000' }, - // ], ]; sideToContractMethods.forEach((contractMethods, side) => diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 85df1682c..06ca492e8 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -963,7 +963,7 @@ export const Holders: { DAI: '0x370f4b2dcf75c94d8d4450b493661a9c6170d0b5', FTM: '0x431e81E5dfB5A24541b5Ff8762bDEF3f32F96354', WFTM: '0x3e923747ca2675e096d812c3b24846ac39aed645', - USDC: '0xe48793b1533b351ae184e1c3119d0955dde7b330', + USDC: '0xf53feaeb035361c046e5669745695e450ebb4028', FUSDT: '0x9ade1c17d25246c405604344f89E8F23F8c1c632', POPS: '0x4b78b52e7de4d8b7d367297cb8a87c1875a9d591', aFanUSDT: '0x8EBc96fF91A30059E447bFC7C0a7394f8A5793E6', From 80b2d5c65dd6e646ddfa8903ffbb1170d8665e6c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 29 Aug 2023 15:56:13 +0300 Subject: [PATCH 170/833] 2.31.6-sushi-v3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 58414449c..30efe6fb0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.5", + "version": "2.31.6-sushi-v3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 81c87d87fe2750137cd61b8796f2d13697445e47 Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 29 Aug 2023 17:34:20 +0200 Subject: [PATCH 171/833] chore: template initialization --- src/dex/index.ts | 2 + src/dex/smardex/config.ts | 15 ++ src/dex/smardex/smardex-e2e.test.ts | 162 +++++++++++++ src/dex/smardex/smardex-events.test.ts | 106 +++++++++ src/dex/smardex/smardex-integration.test.ts | 251 ++++++++++++++++++++ src/dex/smardex/smardex-pool.ts | 91 +++++++ src/dex/smardex/smardex.ts | 178 ++++++++++++++ src/dex/smardex/types.ts | 22 ++ 8 files changed, 827 insertions(+) create mode 100644 src/dex/smardex/config.ts create mode 100644 src/dex/smardex/smardex-e2e.test.ts create mode 100644 src/dex/smardex/smardex-events.test.ts create mode 100644 src/dex/smardex/smardex-integration.test.ts create mode 100644 src/dex/smardex/smardex-pool.ts create mode 100644 src/dex/smardex/smardex.ts create mode 100644 src/dex/smardex/types.ts diff --git a/src/dex/index.ts b/src/dex/index.ts index 11302d4c3..15f3a9f2d 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -71,6 +71,7 @@ import { SpiritSwapV3 } from './quickswap/spiritswap-v3'; import { TraderJoeV21 } from './trader-joe-v2.1'; import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3'; import { Algebra } from './algebra/algebra'; +import { Smardex } from './smardex/smardex'; const LegacyDexes = [ CurveV2, @@ -139,6 +140,7 @@ const Dexes = [ MaverickV1, Camelot, SwaapV2, + Smardex, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< diff --git a/src/dex/smardex/config.ts b/src/dex/smardex/config.ts new file mode 100644 index 000000000..17e1d914a --- /dev/null +++ b/src/dex/smardex/config.ts @@ -0,0 +1,15 @@ +import { DexParams } from './types'; +import { DexConfigMap, AdapterMappings } from '../../types'; +import { Network, SwapSide } from '../../constants'; + +export const SmardexConfig: DexConfigMap = { + Smardex: { + // TODO: complete me! + }, +}; + +export const Adapters: Record = { + // TODO: add adapters for each chain + // This is an example to copy + [Network.MAINNET]: { [SwapSide.SELL]: [{ name: '', index: 0 }] }, +}; diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts new file mode 100644 index 000000000..486fe1882 --- /dev/null +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -0,0 +1,162 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { testE2E } from '../../../tests/utils-e2e'; +import { + Tokens, + Holders, + NativeTokenSymbols, +} from '../../../tests/constants-e2e'; +import { Network, ContractMethod, SwapSide } from '../../constants'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; + +/* + README + ====== + + This test script should add e2e tests for Smardex. The tests + should cover as many cases as possible. Most of the DEXes follow + the following test structure: + - DexName + - ForkName + Network + - ContractMethod + - ETH -> Token swap + - Token -> ETH swap + - Token -> Token swap + + The template already enumerates the basic structure which involves + testing simpleSwap, multiSwap, megaSwap contract methods for + ETH <> TOKEN and TOKEN <> TOKEN swaps. You should replace tokenA and + tokenB with any two highly liquid tokens on Smardex for the tests + to work. If the tokens that you would like to use are not defined in + Tokens or Holders map, you can update the './tests/constants-e2e' + + Other than the standard cases that are already added by the template + it is highly recommended to add test cases which could be specific + to testing Smardex (Eg. Tests based on poolType, special tokens, + etc). + + You can run this individual test script by running: + `npx jest src/dex//-e2e.test.ts` + + e2e tests use the Tenderly fork api. Please add the following to your + .env file: + TENDERLY_TOKEN=Find this under Account>Settings>Authorization. + TENDERLY_ACCOUNT_ID=Your Tenderly account name. + TENDERLY_PROJECT=Name of a Tenderly project you have created in your + dashboard. + + (This comment should be removed from the final implementation) +*/ + +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + // TODO: Add any direct swap contractMethod name if it exists + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + // TODO: If buy is not supported remove the buy contract methods + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }), + ); + }); +} + +describe('Smardex E2E', () => { + const dexKey = 'Smardex'; + + describe('Mainnet', () => { + const network = Network.MAINNET; + + // TODO: Modify the tokenASymbol, tokenBSymbol, tokenAAmount; + const tokenASymbol: string = 'tokenASymbol'; + const tokenBSymbol: string = 'tokenBSymbol'; + + const tokenAAmount: string = 'tokenAAmount'; + const tokenBAmount: string = 'tokenBAmount'; + const nativeTokenAmount = '1000000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + + // TODO: Add any additional test cases required to test Smardex + }); +}); diff --git a/src/dex/smardex/smardex-events.test.ts b/src/dex/smardex/smardex-events.test.ts new file mode 100644 index 000000000..1deaa5db2 --- /dev/null +++ b/src/dex/smardex/smardex-events.test.ts @@ -0,0 +1,106 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { SmardexEventPool } from './smardex-pool'; +import { Network } from '../../constants'; +import { Address } from '../../types'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { testEventSubscriber } from '../../../tests/utils-events'; +import { PoolState } from './types'; + +/* + README + ====== + + This test script adds unit tests for Smardex event based + system. This is done by fetching the state on-chain before the + event block, manually pushing the block logs to the event-subscriber, + comparing the local state with on-chain state. + + Most of the logic for testing is abstracted by `testEventSubscriber`. + You need to do two things to make the tests work: + + 1. Fetch the block numbers where certain events were released. You + can modify the `./scripts/fetch-event-blocknumber.ts` to get the + block numbers for different events. Make sure to get sufficient + number of blockNumbers to cover all possible cases for the event + mutations. + + 2. Complete the implementation for fetchPoolState function. The + function should fetch the on-chain state of the event subscriber + using just the blocknumber. + + The template tests only include the test for a single event + subscriber. There can be cases where multiple event subscribers + exist for a single DEX. In such cases additional tests should be + added. + + You can run this individual test script by running: + `npx jest src/dex//-events.test.ts` + + (This comment should be removed from the final implementation) +*/ + +jest.setTimeout(50 * 1000); + +async function fetchPoolState( + smardexPools: SmardexEventPool, + blockNumber: number, + poolAddress: string, +): Promise { + // TODO: complete me! + return {}; +} + +// eventName -> blockNumbers +type EventMappings = Record; + +describe('Smardex EventPool Mainnet', function () { + const dexKey = 'Smardex'; + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + const logger = dexHelper.getLogger(dexKey); + let smardexPool: SmardexEventPool; + + // poolAddress -> EventMappings + const eventsToTest: Record = { + // TODO: complete me! + }; + + beforeEach(async () => { + smardexPool = new SmardexEventPool( + dexKey, + network, + dexHelper, + logger, + /* TODO: Put here additional constructor arguments if needed */ + ); + }); + + Object.entries(eventsToTest).forEach( + ([poolAddress, events]: [string, EventMappings]) => { + describe(`Events for ${poolAddress}`, () => { + Object.entries(events).forEach( + ([eventName, blockNumbers]: [string, number[]]) => { + describe(`${eventName}`, () => { + blockNumbers.forEach((blockNumber: number) => { + it(`State after ${blockNumber}`, async function () { + await testEventSubscriber( + smardexPool, + smardexPool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolState(smardexPool, _blockNumber, poolAddress), + blockNumber, + `${dexKey}_${poolAddress}`, + dexHelper.provider, + ); + }); + }); + }); + }, + ); + }); + }, + ); +}); diff --git a/src/dex/smardex/smardex-integration.test.ts b/src/dex/smardex/smardex-integration.test.ts new file mode 100644 index 000000000..6499260f6 --- /dev/null +++ b/src/dex/smardex/smardex-integration.test.ts @@ -0,0 +1,251 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { Interface, Result } from '@ethersproject/abi'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { Network, SwapSide } from '../../constants'; +import { BI_POWS } from '../../bigint-constants'; +import { Smardex } from './smardex'; +import { + checkPoolPrices, + checkPoolsLiquidity, + checkConstantPoolPrices, +} from '../../../tests/utils'; +import { Tokens } from '../../../tests/constants-e2e'; + +/* + README + ====== + + This test script adds tests for Smardex general integration + with the DEX interface. The test cases below are example tests. + It is recommended to add tests which cover Smardex specific + logic. + + You can run this individual test script by running: + `npx jest src/dex//-integration.test.ts` + + (This comment should be removed from the final implementation) +*/ + +function getReaderCalldata( + exchangeAddress: string, + readerIface: Interface, + amounts: bigint[], + funcName: string, + // TODO: Put here additional arguments you need +) { + return amounts.map(amount => ({ + target: exchangeAddress, + callData: readerIface.encodeFunctionData(funcName, [ + // TODO: Put here additional arguments to encode them + amount, + ]), + })); +} + +function decodeReaderResult( + results: Result, + readerIface: Interface, + funcName: string, +) { + // TODO: Adapt this function for your needs + return results.map(result => { + const parsed = readerIface.decodeFunctionResult(funcName, result); + return BigInt(parsed[0]._hex); + }); +} + +async function checkOnChainPricing( + smardex: Smardex, + funcName: string, + blockNumber: number, + prices: bigint[], + amounts: bigint[], +) { + const exchangeAddress = ''; // TODO: Put here the real exchange address + + // TODO: Replace dummy interface with the real one + // Normally you can get it from smardex.Iface or from eventPool. + // It depends on your implementation + const readerIface = new Interface(''); + + const readerCallData = getReaderCalldata( + exchangeAddress, + readerIface, + amounts.slice(1), + funcName, + ); + const readerResult = ( + await smardex.dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blockNumber) + ).returnData; + + const expectedPrices = [0n].concat( + decodeReaderResult(readerResult, readerIface, funcName), + ); + + expect(prices).toEqual(expectedPrices); +} + +async function testPricingOnNetwork( + smardex: Smardex, + network: Network, + dexKey: string, + blockNumber: number, + srcTokenSymbol: string, + destTokenSymbol: string, + side: SwapSide, + amounts: bigint[], + funcNameToCheck: string, +) { + const networkTokens = Tokens[network]; + + const pools = await smardex.getPoolIdentifiers( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + side, + blockNumber, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await smardex.getPricesVolume( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + amounts, + side, + blockNumber, + pools, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + if (smardex.hasConstantPriceLargeAmounts) { + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + } else { + checkPoolPrices(poolPrices!, amounts, side, dexKey); + } + + // Check if onchain pricing equals to calculated ones + await checkOnChainPricing( + smardex, + funcNameToCheck, + blockNumber, + poolPrices![0].prices, + amounts, + ); +} + +describe('Smardex', function () { + const dexKey = 'Smardex'; + let blockNumber: number; + let smardex: Smardex; + + describe('Mainnet', () => { + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + + // TODO: Put here token Symbol to check against + // Don't forget to update relevant tokens in constant-e2e.ts + const srcTokenSymbol = 'srcTokenSymbol'; + const destTokenSymbol = 'destTokenSymbol'; + + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals], + 2n * BI_POWS[tokens[destTokenSymbol].decimals], + 3n * BI_POWS[tokens[destTokenSymbol].decimals], + 4n * BI_POWS[tokens[destTokenSymbol].decimals], + 5n * BI_POWS[tokens[destTokenSymbol].decimals], + 6n * BI_POWS[tokens[destTokenSymbol].decimals], + 7n * BI_POWS[tokens[destTokenSymbol].decimals], + 8n * BI_POWS[tokens[destTokenSymbol].decimals], + 9n * BI_POWS[tokens[destTokenSymbol].decimals], + 10n * BI_POWS[tokens[destTokenSymbol].decimals], + ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + smardex = new Smardex(network, dexKey, dexHelper); + if (smardex.initializePricing) { + await smardex.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + smardex, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + '', // TODO: Put here proper function name to check pricing + ); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + smardex, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + '', // TODO: Put here proper function name to check pricing + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newSmardex = new Smardex(network, dexKey, dexHelper); + if (newSmardex.updatePoolState) { + await newSmardex.updatePoolState(); + } + const poolLiquidity = await newSmardex.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newSmardex.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); + }); +}); diff --git a/src/dex/smardex/smardex-pool.ts b/src/dex/smardex/smardex-pool.ts new file mode 100644 index 000000000..1f81f18a5 --- /dev/null +++ b/src/dex/smardex/smardex-pool.ts @@ -0,0 +1,91 @@ +import { Interface } from '@ethersproject/abi'; +import { DeepReadonly } from 'ts-essentials'; +import { Log, Logger } from '../../types'; +import { catchParseLogError } from '../../utils'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { PoolState } from './types'; + +export class SmardexEventPool extends StatefulEventSubscriber { + handlers: { + [event: string]: ( + event: any, + state: DeepReadonly, + log: Readonly, + ) => DeepReadonly | null; + } = {}; + + logDecoder: (log: Log) => any; + + addressesSubscribed: string[]; + + constructor( + readonly parentName: string, + protected network: number, + protected dexHelper: IDexHelper, + logger: Logger, + protected smardexIface = new Interface( + '' /* TODO: Import and put here Smardex ABI */, + ), // TODO: add any additional params required for event subscriber + ) { + // TODO: Add pool name + super(parentName, 'POOL_NAME', dexHelper, logger); + + // TODO: make logDecoder decode logs that + this.logDecoder = (log: Log) => this.smardexIface.parseLog(log); + this.addressesSubscribed = [ + /* subscribed addresses */ + ]; + + // Add handlers + this.handlers['myEvent'] = this.handleMyEvent.bind(this); + } + + /** + * The function is called every time any of the subscribed + * addresses release log. The function accepts the current + * state, updates the state according to the log, and returns + * the updated state. + * @param state - Current state of event subscriber + * @param log - Log released by one of the subscribed addresses + * @returns Updates state of the event subscriber after the log + */ + protected processLog( + state: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + try { + const event = this.logDecoder(log); + if (event.name in this.handlers) { + return this.handlers[event.name](event, state, log); + } + } catch (e) { + catchParseLogError(e, this.logger); + } + + return null; + } + + /** + * The function generates state using on-chain calls. This + * function is called to regenerate state if the event based + * system fails to fetch events and the local state is no + * more correct. + * @param blockNumber - Blocknumber for which the state should + * should be generated + * @returns state of the event subscriber at blocknumber + */ + async generateState(blockNumber: number): Promise> { + // TODO: complete me! + return {}; + } + + // Its just a dummy example + handleMyEvent( + event: any, + state: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + return null; + } +} diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts new file mode 100644 index 000000000..08e9e840a --- /dev/null +++ b/src/dex/smardex/smardex.ts @@ -0,0 +1,178 @@ +import { AsyncOrSync } from 'ts-essentials'; +import { + Token, + Address, + ExchangePrices, + PoolPrices, + AdapterExchangeParam, + SimpleExchangeParam, + PoolLiquidity, + Logger, +} from '../../types'; +import { SwapSide, Network } from '../../constants'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { getDexKeysWithNetwork } from '../../utils'; +import { IDex } from '../../dex/idex'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { SmardexData } from './types'; +import { SimpleExchange } from '../simple-exchange'; +import { SmardexConfig, Adapters } from './config'; +import { SmardexEventPool } from './smardex-pool'; + +export class Smardex extends SimpleExchange implements IDex { + protected eventPools: SmardexEventPool; + + readonly hasConstantPriceLargeAmounts = false; + // TODO: set true here if protocols works only with wrapped asset + readonly needWrapNative = true; + + readonly isFeeOnTransferSupported = false; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(SmardexConfig); + + logger: Logger; + + constructor( + readonly network: Network, + readonly dexKey: string, + readonly dexHelper: IDexHelper, + protected adapters = Adapters[network] || {}, // TODO: add any additional optional params to support other fork DEXes + ) { + super(dexHelper, dexKey); + this.logger = dexHelper.getLogger(dexKey); + this.eventPools = new SmardexEventPool( + dexKey, + network, + dexHelper, + this.logger, + ); + } + + // Initialize pricing is called once in the start of + // pricing service. It is intended to setup the integration + // for pricing requests. It is optional for a DEX to + // implement this function + async initializePricing(blockNumber: number) { + // TODO: complete me! + } + + // Returns the list of contract adapters (name and index) + // for a buy/sell. Return null if there are no adapters. + getAdapters(side: SwapSide): { name: string; index: number }[] | null { + return this.adapters[side] ? this.adapters[side] : null; + } + + // Returns list of pool identifiers that can be used + // for a given swap. poolIdentifiers must be unique + // across DEXes. It is recommended to use + // ${dexKey}_${poolAddress} as a poolIdentifier + async getPoolIdentifiers( + srcToken: Token, + destToken: Token, + side: SwapSide, + blockNumber: number, + ): Promise { + // TODO: complete me! + return []; + } + + // Returns pool prices for amounts. + // If limitPools is defined only pools in limitPools + // should be used. If limitPools is undefined then + // any pools can be used. + async getPricesVolume( + srcToken: Token, + destToken: Token, + amounts: bigint[], + side: SwapSide, + blockNumber: number, + limitPools?: string[], + ): Promise> { + // TODO: complete me! + return null; + } + + // Returns estimated gas cost of calldata for this DEX in multiSwap + getCalldataGasCost(poolPrices: PoolPrices): number | number[] { + // TODO: update if there is any payload in getAdapterParam + return CALLDATA_GAS_COST.DEX_NO_PAYLOAD; + } + + // Encode params required by the exchange adapter + // Used for multiSwap, buy & megaSwap + // Hint: abiCoder.encodeParameter() could be useful + getAdapterParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: SmardexData, + side: SwapSide, + ): AdapterExchangeParam { + // TODO: complete me! + const { exchange } = data; + + // Encode here the payload for adapter + const payload = ''; + + return { + targetExchange: exchange, + payload, + networkFee: '0', + }; + } + + // Encode call data used by simpleSwap like routers + // Used for simpleSwap & simpleBuy + // Hint: this.buildSimpleParamWithoutWETHConversion + // could be useful + async getSimpleParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: SmardexData, + side: SwapSide, + ): Promise { + // TODO: complete me! + const { exchange } = data; + + // Encode here the transaction arguments + const swapData = ''; + + return this.buildSimpleParamWithoutWETHConversion( + srcToken, + srcAmount, + destToken, + destAmount, + swapData, + exchange, + ); + } + + // This is called once before getTopPoolsForToken is + // called for multiple tokens. This can be helpful to + // update common state required for calculating + // getTopPoolsForToken. It is optional for a DEX + // to implement this + async updatePoolState(): Promise { + // TODO: complete me! + } + + // Returns list of top pools based on liquidity. Max + // limit number pools should be returned. + async getTopPoolsForToken( + tokenAddress: Address, + limit: number, + ): Promise { + //TODO: complete me! + return []; + } + + // This is optional function in case if your implementation has acquired any resources + // you need to release for graceful shutdown. For example, it may be any interval timer + releaseResources(): AsyncOrSync { + // TODO: complete me! + } +} diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts new file mode 100644 index 000000000..f2e0843e9 --- /dev/null +++ b/src/dex/smardex/types.ts @@ -0,0 +1,22 @@ +import { Address } from '../../types'; + +export type PoolState = { + // TODO: poolState is the state of event + // subscriber. This should be the minimum + // set of parameters required to compute + // pool prices. Complete me! +}; + +export type SmardexData = { + // TODO: SmardexData is the dex data that is + // returned by the API that can be used for + // tx building. The data structure should be minimal. + // Complete me! + exchange: Address; +}; + +export type DexParams = { + // TODO: DexParams is set of parameters the can + // be used to initiate a DEX fork. + // Complete me! +}; From 240a431b99c043dcb3688f2753152eaf15913e52 Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 29 Aug 2023 17:59:42 +0100 Subject: [PATCH 172/833] feat: update quick perps pricing is working --- src/abi/api3-proxy.json | 33 ++ src/abi/api3-server-v1.json | 463 ++++++++++++++++++ src/abi/quick-perps/fast-price-feed.json | 19 +- src/abi/quick-perps/vault-price-feed.json | 184 +------ src/dex/quick-perps/fast-price-feed.ts | 8 +- src/dex/quick-perps/pool.ts | 41 +- src/dex/quick-perps/quick-perps-e2e.test.ts | 87 +--- .../quick-perps/quick-perps-events.test.ts | 84 ++-- src/dex/quick-perps/quick-perps.ts | 3 - src/dex/quick-perps/types.ts | 11 +- src/dex/quick-perps/vault-price-feed.ts | 104 +--- src/lib/api3-feed.ts | 100 ++++ tests/constants-e2e.ts | 14 + 13 files changed, 723 insertions(+), 428 deletions(-) create mode 100644 src/abi/api3-proxy.json create mode 100644 src/abi/api3-server-v1.json create mode 100644 src/lib/api3-feed.ts diff --git a/src/abi/api3-proxy.json b/src/abi/api3-proxy.json new file mode 100644 index 000000000..a9b902bca --- /dev/null +++ b/src/abi/api3-proxy.json @@ -0,0 +1,33 @@ +[ + { + "inputs": [], + "name": "api3ServerV1", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "read", + "outputs": [ + { + "internalType": "int224", + "name": "value", + "type": "int224" + }, + { + "internalType": "uint32", + "name": "timestamp", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/abi/api3-server-v1.json b/src/abi/api3-server-v1.json new file mode 100644 index 000000000..c897541e0 --- /dev/null +++ b/src/abi/api3-server-v1.json @@ -0,0 +1,463 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_accessControlRegistry", + "type": "address" + }, + { + "internalType": "string", + "name": "_adminRoleDescription", + "type": "string" + }, + { "internalType": "address", "name": "_manager", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dataFeedId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "dapiName", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SetDapiName", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "beaconSetId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "int224", + "name": "value", + "type": "int224" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "timestamp", + "type": "uint32" + } + ], + "name": "UpdatedBeaconSetWithBeacons", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "beaconId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "int224", + "name": "value", + "type": "int224" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "timestamp", + "type": "uint32" + } + ], + "name": "UpdatedBeaconWithSignedData", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "beaconSetId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "updateId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "int224", + "name": "value", + "type": "int224" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "timestamp", + "type": "uint32" + } + ], + "name": "UpdatedOevProxyBeaconSetWithSignedData", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "beaconId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "updateId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "int224", + "name": "value", + "type": "int224" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "timestamp", + "type": "uint32" + } + ], + "name": "UpdatedOevProxyBeaconWithSignedData", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oevProxy", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "oevBeneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdrew", + "type": "event" + }, + { + "inputs": [], + "name": "DAPI_NAME_SETTER_ROLE_DESCRIPTION", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlRegistry", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "adminRole", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "adminRoleDescription", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "containsBytecode", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "name": "dapiNameHashToDataFeedId", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "dapiNameSetterRole", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "dapiName", "type": "bytes32" } + ], + "name": "dapiNameToDataFeedId", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "dataFeedId", "type": "bytes32" } + ], + "name": "dataFeeds", + "outputs": [ + { "internalType": "int224", "name": "value", "type": "int224" }, + { "internalType": "uint32", "name": "timestamp", "type": "uint32" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "account", "type": "address" } + ], + "name": "getBalance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockBasefee", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockTimestamp", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getChainId", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes[]", "name": "data", "type": "bytes[]" } + ], + "name": "multicall", + "outputs": [ + { "internalType": "bytes[]", "name": "returndata", "type": "bytes[]" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "oevProxyToBalance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "proxy", "type": "address" }, + { "internalType": "bytes32", "name": "dataFeedId", "type": "bytes32" } + ], + "name": "oevProxyToIdToDataFeed", + "outputs": [ + { "internalType": "int224", "name": "value", "type": "int224" }, + { "internalType": "uint32", "name": "timestamp", "type": "uint32" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "dapiNameHash", "type": "bytes32" } + ], + "name": "readDataFeedWithDapiNameHash", + "outputs": [ + { "internalType": "int224", "name": "value", "type": "int224" }, + { "internalType": "uint32", "name": "timestamp", "type": "uint32" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "dapiNameHash", "type": "bytes32" } + ], + "name": "readDataFeedWithDapiNameHashAsOevProxy", + "outputs": [ + { "internalType": "int224", "name": "value", "type": "int224" }, + { "internalType": "uint32", "name": "timestamp", "type": "uint32" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "dataFeedId", "type": "bytes32" } + ], + "name": "readDataFeedWithId", + "outputs": [ + { "internalType": "int224", "name": "value", "type": "int224" }, + { "internalType": "uint32", "name": "timestamp", "type": "uint32" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "dataFeedId", "type": "bytes32" } + ], + "name": "readDataFeedWithIdAsOevProxy", + "outputs": [ + { "internalType": "int224", "name": "value", "type": "int224" }, + { "internalType": "uint32", "name": "timestamp", "type": "uint32" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "dapiName", "type": "bytes32" }, + { "internalType": "bytes32", "name": "dataFeedId", "type": "bytes32" } + ], + "name": "setDapiName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes[]", "name": "data", "type": "bytes[]" } + ], + "name": "tryMulticall", + "outputs": [ + { "internalType": "bool[]", "name": "successes", "type": "bool[]" }, + { "internalType": "bytes[]", "name": "returndata", "type": "bytes[]" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32[]", "name": "beaconIds", "type": "bytes32[]" } + ], + "name": "updateBeaconSetWithBeacons", + "outputs": [ + { "internalType": "bytes32", "name": "beaconSetId", "type": "bytes32" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "airnode", "type": "address" }, + { "internalType": "bytes32", "name": "templateId", "type": "bytes32" }, + { "internalType": "uint256", "name": "timestamp", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" }, + { "internalType": "bytes", "name": "signature", "type": "bytes" } + ], + "name": "updateBeaconWithSignedData", + "outputs": [ + { "internalType": "bytes32", "name": "beaconId", "type": "bytes32" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "oevProxy", "type": "address" }, + { "internalType": "bytes32", "name": "dataFeedId", "type": "bytes32" }, + { "internalType": "bytes32", "name": "updateId", "type": "bytes32" }, + { "internalType": "uint256", "name": "timestamp", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" }, + { + "internalType": "bytes[]", + "name": "packedOevUpdateSignatures", + "type": "bytes[]" + } + ], + "name": "updateOevProxyDataFeedWithSignedData", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "oevProxy", "type": "address" } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/abi/quick-perps/fast-price-feed.json b/src/abi/quick-perps/fast-price-feed.json index 502cec0ed..5cf8fccdf 100644 --- a/src/abi/quick-perps/fast-price-feed.json +++ b/src/abi/quick-perps/fast-price-feed.json @@ -26,12 +26,7 @@ "name": "_fastPriceEvents", "type": "address" }, - { "internalType": "address", "name": "_tokenManager", "type": "address" }, - { - "internalType": "address", - "name": "_positionRouter", - "type": "address" - } + { "internalType": "address", "name": "_tokenManager", "type": "address" } ], "stateMutability": "nonpayable", "type": "constructor" @@ -367,13 +362,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "positionRouter", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, { "inputs": [{ "internalType": "address", "name": "", "type": "address" }], "name": "priceData", @@ -593,6 +581,11 @@ }, { "inputs": [ + { + "internalType": "address", + "name": "_positionRouter", + "type": "address" + }, { "internalType": "uint256", "name": "_priceBits", "type": "uint256" }, { "internalType": "uint256", "name": "_timestamp", "type": "uint256" }, { diff --git a/src/abi/quick-perps/vault-price-feed.json b/src/abi/quick-perps/vault-price-feed.json index d917d96cf..42c932f08 100644 --- a/src/abi/quick-perps/vault-price-feed.json +++ b/src/abi/quick-perps/vault-price-feed.json @@ -51,50 +51,8 @@ }, { "inputs": [], - "name": "bnb", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bnbBusd", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "btc", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "btcBnb", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "chainlinkFlags", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "eth", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ethBnb", - "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "expireTimeForPriceFeed", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, @@ -105,26 +63,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { "internalType": "address", "name": "_token", "type": "address" } - ], - "name": "getAmmPrice", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "_token", "type": "address" }, - { "internalType": "bool", "name": "_maximise", "type": "bool" }, - { "internalType": "uint256", "name": "_primaryPrice", "type": "uint256" } - ], - "name": "getAmmPriceV2", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { "internalType": "address", "name": "_token", "type": "address" } @@ -134,21 +72,11 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { "internalType": "address", "name": "_pair", "type": "address" }, - { "internalType": "bool", "name": "_divByReserve0", "type": "bool" } - ], - "name": "getPairPrice", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { "internalType": "address", "name": "_token", "type": "address" }, { "internalType": "bool", "name": "_maximise", "type": "bool" }, - { "internalType": "bool", "name": "_includeAmmPrice", "type": "bool" }, + { "internalType": "bool", "name": "", "type": "bool" }, { "internalType": "bool", "name": "", "type": "bool" } ], "name": "getPrice", @@ -159,8 +87,7 @@ { "inputs": [ { "internalType": "address", "name": "_token", "type": "address" }, - { "internalType": "bool", "name": "_maximise", "type": "bool" }, - { "internalType": "bool", "name": "_includeAmmPrice", "type": "bool" } + { "internalType": "bool", "name": "_maximise", "type": "bool" } ], "name": "getPriceV1", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], @@ -170,18 +97,7 @@ { "inputs": [ { "internalType": "address", "name": "_token", "type": "address" }, - { "internalType": "bool", "name": "_maximise", "type": "bool" }, - { "internalType": "bool", "name": "_includeAmmPrice", "type": "bool" } - ], - "name": "getPriceV2", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { "internalType": "address", "name": "_token", "type": "address" }, - { "internalType": "bool", "name": "_maximise", "type": "bool" } + { "internalType": "bool", "name": "", "type": "bool" } ], "name": "getPrimaryPrice", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], @@ -217,13 +133,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "isAmmEnabled", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "isSecondaryPriceEnabled", @@ -254,18 +163,11 @@ }, { "inputs": [{ "internalType": "address", "name": "", "type": "address" }], - "name": "priceFeeds", + "name": "priceFeedProxies", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "priceSampleSpace", - "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "secondaryPriceFeed", @@ -287,12 +189,12 @@ { "inputs": [ { - "internalType": "address", - "name": "_chainlinkFlags", - "type": "address" + "internalType": "uint256", + "name": "_expireTimeForPriceFeed", + "type": "uint256" } ], - "name": "setChainlinkFlags", + "name": "setExpireTimeForPriceFeed", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -315,15 +217,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { "internalType": "bool", "name": "_isEnabled", "type": "bool" } - ], - "name": "setIsAmmEnabled", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { "internalType": "bool", "name": "_isEnabled", "type": "bool" } @@ -346,30 +239,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { "internalType": "address", "name": "_bnbBusd", "type": "address" }, - { "internalType": "address", "name": "_ethBnb", "type": "address" }, - { "internalType": "address", "name": "_btcBnb", "type": "address" } - ], - "name": "setPairs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_priceSampleSpace", - "type": "uint256" - } - ], - "name": "setPriceSampleSpace", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -413,7 +282,11 @@ { "inputs": [ { "internalType": "address", "name": "_token", "type": "address" }, - { "internalType": "address", "name": "_priceFeed", "type": "address" }, + { + "internalType": "address", + "name": "_priceFeedProxy", + "type": "address" + }, { "internalType": "uint256", "name": "_priceDecimals", @@ -426,26 +299,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { "internalType": "address", "name": "_btc", "type": "address" }, - { "internalType": "address", "name": "_eth", "type": "address" }, - { "internalType": "address", "name": "_bnb", "type": "address" } - ], - "name": "setTokens", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { "internalType": "bool", "name": "_useV2Pricing", "type": "bool" } - ], - "name": "setUseV2Pricing", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [{ "internalType": "address", "name": "", "type": "address" }], "name": "spreadBasisPoints", @@ -466,12 +319,5 @@ "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "view", "type": "function" - }, - { - "inputs": [], - "name": "useV2Pricing", - "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], - "stateMutability": "view", - "type": "function" } ] diff --git a/src/dex/quick-perps/fast-price-feed.ts b/src/dex/quick-perps/fast-price-feed.ts index 8af150067..0d554b47d 100644 --- a/src/dex/quick-perps/fast-price-feed.ts +++ b/src/dex/quick-perps/fast-price-feed.ts @@ -79,14 +79,14 @@ export class FastPriceFeed extends PartialEventSubscriber< _state: DeepReadonly, _token: Address, _refPrice: bigint, - _maximise: boolean, + _maximize: boolean, ) { const state = this.lens.get()(_state); const timestamp = Math.floor(Date.now() / 1000); if (timestamp > state.lastUpdatedAt + this.maxPriceUpdateDelay) { - if (_maximise) { + if (_maximize) { return ( (_refPrice * (this.BASIS_POINTS_DIVISOR + this.spreadBasisPointsIfChainError)) / @@ -102,7 +102,7 @@ export class FastPriceFeed extends PartialEventSubscriber< } if (timestamp > state.lastUpdatedAt + this.priceDuration) { - if (_maximise) { + if (_maximize) { return ( (_refPrice * (this.BASIS_POINTS_DIVISOR + this.spreadBasisPointsIfInactive)) / @@ -132,7 +132,7 @@ export class FastPriceFeed extends PartialEventSubscriber< if (hasSpread) { // return the higher of the two prices - if (_maximise) { + if (_maximize) { return _refPrice > fastPrice ? _refPrice : fastPrice; } diff --git a/src/dex/quick-perps/pool.ts b/src/dex/quick-perps/pool.ts index da81d0f82..7d641706e 100644 --- a/src/dex/quick-perps/pool.ts +++ b/src/dex/quick-perps/pool.ts @@ -1,10 +1,10 @@ import { DeepReadonly } from 'ts-essentials'; -import { Lens, lens } from '../../lens'; -import { Address, Log, Logger, MultiCallInput } from '../../types'; +import { lens } from '../../lens'; +import { Address, Logger, MultiCallInput } from '../../types'; import { ComposedEventSubscriber } from '../../composed-event-subscriber'; import { IDexHelper } from '../../dex-helper/idex-helper'; import { PoolState, DexParams, PoolConfig } from './types'; -import { ChainLinkSubscriber } from '../../lib/chainlink'; +import { Api3FeedSubscriber } from '../../lib/api3-feed'; import { FastPriceFeed } from './fast-price-feed'; import { VaultPriceFeed } from './vault-price-feed'; import { Vault } from './vault'; @@ -29,14 +29,14 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { logger: Logger, config: PoolConfig, ) { - const chainlinkMap = Object.entries(config.chainlink).reduce( + const api3ServerV1Map = Object.entries(config.api3ServerV1).reduce( ( - acc: { [address: string]: ChainLinkSubscriber }, + acc: { [address: string]: Api3FeedSubscriber }, [key, value], ) => { - acc[key] = new ChainLinkSubscriber( + acc[key] = new Api3FeedSubscriber( value.proxy, - value.aggregator, + value.api3ServerV1, lens>().primaryPrices[key], dexHelper.getLogger(`${key} ChainLink for ${parentName}-${network}`), ); @@ -54,7 +54,7 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { ); const vaultPriceFeed = new VaultPriceFeed( config.vaultPriceFeedConfig, - chainlinkMap, + api3ServerV1Map, fastPriceFeed, ); const usdq = new USDQ( @@ -76,7 +76,7 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { 'pool', dexHelper.getLogger(`${parentName}-${network}`), dexHelper, - [...Object.values(chainlinkMap), fastPriceFeed, usdq, vault], + [...Object.values(api3ServerV1Map), fastPriceFeed, usdq, vault], { primaryPrices: {}, secondaryPrices: { @@ -255,9 +255,10 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { // get price chainlink price feed const getPriceFeedCalldata = tokens.map(t => { return { - callData: VaultPriceFeed.interface.encodeFunctionData('priceFeeds', [ - t, - ]), + callData: VaultPriceFeed.interface.encodeFunctionData( + 'priceFeedProxies', + [t], + ), target: dexParams.priceFeed, }; }); @@ -268,7 +269,7 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { ).returnData; const priceFeeds = priceFeedResult.map((p: any) => VaultPriceFeed.interface - .decodeFunctionResult('priceFeeds', p)[0] + .decodeFunctionResult('priceFeedProxies', p)[0] .toString() .toLowerCase(), ); @@ -279,7 +280,7 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { let i = 0; for (let priceFeed of priceFeeds) { const chainlinkConfigCallData = - ChainLinkSubscriber.getReadAggregatorMultiCallInput(priceFeed); + Api3FeedSubscriber.getApi3ServerV1MultiCallInput(priceFeed); multiCallData.push(chainlinkConfigCallData); multicallSlices.push([i, i + 1]); i += 1; @@ -311,16 +312,16 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { await multiContract.methods.aggregate(multiCallData).call({}, blockNumber) ).returnData; - const chainlink: { - [address: string]: { proxy: Address; aggregator: Address }; + const api3ServerV1: { + [address: string]: { proxy: Address; api3ServerV1: Address }; } = {}; for (let token of tokens) { - const aggregator = ChainLinkSubscriber.readAggregator( + const serverV1Address = Api3FeedSubscriber.decodeApi3ServerV1Result( configResults.slice(...multicallSlices.shift()!)[0], ); - chainlink[token] = { + api3ServerV1[token] = { proxy: priceFeeds.shift(), - aggregator, + api3ServerV1: serverV1Address, }; } @@ -354,7 +355,7 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { vaultConfig, vaultPriceFeedConfig, fastPriceFeedConfig, - chainlink, + api3ServerV1, }; } } diff --git a/src/dex/quick-perps/quick-perps-e2e.test.ts b/src/dex/quick-perps/quick-perps-e2e.test.ts index 2f84ff765..f4a72acf8 100644 --- a/src/dex/quick-perps/quick-perps-e2e.test.ts +++ b/src/dex/quick-perps/quick-perps-e2e.test.ts @@ -14,8 +14,8 @@ import { generateConfig } from '../../config'; describe('QuickPerps E2E', () => { const dexKey = 'QuickPerps'; - describe('QuickPerps AVALANCHE', () => { - const network = Network.AVALANCHE; + describe('QuickPerps zkEVM', () => { + const network = Network.ZKEVM; const tokens = Tokens[network]; const holders = Holders[network]; const provider = new StaticJsonRpcProvider( @@ -23,87 +23,12 @@ describe('QuickPerps E2E', () => { network, ); - const tokenASymbol: string = 'WETHe'; - const tokenBSymbol: string = 'USDCe'; + const tokenASymbol: string = 'WETH'; + const tokenBSymbol: string = 'MATIC'; const nativeTokenSymbol = NativeTokenSymbols[network]; - const tokenAAmount: string = '1000000000000000000'; - const tokenBAmount: string = '2000000000'; - const nativeTokenAmount = '1000000000000000000'; - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ], - ], - ]); - - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(nativeTokenSymbol + ' -> TOKEN', async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it('TOKEN -> ' + nativeTokenSymbol, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it('TOKEN -> TOKEN', async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }), - ); - }); - - describe('QuickPerps ARBITRUM', () => { - const network = Network.ARBITRUM; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'WETH'; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const tokenAAmount: string = '2000000000'; - const tokenBAmount: string = '1000000000000000000'; + const tokenAAmount: string = '100000000000000000'; + const tokenBAmount: string = '10000000000000000000'; const nativeTokenAmount = '1000000000000000000'; const sideToContractMethods = new Map([ diff --git a/src/dex/quick-perps/quick-perps-events.test.ts b/src/dex/quick-perps/quick-perps-events.test.ts index 2964f35f6..020db0ab7 100644 --- a/src/dex/quick-perps/quick-perps-events.test.ts +++ b/src/dex/quick-perps/quick-perps-events.test.ts @@ -6,12 +6,14 @@ import { QuickPerpsConfig } from './config'; import { Network } from '../../constants'; import { DummyDexHelper } from '../../dex-helper/index'; import { testEventSubscriber } from '../../../tests/utils-events'; -import { PoolState } from './types'; +import { PoolConfig, PoolState } from './types'; jest.setTimeout(50 * 1000); const dexKey = 'QuickPerps'; -const network = Network.AVALANCHE; +const network = Network.ZKEVM; const params = QuickPerpsConfig[dexKey][network]; +const dexHelper = new DummyDexHelper(network); +const logger = dexHelper.getLogger(dexKey); async function fetchPoolState( quickPerpsPool: QuickPerpsEventPool, @@ -28,7 +30,6 @@ const stateWithoutTimestamp = (state: PoolState) => ({ ...state, secondaryPrices: { prices: state.secondaryPrices.prices, - // timestamp (this is removed) }, }); @@ -41,63 +42,48 @@ function compareState(state: PoolState, expectedState: PoolState) { describe('QuickPerps Event', function () { const blockNumbers: { [eventName: string]: number[] } = { IncreaseUsdqAmount: [ - 19403150, 19403175, 19403183, 19403215, 19403232, 19403246, 19403344, - 19403484, 19403545, 19403553, 19403586, 19403662, 19403712, 19403721, - 19403757, 19403775, 19403782, 19403800, 19403807, 19403808, 19403826, - 19403844, 19403848, 19403852, 19403860, 19403863, 19403875, 19403877, - 19403885, 19403900, 19403904, 19403938, 19403963, 19403970, 19403973, - 19403978, 19403999, 19404000, 19404023, 19404026, 19404046, 19404056, - 19404060, 19404078, 19404083, 19404097, 19404149, 19404164, 19404178, - 19404182, 19404229, 19404243, 19404264, 19404272, 19404287, 19404347, - 19404378, 19404379, 19404389, 19404408, 19404463, 19404491, 19404560, - 19404625, 19404657, 19404687, 19404700, 19404714, 19404763, 19404889, - 19404892, 19404893, 19404894, 19404897, 19404904, 19404916, 19404917, - 19404927, 19404935, 19404946, 19404949, 19404951, 19404959, 19404973, - 19405017, 19405027, 19405034, + 4960808, 4961034, 4961037, 4961046, 4961052, 4961055, 4961062, 4961153, + 4961167, 4961190, 4961194, 4961215, 4961220, 4961353, 4961472, 4961476, + 4961521, 4961628, 4961629, 4961648, 4961664, 4961683, 4961710, 4961716, + 4961848, 4961853, 4961863, 4961866, 4962156, 4962180, 4962200, 4962296, ], DecreaseUsdqAmount: [ - 19403150, 19403175, 19403183, 19403215, 19403232, 19403246, 19403344, - 19403545, 19403553, 19403662, 19403712, 19403721, 19403757, 19403775, - 19403782, 19403800, 19403807, 19403808, 19403826, 19403844, 19403848, - 19403852, 19403860, 19403863, 19403875, 19403877, 19403885, 19403900, - 19403904, 19403938, 19403963, 19403970, 19403973, 19403978, 19403999, - 19404000, 19404023, 19404026, 19404046, 19404056, 19404060, 19404078, - 19404083, 19404097, 19404149, 19404164, 19404178, 19404182, 19404229, - 19404243, 19404264, 19404272, 19404287, 19404347, 19404378, 19404379, - 19404389, 19404408, 19404463, 19404491, 19404560, 19404625, 19404657, - 19404687, 19404700, 19404714, 19404763, 19404889, 19404892, 19404893, - 19404894, 19404897, 19404904, 19404916, 19404917, 19404927, 19404935, - 19404946, 19404949, 19404951, 19404959, 19404973, 19405017, 19405027, - 19405034, + 4960808, 4960808, 4961034, 4961037, 4961046, 4961052, 4961055, 4961062, + 4961153, 4961167, 4961190, 4961194, 4961215, 4961220, 4961353, 4961472, + 4961476, 4961521, 4961628, 4961629, 4961648, 4961664, 4961683, 4961710, + 4961716, 4961848, 4961853, 4961863, 4961866, 4962156, 4962180, 4962200, + 4962296, ], - Transfer: [19403484, 19403586, 19405046, 19405100, 19405154, 19405318], + Transfer: [4958541, 4959994, 4959998, 4960452, 4960452], PriceUpdate: [ - 19403134, 19403135, 19403140, 19403141, 19403144, 19403148, 19403151, - 19403154, 19403163, 19403169, 19403170, 19403171, 19403178, 19403185, - 19403186, 19403202, + 4960534, 4960569, 4960584, 4960609, 4960637, 4960660, 4960694, 4960700, ], }; describe('QuickPerpsEventPool', function () { + let config: PoolConfig; + let quickPerpsPool: QuickPerpsEventPool; + let blockNumber: number; + beforeAll(async function () { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + + config = await QuickPerpsEventPool.getConfig( + params, + blockNumber, + dexHelper.multiContract, + ); + + quickPerpsPool = new QuickPerpsEventPool( + dexKey, + network, + dexHelper, + logger, + config, + ); + }); Object.keys(blockNumbers).forEach((event: string) => { blockNumbers[event].forEach((blockNumber: number) => { it(`Should return the correct state after the ${blockNumber}:${event}`, async function () { - const dexHelper = new DummyDexHelper(network); - const logger = dexHelper.getLogger(dexKey); - - const config = await QuickPerpsEventPool.getConfig( - params, - blockNumber, - dexHelper.multiContract, - ); - const quickPerpsPool = new QuickPerpsEventPool( - dexKey, - network, - dexHelper, - logger, - config, - ); - await testEventSubscriber( quickPerpsPool, quickPerpsPool.addressesSubscribed, diff --git a/src/dex/quick-perps/quick-perps.ts b/src/dex/quick-perps/quick-perps.ts index f31ba1523..a803741b4 100644 --- a/src/dex/quick-perps/quick-perps.ts +++ b/src/dex/quick-perps/quick-perps.ts @@ -54,9 +54,6 @@ export class QuickPerps extends SimpleExchange implements IDex { this.logger = dexHelper.getLogger(dexKey); } - // Initialize pricing is called once in the start of - // pricing service. It is intended to setup the integration - // for pricing requests. async initializePricing(blockNumber: number) { const config = await QuickPerpsEventPool.getConfig( this.params, diff --git a/src/dex/quick-perps/types.ts b/src/dex/quick-perps/types.ts index 284933bb4..3c52ee327 100644 --- a/src/dex/quick-perps/types.ts +++ b/src/dex/quick-perps/types.ts @@ -1,8 +1,8 @@ import { Address } from '../../types'; -import { ChainLinkState } from '../../lib/chainlink'; +import { Api3FeedSubscriberState } from '../../lib/api3-feed'; export type PoolState = { - primaryPrices: { [poolAddress: string]: ChainLinkState }; + primaryPrices: { [poolAddress: string]: Api3FeedSubscriberState }; secondaryPrices: FastPriceFeedState; vault: VaultState; usdq: USDQState; @@ -53,7 +53,6 @@ export type FastPriceFeedConfig = { }; export type VaultPriceFeedConfig = { - isAmmEnabled: boolean; isSecondaryPriceEnabled: boolean; strictStableTokens: { [address: string]: boolean }; spreadBasisPoints: { [address: string]: bigint }; @@ -61,8 +60,6 @@ export type VaultPriceFeedConfig = { isAdjustmentAdditive: { [address: string]: boolean }; priceDecimals: { [address: string]: number }; maxStrictPriceDeviation: bigint; - useV2Pricing: boolean; - priceSampleSpace: number; }; export type VaultConfig = { @@ -90,5 +87,7 @@ export type PoolConfig = { vaultConfig: VaultConfig; vaultPriceFeedConfig: VaultPriceFeedConfig; fastPriceFeedConfig: FastPriceFeedConfig; - chainlink: { [address: string]: { proxy: Address; aggregator: Address } }; + api3ServerV1: { + [address: string]: { proxy: Address; api3ServerV1: Address }; + }; }; diff --git a/src/dex/quick-perps/vault-price-feed.ts b/src/dex/quick-perps/vault-price-feed.ts index 43a96e7e2..eeff27b08 100644 --- a/src/dex/quick-perps/vault-price-feed.ts +++ b/src/dex/quick-perps/vault-price-feed.ts @@ -1,10 +1,10 @@ import { Interface } from '@ethersproject/abi'; import { Address, MultiCallInput, MultiCallOutput } from '../../types'; -import { PoolState, VaultPriceFeedConfig } from './types'; +import { VaultPriceFeedConfig } from './types'; import { FastPriceFeed } from './fast-price-feed'; import VaultPriceFeedAbi from '../../abi/quick-perps/vault-price-feed.json'; -import { ChainLinkSubscriber } from '../../lib/chainlink'; import { DeepReadonly } from 'ts-essentials'; +import { Api3FeedSubscriber } from '../../lib/api3-feed'; export class VaultPriceFeed { BASIS_POINTS_DIVISOR = 10000n; @@ -13,7 +13,6 @@ export class VaultPriceFeed { static interface = new Interface(VaultPriceFeedAbi); - protected isAmmEnabled: boolean; protected isSecondaryPriceEnabled: boolean; protected strictStableTokens: { [address: string]: boolean }; protected spreadBasisPoints: { [address: string]: bigint }; @@ -21,15 +20,12 @@ export class VaultPriceFeed { protected isAdjustmentAdditive: { [address: string]: boolean }; protected priceDecimals: { [address: string]: number }; protected maxStrictPriceDeviation: bigint; - protected useV2Pricing: boolean; - protected priceSampleSpace: number; constructor( config: VaultPriceFeedConfig, - protected primaryPrices: { [token: string]: ChainLinkSubscriber }, + protected primaryPrices: { [token: string]: Api3FeedSubscriber }, protected secondaryPrice: FastPriceFeed, ) { - this.isAmmEnabled = config.isAmmEnabled; this.isSecondaryPriceEnabled = config.isSecondaryPriceEnabled; this.strictStableTokens = config.strictStableTokens; this.spreadBasisPoints = config.spreadBasisPoints; @@ -37,20 +33,16 @@ export class VaultPriceFeed { this.isAdjustmentAdditive = config.isAdjustmentAdditive; this.priceDecimals = config.priceDecimals; this.maxStrictPriceDeviation = config.maxStrictPriceDeviation; - this.useV2Pricing = config.useV2Pricing; - this.priceSampleSpace = config.priceSampleSpace; } getPrice( state: DeepReadonly, _token: Address, - _maximise: boolean, + _maximize: boolean, _includeAmmPrice: boolean, _useSwapPricing: boolean, ): bigint { - let price = this.useV2Pricing - ? this.getPriceV2(state, _token, _maximise, _includeAmmPrice) - : this.getPriceV1(state, _token, _maximise, _includeAmmPrice); + let price = this.getPriceV1(state, _token, _maximize, _includeAmmPrice); const adjustmentBps = this.adjustmentBasisPoints[_token]; if (adjustmentBps > 0n) { @@ -69,39 +61,16 @@ export class VaultPriceFeed { return price; } - getPriceV2( - state: DeepReadonly, - _token: Address, - _maximise: boolean, - _includeAmmPrice: boolean, - ): bigint { - throw new Error( - 'getPriceV2 implementation is not complete, devs should disable the dex or complete the implementation', - ); - } - getPriceV1( state: DeepReadonly, _token: Address, - _maximise: boolean, + _maximize: boolean, _includeAmmPrice: boolean, ): bigint { - let price = this.getPrimaryPrice(state, _token, _maximise); - - if (_includeAmmPrice && this.isAmmEnabled) { - const ammPrice = this.getAmmPrice(state, _token); - if (ammPrice > 0n) { - if (_maximise && ammPrice > price) { - price = ammPrice; - } - if (!_maximise && ammPrice < price) { - price = ammPrice; - } - } - } + let price = this.getPrimaryPrice(state, _token, _maximize); if (this.isSecondaryPriceEnabled) { - price = this.getSecondaryPrice(state, _token, price, _maximise); + price = this.getSecondaryPrice(state, _token, price, _maximize); } if (this.strictStableTokens[_token]) { @@ -111,13 +80,13 @@ export class VaultPriceFeed { return this.ONE_USD; } - // if _maximise and price is e.g. 1.02, return 1.02 - if (_maximise && price > this.ONE_USD) { + // if _maximize and price is e.g. 1.02, return 1.02 + if (_maximize && price > this.ONE_USD) { return price; } - // if !_maximise and price is e.g. 0.98, return 0.98 - if (!_maximise && price < this.ONE_USD) { + // if !_maximize and price is e.g. 0.98, return 0.98 + if (!_maximize && price < this.ONE_USD) { return price; } @@ -126,7 +95,7 @@ export class VaultPriceFeed { const _spreadBasisPoints = this.spreadBasisPoints[_token]; - if (_maximise) { + if (_maximize) { return ( (price * (this.BASIS_POINTS_DIVISOR + _spreadBasisPoints)) / this.BASIS_POINTS_DIVISOR @@ -141,14 +110,14 @@ export class VaultPriceFeed { getAmmPrice(state: DeepReadonly, token: Address): bigint { throw new Error( - 'getAmmPrice implementation is not complete, devs should disable the dex or complete the implementation', + 'getAmmPrice implementation is not complete, developers should disable the dex or complete the implementation', ); } getPrimaryPrice( state: DeepReadonly, _token: Address, - _maximise: boolean, + _maximize: boolean, ): bigint { // const priceFeedAddress = this.priceFeeds[_token]; // require(priceFeedAddress != address(0), "VaultPriceFeed: invalid price feed"); @@ -185,25 +154,20 @@ export class VaultPriceFeed { // continue; // } - // if (_maximise && p > price) { + // if (_maximize && p > price) { // price = p; // continue; // } - // if (!_maximise && p < price) { + // if (!_maximize && p < price) { // price = p; // } // } - if (this.priceSampleSpace > 1) { - throw new Error( - 'Chainlink price feed is not implemented for historical prices', - ); - } - price = this.primaryPrices[_token].getLatestRoundData(state); + price = this.primaryPrices[_token].getLatestData(state); // require(price > 0n, "VaultPriceFeed: could not fetch price"); if (price <= 0n) throw new Error('VaultPriceFeed: could not fetch price'); - // normalise price precision + // normalize price precision const _priceDecimals = this.priceDecimals[_token]; return (price * this.PRICE_PRECISION) / BigInt(10 ** _priceDecimals); } @@ -212,13 +176,13 @@ export class VaultPriceFeed { state: DeepReadonly, _token: Address, _referencePrice: bigint, - _maximise: boolean, + _maximize: boolean, ): bigint { return this.secondaryPrice.getPrice( state, _token, _referencePrice, - _maximise, + _maximize, ); } @@ -227,10 +191,6 @@ export class VaultPriceFeed { tokenAddresses: Address[], ): MultiCallInput[] { return [ - { - target: vaultPriceFeedAddress, - callData: VaultPriceFeed.interface.encodeFunctionData('isAmmEnabled'), - }, { target: vaultPriceFeedAddress, callData: VaultPriceFeed.interface.encodeFunctionData( @@ -277,15 +237,6 @@ export class VaultPriceFeed { 'maxStrictPriceDeviation', ), }, - { - target: vaultPriceFeedAddress, - callData: VaultPriceFeed.interface.encodeFunctionData('useV2Pricing'), - }, - { - target: vaultPriceFeedAddress, - callData: - VaultPriceFeed.interface.encodeFunctionData('priceSampleSpace'), - }, ]; } @@ -295,10 +246,6 @@ export class VaultPriceFeed { ): VaultPriceFeedConfig { let i = 0; return { - isAmmEnabled: VaultPriceFeed.interface.decodeFunctionResult( - 'isAmmEnabled', - multicallOutputs[i++], - )[0], isSecondaryPriceEnabled: VaultPriceFeed.interface.decodeFunctionResult( 'isSecondaryPriceEnabled', multicallOutputs[i++], @@ -370,15 +317,6 @@ export class VaultPriceFeed { )[0] .toString(), ), - useV2Pricing: VaultPriceFeed.interface.decodeFunctionResult( - 'useV2Pricing', - multicallOutputs[i++], - )[0], - priceSampleSpace: parseInt( - VaultPriceFeed.interface - .decodeFunctionResult('priceSampleSpace', multicallOutputs[i++])[0] - .toString(), - ), }; } } diff --git a/src/lib/api3-feed.ts b/src/lib/api3-feed.ts new file mode 100644 index 000000000..103965360 --- /dev/null +++ b/src/lib/api3-feed.ts @@ -0,0 +1,100 @@ +import { DeepReadonly } from 'ts-essentials'; +import { PartialEventSubscriber } from '../composed-event-subscriber'; +import { + Address, + BlockHeader, + Log, + Logger, + MultiCallInput, + MultiCallOutput, +} from '../types'; +import { Lens } from '../lens'; +import { Interface } from '@ethersproject/abi'; +import ProxyABI from '../abi/api3-proxy.json'; +import Api3ServerV1ABI from '../abi/api3-server-v1.json'; + +export type Api3FeedSubscriberState = { + value: bigint; + timestamp: bigint; +}; + +export class Api3FeedSubscriber extends PartialEventSubscriber< + State, + Api3FeedSubscriberState +> { + static readonly proxyInterface = new Interface(ProxyABI); + static readonly api3ServerV1Iface = new Interface(Api3ServerV1ABI); + static readonly ANSWER_UPDATED_SIGNED_DATA = + Api3FeedSubscriber.api3ServerV1Iface.getEventTopic( + 'UpdatedBeaconWithSignedData', + ); + + constructor( + private proxy: Address, + api3Server: Address, + lens: Lens, DeepReadonly>, + logger: Logger, + ) { + super([api3Server], lens, logger); + } + + static getApi3ServerV1MultiCallInput(proxy: Address): MultiCallInput { + return { + target: proxy, + callData: + Api3FeedSubscriber.proxyInterface.encodeFunctionData('api3ServerV1'), + }; + } + + static decodeApi3ServerV1Result(multicallOutput: MultiCallOutput): Address { + return Api3FeedSubscriber.proxyInterface.decodeFunctionResult( + 'api3ServerV1', + multicallOutput, + )[0]; + } + + public processLog( + state: DeepReadonly, + log: Readonly, + blockHeader: Readonly, + ): DeepReadonly | null { + if (log.topics[0] !== Api3FeedSubscriber.ANSWER_UPDATED_SIGNED_DATA) + return null; // Ignore other events + const decoded = Api3FeedSubscriber.api3ServerV1Iface.decodeEventLog( + 'UpdatedBeaconWithSignedData', + log.data, + log.topics, + ); + return { + value: BigInt(decoded.value.toString()), + timestamp: BigInt(decoded.timestamp.toString()), + }; + } + + public getGenerateStateMultiCallInputs(): MultiCallInput[] { + return [ + { + target: this.proxy, + callData: Api3FeedSubscriber.proxyInterface.encodeFunctionData('read'), + }, + ]; + } + + public generateState( + multicallOutputs: MultiCallOutput[], + blockNumber?: number | 'latest', + ): DeepReadonly { + const decoded = Api3FeedSubscriber.proxyInterface.decodeFunctionResult( + 'read', + multicallOutputs[0], + ); + return { + value: BigInt(decoded.value.toString()), + timestamp: BigInt(decoded.timestamp.toString()), + }; + } + + public getLatestData(state: DeepReadonly): bigint { + return this.lens.get()(state).value; + } +} diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 85df1682c..7f02a8f2f 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -857,6 +857,16 @@ export const Tokens: { decimals: 8, }, }, + [Network.ZKEVM]: { + WETH: { + address: '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9', + decimals: 18, + }, + MATIC: { + address: '0xa2036f0538221a77a3937f1379699f44945018d0', + decimals: 18, + }, + }, }; export const Holders: { @@ -1068,6 +1078,10 @@ export const Holders: { rETH: '0x4c2e69e58b14de9afedfb94319519ce34e087283', WBTC: '0xb9c8f0d3254007ee4b98970b94544e473cd610ec', }, + [Network.ZKEVM]: { + WETH: '0xc44ad482f24fd750caeba387d2726d8653f8c4bb', + MATIC: '0x8f2a1450c040b3c19efe9676165d8f30d8280019', + }, }; export const SmartTokens = Object.keys(Tokens).reduce((acc, _network) => { From ac9751c979502cb95bde7471d543bcb5fa5c1aaa Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 30 Aug 2023 11:17:53 +0300 Subject: [PATCH 173/833] add tests --- src/dex/solidly/forks-override/velodromeV2.ts | 2 +- src/dex/solidly/solidly-e2e.test.ts | 108 +++++++++++++++++- 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/src/dex/solidly/forks-override/velodromeV2.ts b/src/dex/solidly/forks-override/velodromeV2.ts index 45dad7644..8c8405fed 100644 --- a/src/dex/solidly/forks-override/velodromeV2.ts +++ b/src/dex/solidly/forks-override/velodromeV2.ts @@ -4,7 +4,7 @@ import { getDexKeysWithNetwork } from '../../../utils'; import { SolidlyConfig } from '../config'; import _ from 'lodash'; -export class Velodrome extends Solidly { +export class VelodromeV2 extends Solidly { public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork(_.pick(SolidlyConfig, ['VelodromeV2'])); } diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index 86c59fbaa..bf3db1a26 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -2,11 +2,93 @@ import dotenv from 'dotenv'; dotenv.config(); import { testE2E } from '../../../tests/utils-e2e'; -import { Tokens, Holders } from '../../../tests/constants-e2e'; +import { Tokens, Holders, NativeTokenSymbols } from '../../../tests/constants-e2e'; import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + // TODO: Add any direct swap contractMethod name if it exists + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + // TODO: If buy is not supported remove the buy contract methods + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }), + ); + }); +} + describe('Solidly E2E', () => { describe('Fantom', () => { const network = Network.FANTOM; @@ -689,6 +771,29 @@ describe('Solidly E2E', () => { }); }); }); + + describe('VelodromeV2', () => { + const dexKey = 'VelodromeV2'; + + const network = Network.OPTIMISM; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '1100000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); }); describe('BSC', () => { @@ -1275,4 +1380,5 @@ describe('Solidly E2E', () => { ); }); }); + }); From dbe61f04973cb90e27c72a63bdbc5d67018550fb Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 30 Aug 2023 11:37:08 +0300 Subject: [PATCH 174/833] update tests --- src/dex/solidly/solidly-e2e.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index bf3db1a26..93e4e791f 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -34,8 +34,6 @@ function testForNetwork( ContractMethod.megaSwap, ], ], - // TODO: If buy is not supported remove the buy contract methods - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], ]); describe(`${network}`, () => { From b3e81ae63ba7b3f9abe589eee675dea5abb49a48 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 30 Aug 2023 11:40:41 +0300 Subject: [PATCH 175/833] update config --- src/dex/solidly/config.ts | 4 +--- tests/utils-e2e.ts | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index 43b8ff24c..1bed7b08d 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -74,13 +74,11 @@ export const SolidlyConfig: DexConfigMap = { }, VelodromeV2: { [Network.OPTIMISM]: { - subgraphURL: 'https://api.thegraph.com/subgraphs/name/dmihal/velodrome', factoryAddress: '0xF1046053aa5682b4F9a81b5481394DA16BE5FF5a', - router: '0xa062aE8A9c5e11aaA026fc2670B0D65cCc8B2858', + router: '0xa2f581b012E0f2dcCDe86fCbfb529f4aC5dD4983', initCode: '0x1a8f01f7eab324003d9388f229ea17991eee9c9d14586f429799f3656790eba0', poolGasCost: 180 * 1000, - // Variable fees. feeCode: 0, }, }, diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index 12143c4dc..2e454463c 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -368,6 +368,7 @@ export async function testE2E( poolIdentifiers, transferFees, ); + console.log('PRICE ROUTE: ', priceRoute); expect(parseFloat(priceRoute.destAmount)).toBeGreaterThan(0); // Calculate slippage. Default is 1% From 5931d6099291a0cc3dedc6ddce7f89dd4bb5e785 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 30 Aug 2023 09:56:41 +0100 Subject: [PATCH 176/833] 2.31.4-zkevm-revive.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4dbd325ce..2576a08ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.9", + "version": "2.31.4-zkevm-revive.10", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 0bad8193c5e00d5d508ef016b335819727648b7c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 30 Aug 2023 12:39:35 +0300 Subject: [PATCH 177/833] update implementation --- src/dex/solidly/forks-override/velodromeV2.ts | 38 ++++++ src/dex/solidly/solidly-integration.test.ts | 121 ++++++++++++++++++ 2 files changed, 159 insertions(+) diff --git a/src/dex/solidly/forks-override/velodromeV2.ts b/src/dex/solidly/forks-override/velodromeV2.ts index 8c8405fed..05880a9e8 100644 --- a/src/dex/solidly/forks-override/velodromeV2.ts +++ b/src/dex/solidly/forks-override/velodromeV2.ts @@ -3,8 +3,46 @@ import { Network } from '../../../constants'; import { getDexKeysWithNetwork } from '../../../utils'; import { SolidlyConfig } from '../config'; import _ from 'lodash'; +import { Address, PoolLiquidity } from '../../../types'; +import { SolidlyPair } from '../types'; + +const VelodromeFactoryABI = [ + { + inputs: [{ internalType: 'bool', name: '_stable', type: 'bool' }], + name: 'getFee', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, +]; export class VelodromeV2 extends Solidly { public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork(_.pick(SolidlyConfig, ['VelodromeV2'])); + + // there is no subgraph for VelodromeV2 + async getTopPoolsForToken( + tokenAddress: Address, + count: number, + ): Promise { + return []; + } + + protected getFeesMultiCallData(pair: SolidlyPair) { + const callEntry = { + target: this.factoryAddress, + callData: chronosFactoryIface.encodeFunctionData('getFee', [pair.stable]), + }; + const callDecoder = (values: any[]) => + parseInt( + chronosFactoryIface + .decodeFunctionResult('getFee', values)[0] + .toString(), + ); + + return { + callEntry, + callDecoder, + }; + } } diff --git a/src/dex/solidly/solidly-integration.test.ts b/src/dex/solidly/solidly-integration.test.ts index c4d3163e1..bdd94852a 100644 --- a/src/dex/solidly/solidly-integration.test.ts +++ b/src/dex/solidly/solidly-integration.test.ts @@ -14,6 +14,7 @@ import { Cone } from './forks-override/cone'; import { Chronos } from './forks-override/chronos'; import { Ramses } from './forks-override/ramses'; import * as util from 'util'; +import { VelodromeV2 } from './forks-override/velodromeV2'; const amounts18 = [0n, BI_POWS[18], 2000000000000000000n]; const amounts6 = [0n, BI_POWS[6], 2000000n]; @@ -909,4 +910,124 @@ describe('Solidly integration tests', () => { }); }); }); + + describe('Optimism', () => { + const network = Network.OPTIMISM; + const dexHelper = new DummyDexHelper(network); + const checkOnChainPricing = constructCheckOnChainPricing(dexHelper); + + describe('VelodromeV2', () => { + const dexKey = 'VelodromeV2'; + const velodromeV2 = new VelodromeV2(network, dexKey, dexHelper); + + describe('UniswapV2 like pool', function () { + const TokenASymbol = 'USDC'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'WETH'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts18; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await velodromeV2.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await velodromeV2.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + + for (const i in poolPrices || []) { + await checkOnChainPricing( + velodromeV2, + 'getAmountOut', + blocknumber, + poolPrices![i].prices, + poolPrices![i].poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + }); + + describe('Curve like stable pool', function () { + const TokenASymbol = 'USDT'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'USDC'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts6; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await velodromeV2.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await velodromeV2.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + for (const i in poolPrices || []) { + await checkOnChainPricing( + velodromeV2, + 'getAmountOut', + blocknumber, + poolPrices![i].prices, + poolPrices![i].poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + }); + }); + }); }); From 55a12e09459a3f85597e6281353c6bdf7d62079a Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 30 Aug 2023 12:41:02 +0300 Subject: [PATCH 178/833] 2.32.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 30efe6fb0..db50d52e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.6-sushi-v3", + "version": "2.32.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From b8da8dfb4942a6e3a26b28ec41d16408048d8868 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 30 Aug 2023 13:11:00 +0300 Subject: [PATCH 179/833] update implementation --- src/dex/solidly/forks-override/velodromeV2.ts | 41 ++++++++++++++----- src/dex/solidly/solidly-integration.test.ts | 4 +- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/dex/solidly/forks-override/velodromeV2.ts b/src/dex/solidly/forks-override/velodromeV2.ts index 05880a9e8..55849286a 100644 --- a/src/dex/solidly/forks-override/velodromeV2.ts +++ b/src/dex/solidly/forks-override/velodromeV2.ts @@ -5,10 +5,15 @@ import { SolidlyConfig } from '../config'; import _ from 'lodash'; import { Address, PoolLiquidity } from '../../../types'; import { SolidlyPair } from '../types'; +import { Interface } from '@ethersproject/abi'; +import { IDexHelper } from '../../../dex-helper'; -const VelodromeFactoryABI = [ +const VelodromeV2FactoryABI = [ { - inputs: [{ internalType: 'bool', name: '_stable', type: 'bool' }], + inputs: [ + { internalType: 'address', name: 'pool', type: 'address' }, + { internalType: 'bool', name: '_stable', type: 'bool' }, + ], name: 'getFee', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', @@ -16,26 +21,34 @@ const VelodromeFactoryABI = [ }, ]; +const velodromeV2FactoryIface = new Interface(VelodromeV2FactoryABI); + export class VelodromeV2 extends Solidly { + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork(_.pick(SolidlyConfig, ['VelodromeV2'])); - // there is no subgraph for VelodromeV2 - async getTopPoolsForToken( - tokenAddress: Address, - count: number, - ): Promise { - return []; + constructor( + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + ) { + super( + network, + dexKey, + dexHelper, + true, // dynamic fees + ); } protected getFeesMultiCallData(pair: SolidlyPair) { const callEntry = { target: this.factoryAddress, - callData: chronosFactoryIface.encodeFunctionData('getFee', [pair.stable]), + callData: velodromeV2FactoryIface.encodeFunctionData('getFee', [pair.exchange, pair.stable]), }; const callDecoder = (values: any[]) => parseInt( - chronosFactoryIface + velodromeV2FactoryIface .decodeFunctionResult('getFee', values)[0] .toString(), ); @@ -45,4 +58,12 @@ export class VelodromeV2 extends Solidly { callDecoder, }; } + + // there is no subgraph for VelodromeV2 + async getTopPoolsForToken( + tokenAddress: Address, + count: number, + ): Promise { + return []; + } } diff --git a/src/dex/solidly/solidly-integration.test.ts b/src/dex/solidly/solidly-integration.test.ts index bdd94852a..77e70a694 100644 --- a/src/dex/solidly/solidly-integration.test.ts +++ b/src/dex/solidly/solidly-integration.test.ts @@ -928,7 +928,7 @@ describe('Solidly integration tests', () => { const amounts = amounts18; - it('getPoolIdentifiers and getPricesVolume', async function () { + it('getPoolIdentifiers and getPricesVolume SELL', async function () { const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); const pools = await velodromeV2.getPoolIdentifiers( tokenA, @@ -983,7 +983,7 @@ describe('Solidly integration tests', () => { const amounts = amounts6; - it('getPoolIdentifiers and getPricesVolume', async function () { + it('getPoolIdentifiers and getPricesVolume SELL', async function () { const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); const pools = await velodromeV2.getPoolIdentifiers( tokenA, From ce57dc9df69353c2b871e77507f47168a01f3c87 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 30 Aug 2023 13:11:33 +0300 Subject: [PATCH 180/833] rremove console.log --- tests/utils-e2e.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index 2e454463c..12143c4dc 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -368,7 +368,6 @@ export async function testE2E( poolIdentifiers, transferFees, ); - console.log('PRICE ROUTE: ', priceRoute); expect(parseFloat(priceRoute.destAmount)).toBeGreaterThan(0); // Calculate slippage. Default is 1% From 20d05fb608521d675ec4c3f98481325ee4673269 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 30 Aug 2023 13:14:08 +0300 Subject: [PATCH 181/833] 2.32.1-velodrome-v2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index db50d52e9..ea1205884 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.32.0", + "version": "2.32.1-velodrome-v2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From cb2e9a8536995b04fd783b148332f8d301e529c6 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 30 Aug 2023 11:21:56 +0100 Subject: [PATCH 182/833] fix: initialize quickPerps --- src/dex/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dex/index.ts b/src/dex/index.ts index 11302d4c3..9713509cd 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -71,6 +71,7 @@ import { SpiritSwapV3 } from './quickswap/spiritswap-v3'; import { TraderJoeV21 } from './trader-joe-v2.1'; import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3'; import { Algebra } from './algebra/algebra'; +import { QuickPerps } from './quick-perps/quick-perps'; const LegacyDexes = [ CurveV2, @@ -139,6 +140,7 @@ const Dexes = [ MaverickV1, Camelot, SwaapV2, + QuickPerps, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< From d342e6fe8259d1a3c58867e954aab5b484d23878 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 30 Aug 2023 11:23:29 +0100 Subject: [PATCH 183/833] 2.31.4-zkevm-revive.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2576a08ba..f0e0fd5a5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.10", + "version": "2.31.4-zkevm-revive.11", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e766b18a81651afe1970f970887791ce3f6cbd46 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 30 Aug 2023 13:33:04 +0300 Subject: [PATCH 184/833] update --- src/dex/solidly/config.ts | 1 + src/dex/solidly/forks-override/velodromeV2.ts | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index 1bed7b08d..f2bb28d5c 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -74,6 +74,7 @@ export const SolidlyConfig: DexConfigMap = { }, VelodromeV2: { [Network.OPTIMISM]: { + // There is no subgraph for VelodromeV2 factoryAddress: '0xF1046053aa5682b4F9a81b5481394DA16BE5FF5a', router: '0xa2f581b012E0f2dcCDe86fCbfb529f4aC5dD4983', initCode: diff --git a/src/dex/solidly/forks-override/velodromeV2.ts b/src/dex/solidly/forks-override/velodromeV2.ts index 55849286a..c15663cc2 100644 --- a/src/dex/solidly/forks-override/velodromeV2.ts +++ b/src/dex/solidly/forks-override/velodromeV2.ts @@ -58,12 +58,4 @@ export class VelodromeV2 extends Solidly { callDecoder, }; } - - // there is no subgraph for VelodromeV2 - async getTopPoolsForToken( - tokenAddress: Address, - count: number, - ): Promise { - return []; - } } From c8e7dc8f1c8e6d3381275273feb29ec55415838a Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 30 Aug 2023 11:52:02 +0100 Subject: [PATCH 185/833] feat: update adapter addresses for polygon zkevm --- src/config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index 399298705..bac6becaf 100644 --- a/src/config.ts +++ b/src/config.ts @@ -332,8 +332,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { multicallV2Address: '0x6cA478C852DfA8941FC819fDf248606eA04780B6', privateHttpProvider: process.env.HTTP_PROVIDER_1101, adapterAddresses: { - PolygonZkEvmAdapter01: '0x760870be538e7b4E2110e2890473CC17ADB1fdC1', - PolygonZkEvmBuyAdapter: '0x61bFA60A992472869F8d7b4705609A6E0BCf383f', + PolygonZkEvmAdapter01: '0xd63B7691dD98fa89A2ea5e1604700489c585aa7B', + PolygonZkEvmBuyAdapter: '0xe2137168CdA486a2555E16c597905854C84F9127', }, rpcPollingMaxAllowedStateDelayInBlocks: 0, From c010c683a8913fb0b2e6a868a8f403768f702b8c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 30 Aug 2023 14:21:46 +0300 Subject: [PATCH 186/833] 2.33.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ea1205884..3ed144096 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.32.1-velodrome-v2", + "version": "2.33.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From d9dcfe300e1ee8040d98280fb5e1bafa548f77fe Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 30 Aug 2023 14:31:26 +0300 Subject: [PATCH 187/833] add fixes --- src/dex/solidly/solidly.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/dex/solidly/solidly.ts b/src/dex/solidly/solidly.ts index 11a32031f..899acd50f 100644 --- a/src/dex/solidly/solidly.ts +++ b/src/dex/solidly/solidly.ts @@ -128,6 +128,8 @@ export class Solidly extends UniswapV2 { routerAddress !== undefined ? routerAddress : SolidlyConfig[dexKey][network].router || ''; + + this.feeFactor = SolidlyConfig[dexKey][network].feeFactor || this.feeFactor; } async findSolidlyPair(from: Token, to: Token, stable: boolean) { @@ -429,8 +431,13 @@ export class Solidly extends UniswapV2 { ): Promise { if (!this.subgraphURL) return []; - const stableFieldKey = - this.dexKey.toLowerCase() === 'solidly' ? 'stable' : 'isStable'; + let stableFieldKey = ''; + + if (this.dexKey.toLowerCase() === 'solidly') { + stableFieldKey = 'stable'; + } else if (this.dexKey.toLowerCase() !== 'solidlyv2') { + stableFieldKey = 'isStable'; + } const query = `query ($token: Bytes!, $count: Int) { pools0: pairs(first: $count, orderBy: reserveUSD, orderDirection: desc, where: {token0: $token, reserve0_gt: 1, reserve1_gt: 1}) { @@ -516,6 +523,7 @@ export class Solidly extends UniswapV2 { const pair = await this.findSolidlyPair(from, to, stable); if (!(pair && pair.pool && pair.exchange)) return null; const pairState = pair.pool.getState(blockNumber); + if (!pairState) { this.logger.error( `Error_orderPairParams expected reserves, got none (maybe the pool doesn't exist) ${ From 5f1d708cac51aca35098cc8d36c8ac9464b9182f Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 30 Aug 2023 12:58:10 +0100 Subject: [PATCH 188/833] fix: move quickswap instance initializer inside test function --- .../quick-perps/quick-perps-events.test.ts | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/dex/quick-perps/quick-perps-events.test.ts b/src/dex/quick-perps/quick-perps-events.test.ts index 020db0ab7..f3d4999e2 100644 --- a/src/dex/quick-perps/quick-perps-events.test.ts +++ b/src/dex/quick-perps/quick-perps-events.test.ts @@ -42,10 +42,11 @@ function compareState(state: PoolState, expectedState: PoolState) { describe('QuickPerps Event', function () { const blockNumbers: { [eventName: string]: number[] } = { IncreaseUsdqAmount: [ - 4960808, 4961034, 4961037, 4961046, 4961052, 4961055, 4961062, 4961153, - 4961167, 4961190, 4961194, 4961215, 4961220, 4961353, 4961472, 4961476, - 4961521, 4961628, 4961629, 4961648, 4961664, 4961683, 4961710, 4961716, - 4961848, 4961853, 4961863, 4961866, 4962156, 4962180, 4962200, 4962296, + 4960808, 4960808, 4961034, 4961037, 4961046, 4961052, 4961055, 4961062, + 4961153, 4961167, 4961190, 4961194, 4961215, 4961220, 4961353, 4961472, + 4961476, 4961521, 4961628, 4961629, 4961648, 4961664, 4961683, 4961710, + 4961716, 4961848, 4961853, 4961863, 4961866, 4962156, 4962180, 4962200, + 4962296, ], DecreaseUsdqAmount: [ 4960808, 4960808, 4961034, 4961037, 4961046, 4961052, 4961055, 4961062, @@ -72,18 +73,17 @@ describe('QuickPerps Event', function () { blockNumber, dexHelper.multiContract, ); - - quickPerpsPool = new QuickPerpsEventPool( - dexKey, - network, - dexHelper, - logger, - config, - ); }); Object.keys(blockNumbers).forEach((event: string) => { blockNumbers[event].forEach((blockNumber: number) => { it(`Should return the correct state after the ${blockNumber}:${event}`, async function () { + quickPerpsPool = new QuickPerpsEventPool( + dexKey, + network, + dexHelper, + logger, + config, + ); await testEventSubscriber( quickPerpsPool, quickPerpsPool.addressesSubscribed, From 63a0ef95f54cf1699c902bf7b29ff339d28eb56e Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 30 Aug 2023 13:43:22 +0100 Subject: [PATCH 189/833] test: create EstimateGas simulator for zkEVM --- src/dex/quick-perps/quick-perps-e2e.test.ts | 38 ++++------------ tests/constants-e2e.ts | 5 +++ tests/tenderly-simulation.ts | 48 ++++++++++++++++++++- tests/utils-e2e.ts | 28 +++++++----- 4 files changed, 77 insertions(+), 42 deletions(-) diff --git a/src/dex/quick-perps/quick-perps-e2e.test.ts b/src/dex/quick-perps/quick-perps-e2e.test.ts index f4a72acf8..43bb516a8 100644 --- a/src/dex/quick-perps/quick-perps-e2e.test.ts +++ b/src/dex/quick-perps/quick-perps-e2e.test.ts @@ -23,13 +23,11 @@ describe('QuickPerps E2E', () => { network, ); - const tokenASymbol: string = 'WETH'; + const tokenASymbol: string = 'ETH'; const tokenBSymbol: string = 'MATIC'; - const nativeTokenSymbol = NativeTokenSymbols[network]; const tokenAAmount: string = '100000000000000000'; const tokenBAmount: string = '10000000000000000000'; - const nativeTokenAmount = '1000000000000000000'; const sideToContractMethods = new Map([ [ @@ -45,33 +43,7 @@ describe('QuickPerps E2E', () => { sideToContractMethods.forEach((contractMethods, side) => contractMethods.forEach((contractMethod: ContractMethod) => { describe(`${contractMethod}`, () => { - it(nativeTokenSymbol + ' -> TOKEN', async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it('TOKEN -> ' + nativeTokenSymbol, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it('TOKEN -> TOKEN', async () => { + it('ETH -> MATIC', async () => { await testE2E( tokens[tokenASymbol], tokens[tokenBSymbol], @@ -82,6 +54,12 @@ describe('QuickPerps E2E', () => { contractMethod, network, provider, + undefined, + undefined, + undefined, + undefined, + undefined, + true, ); }); }); diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 7f02a8f2f..e86553f32 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -858,6 +858,10 @@ export const Tokens: { }, }, [Network.ZKEVM]: { + ETH: { + address: ETHER_ADDRESS, + decimals: 18, + }, WETH: { address: '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9', decimals: 18, @@ -1079,6 +1083,7 @@ export const Holders: { WBTC: '0xb9c8f0d3254007ee4b98970b94544e473cd610ec', }, [Network.ZKEVM]: { + ETH: '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9', WETH: '0xc44ad482f24fd750caeba387d2726d8653f8c4bb', MATIC: '0x8f2a1450c040b3c19efe9676165d8f30d8280019', }, diff --git a/tests/tenderly-simulation.ts b/tests/tenderly-simulation.ts index f24bbda98..1d845b5ac 100644 --- a/tests/tenderly-simulation.ts +++ b/tests/tenderly-simulation.ts @@ -1,5 +1,7 @@ +/* eslint-disable no-console */ import axios from 'axios'; import { Address } from '@paraswap/core'; +import { Provider } from '@ethersproject/providers'; import { TxObject } from '../src/types'; import { StateOverrides, StateSimulateApiOverride } from './smart-tokens'; @@ -9,7 +11,50 @@ const TENDERLY_PROJECT = process.env.TENDERLY_PROJECT; const TENDERLY_FORK_ID = process.env.TENDERLY_FORK_ID; const TENDERLY_FORK_LAST_TX_ID = process.env.TENDERLY_FORK_LAST_TX_ID; -export class TenderlySimulation { +export type SimulationResult = { + success: boolean; + gasUsed?: string; + url?: string; + transaction?: any; +}; + +export interface TransactionSimulator { + forkId: string; + setup(): Promise; + + simulate( + params: TxObject, + stateOverrides?: StateOverrides, + ): Promise; +} + +export class EstimateGasSimulation implements TransactionSimulator { + forkId: string = '0'; + + constructor(private provider: Provider) {} + + async setup() {} + + async simulate( + params: TxObject, + _: StateOverrides, + ): Promise { + try { + const result = await this.provider.estimateGas(params); + return { + success: true, + gasUsed: result.toNumber().toString(), + }; + } catch (e) { + console.error(`Estimate gas simulation failed:`, e); + return { + success: false, + }; + } + } +} + +export class TenderlySimulation implements TransactionSimulator { lastTx: string = ''; forkId: string = ''; maxGasLimit = 80000000; @@ -118,7 +163,6 @@ export class TenderlySimulation { console.error(`TenderlySimulation_simulate:`, e); return { success: false, - tenderlyUrl: '', }; } } diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index 12143c4dc..ca5e068df 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -5,7 +5,11 @@ import { IParaSwapSDK, LocalParaswapSDK, } from '../src/implementations/local-paraswap-sdk'; -import { TenderlySimulation } from './tenderly-simulation'; +import { + EstimateGasSimulation, + TenderlySimulation, + TransactionSimulator, +} from './tenderly-simulation'; import { SwapSide, ETHER_ADDRESS, @@ -24,7 +28,7 @@ import { import Erc20ABI from '../src/abi/erc20.json'; import AugustusABI from '../src/abi/augustus.json'; import { generateConfig } from '../src/config'; -import { DummyLimitOrderProvider } from '../src/dex-helper'; +import { DummyDexHelper, DummyLimitOrderProvider } from '../src/dex-helper'; import { constructSimpleSDK, SimpleFetchSDK } from '@paraswap/sdk'; import axios from 'axios'; import { SmartToken, StateOverrides } from './smart-tokens'; @@ -268,16 +272,20 @@ export async function testE2E( // Specified in BPS: part of 10000 slippage?: number, sleepMs?: number, + replaceTenderlyWithEstimateGas?: boolean, ) { const amount = BigInt(_amount); - const ts = new TenderlySimulation(network); + + const ts: TransactionSimulator = replaceTenderlyWithEstimateGas + ? new EstimateGasSimulation(new DummyDexHelper(network).provider) + : new TenderlySimulation(network); await ts.setup(); if (srcToken.address.toLowerCase() !== ETHER_ADDRESS.toLowerCase()) { const allowanceTx = await ts.simulate( allowTokenTransferProxyParams(srcToken.address, senderAddress, network), ); - if (!allowanceTx.success) console.log(allowanceTx.tenderlyUrl); + if (!allowanceTx.success) console.log(allowanceTx.url); expect(allowanceTx!.success).toEqual(true); } @@ -309,7 +317,7 @@ export async function testE2E( expect(deployTx.success).toEqual(true); const contractAddress = - deployTx.transaction.transaction_info.contract_address; + deployTx.transaction?.transaction_info.contract_address; console.log( formatDeployMessage( 'adapter', @@ -384,15 +392,15 @@ export async function testE2E( const swapTx = await ts.simulate(swapParams); // Only log gas estimate if testing against API - if (useAPI) + if (useAPI) { + const gasUsed = swapTx.gasUsed || '0'; console.log( `Gas Estimate API: ${priceRoute.gasCost}, Simulated: ${ swapTx!.gasUsed - }, Difference: ${ - parseInt(priceRoute.gasCost) - parseInt(swapTx!.gasUsed) - }`, + }, Difference: ${parseInt(priceRoute.gasCost) - parseInt(gasUsed)}`, ); - console.log(`Tenderly URL: ${swapTx!.tenderlyUrl}`); + } + console.log(`Tenderly URL: ${swapTx!.url}`); expect(swapTx!.success).toEqual(true); } finally { if (paraswap.releaseResources) { From fea02932491ea059c630a85cf930b821e4dfacf0 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 30 Aug 2023 15:06:40 +0100 Subject: [PATCH 190/833] fix: add logger when generateState fails --- src/composed-event-subscriber.ts | 27 ++++++++++++++++----------- src/dex/quick-perps/pool.ts | 5 +++-- src/dex/quick-perps/quick-perps.ts | 1 - 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/composed-event-subscriber.ts b/src/composed-event-subscriber.ts index 0a7d15d28..fb18ed88d 100644 --- a/src/composed-event-subscriber.ts +++ b/src/composed-event-subscriber.ts @@ -110,17 +110,22 @@ export abstract class ComposedEventSubscriber< .call({}, blockNumber) ).returnData; } - const stateParts = await Promise.all( - this.parts.map((p, i) => - p.generateState( - returnData.slice(...this.multiCallSlices[i]), - blockNumber, + try { + const stateParts = await Promise.all( + this.parts.map((p, i) => + p.generateState( + returnData.slice(...this.multiCallSlices[i]), + blockNumber, + ), ), - ), - ); - return this.parts.reduce( - (acc, p, i) => p.lens.set(stateParts[i])(acc), - this.blankState, - ); + ); + return this.parts.reduce( + (acc, p, i) => p.lens.set(stateParts[i])(acc), + this.blankState, + ); + } catch (e) { + this.logger.error(`Error generating state: ${e}`); + throw e; + } } } diff --git a/src/dex/quick-perps/pool.ts b/src/dex/quick-perps/pool.ts index 7d641706e..c6ddf02c0 100644 --- a/src/dex/quick-perps/pool.ts +++ b/src/dex/quick-perps/pool.ts @@ -26,7 +26,6 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { parentName: string, protected network: number, protected dexHelper: IDexHelper, - logger: Logger, config: PoolConfig, ) { const api3ServerV1Map = Object.entries(config.api3ServerV1).reduce( @@ -38,7 +37,9 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { value.proxy, value.api3ServerV1, lens>().primaryPrices[key], - dexHelper.getLogger(`${key} ChainLink for ${parentName}-${network}`), + dexHelper.getLogger( + `${key} Api3FeedSubscriber for ${parentName}-${network}`, + ), ); return acc; }, diff --git a/src/dex/quick-perps/quick-perps.ts b/src/dex/quick-perps/quick-perps.ts index a803741b4..ac0e4e0c3 100644 --- a/src/dex/quick-perps/quick-perps.ts +++ b/src/dex/quick-perps/quick-perps.ts @@ -67,7 +67,6 @@ export class QuickPerps extends SimpleExchange implements IDex { this.dexKey, this.network, this.dexHelper, - this.logger, config, ); await this.pool.initialize(blockNumber); From 026bddad899ba29b2d3ab7ecb308d5b69cc89a63 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 30 Aug 2023 15:08:42 +0100 Subject: [PATCH 191/833] 2.31.4-zkevm-revive.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f0e0fd5a5..ebf0924fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.11", + "version": "2.31.4-zkevm-revive.12", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e8e24ea665c6a2d1cb9357ba2479c3a26b61a886 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 30 Aug 2023 18:14:49 +0100 Subject: [PATCH 192/833] feat: WIP adding dapiNameHash to beaconId --- src/abi/api3-proxy.json | 13 +++ src/dex/quick-perps/pool.ts | 27 +++++-- src/dex/quick-perps/quick-perps-e2e.test.ts | 6 +- .../quick-perps-integration.test.ts | 79 +++++++++++++------ src/dex/quick-perps/types.ts | 6 +- src/lib/api3-feed.ts | 32 ++++++++ tests/constants-e2e.ts | 10 +++ 7 files changed, 136 insertions(+), 37 deletions(-) diff --git a/src/abi/api3-proxy.json b/src/abi/api3-proxy.json index a9b902bca..c4bb9ab9d 100644 --- a/src/abi/api3-proxy.json +++ b/src/abi/api3-proxy.json @@ -12,6 +12,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "dapiNameHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "read", diff --git a/src/dex/quick-perps/pool.ts b/src/dex/quick-perps/pool.ts index c6ddf02c0..6c90b8baa 100644 --- a/src/dex/quick-perps/pool.ts +++ b/src/dex/quick-perps/pool.ts @@ -280,11 +280,13 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { let multiCallData: MultiCallInput[] = []; let i = 0; for (let priceFeed of priceFeeds) { - const chainlinkConfigCallData = + const api3ServerAddressCallData = Api3FeedSubscriber.getApi3ServerV1MultiCallInput(priceFeed); - multiCallData.push(chainlinkConfigCallData); - multicallSlices.push([i, i + 1]); - i += 1; + const dapiNameHashCallData = + Api3FeedSubscriber.getApi3ServerV1MultiCallInput(priceFeed); + multiCallData.push(...[api3ServerAddressCallData, dapiNameHashCallData]); + multicallSlices.push([i, i + 2]); + i += 2; } const fastPriceFeedConfigCallData = FastPriceFeed.getConfigMulticallInputs( @@ -314,15 +316,24 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { ).returnData; const api3ServerV1: { - [address: string]: { proxy: Address; api3ServerV1: Address }; + [address: string]: { + proxy: Address; + api3ServerV1: Address; + dapiNameHash: string; + }; } = {}; for (let token of tokens) { - const serverV1Address = Api3FeedSubscriber.decodeApi3ServerV1Result( - configResults.slice(...multicallSlices.shift()!)[0], + const [api3ServerAddressRes, dapiHashNameRes] = configResults.slice( + ...multicallSlices.shift()!, ); + const serverV1Address = + Api3FeedSubscriber.decodeApi3ServerV1Result(api3ServerAddressRes); + const dapiNameHash = + Api3FeedSubscriber.decodeApi3ServerV1Result(dapiHashNameRes); api3ServerV1[token] = { proxy: priceFeeds.shift(), api3ServerV1: serverV1Address, + dapiNameHash, }; } @@ -345,6 +356,8 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { const vaultConfigResults = configResults.slice(...multicallSlices.shift()!); const vaultConfig = Vault.getConfig(vaultConfigResults, tokens); + const beeconIdMulticall = + return { vaultAddress: dexParams.vault, readerAddress: dexParams.reader, diff --git a/src/dex/quick-perps/quick-perps-e2e.test.ts b/src/dex/quick-perps/quick-perps-e2e.test.ts index 43bb516a8..6d42bdf0d 100644 --- a/src/dex/quick-perps/quick-perps-e2e.test.ts +++ b/src/dex/quick-perps/quick-perps-e2e.test.ts @@ -2,11 +2,7 @@ import dotenv from 'dotenv'; dotenv.config(); import { testE2E } from '../../../tests/utils-e2e'; -import { - Tokens, - Holders, - NativeTokenSymbols, -} from '../../../tests/constants-e2e'; +import { Tokens, Holders } from '../../../tests/constants-e2e'; import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; diff --git a/src/dex/quick-perps/quick-perps-integration.test.ts b/src/dex/quick-perps/quick-perps-integration.test.ts index 28e243a78..e45db84c5 100644 --- a/src/dex/quick-perps/quick-perps-integration.test.ts +++ b/src/dex/quick-perps/quick-perps-integration.test.ts @@ -16,32 +16,19 @@ import { Tokens } from '../../../tests/constants-e2e'; import ReaderABI from '../../abi/quick-perps/reader.json'; const network = Network.ZKEVM; -const TokenASymbol = 'WETH'; -const TokenA = Tokens[network][TokenASymbol]; - -const TokenBSymbol = 'MATIC'; -const TokenB = Tokens[network][TokenBSymbol]; - -const amounts = [ - 0n, - 100000000000000000n, - 200000000000000000n, - 300000000000000000n, - 400000000000000000n, - 500000000000000000n, - 600000000000000000n, - 700000000000000000n, - 800000000000000000n, - 900000000000000000n, - 1000000000000000000n, -]; - const dexKey = 'QuickPerps'; const params = QuickPerpsConfig[dexKey][network]; const readerInterface = new Interface(ReaderABI); const readerAddress = '0xf1CFB75854DE535475B88Bb6FBad317eea98c0F9'; -describe('QuickPerps', function () { +function testsForCase( + tokenASymbol: string, + tokenBSymbol: string, + amounts: bigint[], +) { + const TokenA = Tokens[network][tokenASymbol]; + const TokenB = Tokens[network][tokenBSymbol]; + it('getPoolIdentifiers and getPricesVolume SELL', async function () { const dexHelper = new DummyDexHelper(network); const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); @@ -55,7 +42,7 @@ describe('QuickPerps', function () { SwapSide.SELL, blocknumber, ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + console.log(`${tokenASymbol} <> ${tokenBSymbol} Pool Identifiers: `, pools); expect(pools.length).toBeGreaterThan(0); @@ -67,7 +54,7 @@ describe('QuickPerps', function () { blocknumber, pools, ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + console.log(`${tokenASymbol} <> ${tokenBSymbol} Pool Prices: `, poolPrices); expect(poolPrices).not.toBeNull(); if (quickPerps.hasConstantPriceLargeAmounts) { @@ -111,7 +98,7 @@ describe('QuickPerps', function () { 10, ); console.log( - `${TokenASymbol} Top Pools:`, + `${tokenASymbol} Top Pools:`, JSON.stringify(poolLiquidity, null, 2), ); @@ -119,4 +106,48 @@ describe('QuickPerps', function () { checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); } }); +} + +describe('QuickPerps', function () { + describe('WETH -> MATIC', function () { + const TokenASymbol = 'WETH'; + const TokenBSymbol = 'MATIC'; + + const amounts = [ + 0n, + 100000000000000000n, + 200000000000000000n, + 300000000000000000n, + 400000000000000000n, + 500000000000000000n, + 600000000000000000n, + 700000000000000000n, + 800000000000000000n, + 900000000000000000n, + 1000000000000000000n, + ]; + + testsForCase(TokenASymbol, TokenBSymbol, amounts); + }); + + describe('WBTC -> USDC', function () { + const TokenASymbol = 'WBTC'; + const TokenBSymbol = 'USDC'; + + const amounts = [ + 0n, + 100000000n, + 200000000n, + 300000000n, + 400000000n, + 500000000n, + 600000000n, + 700000000n, + 800000000n, + 900000000n, + 1000000000n, + ]; + + testsForCase(TokenASymbol, TokenBSymbol, amounts); + }); }); diff --git a/src/dex/quick-perps/types.ts b/src/dex/quick-perps/types.ts index 3c52ee327..6bf52114a 100644 --- a/src/dex/quick-perps/types.ts +++ b/src/dex/quick-perps/types.ts @@ -88,6 +88,10 @@ export type PoolConfig = { vaultPriceFeedConfig: VaultPriceFeedConfig; fastPriceFeedConfig: FastPriceFeedConfig; api3ServerV1: { - [address: string]: { proxy: Address; api3ServerV1: Address }; + [address: string]: { + proxy: Address; + api3ServerV1: Address; + beaconId: string; + }; }; }; diff --git a/src/lib/api3-feed.ts b/src/lib/api3-feed.ts index 103965360..44fb76826 100644 --- a/src/lib/api3-feed.ts +++ b/src/lib/api3-feed.ts @@ -32,6 +32,7 @@ export class Api3FeedSubscriber extends PartialEventSubscriber< constructor( private proxy: Address, api3Server: Address, + private beaconId: string, lens: Lens, DeepReadonly>, logger: Logger, ) { @@ -46,6 +47,30 @@ export class Api3FeedSubscriber extends PartialEventSubscriber< }; } + static getDapiNameHash(proxy: Address): MultiCallInput { + return { + target: proxy, + callData: + Api3FeedSubscriber.proxyInterface.encodeFunctionData('dapiNameHash'), + }; + } + + static getFeedIdFromDapiNameHash(api3Server: string, dapiNameHash: string) { + return { + target: api3Server, + callData: Api3FeedSubscriber.api3ServerV1Iface.encodeFunctionData( + 'dapiNameHashToDataFeedId', + ), + }; + } + + static decodeFeedIdFromDapiNameHash(multicallOutput: MultiCallOutput) { + return Api3FeedSubscriber.proxyInterface.decodeFunctionResult( + 'dapiNameHashToDataFeedId', + multicallOutput, + )[0]; + } + static decodeApi3ServerV1Result(multicallOutput: MultiCallOutput): Address { return Api3FeedSubscriber.proxyInterface.decodeFunctionResult( 'api3ServerV1', @@ -53,6 +78,13 @@ export class Api3FeedSubscriber extends PartialEventSubscriber< )[0]; } + static decodeDapiNameHash(multicallOutput: MultiCallOutput): Address { + return Api3FeedSubscriber.proxyInterface.decodeFunctionResult( + 'dapiNameHash', + multicallOutput, + )[0]; + } + public processLog( state: DeepReadonly, log: Readonly, diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 2deaae8ac..6f0bddf55 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -870,6 +870,14 @@ export const Tokens: { address: '0xa2036f0538221a77a3937f1379699f44945018d0', decimals: 18, }, + WBTC: { + address: '0xea034fb02eb1808c2cc3adbc15f447b93cbe08e1', + decimals: 8, + }, + USDC: { + address: '0xa8ce8aee21bc2a48a5ef670afcc9274c7bbbc035', + decimals: 6, + }, }, }; @@ -1086,6 +1094,8 @@ export const Holders: { ETH: '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9', WETH: '0xc44ad482f24fd750caeba387d2726d8653f8c4bb', MATIC: '0x8f2a1450c040b3c19efe9676165d8f30d8280019', + WBTC: '0x99b31498b0a1dae01fc3433e3cb60f095340935c', + USDC: '0x99b31498b0a1dae01fc3433e3cb60f095340935c', }, }; From 6ad533ffe98030c0fdc24d61855aeb1317b3cc5a Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Wed, 30 Aug 2023 20:54:41 +0100 Subject: [PATCH 193/833] chore: add error checks for rfq amounts --- src/dex/dexalot/dexalot.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index a9e9915e4..250d79c97 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -509,6 +509,17 @@ export class Dexalot extends SimpleExchange implements IDex { order.takerAsset.toLowerCase() === takerToken.address, `QuoteData takerAsset=${order.takerAsset} is different from Paraswap takerAsset=${takerToken.address}`, ); + if (side === SwapSide.SELL) { + assert( + order.takerAmount === optimalSwapExchange.srcAmount, + `QuoteData takerAmount=${order.takerAmount} is different from Paraswap srcAmount=${optimalSwapExchange.srcAmount}`, + ); + } else { + assert( + order.makerAmount === optimalSwapExchange.destAmount, + `QuoteData makerAmount=${order.makerAmount} is different from Paraswap destAmount=${optimalSwapExchange.destAmount}`, + ); + } const expiryAsBigInt = BigInt(order.expiry); const minDeadline = expiryAsBigInt > 0 ? expiryAsBigInt : BI_MAX_UINT256; @@ -528,7 +539,7 @@ export class Dexalot extends SimpleExchange implements IDex { } } else { if ( - BigInt(order.takerAmount) < + BigInt(order.takerAmount) > BigInt( new BigNumber(optimalSwapExchange.srcAmount) .times(slippageFactor) From 8dbb211d3b723a39523532a8a7082dbd2a734bfb Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Wed, 30 Aug 2023 20:56:36 +0100 Subject: [PATCH 194/833] chore: add buy side --- src/dex/dexalot/dexalot-e2e.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dex/dexalot/dexalot-e2e.test.ts b/src/dex/dexalot/dexalot-e2e.test.ts index 7c0c4a1ae..59a872f47 100644 --- a/src/dex/dexalot/dexalot-e2e.test.ts +++ b/src/dex/dexalot/dexalot-e2e.test.ts @@ -33,6 +33,7 @@ function testForNetwork( const sideToContractMethods = new Map([ [SwapSide.SELL, [ContractMethod.simpleSwap]], + [SwapSide.BUY, [ContractMethod.simpleBuy]], ]); describe(`${network}`, () => { From 3986835a78963930e56fcc187b6711cac1bbc641 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 31 Aug 2023 13:15:58 +0300 Subject: [PATCH 195/833] add tests --- src/dex/solidly/config.ts | 9 +- src/dex/solidly/solidly-e2e.test.ts | 23 ++++ src/dex/solidly/solidly-integration.test.ts | 115 ++++++++++++++++++++ 3 files changed, 140 insertions(+), 7 deletions(-) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index f1fe91653..b18dba6d7 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -150,16 +150,11 @@ export const SolidlyConfig: DexConfigMap = { }, Equalizer: { [Network.FANTOM]: { - subgraphURL: '',//'https://api.thegraph.com/subgraphs/name/ftm1337/equalizer-subgraph-1',//inactive factoryAddress: '0xc6366EFD0AF1d09171fe0EBF32c7943BB310832a', - router: '0x1A05EB736873485655F29a37DEf8a0AA87F5a447', + router: '0x93d2611EB8b85bE4FDEa9D94Ce9913D90072eC0f', initCode: '0x02ada2a0163cd4f7e0f0c9805f5230716a95b174140e4c84c14883de216cc6a3', - // updatable fees on the factory without event - //stableFee: 2, - //volatileFee: 20, - //feeCode: 2, - feeCode: 0, // variable + feeCode: 0, poolGasCost: 180 * 1000, }, }, diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index 93e4e791f..96bb9796f 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -389,6 +389,29 @@ describe('Solidly E2E', () => { }); }); }); + + describe('Equalizer', () => { + const dexKey = 'Equalizer'; + const network = Network.FANTOM; + + const tokenASymbol: string = 'FUSDT'; + const tokenBSymbol: string = 'USDC'; + + const tokenAAmount: string = '111110'; + const tokenBAmount: string = '100000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + + }); }); describe('Mainnet', () => { diff --git a/src/dex/solidly/solidly-integration.test.ts b/src/dex/solidly/solidly-integration.test.ts index 77e70a694..629fa1025 100644 --- a/src/dex/solidly/solidly-integration.test.ts +++ b/src/dex/solidly/solidly-integration.test.ts @@ -15,6 +15,7 @@ import { Chronos } from './forks-override/chronos'; import { Ramses } from './forks-override/ramses'; import * as util from 'util'; import { VelodromeV2 } from './forks-override/velodromeV2'; +import { Equalizer } from './forks-override/equalizer'; const amounts18 = [0n, BI_POWS[18], 2000000000000000000n]; const amounts6 = [0n, BI_POWS[6], 2000000n]; @@ -353,6 +354,120 @@ describe('Solidly integration tests', () => { }); }); }); + + describe('Equalizer', () => { + const dexKey = 'Equalizer'; + const equalizer = new Equalizer(network, dexKey, dexHelper); + + describe('UniswapV2 like pool', function () { + const TokenASymbol = 'WFTM'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'FUSDT'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts18; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await equalizer.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await equalizer.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + + for (const i in poolPrices || []) { + await checkOnChainPricing( + equalizer, + 'getAmountOut', + blocknumber, + poolPrices![i].prices, + poolPrices![i].poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + }); + + describe('Curve like stable pool', function () { + const TokenASymbol = 'FUSDT'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'USDC'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts6; // amounts6; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await equalizer.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await equalizer.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + for (const i in poolPrices || []) { + await checkOnChainPricing( + equalizer, + 'getAmountOut', + blocknumber, + poolPrices![i].prices, + poolPrices![i].poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + }); + }); }); describe('Polygon', () => { From fba865acff11976f21dbc1d223778e2efee8708c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 31 Aug 2023 13:17:57 +0300 Subject: [PATCH 196/833] 2.33.1-equalizer --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ed144096..151015786 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.33.0", + "version": "2.33.1-equalizer", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 0a818755d38ec1d29ffad40728470ae1306fb6c9 Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 31 Aug 2023 11:26:10 +0100 Subject: [PATCH 197/833] fix: use dataFeedId to filter irrelevant events --- src/abi/api3-proxy.json | 2 +- src/dex/quick-perps/pool.ts | 17 ++++----- src/dex/quick-perps/types.ts | 2 +- src/lib/api3-feed.ts | 72 ++++++++++++++++++++---------------- 4 files changed, 49 insertions(+), 44 deletions(-) diff --git a/src/abi/api3-proxy.json b/src/abi/api3-proxy.json index c4bb9ab9d..41ce3c43e 100644 --- a/src/abi/api3-proxy.json +++ b/src/abi/api3-proxy.json @@ -14,7 +14,7 @@ }, { "inputs": [], - "name": "dapiNameHash", + "name": "dataFeedId", "outputs": [ { "internalType": "bytes32", diff --git a/src/dex/quick-perps/pool.ts b/src/dex/quick-perps/pool.ts index 6c90b8baa..8b922b236 100644 --- a/src/dex/quick-perps/pool.ts +++ b/src/dex/quick-perps/pool.ts @@ -36,6 +36,7 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { acc[key] = new Api3FeedSubscriber( value.proxy, value.api3ServerV1, + value.dataFeedId, lens>().primaryPrices[key], dexHelper.getLogger( `${key} Api3FeedSubscriber for ${parentName}-${network}`, @@ -282,9 +283,8 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { for (let priceFeed of priceFeeds) { const api3ServerAddressCallData = Api3FeedSubscriber.getApi3ServerV1MultiCallInput(priceFeed); - const dapiNameHashCallData = - Api3FeedSubscriber.getApi3ServerV1MultiCallInput(priceFeed); - multiCallData.push(...[api3ServerAddressCallData, dapiNameHashCallData]); + const dataFeedIdCallData = Api3FeedSubscriber.getDataFeedId(priceFeed); + multiCallData.push(...[api3ServerAddressCallData, dataFeedIdCallData]); multicallSlices.push([i, i + 2]); i += 2; } @@ -319,21 +319,20 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { [address: string]: { proxy: Address; api3ServerV1: Address; - dapiNameHash: string; + dataFeedId: string; }; } = {}; for (let token of tokens) { - const [api3ServerAddressRes, dapiHashNameRes] = configResults.slice( + const [api3ServerAddressRes, dataFeedIdRes] = configResults.slice( ...multicallSlices.shift()!, ); const serverV1Address = Api3FeedSubscriber.decodeApi3ServerV1Result(api3ServerAddressRes); - const dapiNameHash = - Api3FeedSubscriber.decodeApi3ServerV1Result(dapiHashNameRes); + const dataFeedId = Api3FeedSubscriber.decodeDataFeedId(dataFeedIdRes); api3ServerV1[token] = { proxy: priceFeeds.shift(), api3ServerV1: serverV1Address, - dapiNameHash, + dataFeedId, }; } @@ -356,8 +355,6 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { const vaultConfigResults = configResults.slice(...multicallSlices.shift()!); const vaultConfig = Vault.getConfig(vaultConfigResults, tokens); - const beeconIdMulticall = - return { vaultAddress: dexParams.vault, readerAddress: dexParams.reader, diff --git a/src/dex/quick-perps/types.ts b/src/dex/quick-perps/types.ts index 6bf52114a..fc0326e10 100644 --- a/src/dex/quick-perps/types.ts +++ b/src/dex/quick-perps/types.ts @@ -91,7 +91,7 @@ export type PoolConfig = { [address: string]: { proxy: Address; api3ServerV1: Address; - beaconId: string; + dataFeedId: string; }; }; }; diff --git a/src/lib/api3-feed.ts b/src/lib/api3-feed.ts index 44fb76826..588204372 100644 --- a/src/lib/api3-feed.ts +++ b/src/lib/api3-feed.ts @@ -28,11 +28,15 @@ export class Api3FeedSubscriber extends PartialEventSubscriber< Api3FeedSubscriber.api3ServerV1Iface.getEventTopic( 'UpdatedBeaconWithSignedData', ); + static readonly ANSWER_UPDATED_BEACON_SET_DATA = + Api3FeedSubscriber.api3ServerV1Iface.getEventTopic( + 'UpdatedBeaconSetWithBeacons', + ); constructor( private proxy: Address, api3Server: Address, - private beaconId: string, + private dataFeedId: string, lens: Lens, DeepReadonly>, logger: Logger, ) { @@ -47,26 +51,17 @@ export class Api3FeedSubscriber extends PartialEventSubscriber< }; } - static getDapiNameHash(proxy: Address): MultiCallInput { + static getDataFeedId(proxy: Address): MultiCallInput { return { target: proxy, callData: - Api3FeedSubscriber.proxyInterface.encodeFunctionData('dapiNameHash'), - }; - } - - static getFeedIdFromDapiNameHash(api3Server: string, dapiNameHash: string) { - return { - target: api3Server, - callData: Api3FeedSubscriber.api3ServerV1Iface.encodeFunctionData( - 'dapiNameHashToDataFeedId', - ), + Api3FeedSubscriber.proxyInterface.encodeFunctionData('dataFeedId'), }; } - static decodeFeedIdFromDapiNameHash(multicallOutput: MultiCallOutput) { + static decodeDataFeedId(multicallOutput: MultiCallOutput) { return Api3FeedSubscriber.proxyInterface.decodeFunctionResult( - 'dapiNameHashToDataFeedId', + 'dataFeedId', multicallOutput, )[0]; } @@ -78,29 +73,42 @@ export class Api3FeedSubscriber extends PartialEventSubscriber< )[0]; } - static decodeDapiNameHash(multicallOutput: MultiCallOutput): Address { - return Api3FeedSubscriber.proxyInterface.decodeFunctionResult( - 'dapiNameHash', - multicallOutput, - )[0]; - } - public processLog( state: DeepReadonly, log: Readonly, blockHeader: Readonly, ): DeepReadonly | null { - if (log.topics[0] !== Api3FeedSubscriber.ANSWER_UPDATED_SIGNED_DATA) - return null; // Ignore other events - const decoded = Api3FeedSubscriber.api3ServerV1Iface.decodeEventLog( - 'UpdatedBeaconWithSignedData', - log.data, - log.topics, - ); - return { - value: BigInt(decoded.value.toString()), - timestamp: BigInt(decoded.timestamp.toString()), - }; + if (log.topics[0] === Api3FeedSubscriber.ANSWER_UPDATED_SIGNED_DATA) { + const decoded = Api3FeedSubscriber.api3ServerV1Iface.decodeEventLog( + 'UpdatedBeaconWithSignedData', + log.data, + log.topics, + ); + + if (decoded.beaconId !== this.dataFeedId) return null; + + return { + value: BigInt(decoded.value.toString()), + timestamp: BigInt(decoded.timestamp.toString()), + }; + } else if ( + log.topics[0] === Api3FeedSubscriber.ANSWER_UPDATED_BEACON_SET_DATA + ) { + const decoded = Api3FeedSubscriber.api3ServerV1Iface.decodeEventLog( + 'UpdatedBeaconSetWithBeacons', + log.data, + log.topics, + ); + + if (decoded.beaconSetId !== this.dataFeedId) return null; + + return { + value: BigInt(decoded.value.toString()), + timestamp: BigInt(decoded.timestamp.toString()), + }; + } else { + return null; + } } public getGenerateStateMultiCallInputs(): MultiCallInput[] { From fc607fb9762971fc38117ca1be84770c9111c8ca Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 31 Aug 2023 11:27:53 +0100 Subject: [PATCH 198/833] 2.31.4-zkevm-revive.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ebf0924fd..f84d00f82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.12", + "version": "2.31.4-zkevm-revive.13", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From f600d8970fe009240b8e0fe219b031bd2181a5d8 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 31 Aug 2023 14:01:36 +0300 Subject: [PATCH 199/833] update tests --- src/dex/uniswap-v2/uniswap-v2-e2e-bsc.test.ts | 261 ++++++++---------- src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 1 - 2 files changed, 118 insertions(+), 144 deletions(-) diff --git a/src/dex/uniswap-v2/uniswap-v2-e2e-bsc.test.ts b/src/dex/uniswap-v2/uniswap-v2-e2e-bsc.test.ts index 24d23a214..6d2872ce3 100644 --- a/src/dex/uniswap-v2/uniswap-v2-e2e-bsc.test.ts +++ b/src/dex/uniswap-v2/uniswap-v2-e2e-bsc.test.ts @@ -2,11 +2,110 @@ import dotenv from 'dotenv'; dotenv.config(); import { testE2E } from '../../../tests/utils-e2e'; -import { Tokens, Holders } from '../../../tests/constants-e2e'; +import { Tokens, Holders, NativeTokenSymbols } from '../../../tests/constants-e2e'; import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, + slippage?: number | undefined, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ], + ], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + 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, + 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, + network, + provider, + undefined, + undefined, + undefined, + slippage, + ); + }); + }); + }); + }), + ); + }); +} + describe('UniswapV2 E2E BSC', () => { const network = Network.BSC; const tokens = Tokens[network]; @@ -1409,148 +1508,24 @@ describe('UniswapV2 E2E BSC', () => { describe('NomiswapV2', () => { const dexKey = 'NomiswapV2'; - - describe('Simpleswap', () => { - it('BNB -> TOKEN', async () => { - await testE2E( - tokens.BNB, - tokens.USDT, - holders.BNB, - '100000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - it('Token -> TOKEN', async () => { - await testE2E( - tokens.USDT, - tokens.USDC, - holders.USDT, - '1000000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - it('Token -> BNB', async () => { - await testE2E( - tokens.USDT, - tokens.BNB, - holders.USDT, - '1000000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - }); - - describe('BUY', () => { - it('BNB -> TOKEN', async () => { - await testE2E( - tokens.BNB, - tokens.USDT, - holders.BNB, - '100000000000000000000', - SwapSide.BUY, - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - it('Token -> TOKEN', async () => { - await testE2E( - tokens.USDT, - tokens.USDC, - holders.USDT, - '1000000000000000000000', - SwapSide.BUY, - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - it('Token -> BNB', async () => { - await testE2E( - tokens.BUSD, - tokens.BNB, - holders.BUSD, - '10000000000000000000', - SwapSide.BUY, - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - }); - - describe('Multiswap', () => { - it('BNB -> TOKEN', async () => { - await testE2E( - tokens.BNB, - tokens.USDT, - holders.BNB, - '100000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.multiSwap, - network, - provider, - ); - }); - it('Token -> TOKEN', async () => { - await testE2E( - tokens.USDT, - tokens.USDC, - holders.USDT, - '1000000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.multiSwap, - network, - provider, - ); - }); - it('Token -> BNB', async () => { - await testE2E( - tokens.USDT, - tokens.BNB, - holders.USDT, - '1000000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.multiSwap, - network, - provider, - ); - }); - }); - - describe('Megapath', () => { - it('Token -> TOKEN', async () => { - await testE2E( - tokens.USDT, - tokens.USDC, - holders.USDT, - '1000000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.megaSwap, - network, - provider, - ); - }); - }); + const network = Network.BSC; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '1111100000'; + const tokenBAmount: string = '1000000000'; + const nativeTokenAmount = '11000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); }); describe(`Swapsicle`, () => { diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index 57d0ed3a4..ed2e642c6 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -112,7 +112,6 @@ function testForNetwork( }); } - describe('UniswapV3 E2E', () => { describe('UniswapV3', () => { From 2847acf8e756454d10dc550b7740b4e46e102950 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 31 Aug 2023 14:04:02 +0300 Subject: [PATCH 200/833] 2.33.1-nomiswap-v2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ed144096..be2eba6ff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.33.0", + "version": "2.33.1-nomiswap-v2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 5a55c83c247f94f934260a56d6b62a0574735c4e Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 31 Aug 2023 18:57:17 +0300 Subject: [PATCH 201/833] add tintegration test for FTM -> EQUAL --- src/dex/solidly/solidly-integration.test.ts | 56 +++++++++++++++++++++ tests/constants-e2e.ts | 5 ++ 2 files changed, 61 insertions(+) diff --git a/src/dex/solidly/solidly-integration.test.ts b/src/dex/solidly/solidly-integration.test.ts index 629fa1025..5ff9928cf 100644 --- a/src/dex/solidly/solidly-integration.test.ts +++ b/src/dex/solidly/solidly-integration.test.ts @@ -467,6 +467,62 @@ describe('Solidly integration tests', () => { } }); }); + + describe('FTM -> EQUAL', () => { + const TokenASymbol = 'WFTM'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'EQUAL'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = [0n, 10000000n]; + + console.log('AMOUNTS: ', amounts); + it('getPoolIdentifiers and getPricesVolume', async function () { + // const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const blocknumber = 67666611; + const pools = await equalizer.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await equalizer.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + for (const i in poolPrices || []) { + await checkOnChainPricing( + equalizer, + 'getAmountOut', + blocknumber, + poolPrices![i].prices, + poolPrices![i].poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + }); }); }); diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 06ca492e8..faa56d798 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -460,6 +460,10 @@ export const Tokens: { address: '0x049d68029688eabf473097a2fc38ef61633a3c7a', decimals: 6, }, + EQUAL: { + address: '0x3fd3a0c85b70754efc07ac9ac0cbbdce664865a6', + decimals: 18 + }, POPS: { address: '0x9dE4b40bDcE50Ec6a1A668bF85997BbBD324069a', decimals: 18, @@ -979,6 +983,7 @@ export const Holders: { ETH: '0xf48883940b4056801de30f12b934dcea90133ee6', GUSDC: '0x894d774a293f8aa3d23d67815d4cadb5319c1094', GDAI: '0x0e2ed73f9c1409e2b36fe6c46e60d4557b7c2ac0', + EQUAL: '0x8b187ea19c93091a4d6b426b71871648182b5fac', }, [Network.BSC]: { DAI: '0xf68a4b64162906eff0ff6ae34e2bb1cd42fef62d', From 21ff9a12727d1b794ca236d2f09b21793cb5d74d Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 1 Sep 2023 10:45:16 +0100 Subject: [PATCH 202/833] fix: add address for multicall --- src/dex/uniswap-v3/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index c4d58d165..86d0e6163 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -151,7 +151,7 @@ export const UniswapV3Config: DexConfigMap = { quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', router: '0x24c90C7d8fb463722e304A71255341610Fa7589b', supportedFees: SUPPORTED_FEES, - stateMulticall: '', + stateMulticall: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', uniswapMulticall: '0x8C0F842791F03C095b6c633759224FcC9ACe68ea', chunksCount: 10, initRetryFrequency: 10, From d29d116a7757ed92711108537a2de27aed622334 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 1 Sep 2023 10:46:09 +0100 Subject: [PATCH 203/833] 2.33.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ed144096..1d70eb47b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.33.0", + "version": "2.33.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 078fe78c10e19136210dfa9fb04535e4ac53acb6 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 1 Sep 2023 12:09:23 +0100 Subject: [PATCH 204/833] fix: use getRealFee instead of getFee --- src/dex/solidly/forks-override/equalizer.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dex/solidly/forks-override/equalizer.ts b/src/dex/solidly/forks-override/equalizer.ts index ee9531e64..c72a61068 100644 --- a/src/dex/solidly/forks-override/equalizer.ts +++ b/src/dex/solidly/forks-override/equalizer.ts @@ -9,8 +9,8 @@ import _ from 'lodash'; const EqualizerFactoryABI = [ { - inputs: [{ internalType: 'bool', name: '_stable', type: 'bool' }], - name: 'getFee', + inputs: [{ internalType: 'address', name: '_pair', type: 'address' }], + name: 'getRealFee', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', type: 'function', @@ -39,14 +39,14 @@ export class Equalizer extends Solidly { protected getFeesMultiCallData(pair: SolidlyPair) { const callEntry = { target: this.factoryAddress, - callData: equalizerFactoryIface.encodeFunctionData('getFee', [ - pair.stable, + callData: equalizerFactoryIface.encodeFunctionData('getRealFee', [ + pair.exchange, ]), }; const callDecoder = (values: any[]) => parseInt( equalizerFactoryIface - .decodeFunctionResult('getFee', values)[0] + .decodeFunctionResult('getRealFee', values)[0] .toString(), ); From 5f3f501ef92cbd28755289068f578625a42f92cc Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 1 Sep 2023 12:25:10 +0100 Subject: [PATCH 205/833] test: update tests and fix issues --- src/dex/solidly/solidly-integration.test.ts | 123 ++++++++++---------- 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/src/dex/solidly/solidly-integration.test.ts b/src/dex/solidly/solidly-integration.test.ts index 5ff9928cf..73f50a127 100644 --- a/src/dex/solidly/solidly-integration.test.ts +++ b/src/dex/solidly/solidly-integration.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import dotenv from 'dotenv'; dotenv.config(); @@ -47,7 +48,7 @@ function decodeReaderResult( const constructCheckOnChainPricing = (dexHelper: DummyDexHelper) => async ( - soldily: Solidly, + solidly: Solidly, funcName: string, blockNumber: number, prices: bigint[], @@ -89,7 +90,7 @@ describe('Solidly integration tests', () => { describe('Solidly', function () { const dexKey = 'Solidly'; - const soldily = new Solidly(network, dexKey, dexHelper); + const solidly = new Solidly(network, dexKey, dexHelper); describe('UniswapV2 like pool', function () { const TokenASymbol = 'WFTM'; @@ -101,7 +102,7 @@ describe('Solidly integration tests', () => { it('getPoolIdentifiers and getPricesVolume', async function () { const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); - const pools = await soldily.getPoolIdentifiers( + const pools = await solidly.getPoolIdentifiers( tokenA, tokenB, SwapSide.SELL, @@ -114,7 +115,7 @@ describe('Solidly integration tests', () => { expect(pools.length).toBeGreaterThan(0); - const poolPrices = await soldily.getPricesVolume( + const poolPrices = await solidly.getPricesVolume( tokenA, tokenB, amounts, @@ -132,13 +133,13 @@ describe('Solidly integration tests', () => { // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( - soldily, + solidly, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -146,7 +147,7 @@ describe('Solidly integration tests', () => { }); it('getTopPoolsForToken', async function () { - const poolLiquidity = await soldily.getTopPoolsForToken( + const poolLiquidity = await solidly.getTopPoolsForToken( tokenA.address, 10, ); @@ -166,7 +167,7 @@ describe('Solidly integration tests', () => { it('getPoolIdentifiers and getPricesVolume', async function () { const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); - const pools = await soldily.getPoolIdentifiers( + const pools = await solidly.getPoolIdentifiers( tokenA, tokenB, SwapSide.SELL, @@ -179,7 +180,7 @@ describe('Solidly integration tests', () => { expect(pools.length).toBeGreaterThan(0); - const poolPrices = await soldily.getPricesVolume( + const poolPrices = await solidly.getPricesVolume( tokenA, tokenB, amounts, @@ -196,13 +197,13 @@ describe('Solidly integration tests', () => { checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( - soldily, + solidly, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -210,7 +211,7 @@ describe('Solidly integration tests', () => { }); it('getTopPoolsForToken', async function () { - const poolLiquidity = await soldily.getTopPoolsForToken( + const poolLiquidity = await solidly.getTopPoolsForToken( tokenA.address, 10, ); @@ -266,13 +267,13 @@ describe('Solidly integration tests', () => { // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( spiritSwapV2, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -330,13 +331,13 @@ describe('Solidly integration tests', () => { checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( spiritSwapV2, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -400,13 +401,13 @@ describe('Solidly integration tests', () => { // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( equalizer, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -454,13 +455,13 @@ describe('Solidly integration tests', () => { checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( equalizer, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -510,13 +511,13 @@ describe('Solidly integration tests', () => { checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( equalizer, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -576,13 +577,13 @@ describe('Solidly integration tests', () => { // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( dystopia, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -640,13 +641,13 @@ describe('Solidly integration tests', () => { checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( dystopia, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -716,13 +717,13 @@ describe('Solidly integration tests', () => { // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( cone, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -780,13 +781,13 @@ describe('Solidly integration tests', () => { checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( cone, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -856,13 +857,13 @@ describe('Solidly integration tests', () => { // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( chronos, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -920,13 +921,13 @@ describe('Solidly integration tests', () => { checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( chronos, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -992,13 +993,13 @@ describe('Solidly integration tests', () => { // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( ramses, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -1056,13 +1057,13 @@ describe('Solidly integration tests', () => { checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( ramses, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -1132,13 +1133,13 @@ describe('Solidly integration tests', () => { // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( velodromeV2, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); @@ -1186,13 +1187,13 @@ describe('Solidly integration tests', () => { checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); // Check if onchain pricing equals to calculated ones - for (const i in poolPrices || []) { + for (const poolPrice of poolPrices || []) { await checkOnChainPricing( velodromeV2, 'getAmountOut', blocknumber, - poolPrices![i].prices, - poolPrices![i].poolAddresses![0], + poolPrice.prices, + poolPrice.poolAddresses![0], tokenA.address, amounts, ); From 5e331cc355b67a56fd8d98abee5386ad696e587c Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 1 Sep 2023 12:26:38 +0100 Subject: [PATCH 206/833] chore: set version number --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 151015786..1d70eb47b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.33.1-equalizer", + "version": "2.33.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 9bf6de48998d0f0deac0cd159ce655ceb46c3047 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 1 Sep 2023 12:27:08 +0100 Subject: [PATCH 207/833] 2.33.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1d70eb47b..5383acecf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.33.1", + "version": "2.33.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 2b0895130e942ebb892757e67c09eb9b7fbc7a7d Mon Sep 17 00:00:00 2001 From: Esteban Date: Fri, 1 Sep 2023 16:51:40 +0200 Subject: [PATCH 208/833] feat: initialization --- src/abi/smardex/layer-1/smardex-factory.json | 176 +++ src/abi/smardex/layer-1/smardex-pool.json | 768 ++++++++++ src/abi/smardex/layer-2/smardex-factory.json | 265 ++++ src/abi/smardex/layer-2/smardex-pool.json | 898 +++++++++++ src/dex/smardex/config.ts | 35 +- src/dex/smardex/smardex-e2e.test.ts | 686 +++++++-- src/dex/smardex/smardex-events.test.ts | 106 -- src/dex/smardex/smardex-integration.test.ts | 6 - src/dex/smardex/smardex-pool.ts | 91 -- src/dex/smardex/smardex-sdk.ts | 1429 ++++++++++++++++++ src/dex/smardex/smardex.ts | 882 +++++++++-- src/dex/smardex/types.ts | 49 +- 12 files changed, 4922 insertions(+), 469 deletions(-) create mode 100644 src/abi/smardex/layer-1/smardex-factory.json create mode 100644 src/abi/smardex/layer-1/smardex-pool.json create mode 100644 src/abi/smardex/layer-2/smardex-factory.json create mode 100644 src/abi/smardex/layer-2/smardex-pool.json delete mode 100644 src/dex/smardex/smardex-events.test.ts delete mode 100644 src/dex/smardex/smardex-pool.ts create mode 100644 src/dex/smardex/smardex-sdk.ts diff --git a/src/abi/smardex/layer-1/smardex-factory.json b/src/abi/smardex/layer-1/smardex-factory.json new file mode 100644 index 000000000..f534230a0 --- /dev/null +++ b/src/abi/smardex/layer-1/smardex-factory.json @@ -0,0 +1,176 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_feeToSetter", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "pair", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalPair", + "type": "uint256" + } + ], + "name": "PairCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allPairs", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPairsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "_tokenB", + "type": "address" + } + ], + "name": "createPair", + "outputs": [ + { + "internalType": "address", + "name": "pair_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feeTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeToSetter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "getPair", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeTo", + "type": "address" + } + ], + "name": "setFeeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeToSetter", + "type": "address" + } + ], + "name": "setFeeToSetter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/abi/smardex/layer-1/smardex-pool.json b/src/abi/smardex/layer-1/smardex-pool.json new file mode 100644 index 000000000..8e6b2a9a9 --- /dev/null +++ b/src/abi/smardex/layer-1/smardex-pool.json @@ -0,0 +1,768 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "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": "Burn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "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": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "int256", + "name": "amount0", + "type": "int256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "amount1", + "type": "int256" + } + ], + "name": "Swap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "reserve0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reserve1", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fictiveReserve0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fictiveReserve1", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "priceAverage0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "priceAverage1", + "type": "uint256" + } + ], + "name": "Sync", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1_", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFees", + "outputs": [ + { + "internalType": "uint256", + "name": "fees0_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fees1_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFictiveReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "fictiveReserve0_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fictiveReserve1_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPriceAverage", + "outputs": [ + { + "internalType": "uint256", + "name": "priceAverage0_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priceAverage1_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priceAverageLastTimestamp_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "reserve0_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserve1_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_fictiveReserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_fictiveReserveOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_priceAverageLastTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_priceAverageIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_priceAverageOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_currentTimestamp", + "type": "uint256" + } + ], + "name": "getUpdatedPriceAverage", + "outputs": [ + { + "internalType": "uint256", + "name": "priceAverageIn_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priceAverageOut_", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token0", + "type": "address" + }, + { + "internalType": "address", + "name": "_token1", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount1", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_payer", + "type": "address" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "liquidity_", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "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": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "bool", + "name": "_zeroForOne", + "type": "bool" + }, + { + "internalType": "int256", + "name": "_amountSpecified", + "type": "int256" + }, + { + "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": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "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": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/abi/smardex/layer-2/smardex-factory.json b/src/abi/smardex/layer-2/smardex-factory.json new file mode 100644 index 000000000..9dc5bc77b --- /dev/null +++ b/src/abi/smardex/layer-2/smardex-factory.json @@ -0,0 +1,265 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousFeeTo", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newFeeTo", + "type": "address" + } + ], + "name": "FeeToUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "feesLP", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "feesPool", + "type": "uint256" + } + ], + "name": "FeesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "pair", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalPair", + "type": "uint256" + } + ], + "name": "PairCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allPairs", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPairsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "_tokenB", + "type": "address" + } + ], + "name": "createPair", + "outputs": [ + { + "internalType": "address", + "name": "pair_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "feeTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDefaultFees", + "outputs": [ + { + "internalType": "uint128", + "name": "feesLP_", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "feesPool_", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "getPair", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeTo", + "type": "address" + } + ], + "name": "setFeeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "_feesLP", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "_feesPool", + "type": "uint128" + } + ], + "name": "setFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/abi/smardex/layer-2/smardex-pool.json b/src/abi/smardex/layer-2/smardex-pool.json new file mode 100644 index 000000000..f8e62aac2 --- /dev/null +++ b/src/abi/smardex/layer-2/smardex-pool.json @@ -0,0 +1,898 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "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": "Burn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "feesLP", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "feesPool", + "type": "uint256" + } + ], + "name": "FeesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "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": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "int256", + "name": "amount0", + "type": "int256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "amount1", + "type": "int256" + } + ], + "name": "Swap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "reserve0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reserve1", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fictiveReserve0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fictiveReserve1", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "priceAverage0", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "priceAverage1", + "type": "uint256" + } + ], + "name": "Sync", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "burn", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1_", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFeeToAmounts", + "outputs": [ + { + "internalType": "uint256", + "name": "fees0_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fees1_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFictiveReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "fictiveReserve0_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fictiveReserve1_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPairFees", + "outputs": [ + { + "internalType": "uint128", + "name": "feesLP_", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "feesPool_", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPriceAverage", + "outputs": [ + { + "internalType": "uint256", + "name": "priceAverage0_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priceAverage1_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priceAverageLastTimestamp_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "reserve0_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserve1_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_fictiveReserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_fictiveReserveOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_priceAverageLastTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_priceAverageIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_priceAverageOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_currentTimestamp", + "type": "uint256" + } + ], + "name": "getUpdatedPriceAverage", + "outputs": [ + { + "internalType": "uint256", + "name": "priceAverageIn_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priceAverageOut_", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token0", + "type": "address" + }, + { + "internalType": "address", + "name": "_token1", + "type": "address" + }, + { + "internalType": "uint128", + "name": "_feesLP", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "_feesPool", + "type": "uint128" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount0", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount1", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_payer", + "type": "address" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "liquidity_", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "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": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "_feesLP", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "_feesPool", + "type": "uint128" + } + ], + "name": "setFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "bool", + "name": "_zeroForOne", + "type": "bool" + }, + { + "internalType": "int256", + "name": "_amountSpecified", + "type": "int256" + }, + { + "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": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "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": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/dex/smardex/config.ts b/src/dex/smardex/config.ts index 17e1d914a..7d3ed262d 100644 --- a/src/dex/smardex/config.ts +++ b/src/dex/smardex/config.ts @@ -2,9 +2,42 @@ import { DexParams } from './types'; import { DexConfigMap, AdapterMappings } from '../../types'; import { Network, SwapSide } from '../../constants'; +const gatewaySubgraph = 'https://subgraph.smardex.io/paraswap'; +const mainnetInitHash = + '0xb477a06204165d50e6d795c7c216306290eff5d6015f8b65bb46002a8775b548'; +const layer2InitHash = + '0x33bee911475f015247aeb1eebe149d1c6d2669be54126c29d85df6b0abb4c4e9'; + export const SmardexConfig: DexConfigMap = { Smardex: { - // TODO: complete me! + [Network.MAINNET]: { + factoryAddress: '0x7753F36E711B66a0350a753aba9F5651BAE76A1D', + router: '0xEf2f9b48d7EC80440Ab4573dF1A2aBDBE06D3f60', + initCode: mainnetInitHash, + subgraphURL: `${gatewaySubgraph}/ethereum`, + feeCode: 0, + }, + [Network.ARBITRUM]: { + factoryAddress: '0x41A00e3FbE7F479A99bA6822704d9c5dEB611F22', + router: '0xdd4536dD9636564D891c919416880a3e250f975A', + initCode: layer2InitHash, + subgraphURL: `${gatewaySubgraph}/arbitrum`, + feeCode: 0, + }, + [Network.BSC]: { + factoryAddress: '0xA8EF6FEa013034E62E2C4A9Ec1CDb059fE23Af33', + router: '0x391BeCc8DAaf32b9ba8e602e9527Bf9DA04C8deb', + initCode: layer2InitHash, + subgraphURL: `${gatewaySubgraph}/bsc`, + feeCode: 0, + }, + [Network.POLYGON]: { + factoryAddress: '0x9A1e1681f6D59Ca051776410465AfAda6384398f', + router: '0xA8EF6FEa013034E62E2C4A9Ec1CDb059fE23Af33', + initCode: layer2InitHash, + subgraphURL: `${gatewaySubgraph}/polygon`, + feeCode: 0, + }, }, }; diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index 486fe1882..e65cfd2a2 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -1,162 +1,564 @@ -/* eslint-disable no-console */ import dotenv from 'dotenv'; dotenv.config(); import { testE2E } from '../../../tests/utils-e2e'; -import { - Tokens, - Holders, - NativeTokenSymbols, -} from '../../../tests/constants-e2e'; +import { Tokens, Holders } from '../../../tests/constants-e2e'; import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; -/* - README - ====== - - This test script should add e2e tests for Smardex. The tests - should cover as many cases as possible. Most of the DEXes follow - the following test structure: - - DexName - - ForkName + Network - - ContractMethod - - ETH -> Token swap - - Token -> ETH swap - - Token -> Token swap - - The template already enumerates the basic structure which involves - testing simpleSwap, multiSwap, megaSwap contract methods for - ETH <> TOKEN and TOKEN <> TOKEN swaps. You should replace tokenA and - tokenB with any two highly liquid tokens on Smardex for the tests - to work. If the tokens that you would like to use are not defined in - Tokens or Holders map, you can update the './tests/constants-e2e' - - Other than the standard cases that are already added by the template - it is highly recommended to add test cases which could be specific - to testing Smardex (Eg. Tests based on poolType, special tokens, - etc). - - You can run this individual test script by running: - `npx jest src/dex//-e2e.test.ts` - - e2e tests use the Tenderly fork api. Please add the following to your - .env file: - TENDERLY_TOKEN=Find this under Account>Settings>Authorization. - TENDERLY_ACCOUNT_ID=Your Tenderly account name. - TENDERLY_PROJECT=Name of a Tenderly project you have created in your - dashboard. - - (This comment should be removed from the final implementation) -*/ - -function testForNetwork( - network: Network, - dexKey: string, - tokenASymbol: string, - tokenBSymbol: string, - tokenAAmount: string, - tokenBAmount: string, - nativeTokenAmount: string, -) { +describe('Smardex E2E Mainnet', () => { + const network = Network.MAINNET; + const tokens = Tokens[network]; + const holders = Holders[network]; const provider = new StaticJsonRpcProvider( generateConfig(network).privateHttpProvider, network, ); - const tokens = Tokens[network]; - const holders = Holders[network]; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - // TODO: Add any direct swap contractMethod name if it exists - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ], - ], - // TODO: If buy is not supported remove the buy contract methods - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - ]); - - describe(`${network}`, () => { - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - 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, - network, - provider, - ); - }); - it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }); - }), - ); - }); -} + describe('Smardex', () => { + const dexKey = 'Smardex'; + + describe('Simpleswap', () => { + it('ETH -> TOKEN', async () => { + await testE2E( + tokens.ETH, + tokens.USDC, + holders.ETH, + '7000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.swapOnUniswap, + network, + provider, + ); + }); + it('TOKEN -> ETH', async () => { + await testE2E( + tokens.USDC, + tokens.ETH, + holders.USDC, + '2000000000', + SwapSide.SELL, + dexKey, + ContractMethod.swapOnUniswap, + network, + provider, + ); + }); + // it('TOKEN -> TOKEN', async () => { + // await testE2E( + // tokens.WBTC, + // tokens.BADGER, + // holders.WBTC, + // '20000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod., + // network, + // provider, + // ); + // }); + }); + + // describe('Multiswap', () => { + // it('ETH -> TOKEN', async () => { + // await testE2E( + // tokens.ETH, + // tokens.WBTC, + // holders.ETH, + // '7000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.multiSwap, + // network, + // provider, + // ); + // }); + // it('TOKEN -> ETH', async () => { + // await testE2E( + // tokens.BADGER, + // tokens.ETH, + // holders.BADGER, + // '700000000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.multiSwap, + // network, + // provider, + // ); + // }); + // it('TOKEN -> TOKEN', async () => { + // await testE2E( + // tokens.USDC, + // tokens.WBTC, + // holders.USDC, + // '200000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.multiSwap, + // network, + // provider, + // ); + // }); + // }); + + // describe('swapOnUniswap', () => { + // it('ETH -> TOKEN', async () => { + // await testE2E( + // tokens.ETH, + // tokens.WBTC, + // holders.ETH, + // '7000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.swapOnUniswap, + // network, + // provider, + // ); + // }); + // it('TOKEN[BADGER] -> ETH', async () => { + // await testE2E( + // tokens.BADGER, + // tokens.ETH, + // holders.BADGER, + // '700000000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.swapOnUniswap, + // network, + // provider, + // ); + // }); + // it('TOKEN[USDC] -> ETH', async () => { + // await testE2E( + // tokens.USDC, + // tokens.ETH, + // holders.USDC, + // '200000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.swapOnUniswap, + // network, + // provider, + // ); + // }); + // it('TOKEN -> TOKEN', async () => { + // await testE2E( + // tokens.USDC, + // tokens.WBTC, + // holders.USDC, + // '200000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.swapOnUniswap, + // network, + // provider, + // ); + // }); + // }); + + // describe('swapOnUniswapFork', () => { + // it('ETH -> TOKEN', async () => { + // await testE2E( + // tokens.ETH, + // tokens.WBTC, + // holders.ETH, + // '7000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.swapOnUniswapFork, + // network, + // provider, + // ); + // }); + // it('TOKEN -> ETH', async () => { + // await testE2E( + // tokens.BADGER, + // tokens.ETH, + // holders.BADGER, + // '700000000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.swapOnUniswapFork, + // network, + // provider, + // ); + // }); + // it('TOKEN -> TOKEN', async () => { + // await testE2E( + // tokens.USDC, + // tokens.WBTC, + // holders.USDC, + // '200000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.swapOnUniswapFork, + // network, + // provider, + // ); + // }); + // }); + + // describe('swapOnUniswapV2Fork', () => { + // it('ETH -> TOKEN', async () => { + // await testE2E( + // tokens.ETH, + // tokens.WBTC, + // holders.ETH, + // '7000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.swapOnUniswapV2Fork, + // network, + // provider, + // ); + // }); + // it('TOKEN -> ETH', async () => { + // await testE2E( + // tokens.BADGER, + // tokens.ETH, + // holders.BADGER, + // '700000000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.swapOnUniswapV2Fork, + // network, + // provider, + // ); + // }); + // it('TOKEN -> TOKEN', async () => { + // await testE2E( + // tokens.USDC, + // tokens.WBTC, + // holders.USDC, + // '200000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.swapOnUniswapV2Fork, + // network, + // provider, + // ); + // }); + // }); + + // describe('buyOnUniswap', () => { + // it('TOKEN -> ETH', async () => { + // await testE2E( + // tokens.USDT, + // tokens.ETH, + // holders.USDT, + // '700000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buyOnUniswap, + // network, + // provider, + // ); + // }); + // it('ETH -> TOKEN[BADGER]', async () => { + // await testE2E( + // tokens.ETH, + // tokens.BADGER, + // holders.ETH, + // '700000000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buyOnUniswap, + // network, + // provider, + // ); + // }); + // it('TOKEN[USDC] -> ETH', async () => { + // await testE2E( + // tokens.USDC, + // tokens.ETH, + // holders.USDC, + // '2000000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buyOnUniswap, + // network, + // provider, + // ); + // }); + + // it('TOKEN -> TOKEN', async () => { + // await testE2E( + // tokens.USDC, + // tokens.WBTC, + // holders.USDC, + // '200000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buyOnUniswap, + // network, + // provider, + // ); + // }); + // }); + + // describe('buyOnUniswapFork', () => { + // it('TOKEN -> ETH', async () => { + // await testE2E( + // tokens.USDT, + // tokens.ETH, + // holders.USDT, + // '700000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buyOnUniswapFork, + // network, + // provider, + // ); + // }); + // it('ETH -> TOKEN[BADGER]', async () => { + // await testE2E( + // tokens.ETH, + // tokens.BADGER, + // holders.ETH, + // '700000000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buyOnUniswapFork, + // network, + // provider, + // ); + // }); + // it('TOKEN[USDC] -> ETH', async () => { + // await testE2E( + // tokens.USDC, + // tokens.ETH, + // holders.USDC, + // '2000000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buyOnUniswapFork, + // network, + // provider, + // ); + // }); -describe('Smardex E2E', () => { - const dexKey = 'Smardex'; + // it('TOKEN -> TOKEN', async () => { + // await testE2E( + // tokens.USDC, + // tokens.WBTC, + // holders.USDC, + // '200000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buyOnUniswapFork, + // network, + // provider, + // ); + // }); + // }); - describe('Mainnet', () => { - const network = Network.MAINNET; + // describe('buyOnUniswapV2Fork', () => { + // it('TOKEN -> ETH', async () => { + // await testE2E( + // tokens.USDT, + // tokens.ETH, + // holders.USDT, + // '700000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buyOnUniswapV2Fork, + // network, + // provider, + // ); + // }); + // it('ETH -> TOKEN[BADGER]', async () => { + // await testE2E( + // tokens.ETH, + // tokens.BADGER, + // holders.ETH, + // '700000000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buyOnUniswapV2Fork, + // network, + // provider, + // ); + // }); + // it('TOKEN[USDC] -> ETH', async () => { + // await testE2E( + // tokens.USDC, + // tokens.ETH, + // holders.USDC, + // '2000000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buyOnUniswapV2Fork, + // network, + // provider, + // ); + // }); - // TODO: Modify the tokenASymbol, tokenBSymbol, tokenAAmount; - const tokenASymbol: string = 'tokenASymbol'; - const tokenBSymbol: string = 'tokenBSymbol'; + // it('TOKEN -> TOKEN', async () => { + // await testE2E( + // tokens.USDC, + // tokens.WBTC, + // holders.USDC, + // '200000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buyOnUniswapV2Fork, + // network, + // provider, + // ); + // }); + // }); - const tokenAAmount: string = 'tokenAAmount'; - const tokenBAmount: string = 'tokenBAmount'; - const nativeTokenAmount = '1000000000000000000'; + // describe('simpleBuy', () => { + // it('TOKEN -> ETH', async () => { + // await testE2E( + // tokens.USDT, + // tokens.ETH, + // holders.USDT, + // '700000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.simpleBuy, + // network, + // provider, + // ); + // }); + // it('ETH -> TOKEN[BADGER]', async () => { + // await testE2E( + // tokens.ETH, + // tokens.BADGER, + // holders.ETH, + // '700000000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.simpleBuy, + // network, + // provider, + // ); + // }); + // it('TOKEN[USDC] -> ETH', async () => { + // await testE2E( + // tokens.USDC, + // tokens.ETH, + // holders.USDC, + // '2000000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.simpleBuy, + // network, + // provider, + // ); + // }); + // it('TOKEN -> TOKEN', async () => { + // await testE2E( + // tokens.USDC, + // tokens.WBTC, + // holders.USDC, + // '20000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.simpleBuy, + // network, + // provider, + // ); + // }); + // }); - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); + // describe('BuyMethod', () => { + // it('TOKEN -> ETH', async () => { + // await testE2E( + // tokens.USDT, + // tokens.ETH, + // holders.USDT, + // '700000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buy, + // network, + // provider, + // ); + // }); + // it('ETH -> TOKEN[BADGER]', async () => { + // await testE2E( + // tokens.ETH, + // tokens.BADGER, + // holders.ETH, + // '700000000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buy, + // network, + // provider, + // ); + // }); + // it('TOKEN[USDC] -> ETH', async () => { + // await testE2E( + // tokens.USDC, + // tokens.ETH, + // holders.USDC, + // '2000000000000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buy, + // network, + // provider, + // ); + // }); + // it('TOKEN -> TOKEN', async () => { + // await testE2E( + // tokens.USDC, + // tokens.WBTC, + // holders.USDC, + // '20000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.buy, + // network, + // provider, + // ); + // }); + // }); - // TODO: Add any additional test cases required to test Smardex + // describe('STETH->ETH', () => { + // it('simpleSwap', async () => { + // await testE2E( + // tokens.STETH, + // tokens.ETH, + // holders.STETH, + // '1000000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.simpleSwap, + // network, + // provider, + // ); + // }); + // it('multiSwap', async () => { + // await testE2E( + // tokens.STETH, + // tokens.ETH, + // holders.STETH, + // '1000000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.multiSwap, + // network, + // provider, + // ); + // }); + // it('megaSwap', async () => { + // await testE2E( + // tokens.STETH, + // tokens.ETH, + // holders.STETH, + // '1000000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.megaSwap, + // network, + // provider, + // ); + // }); + // }); }); }); diff --git a/src/dex/smardex/smardex-events.test.ts b/src/dex/smardex/smardex-events.test.ts deleted file mode 100644 index 1deaa5db2..000000000 --- a/src/dex/smardex/smardex-events.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); - -import { SmardexEventPool } from './smardex-pool'; -import { Network } from '../../constants'; -import { Address } from '../../types'; -import { DummyDexHelper } from '../../dex-helper/index'; -import { testEventSubscriber } from '../../../tests/utils-events'; -import { PoolState } from './types'; - -/* - README - ====== - - This test script adds unit tests for Smardex event based - system. This is done by fetching the state on-chain before the - event block, manually pushing the block logs to the event-subscriber, - comparing the local state with on-chain state. - - Most of the logic for testing is abstracted by `testEventSubscriber`. - You need to do two things to make the tests work: - - 1. Fetch the block numbers where certain events were released. You - can modify the `./scripts/fetch-event-blocknumber.ts` to get the - block numbers for different events. Make sure to get sufficient - number of blockNumbers to cover all possible cases for the event - mutations. - - 2. Complete the implementation for fetchPoolState function. The - function should fetch the on-chain state of the event subscriber - using just the blocknumber. - - The template tests only include the test for a single event - subscriber. There can be cases where multiple event subscribers - exist for a single DEX. In such cases additional tests should be - added. - - You can run this individual test script by running: - `npx jest src/dex//-events.test.ts` - - (This comment should be removed from the final implementation) -*/ - -jest.setTimeout(50 * 1000); - -async function fetchPoolState( - smardexPools: SmardexEventPool, - blockNumber: number, - poolAddress: string, -): Promise { - // TODO: complete me! - return {}; -} - -// eventName -> blockNumbers -type EventMappings = Record; - -describe('Smardex EventPool Mainnet', function () { - const dexKey = 'Smardex'; - const network = Network.MAINNET; - const dexHelper = new DummyDexHelper(network); - const logger = dexHelper.getLogger(dexKey); - let smardexPool: SmardexEventPool; - - // poolAddress -> EventMappings - const eventsToTest: Record = { - // TODO: complete me! - }; - - beforeEach(async () => { - smardexPool = new SmardexEventPool( - dexKey, - network, - dexHelper, - logger, - /* TODO: Put here additional constructor arguments if needed */ - ); - }); - - Object.entries(eventsToTest).forEach( - ([poolAddress, events]: [string, EventMappings]) => { - describe(`Events for ${poolAddress}`, () => { - Object.entries(events).forEach( - ([eventName, blockNumbers]: [string, number[]]) => { - describe(`${eventName}`, () => { - blockNumbers.forEach((blockNumber: number) => { - it(`State after ${blockNumber}`, async function () { - await testEventSubscriber( - smardexPool, - smardexPool.addressesSubscribed, - (_blockNumber: number) => - fetchPoolState(smardexPool, _blockNumber, poolAddress), - blockNumber, - `${dexKey}_${poolAddress}`, - dexHelper.provider, - ); - }); - }); - }); - }, - ); - }); - }, - ); -}); diff --git a/src/dex/smardex/smardex-integration.test.ts b/src/dex/smardex/smardex-integration.test.ts index 6499260f6..d2c5fa1c2 100644 --- a/src/dex/smardex/smardex-integration.test.ts +++ b/src/dex/smardex/smardex-integration.test.ts @@ -193,9 +193,6 @@ describe('Smardex', function () { beforeAll(async () => { blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); smardex = new Smardex(network, dexKey, dexHelper); - if (smardex.initializePricing) { - await smardex.initializePricing(blockNumber); - } }); it('getPoolIdentifiers and getPricesVolume SELL', async function () { @@ -230,9 +227,6 @@ describe('Smardex', function () { // We have to check without calling initializePricing, because // pool-tracker is not calling that function const newSmardex = new Smardex(network, dexKey, dexHelper); - if (newSmardex.updatePoolState) { - await newSmardex.updatePoolState(); - } const poolLiquidity = await newSmardex.getTopPoolsForToken( tokens[srcTokenSymbol].address, 10, diff --git a/src/dex/smardex/smardex-pool.ts b/src/dex/smardex/smardex-pool.ts deleted file mode 100644 index 1f81f18a5..000000000 --- a/src/dex/smardex/smardex-pool.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Interface } from '@ethersproject/abi'; -import { DeepReadonly } from 'ts-essentials'; -import { Log, Logger } from '../../types'; -import { catchParseLogError } from '../../utils'; -import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { PoolState } from './types'; - -export class SmardexEventPool extends StatefulEventSubscriber { - handlers: { - [event: string]: ( - event: any, - state: DeepReadonly, - log: Readonly, - ) => DeepReadonly | null; - } = {}; - - logDecoder: (log: Log) => any; - - addressesSubscribed: string[]; - - constructor( - readonly parentName: string, - protected network: number, - protected dexHelper: IDexHelper, - logger: Logger, - protected smardexIface = new Interface( - '' /* TODO: Import and put here Smardex ABI */, - ), // TODO: add any additional params required for event subscriber - ) { - // TODO: Add pool name - super(parentName, 'POOL_NAME', dexHelper, logger); - - // TODO: make logDecoder decode logs that - this.logDecoder = (log: Log) => this.smardexIface.parseLog(log); - this.addressesSubscribed = [ - /* subscribed addresses */ - ]; - - // Add handlers - this.handlers['myEvent'] = this.handleMyEvent.bind(this); - } - - /** - * The function is called every time any of the subscribed - * addresses release log. The function accepts the current - * state, updates the state according to the log, and returns - * the updated state. - * @param state - Current state of event subscriber - * @param log - Log released by one of the subscribed addresses - * @returns Updates state of the event subscriber after the log - */ - protected processLog( - state: DeepReadonly, - log: Readonly, - ): DeepReadonly | null { - try { - const event = this.logDecoder(log); - if (event.name in this.handlers) { - return this.handlers[event.name](event, state, log); - } - } catch (e) { - catchParseLogError(e, this.logger); - } - - return null; - } - - /** - * The function generates state using on-chain calls. This - * function is called to regenerate state if the event based - * system fails to fetch events and the local state is no - * more correct. - * @param blockNumber - Blocknumber for which the state should - * should be generated - * @returns state of the event subscriber at blocknumber - */ - async generateState(blockNumber: number): Promise> { - // TODO: complete me! - return {}; - } - - // Its just a dummy example - handleMyEvent( - event: any, - state: DeepReadonly, - log: Readonly, - ): DeepReadonly | null { - return null; - } -} diff --git a/src/dex/smardex/smardex-sdk.ts b/src/dex/smardex/smardex-sdk.ts new file mode 100644 index 000000000..fcb650403 --- /dev/null +++ b/src/dex/smardex/smardex-sdk.ts @@ -0,0 +1,1429 @@ +import { BigNumber, constants, utils } from 'ethers/lib/ethers'; + +// Protocol's fees constants +export const FEES_LP = BigNumber.from(500); +export const FEES_POOL = BigNumber.from(200); +export const FEES_TOTAL = FEES_LP.add(FEES_POOL); +export const FEES_BASE = BigNumber.from(1000); +export const FEES_TOTAL_REVERSED = FEES_BASE.sub(FEES_TOTAL); +export interface Pair { + address?: string; + token0: string; + token1: string; + reserve0: BigNumber; + reserve1: BigNumber; + reserve0LastFictive: BigNumber; + reserve1LastFictive: BigNumber; + priceAverageLastTimestamp: number; + priceAverage0: BigNumber; + priceAverage1: BigNumber; + forcedPriceAverageTimestamp?: number; + prevReserveFic0?: BigNumber; + prevReserveFic1?: BigNumber; +} + +export interface CurrencyAmount { + currency: string; + amount: BigNumber; + amountMax?: BigNumber; + newRes0?: BigNumber; + newRes1?: BigNumber; + newRes0Fic?: BigNumber; + newRes1Fic?: BigNumber; + newPriceAverage0?: BigNumber; + newPriceAverage1?: BigNumber; + forcedPriceAverageTimestamp?: number; +} + +export interface BestTradeOptions { + maxNumResults?: number; // how many results to return + maxHops?: number; // the maximum number of hops for the swap + arbitrage?: boolean; // consider arbitrage loops or not +} + +export interface Route { + pairs: Pair[]; + path: string[]; + input: string; + output: string; +} + +export interface Trade { + route: Route; + amountIn: CurrencyAmount; + amountOut: CurrencyAmount; + tradeType: TradeType; + priceImpact?: BigNumber; // defined only after calling bestTradeExactIn or bestTradeExactOut +} +// constant for function 'updatePriceAverage' +export const MAX_BLOCK_DIFF_SECONDS = process.env.SDK_MAX_BLOCK_DIFF_SECONDS + ? Number(process.env.SDK_MAX_BLOCK_DIFF_SECONDS) + : 300; +export const LATENCY_OFFSET_SECONDS = 20; + +export enum TradeType { + EXACT_INPUT, + EXACT_OUTPUT, +} +// compute first trade amountIn using arbitrage feature +function computeFirstTradeQtyIn( + amountIn: BigNumber, + reserveInFic: BigNumber, + reserveOutFic: BigNumber, + priceAverageIn: BigNumber, + priceAverageOut: BigNumber, +): BigNumber { + // default value + let firstAmountIn = amountIn; + + // if trade is in the good direction + if (reserveOutFic.mul(priceAverageIn).gt(reserveInFic.mul(priceAverageOut))) { + // pre-compute all operands + const toSub = reserveInFic.mul( + FEES_BASE.add(FEES_TOTAL_REVERSED).sub(FEES_POOL), + ); + const toDiv = FEES_TOTAL_REVERSED.add(FEES_LP).mul(2); + const inSqrt = reserveInFic + .mul(reserveOutFic) + .mul(4) + .div(priceAverageOut) + .mul(priceAverageIn) + .mul(FEES_TOTAL_REVERSED) + .mul(FEES_BASE.sub(FEES_POOL)) + .add(reserveInFic.mul(reserveInFic).mul(FEES_LP).mul(FEES_LP)); + + // reverse sqrt check to only compute sqrt if really needed + if (inSqrt.lt(amountIn.mul(toDiv).add(toSub).pow(2))) { + firstAmountIn = sqrt(inSqrt).sub(toSub).div(toDiv); + } + } + + return firstAmountIn; +} + +// compute first trade amountOut using arbitrage feature +function computeFirstTradeQtyOut( + amountOut: BigNumber, + reserveInFic: BigNumber, + reserveOutFic: BigNumber, + priceAverageIn: BigNumber, + priceAverageOut: BigNumber, +): BigNumber { + // default value + let firstAmountOut = amountOut; + + // if trade is in the good direction + if (reserveOutFic.mul(priceAverageIn).gt(reserveInFic.mul(priceAverageOut))) { + // pre-compute all operands + const reserveOutFicPredictedFees = reserveInFic + .mul(FEES_LP) + .mul(priceAverageOut) + .div(priceAverageIn); + const toAdd = reserveOutFic + .mul(FEES_TOTAL_REVERSED) + .mul(2) + .add(reserveOutFicPredictedFees); + const toDiv = FEES_TOTAL_REVERSED.mul(2); + const inSqrt = reserveOutFic + .mul(reserveOutFicPredictedFees) + .mul(4) + .mul(FEES_TOTAL_REVERSED) + .mul(FEES_BASE.sub(FEES_POOL)) + .div(FEES_LP) + .add(reserveOutFicPredictedFees.pow(2)); + + // reverse sqrt check to only compute sqrt if really needed + if (inSqrt.gt(toAdd.sub(amountOut.mul(toDiv)).pow(2))) { + firstAmountOut = toAdd.sub(sqrt(inSqrt)).div(toDiv); + } + } + + return firstAmountOut; +} + +// apply uniswap k const rule. amountIn -> amountOut +// return [amountOut, newResIn, newResOut, newResInFic, newResOutFic] +function applyKConstRuleOut( + amountIn: BigNumber, + reserveIn: BigNumber, + reserveOut: BigNumber, + reserveInFic: BigNumber, + reserveOutFic: BigNumber, +): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { + // k const rule + const amountInWithFee = amountIn.mul(FEES_TOTAL_REVERSED); + const numerator = amountInWithFee.mul(reserveOutFic); + const denominator = reserveInFic.mul(FEES_BASE).add(amountInWithFee); + if (denominator.eq(0)) throw new Error('SMARDEX_K_ERROR'); + + const amountOut = numerator.div(denominator); + + // update new reserves and add lp-fees to pools + const amountInWithFeeLp = amountIn + .mul(FEES_LP) + .add(amountInWithFee) + .div(FEES_BASE); + const newResIn = reserveIn.add(amountInWithFeeLp); + const newResInFic = reserveInFic.add(amountInWithFeeLp); + const newResOut = reserveOut.sub(amountOut); + const newResOutFic = reserveOutFic.sub(amountOut); + + return [amountOut, newResIn, newResOut, newResInFic, newResOutFic]; +} + +// apply uniswap k const rule. amountOut -> amountIn +// returns [amountIn, newResIn, newResOut, newResInFic, newResOutFic] +function applyKConstRuleIn( + amountOut: BigNumber, + reserveIn: BigNumber, + reserveOut: BigNumber, + reserveInFic: BigNumber, + reserveOutFic: BigNumber, +): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { + // k const rule + const numerator = reserveInFic.mul(amountOut).mul(FEES_BASE); + const denominator = reserveOutFic.sub(amountOut).mul(FEES_TOTAL_REVERSED); + if (denominator.eq(0)) throw new Error('SMARDEX_K_ERROR'); + + const amountIn = numerator.div(denominator).add(1); + + // update new reserves + const amountInWithFeeLp = FEES_TOTAL_REVERSED.add(FEES_LP) + .mul(amountIn) + .div(FEES_BASE); + const newResIn = reserveIn.add(amountInWithFeeLp); + const newResInFic = reserveInFic.add(amountInWithFeeLp); + const newResOut = reserveOut.sub(amountOut); + const newResOutFic = reserveOutFic.sub(amountOut); + + return [amountIn, newResIn, newResOut, newResInFic, newResOutFic]; +} + +/** + * Compute fictive reserves based on current reserves state + * + * @param {BigNumber} reserveIn the reserves of input token. + * @param {BigNumber} reserveOut the reserves of output token. + * @param {BigNumber} reserveInFic the fictive reserves of input token. + * @param {BigNumber} reserveOutFic the fictive reserves of output token. + * @returns {Array} [ficIn, ficOut] + */ +export function computeReserveFic( + reserveIn: BigNumber, + reserveOut: BigNumber, + reserveInFic: BigNumber, + reserveOutFic: BigNumber, +): [BigNumber, BigNumber] { + if (reserveOut.mul(reserveInFic).lt(reserveIn.mul(reserveOutFic))) { + const temp = reserveOut + .mul(reserveOut) + .div(reserveOutFic) + .mul(reserveInFic) + .div(reserveIn); + const newResFicIn = temp + .mul(reserveInFic) + .div(reserveOutFic) + .add(reserveOut.mul(reserveInFic).div(reserveOutFic)); + const newResFicOut = reserveOut.add(temp); + + return [newResFicIn.div(4), newResFicOut.div(4)]; + } + const newResFicIn = reserveInFic + .mul(reserveOut) + .div(reserveOutFic) + .add(reserveIn); + const newResFicOut = reserveIn + .mul(reserveOutFic) + .div(reserveInFic) + .add(reserveOut); + + return [newResFicIn.div(4), newResFicOut.div(4)]; +} + +/** + * Simulate a full trasaction, if you know the "in" token quantity, provide you the "out" and all reserves change + * Use case: you want to receive exactly amountOut and want to know the exact amountIn to send. + * @param {BigNumber} amountIn the desired input amount of the trade. + * @param {BigNumber} reserveIn the reserves of input token. + * @param {BigNumber} reserveOut the reserves of output token. + * @param {BigNumber} reserveInFic the fictive reserves of input token. + * @param {BigNumber} reserveOutFic the fictive reserves of output token. + * @param {BigNumber} priceAverageIn the price average of input token. + * @param {BigNumber} priceAverageOut the price average of output token. + * @returns {Array} [amountOut, newResIn, newResOut, newResInFic, newResOutFic] + */ +export function getAmountOut( + amountIn: BigNumber, + reserveIn: BigNumber, + reserveOut: BigNumber, + reserveInFic: BigNumber, + reserveOutFic: BigNumber, + priceAverageIn: BigNumber, + priceAverageOut: BigNumber, +): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { + if (amountIn.lt(0)) throw new Error('INSUFFICIENT_INPUT_AMOUNT'); + if (reserveIn.lt(0) || reserveOut.lt(0)) + throw new Error('INSUFFICIENT_LIQUIDITY'); + if (reserveInFic.lt(0) || reserveOutFic.lt(0)) + throw new Error('INSUFFICIENT_LIQUIDITY'); + + let reserveInFicUpdated = BigNumber.from(reserveInFic); + let reserveOutFicUpdated = BigNumber.from(reserveOutFic); + + const amountWithFees = amountIn.mul(FEES_TOTAL_REVERSED).div(FEES_BASE); + const firstAmount = computeFirstTradeQtyIn( + amountWithFees, + reserveInFic, + reserveOutFic, + priceAverageIn, + priceAverageOut, + ); + + // if there are 2 trades: 1st trade mustn't re-compute ReserveFic, 2nd should + if ( + firstAmount.eq(amountWithFees) && + ratioApproxEq(reserveInFic, reserveOutFic, priceAverageIn, priceAverageOut) + ) { + [reserveInFicUpdated, reserveOutFicUpdated] = computeReserveFic( + reserveIn, + reserveOut, + reserveInFic, + reserveOutFic, + ); + } + + // Avoid K constant division by 0 + if (reserveInFicUpdated.lte('0')) + return [ + utils.parseEther('0'), + reserveIn, + reserveOut, + reserveInFicUpdated, + reserveOutFicUpdated, + ]; + + const firstAmountNoFees = firstAmount.mul(FEES_BASE).div(FEES_TOTAL_REVERSED); + let [amountOut, newResIn, newResOut, newResInFic, newResOutFic] = + applyKConstRuleOut( + firstAmountNoFees, + reserveIn, + reserveOut, + reserveInFicUpdated, + reserveOutFicUpdated, + ); + + // if we need a second trade + if (firstAmount.lt(amountWithFees) && firstAmountNoFees.lt(amountIn)) { + [newResInFic, newResOutFic] = computeReserveFic( + newResIn, + newResOut, + newResInFic, + newResOutFic, + ); + + // Avoid K constant division by 0 + if (newResInFic.lte('0')) + return [ + utils.parseEther('0'), + reserveIn, + reserveOut, + reserveInFicUpdated, + reserveOutFicUpdated, + ]; + + let secondAmountOutNoFees: BigNumber; + [secondAmountOutNoFees, newResIn, newResOut, newResInFic, newResOutFic] = + applyKConstRuleOut( + amountIn.sub(firstAmountNoFees), + newResIn, + newResOut, + newResInFic, + newResOutFic, + ); + amountOut = amountOut.add(secondAmountOutNoFees); + } + + if ( + newResIn.lte(0) || + newResOut.lte(0) || + newResInFic.lte(0) || + newResOutFic.lte(0) + ) { + throw new Error('INSUFFICIENT_LIQUIDITY'); + } + return [amountOut, newResIn, newResOut, newResInFic, newResOutFic]; +} + +/** + * Simulate a full transaction, if you know the "out" token quantity, provide you the "in" and all reserves change + * Use case: you want to receive exactly amountOut and want to know the exact amountIn to send. + * @param {BigNumber} amountOut the desired output amount of the trade. + * @param {BigNumber} reserveIn the reserves of input token. + * @param {BigNumber} reserveOut the reserves of output token. + * @param {BigNumber} reserveInFic the fictive reserves of input token. + * @param {BigNumber} reserveOutFic the fictive reserves of output token. + * @param {BigNumber} priceAverageIn the price average of input token. + * @param {BigNumber} priceAverageOut the price average of output token. + * @returns {Array} [amountIn, newResIn, newResOut, newResInFic, newResOutFic] + */ +export function getAmountIn( + amountOut: BigNumber, + reserveIn: BigNumber, + reserveOut: BigNumber, + reserveInFic: BigNumber, + reserveOutFic: BigNumber, + priceAverageIn: BigNumber, + priceAverageOut: BigNumber, +): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { + if (amountOut.lt(0)) throw new Error('INSUFFICIENT_OUTPUT_AMOUNT'); + if (reserveIn.lt(0) || reserveOut.lt(0)) + throw new Error('INSUFFICIENT_LIQUIDITY'); + if (reserveInFic.lt(0) || reserveOutFic.lt(0)) + throw new Error('INSUFFICIENT_LIQUIDITY'); + + let reserveInFicUpdated = BigNumber.from(reserveInFic); + let reserveOutFicUpdated = BigNumber.from(reserveOutFic); + + const firstAmount = computeFirstTradeQtyOut( + amountOut, + reserveInFic, + reserveOutFic, + priceAverageIn, + priceAverageOut, + ); + + // if there are 2 trades: 1st trade mustn't re-compute ReserveFic, 2nd should + if ( + firstAmount.eq(amountOut) && + ratioApproxEq(reserveInFic, reserveOutFic, priceAverageIn, priceAverageOut) + ) { + [reserveInFicUpdated, reserveOutFicUpdated] = computeReserveFic( + reserveIn, + reserveOut, + reserveInFic, + reserveOutFic, + ); + } + + // Avoid K constant division by 0 + if (reserveInFic.lte('0')) + return [ + utils.parseEther('0'), + reserveIn, + reserveOut, + reserveInFicUpdated, + reserveOutFicUpdated, + ]; + + let [amountIn, newResIn, newResOut, newResInFic, newResOutFic] = + applyKConstRuleIn( + firstAmount, + reserveIn, + reserveOut, + reserveInFicUpdated, + reserveOutFicUpdated, + ); + + // if we need a second trade + if (firstAmount.lt(amountOut)) { + // in the second trade ALWAYS recompute fictive reserves + [newResInFic, newResOutFic] = computeReserveFic( + newResIn, + newResOut, + newResInFic, + newResOutFic, + ); + + // Avoid K constant division by 0 + if (newResInFic.lte('0')) + return [ + utils.parseEther('0'), + reserveIn, + reserveOut, + reserveInFicUpdated, + reserveOutFicUpdated, + ]; + + let secondAmountIn: BigNumber; + [secondAmountIn, newResIn, newResOut, newResInFic, newResOutFic] = + applyKConstRuleIn( + amountOut.sub(firstAmount), + newResIn, + newResOut, + newResInFic, + newResOutFic, + ); + amountIn = amountIn.add(secondAmountIn); + } + + if ( + newResIn.lte(0) || + newResOut.lte(0) || + newResInFic.lte(0) || + newResOutFic.lte(0) + ) { + throw new Error('INSUFFICIENT_LIQUIDITY'); + } + return [amountIn, newResIn, newResOut, newResInFic, newResOutFic]; +} + +/** + * Computes the priceAverageIn and priceAverageOut. + * Use case: you want to send an exact amount of tokenIn and know exactly how much you it will give you of tokenOut. + * Price averages are modified only if current timestamp does not match last timestamp + * @param {BigNumber} reserveFicIn the fictuve reserves of input token. + * @param {BigNumber} reserveFicOut the fictuve reserves of output token. + * @param {number} priceAverageLastTimestamp last timestamp in seconds of price average values. + * @param {BigNumber} priceAverageIn the latest price average of input token. + * @param {BigNumber} priceAverageOut the latest price average of output token. + * @param {number} currentTimestampInSecond current timestamp in seconds. + * @returns {Array} [priceAverageIn, priceAverageOut] + */ +export function getUpdatedPriceAverage( + reserveFicIn: BigNumber, + reserveFicOut: BigNumber, + priceAverageLastTimestamp: number, + priceAverageIn: BigNumber, + priceAverageOut: BigNumber, + currentTimestampInSecond: number, +): [BigNumber, BigNumber] { + if (currentTimestampInSecond < priceAverageLastTimestamp) + throw new Error('INVALID_TIMESTAMP'); + + // very first time + if ( + priceAverageLastTimestamp === 0 || + priceAverageIn.eq(0) || + priceAverageOut.eq(0) + ) { + return [reserveFicIn, reserveFicOut]; + } + + // another tx has been done in the same block + if (priceAverageLastTimestamp === currentTimestampInSecond) { + return [priceAverageIn, priceAverageOut]; + } + + // need to compute new linear-average price + // compute new price: + const timeDiff = Math.min( + currentTimestampInSecond - priceAverageLastTimestamp, + MAX_BLOCK_DIFF_SECONDS, + ); + + const priceAverageInRet = reserveFicIn; + const priceAverageOutRet = priceAverageOut + .mul(priceAverageInRet) + .mul(MAX_BLOCK_DIFF_SECONDS - timeDiff) + .div(priceAverageIn) + .add(reserveFicOut.mul(timeDiff)) + .div(MAX_BLOCK_DIFF_SECONDS); + + return [priceAverageInRet, priceAverageOutRet]; +} + +/** + * Computes the amount of tokenOut, at the precision of 1 wei. + * Use case: you want to send an exact amount of tokenIn and know exactly how much you it will give you of tokenOut. + * WARNING: token0 and token1 are pair tokens which addresses hexadecimal's values are sorted as token0 < token1. + * @param {string} token0 the currency address of token0. + * @param {string} token1 the currency address of token1. + * @param {BigNumber} reserve0 the reserves of token0. + * @param {BigNumber} reserve1 the reserves of token1. + * @param {BigNumber} reserve0Fic the fictionnal reserves of token0. + * @param {BigNumber} reserve1Fic the fictionnal reserves of token1. + * @param {BigNumber} tokenAmountIn the input amount of the trade. + * @param {BigNumber} tokenAddressIn address of the input token. + * @param {number} priceAverageLastTimestamp: timestamp in seconds of latest price average. + * @param {BigNumber} priceAverage0 latest price average of token0. + * @param {BigNumber} priceAverage1 latest price average of token1. + * @param {number} forcedPriceAverageTimestamp: current timestamp or timestamp of the trade in seconds. + * @returns {Object} { currency, amount, amountMax, newResIn, newResOut, newResInFic, newResOutFic } + */ +export function computeAmountOut( + token0: string, + token1: string, + reserve0: BigNumber, + reserve1: BigNumber, + reserve0Fic: BigNumber, + reserve1Fic: BigNumber, + tokenAmountIn: BigNumber, + tokenAddressIn: string, + priceAverageLastTimestamp: number, + priceAverage0: BigNumber, + priceAverage1: BigNumber, + forcedPriceAverageTimestamp: number = Math.ceil(Date.now() / 1000) + + LATENCY_OFFSET_SECONDS, +): CurrencyAmount { + if (tokenAddressIn === token0) { + const [newPriceAverage0, newPriceAverage1] = getUpdatedPriceAverage( + reserve0Fic, + reserve1Fic, + priceAverageLastTimestamp, + priceAverage0, + priceAverage1, + forcedPriceAverageTimestamp, + ); + + const [amountOut, newRes0, newRes1, newRes0Fic, newRes1Fic] = getAmountOut( + tokenAmountIn, + reserve0, + reserve1, + reserve0Fic, + reserve1Fic, + newPriceAverage0, + newPriceAverage1, + ); + // const [amountMax] = getAmountOut( + // tokenAmountIn, + // reserve0, + // reserve1, + // reserve0Fic.sub(1).lt(0) ? reserve0Fic : reserve0Fic.sub(1), + // reserve1Fic, + // newPriceAverage0, + // newPriceAverage1, + // ); + + return { + currency: token1, + amount: amountOut, + amountMax: amountOut, // TODO is it still useful ? + newRes0, + newRes1, + newRes0Fic, + newRes1Fic, + newPriceAverage0, + newPriceAverage1, + }; + } + + // token1 is tokenIn + const [newPriceAverage1, newPriceAverage0] = getUpdatedPriceAverage( + reserve1Fic, + reserve0Fic, + priceAverageLastTimestamp, + priceAverage1, + priceAverage0, + forcedPriceAverageTimestamp, + ); + + const [amountOut, newRes1, newRes0, newRes1Fic, newRes0Fic] = getAmountOut( + tokenAmountIn, + reserve1, + reserve0, + reserve1Fic, + reserve0Fic, + newPriceAverage1, + newPriceAverage0, + ); + // const [amountMax] = getAmountOut( + // tokenAmountIn, + // reserve1, + // reserve0, + // reserve1Fic.sub(1).lt(0) ? reserve1Fic : reserve1Fic.sub(1), + // reserve0Fic, + // newPriceAverage1, + // newPriceAverage0, + // ); + + return { + currency: token0, + amount: amountOut, + amountMax: amountOut, // TODO is it still useful ? + newRes0, + newRes1, + newRes0Fic, + newRes1Fic, + newPriceAverage0, + newPriceAverage1, + forcedPriceAverageTimestamp, + }; +} + +/** + * Computes the amount of tokenIn, at the precision of 1 wei. + * Use case: you want to receive exactly tokenOut amount and want to know the exact tokenIn amount to send. + * WARNING: token0 and token1 are pair tokens which addresses hexadecimal's values are sorted as token0 < token1. + * @param {string} token0 the currency address of token0. + * @param {string} token1 the currency address of token1. + * @param {BigNumber} reserve0 the reserves of token0. + * @param {BigNumber} reserve1 the reserves of token1. + * @param {BigNumber} reserve0Fic the fictionnal reserves of token0. + * @param {BigNumber} reserve1Fic the fictionnal reserves of token1. + * @param {BigNumber} tokenAmountOut the output amount of the trade. + * @param {BigNumber} tokenAddressOut address of the output token. + * @param {number} priceAverageLastTimestamp timestamp in seconds of latest price average. + * @param {BigNumber} priceAverage0 latest price average of token0. + * @param {BigNumber} priceAverage1 latest price average of token1. + * @param {number} forcedPriceAverageTimestamp current timestamp or timestamp of the trade in seconds. + * @returns {Object} { currency, amount, amountMax, newResIn, newResOut, newResInFic, newResOutFic } + */ +export function computeAmountIn( + token0: string, + token1: string, + reserve0: BigNumber, + reserve1: BigNumber, + reserve0Fic: BigNumber, + reserve1Fic: BigNumber, + tokenAmountOut: BigNumber, + tokenAddressOut: string, + priceAverageLastTimestamp: number, + priceAverage0: BigNumber, + priceAverage1: BigNumber, + forcedPriceAverageTimestamp: number = Math.ceil(Date.now() / 1000) + + LATENCY_OFFSET_SECONDS, +): CurrencyAmount { + if (tokenAddressOut === token0) { + const [newPriceAverage1, newPriceAverage0] = getUpdatedPriceAverage( + reserve1Fic, + reserve0Fic, + priceAverageLastTimestamp, + priceAverage1, + priceAverage0, + forcedPriceAverageTimestamp, + ); + + const [amountIn, newRes1, newRes0, newRes1Fic, newRes0Fic] = getAmountIn( + tokenAmountOut, + reserve1, + reserve0, + reserve1Fic, + reserve0Fic, + newPriceAverage1, + newPriceAverage0, + ); + // const [amountMax] = getAmountIn( + // tokenAmountOut, + // reserve1, + // reserve0, + // reserve1Fic, + // reserve0Fic.sub(1).lt(0) ? reserve0Fic : reserve0Fic.sub(1), + // newPriceAverage1, + // newPriceAverage0, + // ); + + return { + currency: token1, + amount: amountIn, + amountMax: amountIn, // TODO is it still useful ? + newRes0, + newRes1, + newRes0Fic, + newRes1Fic, + newPriceAverage0, + newPriceAverage1, + }; + } + + // token1 is tokenOut + const [newPriceAverage0, newPriceAverage1] = getUpdatedPriceAverage( + reserve0Fic, + reserve1Fic, + priceAverageLastTimestamp, + priceAverage0, + priceAverage1, + forcedPriceAverageTimestamp, + ); + + const [amountIn, newRes0, newRes1, newRes0Fic, newRes1Fic] = getAmountIn( + tokenAmountOut, + reserve0, + reserve1, + reserve0Fic, + reserve1Fic, + newPriceAverage0, + newPriceAverage1, + ); + + // const [amountMax] = getAmountIn( + // tokenAmountOut, + // reserve0, + // reserve1, + // reserve0Fic, + // reserve1Fic.sub(1).lt(0) ? reserve1Fic : reserve1Fic.sub(1), + // newPriceAverage0, + // newPriceAverage1, + // ); + + return { + currency: token0, + amount: amountIn, + amountMax: amountIn, // TODO is it still useful ? + newRes0, + newRes1, + newRes0Fic, + newRes1Fic, + newPriceAverage0, + newPriceAverage1, + forcedPriceAverageTimestamp, + }; +} + +/** + * Computes price impact + * you can manually verify the values using https://www.calculatorsoup.com/calculators/algebra/percent-change-calculator.php + * @param {string[]} path array of token addresses composing the trade (reverse order for EXACT_OUTPUT). + * @param {Pair[]} pairs array of pairs composing the trade (reverse order for EXACT_OUTPUT). + * @param {BigNumber} inputAmount the input amount of the trade. + * @param {BigNumber} outputAmount the output amount of the trade, calculated with computeAmountOut. + * @returns {BigNumber} the percent change (not difference) between the mid price and the execution price, i.e. price impact. + */ +export function computePriceImpact( + path: string[], + pairs: Pair[], + inputAmount: BigNumber, + outputAmount: BigNumber, +): BigNumber { + // Intermediate results are not exact relative to tokens decimals but the returned result is independant of decimals differences + let initalPrice = utils.parseEther('1'); + const midPrice = priceRatio(outputAmount, inputAmount); + + // returns 100% price impact + if (midPrice.lte(0)) return utils.parseEther('1'); + + for (let i = 0; i < pairs.length; i += 1) { + if ( + !pairs[i].prevReserveFic1 || + !pairs[i].prevReserveFic0 || + pairs[i].prevReserveFic1?.eq(0) || + pairs[i].prevReserveFic0?.eq(0) + ) { + return utils.parseEther('1'); + } + + const refIsToken0 = path[i] === pairs[i].token0; + initalPrice = initalPrice + .mul(refIsToken0 ? pairs[i].prevReserveFic1! : pairs[i].prevReserveFic0!) + .div(refIsToken0 ? pairs[i].prevReserveFic0! : pairs[i].prevReserveFic1!); + } + return priceRatio(initalPrice.sub(midPrice).abs(), initalPrice); +} + +/** + * Comparator function to sort best trades + * Trades are sorted by their output amounts in decreasing order, first + * Then they are sorted by their input amounts in increasing order + * i.e. the best trades have the most outputs for the least inputs and are sorted first. + * @param {CurrencyAmount} inputA trade A input amount. + * @param {CurrencyAmount} outputA trade B input amount. + * @param {CurrencyAmount} inputB trade A input amount. + * @param {CurrencyAmount} outputB trade A input amount. + * @return {number} 1 when 'trade B' is better than 'trade A', -1 when 'trade A' is better than 'B', 0 when trades are equal. + */ +export function inputOutputComparator( + inputA: CurrencyAmount, + outputA: CurrencyAmount, + inputB: CurrencyAmount, + outputB: CurrencyAmount, +): number { + // must have same input and output token for comparison + // invariant(inputA.currency === inputB.currency, 'INPUT_CURRENCY'); + // invariant(outputA.currency === outputB.currency, 'OUTPUT_CURRENCY'); + if (outputA.amount.eq(outputB.amount)) { + if (inputA.amount.eq(inputB.amount)) { + return 0; + } + // trade A requires less input than trade B, so A should come first + if (inputA.amount.lt(inputB.amount)) { + return -1; + } + return 1; + } + // tradeA has less output than trade B, so should come second + if (outputA.amount.lt(outputB.amount)) { + return 1; + } + return -1; +} + +/** + * Compares trades extending inputOutputComparator ranking with price impact and path length + * @param {Trade} a trade A to compare + * @param {Trade} b trade B to compare + * @return {number} 1 when 'b' is better than 'a', -1 when 'a' is better than 'b', 0 when trades are equal + */ +export function tradeComparator(a: Trade, b: Trade): number { + const ioComp = inputOutputComparator( + a.amountIn, + a.amountOut, + b.amountIn, + b.amountOut, + ); + if (ioComp !== 0) { + return ioComp; + } + + // consider lowest priceImpact next, since these are less likely to fail + if (a.priceImpact!.lt(b.priceImpact!)) { + return -1; + } + if (a.priceImpact!.gt(b.priceImpact!)) { + return 1; + } + + // finally consider the number of hops since each hop costs gas + return a.route.path.length - b.route.path.length; +} + +/** + * Extracts the token addresses composing the route ordered in the route's direction starting with inputCurrency. + * @param {Pair[]} pairs array of pairs composing the trade. + * @param {string} inputCurrency the currency from which the route starts. + * @return {string[]} Array of token addresses composing the route ordered in the route's direction starting with inputCurrency. + */ +export function getPathFromInput( + pairs: Pair[], + inputCurrency: string, +): string[] { + const path: string[] = []; + for (let i = 0; i < pairs.length; i += 1) { + const pairCurrencyIn = + path.length === 0 ? inputCurrency : path[path.length - 1]; + const [tokenIn, tokenOut] = + pairCurrencyIn === pairs[i].token0 + ? [pairs[i].token0, pairs[i].token1] + : [pairs[i].token1, pairs[i].token0]; + if (path.length === 0) { + path.push(tokenIn); + } + path.push(tokenOut); + } + return path; +} + +/** + * Extracts the token addresses composing the route ordered in the route's direction ending with outputCurrency. + * @param {Pair[]} pairs array of pairs composing the trade. + * @param {string} outputCurrency the currency for which the route finishes. + * @return {string[]} Array of token addresses composing the route ordered in the route's direction ending with outputCurrency. + */ +export function getPathFromOutput( + pairs: Pair[], + outputCurrency: string, +): string[] { + const path: string[] = []; + for (let i = pairs.length - 1; i >= 0; i -= 1) { + const pairCurrencyOut = + path.length === 0 ? outputCurrency : path[path.length - 1]; + const [tokenOut, tokenIn] = + pairCurrencyOut === pairs[i].token0 + ? [pairs[i].token0, pairs[i].token1] + : [pairs[i].token1, pairs[i].token0]; + if (path.length === 0) { + path.push(tokenOut); + } + path.push(tokenIn); + } + return path.reverse(); +} + +// Computes the best trade for the exact amount in, function is used internally with recursion +// extended parameters includes 'tradeTimestamp' which represents the current timestamp in seconds +// other parameters are used by the function internally in for recursion loop +function bestTradeExactInInternal( + pairs: Pair[], + currencyAmountIn: CurrencyAmount, + currencyOut: string, + tradeTimestamp: number, + { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, + // used in recursion. + currentPairs: Pair[] = [], + nextAmountIn: CurrencyAmount = currencyAmountIn, + bestTrades: Trade[] = [], +): Trade[] { + // invariant(pairs.length > 0, 'PAIRS'); + // invariant(maxHops > 0, 'MAX_HOPS'); + // invariant( + // currencyAmountIn.currency === nextAmountIn.currency || + // currentPairs.length > 0, + // 'INVALID_RECURSION', + // ); + + for (let i = 0; i < pairs.length; i += 1) { + const pair = { ...pairs[i] }; + + // pair irrelevant + if ( + pair.token0 !== nextAmountIn.currency && + pair.token1 !== nextAmountIn.currency + ) + continue; + if (pair.reserve0.eq(0) || pair.reserve1.eq(0)) continue; + if (pair.reserve0LastFictive.eq(0) || pair.reserve1LastFictive.eq(0)) + continue; + + // breaks arbitrage loops in case config disabled such behaviour + const path = getPathFromInput( + [...currentPairs, pair], + currencyAmountIn.currency, + ); + if ( + !arbitrage && + path.find((token, arrayIndex) => arrayIndex !== path.indexOf(token)) + ) + continue; + + let amountOutData: CurrencyAmount; + try { + amountOutData = computeAmountOut( + pair.token0, + pair.token1, + pair.reserve0, + pair.reserve1, + pair.reserve0LastFictive, + pair.reserve1LastFictive, + nextAmountIn.amount, + nextAmountIn.currency, + pair.priceAverageLastTimestamp, + pair.priceAverage0, + pair.priceAverage1, + pair?.forcedPriceAverageTimestamp, + ); + // Update pair's info + pair.reserve0 = amountOutData.newRes0 || pair.reserve0; + pair.reserve1 = amountOutData.newRes1 || pair.reserve1; + pair.prevReserveFic0 = pair.reserve0LastFictive; + pair.prevReserveFic1 = pair.reserve1LastFictive; + pair.reserve0LastFictive = + amountOutData.newRes0Fic || pair.reserve0LastFictive; + pair.reserve1LastFictive = + amountOutData.newRes1Fic || pair.reserve1LastFictive; + pair.priceAverage0 = amountOutData.newPriceAverage0 || pair.priceAverage0; + pair.priceAverage1 = amountOutData.newPriceAverage1 || pair.priceAverage1; + pair.forcedPriceAverageTimestamp = + amountOutData?.forcedPriceAverageTimestamp || tradeTimestamp; + } catch (error: any) { + if (error.name === 'SmarDexSDK') { + continue; + } + throw error; + } + + const selectedPairs = [...currentPairs, pair]; + + // we have arrived at the output token, so this is the final trade of one of the paths + if (amountOutData.currency === currencyOut) { + sortedInsert( + bestTrades, + { + route: { + pairs: selectedPairs, + path, + input: currencyAmountIn.currency, + output: currencyOut, + }, + amountIn: currencyAmountIn, + amountOut: amountOutData, + tradeType: TradeType.EXACT_INPUT, + priceImpact: computePriceImpact( + path, + selectedPairs, + currencyAmountIn.amount, + amountOutData.amount, + ), + }, + maxNumResults, + tradeComparator, + ); + } else if (maxHops > 1 && pairs.length > 1) { + const pairsExcludingThisPair = pairs.filter((_, index) => index !== i); + + // otherwise, consider all the other paths that lead from this token as long as we have not exceeded maxHops + bestTradeExactInInternal( + pairsExcludingThisPair, + currencyAmountIn, + currencyOut, + tradeTimestamp, + { + maxNumResults, + maxHops: maxHops - 1, + arbitrage, + }, + selectedPairs, + amountOutData, + bestTrades, + ); + } + } + return bestTrades; +} + +/** + * Given a list of pairs, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token + * amount to an output token, making at most `maxHops` hops. + * Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting + * the amount in among multiple routes. + * @param {Pair[]} pairs the pairs to consider in finding the best trade. + * @param {CurrencyAmount} currencyAmountIn provided currency with exact amount of input provided for thetrade. + * @param {string} currencyOut address of the desired currency requested in output. + * @param {Object} [option={maxNumResults=3,maxHops=3,arbitrage=false}] additional options, including: + * @param {number} option.maxNumResults maximum number of trade results to return. + * @param {number} option.maxHops maximum number of hops per individual trade, e.g. 1 hop goes through a single pair. + * @param {boolean} option.arbitrage to enable arbitrage loops in the returned trades (i.e. route can pass multiple times by the same token). + * @returns {Trade[]} Array of trades ordered by best trade first. + */ +export function bestTradeExactIn( + pairs: Pair[], + currencyAmountIn: CurrencyAmount, + currencyOut: string, + { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, +) { + return bestTradeExactInInternal( + pairs, + currencyAmountIn, + currencyOut, + Math.ceil(Date.now() / 1000) + LATENCY_OFFSET_SECONDS, + { + maxNumResults, + maxHops, + arbitrage, + }, + ); +} + +// Computes the best trade for the exact amount out, function is used internally with recursion +// extended parameters includes 'tradeTimestamp' which represents the current timestamp in seconds +// other parameters are used by the function internally in for recursion loop +function bestTradeExactOutInternal( + pairs: Pair[], + currencyIn: string, + currencyAmountOut: CurrencyAmount, + tradeTimestamp: number, + { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, + // used in recursion. + currentPairs: Pair[] = [], + nextAmountOut: CurrencyAmount = currencyAmountOut, + bestTrades: Trade[] = [], +): Trade[] { + // invariant(pairs.length > 0, 'PAIRS'); + // invariant(maxHops > 0, 'MAX_HOPS'); + // invariant( + // currencyAmountOut.currency === nextAmountOut.currency || + // currentPairs.length > 0, + // 'INVALID_RECURSION', + // ); + + for (let i = 0; i < pairs.length; i += 1) { + const pair = { ...pairs[i] }; + + // pair irrelevant + if ( + pair.token0 !== nextAmountOut.currency && + pair.token1 !== nextAmountOut.currency + ) + continue; + if (pair.reserve0.eq(0) || pair.reserve1.eq(0)) continue; + if (pair.reserve0LastFictive.eq(0) || pair.reserve1LastFictive.eq(0)) + continue; + + // breaks arbitrage loops in case config disabled such behaviour + const path = getPathFromOutput( + [pair, ...currentPairs], + currencyAmountOut.currency, + ); + if ( + !arbitrage && + path.find((token, arrayIndex) => arrayIndex !== path.indexOf(token)) + ) + continue; + + let amountInData: CurrencyAmount; + try { + amountInData = computeAmountIn( + pair.token0, + pair.token1, + pair.reserve0, + pair.reserve1, + pair.reserve0LastFictive, + pair.reserve1LastFictive, + nextAmountOut.amount, + nextAmountOut.currency, + pair.priceAverageLastTimestamp, + pair.priceAverage0, + pair.priceAverage1, + pair?.forcedPriceAverageTimestamp, + ); + // Update pair's info + pair.reserve0 = amountInData.newRes0 || pair.reserve0; + pair.reserve1 = amountInData.newRes1 || pair.reserve1; + pair.prevReserveFic0 = pair.reserve0LastFictive; + pair.prevReserveFic1 = pair.reserve1LastFictive; + pair.reserve0LastFictive = + amountInData.newRes0Fic || pair.reserve0LastFictive; + pair.reserve1LastFictive = + amountInData.newRes1Fic || pair.reserve1LastFictive; + pair.priceAverage0 = amountInData.newPriceAverage0 || pair.priceAverage0; + pair.priceAverage1 = amountInData.newPriceAverage1 || pair.priceAverage1; + pair.forcedPriceAverageTimestamp = + amountInData?.forcedPriceAverageTimestamp || tradeTimestamp; + } catch (error: any) { + if (error.name === 'SmarDexSDK') { + continue; + } + throw error; + } + + const selectedPairs = [pair, ...currentPairs]; + + // we have arrived at the input token, so this is the final trade of one of the paths + if (amountInData.currency === currencyIn) { + sortedInsert( + bestTrades, + { + route: { + pairs: selectedPairs, + path, + input: currencyIn, + output: currencyAmountOut.currency, + }, + amountIn: amountInData, + amountOut: currencyAmountOut, + tradeType: TradeType.EXACT_OUTPUT, + priceImpact: computePriceImpact( + path, + selectedPairs, + amountInData.amount, + currencyAmountOut.amount, + ), + }, + maxNumResults, + tradeComparator, + ); + } else if (maxHops > 1 && pairs.length > 1) { + const pairsExcludingThisPair = pairs.filter((_, index) => index !== i); + + // otherwise, consider all the other paths that lead from this token as long as we have not exceeded maxHops + bestTradeExactOutInternal( + pairsExcludingThisPair, + currencyIn, + currencyAmountOut, + tradeTimestamp, + { + maxNumResults, + maxHops: maxHops - 1, + arbitrage, + }, + selectedPairs, + amountInData, + bestTrades, + ); + } + } + return bestTrades; +} + +/** + * Given a list of pairs, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token + * amount to an output token, making at most `maxHops` hops. + * Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting + * the amount in among multiple routes. + * @param {Pair[]} pairs the pairs to consider in finding the best trade. + * @param {string} currencyIn address of the desired currency requested in input. + * @param {CurrencyAmount} currencyAmountOut currency with exact amount of output provided for thetrade. + * @param {Object} [option={maxNumResults=3,maxHops=3,arbitrage=false}] additional options, including: + * @param {number} option.maxNumResults maximum number of trade results to return. + * @param {number} option.maxHops maximum number of hops per individual trade, e.g. 1 hop goes through a single pair. + * @param {boolean} option.arbitrage to enable arbitrage loops in the returned trades (i.e. route can pass multiple times by the same token). + * @returns {Trade[]} Array of trades ordered by best trade first. + */ +export function bestTradeExactOut( + pairs: Pair[], + currencyIn: string, + currencyAmountOut: CurrencyAmount, + { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, +) { + return bestTradeExactOutInternal( + pairs, + currencyIn, + currencyAmountOut, + Math.ceil(Date.now() / 1000) + LATENCY_OFFSET_SECONDS, + { + maxNumResults, + maxHops, + arbitrage, + }, + ); +} +// constants to compute approximate equality +const APPROX_EQ_PRECISION: BigNumber = BigNumber.from(1); +const APPROX_EQ_BASE_PRECISION: BigNumber = BigNumber.from(1000000); + +/** + * Computes logarithm in base 2 for a given positive number. Result is rounded down + * + * @param {BigNumber} value - value to compute the log2 + * @returns {BigNumber} the log in base 2 of the value, 0 if given 0. + */ +export function log2(value: BigNumber): BigNumber { + let result = constants.Zero; + if (value.shr(128).gt(0)) { + // eslint-disable-next-line no-param-reassign + value = value.shr(128); + result = result.add(128); + } + if (value.shr(64).gt(0)) { + // eslint-disable-next-line no-param-reassign + value = value.shr(64); + result = result.add(64); + } + if (value.shr(32).gt(0)) { + // eslint-disable-next-line no-param-reassign + value = value.shr(32); + result = result.add(32); + } + if (value.shr(16).gt(0)) { + // eslint-disable-next-line no-param-reassign + value = value.shr(16); + result = result.add(16); + } + if (value.shr(8).gt(0)) { + // eslint-disable-next-line no-param-reassign + value = value.shr(8); + result = result.add(8); + } + if (value.shr(4).gt(0)) { + // eslint-disable-next-line no-param-reassign + value = value.shr(4); + result = result.add(4); + } + if (value.shr(2).gt(0)) { + // eslint-disable-next-line no-param-reassign + value = value.shr(2); + result = result.add(2); + } + if (value.shr(1).gt(0)) { + result = result.add(1); + } + return result; +} + +/** + * Computes the square root of a number. If the number is not a perfect square, the value is rounded down. + * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). + * + * @param {BigNumber} value - value to compute the square root + * @returns {BigNumber} the square root of the value + */ +export function sqrt(a: BigNumber): BigNumber { + if (a.eq(constants.Zero)) { + return constants.Zero; + } + + // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. + // + // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have + // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. + // + // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` + // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` + // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` + // + // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. + let result = constants.One.shl(log2(a).div(2).toNumber()); + + // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, + // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at + // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision + // into the expected uint128 result. + result = result.add(a.div(result)).shr(1); + result = result.add(a.div(result)).shr(1); + result = result.add(a.div(result)).shr(1); + result = result.add(a.div(result)).shr(1); + result = result.add(a.div(result)).shr(1); + result = result.add(a.div(result)).shr(1); + result = result.add(a.div(result)).shr(1); + return result.lt(a.div(result)) ? result : a.div(result); +} + +/** + * Evaluates the equality of two numbers at a precision of 1/1_000_000 + * + * @param {BigNumber} x - value to compare + * @param {BigNumber} y - value to compare + * @returns {boolean} true if numbers are approximatively equal at 1/1_000_000, false otherwise + */ +export function approxEq(x: BigNumber, y: BigNumber): true | false { + return x.gt(y) + ? x.lt(y.add(y.mul(APPROX_EQ_PRECISION).div(APPROX_EQ_BASE_PRECISION))) + : y.lt(x.add(x.mul(APPROX_EQ_PRECISION).div(APPROX_EQ_BASE_PRECISION))); +} + +/** + * Evaluates the equality of two ratio numbers at a precision of 1/1_000_000. xNum / xDen ~= yNum / yDen + * + * @param {BigNumber} _xNum - first number numerator + * @param {BigNumber} _xDen - first number denominator + * @param {BigNumber} _yNum - second number numerator + * @param {BigNumber} _yDen - second number denominator + * @returns {boolean} true if the two ratios are approximatively equal at 1/1_000_000, false otherwise + */ +export function ratioApproxEq( + _xNum: BigNumber, + _xDen: BigNumber, + _yNum: BigNumber, + _yDen: BigNumber, +): true | false { + return approxEq(_xNum.mul(_yDen), _xDen.mul(_yNum)); +} + +/** + * Computes the ratio of two numbers + * + * @param {BigNumber} numerator - numerator number + * @param {BigNumber} denominator - denominator number + * @returns {BigNumber} ratio of the two numbers. returns 0 if denominator is 0 + */ +export function priceRatio(numerator: BigNumber, denominator: BigNumber) { + if (denominator.eq(0)) return BigNumber.from(0); + return utils.parseEther(numerator.toString()).div(denominator); +} + +/** + * Given an array of items sorted by `comparator` function, insert an item into its sort index and constrain + * the size to `maxSize` by removing the last item + * WARNING: This function mutates the input array ! + * Inspired by Uniswap V2: https://github.com/Uniswap/sdk-core/blob/main/src/utils/sortedInsert.ts + * + * @param {T[]} items - array of items to insert result into + * @param {T} add - item to insert + * @param {number} maxSize - maximum size of the desired array + * @param {(a: T, b: T) => number} comparator - comparator function to sort the array + * @returns {T | null} the item which was removed from the array, or null if no item was removed + */ +export function sortedInsert( + items: T[], + add: T, + maxSize: number, + comparator: (a: T, b: T) => number, +): T | null { + // invariant(maxSize > 0, 'MAX_SIZE_ZERO'); + // this is an invariant because the interface cannot return multiple removed items if items.length exceeds maxSize + // invariant(items.length <= maxSize, 'ITEMS_SIZE'); + + // short circuit first item add + if (items.length === 0) { + items.push(add); + return null; + } + + const isFull = items.length === maxSize; + // short circuit if full and the additional item does not come before the last item + if (isFull && comparator(items[items.length - 1], add) <= 0) { + return add; + } + + let lo = 0; + let hi = items.length; + + while (lo < hi) { + // eslint-disable-next-line no-bitwise + const mid = (lo + hi) >>> 1; + if (comparator(items[mid], add) <= 0) { + lo = mid + 1; + } else { + hi = mid; + } + } + items.splice(lo, 0, add); + return isFull ? items.pop()! : null; +} diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 08e9e840a..6b513bc02 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -1,178 +1,850 @@ -import { AsyncOrSync } from 'ts-essentials'; import { - Token, + DEST_TOKEN_PARASWAP_TRANSFERS, + ETHER_ADDRESS, + NULL_ADDRESS, + Network, + SRC_TOKEN_PARASWAP_TRANSFERS, + SwapSide, +} from '../../constants'; +import { + AdapterExchangeParam, Address, ExchangePrices, + Log, + Logger, + NumberAsString, + PoolLiquidity, PoolPrices, - AdapterExchangeParam, SimpleExchangeParam, - PoolLiquidity, - Logger, + Token, + TransferFeeParams, + TxInfo, } from '../../types'; -import { SwapSide, Network } from '../../constants'; -import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { getDexKeysWithNetwork } from '../../utils'; -import { IDex } from '../../dex/idex'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { SmardexData } from './types'; +import { IDexHelper } from '../../dex-helper/index'; +import { AbiCoder, Interface } from '@ethersproject/abi'; +import { + SmardexPair, + SmardexPool, + SmardexPoolOrderedParams, + SmardexPoolState, +} from './types'; +import { + getBigIntPow, + getDexKeysWithNetwork, + isETHAddress, + prependWithOx, +} from '../../utils'; +import SmardexFactoryLayerOneABI from '../../abi/smardex/layer-1/smardex-factory.json'; +import SmardexFactoryLayerTwoABI from '../../abi/smardex/layer-2/smardex-factory.json'; +import SmardexPoolLayerOneABI from '../../abi/smardex/layer-1/smardex-pool.json'; +import SmardexPoolLayerTwoABI from '../../abi/smardex/layer-2/smardex-pool.json'; +import { DeepReadonly, AsyncOrSync } from 'ts-essentials'; import { SimpleExchange } from '../simple-exchange'; -import { SmardexConfig, Adapters } from './config'; -import { SmardexEventPool } from './smardex-pool'; +import { SmardexData } from '../smardex/types'; +import { IDex, StatefulEventSubscriber } from '../..'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { Adapters, SmardexConfig } from './config'; +import { Contract } from 'web3-eth-contract'; +import { directUniswapFunctionName } from '../uniswap-v2/uniswap-v2'; +import ParaSwapABI from '../../abi/IParaswap.json'; +import UniswapV2ExchangeRouterABI from '../../abi/UniswapV2ExchangeRouter.json'; +import { + UniswapDataLegacy, + UniswapParam, + UniswapV2Functions, +} from '../uniswap-v2/types'; +import { applyTransferFee } from '../../lib/token-transfer-fee'; +import erc20ABI from '../../abi/erc20.json'; +import _ from 'lodash'; +import { getAmountIn, getAmountOut } from './smardex-sdk'; +import { BigNumber } from 'ethers'; -export class Smardex extends SimpleExchange implements IDex { - protected eventPools: SmardexEventPool; +// event Sync (uint256 reserve0, uint256 reserve1, uint256 fictiveReserve0, uint256 fictiveReserve1, uint256 priceAverage0, uint256 priceAverage1) +export const SYNC_EVENT_TOPIC = + '0x2a368c7f33bb86e2d999940a3989d849031aff29b750f67947e6b8e8c3d2ffd6'; - readonly hasConstantPriceLargeAmounts = false; - // TODO: set true here if protocols works only with wrapped asset - readonly needWrapNative = true; +const DefaultUniswapV2PoolGasCost = 90 * 1000; - readonly isFeeOnTransferSupported = false; +const smardexPoolL1 = new Interface(SmardexPoolLayerOneABI); +const smardexPoolL2 = new Interface(SmardexPoolLayerTwoABI); - public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(SmardexConfig); +const coder = new AbiCoder(); +export class SmardexEventPool extends StatefulEventSubscriber { + constructor( + protected poolInterface: Interface, + protected dexHelper: IDexHelper, + private poolAddress: Address, + token0: Token, + token1: Token, + logger: Logger, + protected smardexFeesMultiCallEntry?: { + target: string; + callData: string; + }, + protected smardexFeesMulticallDecoder?: (values: any[]) => number, + ) { + super( + 'Smardex', + (token0.symbol || token0.address) + + '-' + + (token1.symbol || token1.address) + + ' pool', + dexHelper, + logger, + ); + } + + protected processLog( + state: DeepReadonly, + log: Readonly, + ): AsyncOrSync | null> { + if (log.topics[0] === SYNC_EVENT_TOPIC) return null; + const event = smardexPoolL1.parseLog(log); + switch (event.name) { + case 'Sync': + return { + reserves0: event.args.reserve0.toString(), + reserves1: event.args.reserve1.toString(), + fictiveReserves0: event.args.fictiveReserve0.toString(), + fictiveReserves1: event.args.fictiveReserve1.toString(), + priceAverageIn: event.args.priceAverageIn.toString(), + priceAverageOut: event.args.priceAverageOut.toString(), + feeCode: state.feeCode, + }; + } + return null; + } + + async generateState( + blockNumber: number | 'latest' = 'latest', + ): Promise> { + const coder = new AbiCoder(); + const dynamicFees = !!this.smardexFeesMultiCallEntry; + let calldata = [ + { + target: this.poolAddress, + callData: this.poolInterface.encodeFunctionData('getReserves', []), + }, + { + target: this.poolAddress, + callData: this.poolInterface.encodeFunctionData( + 'getFictiveReserves', + [], + ), + }, + + { + target: this.poolAddress, + callData: this.poolInterface.encodeFunctionData('getPriceAverage', []), + }, + ]; + if (dynamicFees) { + calldata.push(this.smardexFeesMultiCallEntry!); + } + + const data: { returnData: any[] } = + await this.dexHelper.multiContract.methods + .aggregate(calldata) + .call({}, blockNumber); + + const [reserves0, reserves1] = coder.decode( + ['uint112', 'uint112', 'uint32'], + data.returnData[0], + ); + + const [fictiveReserve0, fictiveReserve1] = coder.decode( + ['uint256', 'uint256'], + data.returnData[1], + ); + + const [priceAverageIn, priceAverageOut] = coder.decode( + ['uint256', 'uint256', 'uint256'], + data.returnData[2], + ); + + return { + reserves0: reserves0.toString(), + reserves1: reserves1.toString(), + fictiveReserves0: fictiveReserve0.toString(), + fictiveReserves1: fictiveReserve1.toString(), + priceAverageIn: priceAverageIn.toString(), + priceAverageOut: priceAverageOut.toString(), + feeCode: dynamicFees + ? this.smardexFeesMulticallDecoder!(data.returnData[3]) + : 700, // TODO: Ensure the fees are correct + }; + } +} + +function encodePools( + pools: SmardexPool[], + feeFactor: number, +): NumberAsString[] { + return pools.map(({ fee, direction, address }) => { + return ( + (BigInt(feeFactor - fee) << 161n) + + ((direction ? 0n : 1n) << 160n) + + BigInt(address) + ).toString(); + }); +} + +export class Smardex + extends SimpleExchange + implements IDex +{ + pairs: { [key: string]: SmardexPair } = {}; + feeFactor = 10000; + factory: Contract; + + routerInterface: Interface; + exchangeRouterInterface: Interface; + static directFunctionName = directUniswapFunctionName; + + factoryAddress: string; + routerAddress: string; + + initCode: string; logger: Logger; + readonly hasConstantPriceLargeAmounts = false; + readonly isFeeOnTransferSupported: boolean = true; + readonly SRC_TOKEN_DEX_TRANSFERS = 1; + readonly DEST_TOKEN_DEX_TRANSFERS = 1; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(SmardexConfig); + constructor( - readonly network: Network, - readonly dexKey: string, - readonly dexHelper: IDexHelper, - protected adapters = Adapters[network] || {}, // TODO: add any additional optional params to support other fork DEXes + protected network: Network, + dexKey: string, + public dexHelper: IDexHelper, ) { super(dexHelper, dexKey); this.logger = dexHelper.getLogger(dexKey); - this.eventPools = new SmardexEventPool( - dexKey, - network, - dexHelper, - this.logger, + const config = SmardexConfig[dexKey]; + this.routerAddress = config[network].router!; + this.factoryAddress = config[network].factoryAddress; + this.initCode = config[network].initCode; + const factoryAbi = this.isLayer1() + ? SmardexFactoryLayerOneABI + : SmardexFactoryLayerTwoABI; + this.factory = new dexHelper.web3Provider.eth.Contract( + factoryAbi as any, + this.factoryAddress, ); + this.routerInterface = new Interface(ParaSwapABI); + this.exchangeRouterInterface = new Interface(UniswapV2ExchangeRouterABI); } - // Initialize pricing is called once in the start of - // pricing service. It is intended to setup the integration - // for pricing requests. It is optional for a DEX to - // implement this function - async initializePricing(blockNumber: number) { - // TODO: complete me! - } - - // Returns the list of contract adapters (name and index) - // for a buy/sell. Return null if there are no adapters. getAdapters(side: SwapSide): { name: string; index: number }[] | null { - return this.adapters[side] ? this.adapters[side] : null; + return Adapters[this.network][side]; } - // Returns list of pool identifiers that can be used - // for a given swap. poolIdentifiers must be unique - // across DEXes. It is recommended to use - // ${dexKey}_${poolAddress} as a poolIdentifier async getPoolIdentifiers( - srcToken: Token, - destToken: Token, + _from: Token, + _to: Token, side: SwapSide, blockNumber: number, ): Promise { - // TODO: complete me! - return []; + const from = this.dexHelper.config.wrapETH(_from); + const to = this.dexHelper.config.wrapETH(_to); + + if (from.address.toLowerCase() === to.address.toLowerCase()) { + return []; + } + + const tokenAddress = [from.address.toLowerCase(), to.address.toLowerCase()] + .sort((a, b) => (a > b ? 1 : -1)) + .join('_'); + + const poolIdentifier = `${this.dexKey}_${tokenAddress}`; + return [poolIdentifier]; } - // Returns pool prices for amounts. - // If limitPools is defined only pools in limitPools - // should be used. If limitPools is undefined then - // any pools can be used. async getPricesVolume( - srcToken: Token, - destToken: Token, + _from: Token, + _to: Token, amounts: bigint[], side: SwapSide, blockNumber: number, + // list of pool identifiers to use for pricing, if undefined use all pools limitPools?: string[], - ): Promise> { - // TODO: complete me! - return null; + transferFees: TransferFeeParams = { + srcFee: 0, + destFee: 0, + srcDexFee: 0, + destDexFee: 0, + }, + ): Promise | null> { + try { + const from = this.dexHelper.config.wrapETH(_from); + const to = this.dexHelper.config.wrapETH(_to); + + if (from.address.toLowerCase() === to.address.toLowerCase()) { + return null; + } + + const tokenAddress = [ + from.address.toLowerCase(), + to.address.toLowerCase(), + ] + .sort((a, b) => (a > b ? 1 : -1)) + .join('_'); + + const poolIdentifier = `${this.dexKey}_${tokenAddress}`; + + if (limitPools && limitPools.every(p => p !== poolIdentifier)) + return null; + + await this.batchCatchUpPairs([[from, to]], blockNumber); + const isSell = side === SwapSide.SELL; + const pairParam = await this.getPairOrderedParams( + from, + to, + blockNumber, + transferFees.srcDexFee, + ); + + if (!pairParam) return null; + + const unitAmount = getBigIntPow(isSell ? from.decimals : to.decimals); + + const [unitVolumeWithFee, ...amountsWithFee] = applyTransferFee( + [unitAmount, ...amounts], + side, + isSell ? transferFees.srcFee : transferFees.destFee, + isSell ? SRC_TOKEN_PARASWAP_TRANSFERS : DEST_TOKEN_PARASWAP_TRANSFERS, + ); + + const unit = isSell + ? await this.getSellPricePath(unitVolumeWithFee, [pairParam]) + : await this.getBuyPricePath(unitVolumeWithFee, [pairParam]); + + const prices = isSell + ? await Promise.all( + amountsWithFee.map(amount => + this.getSellPricePath(amount, [pairParam]), + ), + ) + : await Promise.all( + amountsWithFee.map(amount => + this.getBuyPricePath(amount, [pairParam]), + ), + ); + + const [unitOutWithFee, ...outputsWithFee] = applyTransferFee( + [unit, ...prices], + side, + // This part is confusing, because we treat differently SELL and BUY fees + // If Buy, we should apply transfer fee on srcToken on top of dexFee applied earlier + // But for Sell we should apply only one dexFee + isSell ? transferFees.destDexFee : transferFees.srcFee, + isSell ? this.DEST_TOKEN_DEX_TRANSFERS : SRC_TOKEN_PARASWAP_TRANSFERS, + ); + + // As uniswapv2 just has one pool per token pair + return [ + { + prices: outputsWithFee, + unit: unitOutWithFee, + data: { + router: this.routerAddress, + path: [from.address.toLowerCase(), to.address.toLowerCase()], + factory: this.factoryAddress, + initCode: this.initCode, + feeFactor: this.feeFactor, + pools: [ + { + address: pairParam.exchange, + fee: parseInt(pairParam.fee), + direction: pairParam.direction, + }, + ], + }, + exchange: this.dexKey, + poolIdentifier, + gasCost: DefaultUniswapV2PoolGasCost, + poolAddresses: [pairParam.exchange], + }, + ]; + } catch (e) { + if (blockNumber === 0) + this.logger.error( + `Error_getPricesVolume: Aurelius block manager not yet instantiated`, + ); + this.logger.error(`Error_getPrices:`, e); + return null; + } + } + + async getBuyPricePath( + amount: bigint, + params: SmardexPoolOrderedParams[], + ): Promise { + let price = amount; + for (const param of params.reverse()) { + price = await this.getBuyPrice(param, price); + } + return price; + } + + async getSellPricePath( + amount: bigint, + params: SmardexPoolOrderedParams[], + ): Promise { + let price = amount; + for (const param of params) { + price = await this.getSellPrice(param, price); + } + return price; + } + + async getBuyPrice( + priceParams: SmardexPoolOrderedParams, + destAmount: bigint, + ): Promise { + const amountIn = getAmountIn( + BigNumber.from(destAmount), + BigNumber.from(priceParams.reservesIn), + BigNumber.from(priceParams.reservesOut), + BigNumber.from(priceParams.fictiveReservesIn), + BigNumber.from(priceParams.fictiveReservesOut), + BigNumber.from(priceParams.priceAverageIn), + BigNumber.from(priceParams.priceAverageOut), + )[0]; + return BigInt(amountIn.toString()); + } + + async getSellPrice( + priceParams: SmardexPoolOrderedParams, + srcAmount: bigint, + ): Promise { + const amountOut = getAmountOut( + BigNumber.from(srcAmount), + BigNumber.from(priceParams.reservesIn), + BigNumber.from(priceParams.reservesOut), + BigNumber.from(priceParams.fictiveReservesIn), + BigNumber.from(priceParams.fictiveReservesOut), + BigNumber.from(priceParams.priceAverageIn), + BigNumber.from(priceParams.priceAverageOut), + )[0]; + return BigInt(amountOut.toString()); } // Returns estimated gas cost of calldata for this DEX in multiSwap - getCalldataGasCost(poolPrices: PoolPrices): number | number[] { - // TODO: update if there is any payload in getAdapterParam - return CALLDATA_GAS_COST.DEX_NO_PAYLOAD; + getCalldataGasCost(_poolPrices: PoolPrices): number | number[] { + return ( + CALLDATA_GAS_COST.DEX_OVERHEAD + + CALLDATA_GAS_COST.LENGTH_SMALL + + // ParentStruct header + CALLDATA_GAS_COST.OFFSET_SMALL + + // ParentStruct -> weth + CALLDATA_GAS_COST.ADDRESS + + // ParentStruct -> pools[] header + CALLDATA_GAS_COST.OFFSET_SMALL + + // ParentStruct -> pools[] + CALLDATA_GAS_COST.LENGTH_SMALL + + // ParentStruct -> pools[0] + CALLDATA_GAS_COST.wordNonZeroBytes(22) + ); + } + + async findPair(from: Token, to: Token) { + if (from.address.toLowerCase() === to.address.toLowerCase()) return null; + const [token0, token1] = + from.address.toLowerCase() < to.address.toLowerCase() + ? [from, to] + : [to, from]; + + const key = `${token0.address.toLowerCase()}-${token1.address.toLowerCase()}`; + let pair = this.pairs[key]; + if (pair) return pair; + const exchange = await this.factory.methods + .getPair(token0.address, token1.address) + .call(); + if (exchange === NULL_ADDRESS) { + pair = { token0, token1 }; + } else { + pair = { token0, token1, exchange }; + } + this.pairs[key] = pair; + return pair; + } + + async batchCatchUpPairs(pairs: [Token, Token][], blockNumber: number) { + if (!blockNumber) return; + const pairsToFetch: SmardexPair[] = []; + for (const _pair of pairs) { + const pair = await this.findPair(_pair[0], _pair[1]); + if (!(pair && pair.exchange)) continue; + if (!pair.pool) { + pairsToFetch.push(pair); + } else if (!pair.pool.getState(blockNumber)) { + pairsToFetch.push(pair); + } + } + + if (!pairsToFetch.length) return; + + const reserves = await this.getManyPoolReserves(pairsToFetch, blockNumber); + + if (reserves.length !== pairsToFetch.length) { + this.logger.error( + `Error_getManyPoolReserves didn't get any pool reserves`, + ); + } + + for (let i = 0; i < pairsToFetch.length; i++) { + const pairState = reserves[i]; + const pair = pairsToFetch[i]; + if (!pair.pool) { + await this.addPool( + pair, + pairState.reserves0, + pairState.reserves1, + pairState.fictiveReserves0, + pairState.fictiveReserves1, + pairState.priceAverageIn, + pairState.priceAverageOut, + pairState.feeCode, + blockNumber, + ); + } else pair.pool.setState(pairState, blockNumber); + } + } + + // On Smardex the fees are upgradable on layer 2. + protected getFeesMultiCallData(pair: SmardexPair) { + if (this.isLayer1()) { + return null; + } + const callEntry = { + target: pair.exchange!, + callData: smardexPoolL2.encodeFunctionData('getPairFees'), + }; + const callDecoder = (values: any[]) => + parseInt( + smardexPoolL2.decodeFunctionResult('getPairFees', values)[0].toString(), + ); + + return { + callEntry, + callDecoder, + }; + } + + protected async addPool( + pair: SmardexPair, + reserves0: string, + reserves1: string, + fictiveReserves0: string, + fictiveReserves1: string, + priceAverageIn: string, + priceAverageOut: string, + feeCode: number, + blockNumber: number, + ) { + const multiCallFeeData = this.getFeesMultiCallData(pair); + pair.pool = new SmardexEventPool( + this.isLayer1() ? smardexPoolL1 : smardexPoolL2, + this.dexHelper, + pair.exchange!, + pair.token0, + pair.token1, + this.logger, + // For layer 2 we need to fetch the fees + multiCallFeeData?.callEntry, + multiCallFeeData?.callDecoder, + ); + pair.pool.addressesSubscribed.push(pair.exchange!); + + await pair.pool.initialize(blockNumber, { + state: { + reserves0, + reserves1, + fictiveReserves0, + fictiveReserves1, + priceAverageIn, + priceAverageOut, + feeCode, + }, + }); + } + + async getManyPoolReserves( + pairs: SmardexPair[], + blockNumber: number, + ): Promise { + try { + const multiCallFeeData = pairs.map(pair => + this.getFeesMultiCallData(pair), + ); + const calldata = pairs + .map((pair, i) => { + let calldata = [ + { + target: pair.exchange!, + callData: smardexPoolL1.encodeFunctionData('getReserves'), + }, + { + target: pair.exchange!, + callData: smardexPoolL1.encodeFunctionData('getFictiveReserves'), + }, + { + target: pair.exchange!, + callData: smardexPoolL1.encodeFunctionData('getPriceAverage'), + }, + ]; + // Fetch fees only on layer 2 + !this.isLayer1() && calldata.push(multiCallFeeData[i]!.callEntry); + return calldata; + }) + .flat(); + + const data: { returnData: any[] } = + await this.dexHelper.multiContract.methods + .aggregate(calldata) + .call({}, blockNumber); + + const returnData = _.chunk(data.returnData, 3); + return pairs.map((_pair: SmardexPair, i) => ({ + reserves0: coder + .decode(['uint256', 'uint256'], returnData[i][0])[0] + .toString(), + reserves1: coder + .decode(['uint256', 'uint256'], returnData[i][0])[1] + .toString(), + fictiveReserves0: coder + .decode(['uint256', 'uint256'], returnData[i][1])[0] + .toString(), + fictiveReserves1: coder + .decode(['uint256', 'uint256'], returnData[i][1])[1] + .toString(), + priceAverageIn: coder + .decode(['uint256', 'uint256'], returnData[i][2])[0] + .toString(), + priceAverageOut: coder + .decode(['uint256', 'uint256'], returnData[i][2])[1] + .toString(), + feeCode: this.isLayer1() + ? 700 + : multiCallFeeData[i]!.callDecoder(returnData[i][3]), + })); + } catch (e) { + this.logger.error( + `Error_getManyPoolReserves could not get reserves with error:`, + e, + ); + return []; + } + } + + protected fixPath(path: Address[], srcToken: Address, destToken: Address) { + return path.map((token: string, i: number) => { + if ( + (i === 0 && srcToken.toLowerCase() === ETHER_ADDRESS.toLowerCase()) || + (i === path.length - 1 && + destToken.toLowerCase() === ETHER_ADDRESS.toLowerCase()) + ) + return ETHER_ADDRESS; + return token; + }); + } + + // Necessary to get the correct path for the router + getDirectParam( + srcToken: Address, + destToken: Address, + srcAmount: NumberAsString, + destAmount: NumberAsString, + expectedAmount: NumberAsString, + _data: SmardexData, + side: SwapSide, + permit: string, + uuid: string, + feePercent: NumberAsString, + deadline: NumberAsString, + partner: string, + beneficiary: string, + contractMethod?: string, + ): TxInfo { + if (!contractMethod) throw new Error(`contractMethod need to be passed`); + if (permit !== '0x') contractMethod += 'WithPermit'; + + const swapParams = ((): UniswapParam => { + const data = _data as unknown as UniswapDataLegacy; + const path = this.fixPath(data.path, srcToken, destToken); + + switch (contractMethod) { + case UniswapV2Functions.swapOnUniswap: + case UniswapV2Functions.buyOnUniswap: + return [srcAmount, destAmount, path]; + + case UniswapV2Functions.swapOnUniswapFork: + case UniswapV2Functions.buyOnUniswapFork: + return [ + data.factory, + prependWithOx(data.initCode), + srcAmount, + destAmount, + path, + ]; + + case UniswapV2Functions.swapOnUniswapV2Fork: + case UniswapV2Functions.buyOnUniswapV2Fork: + return [ + srcToken, + srcAmount, + destAmount, + this.getWETHAddress(srcToken, destToken, _data.wethAddress), + encodePools(_data.pools, this.feeFactor), + ]; + + case UniswapV2Functions.swapOnUniswapV2ForkWithPermit: + case UniswapV2Functions.buyOnUniswapV2ForkWithPermit: + return [ + srcToken, + srcAmount, + destAmount, + this.getWETHAddress(srcToken, destToken, _data.wethAddress), + encodePools(_data.pools, this.feeFactor), + permit, + ]; + + default: + throw new Error(`contractMethod=${contractMethod} is not supported`); + } + })(); + + const encoder = (...params: UniswapParam) => + this.routerInterface.encodeFunctionData(contractMethod!, params); + return { + params: swapParams, + encoder, + networkFee: '0', + }; + } + + async getPairOrderedParams( + from: Token, + to: Token, + blockNumber: number, + tokenDexTransferFee: number, + ): Promise { + const pair = await this.findPair(from, to); + if (!(pair && pair.pool && pair.exchange)) return null; + const pairState = pair.pool.getState(blockNumber); + if (!pairState) { + this.logger.error( + `Error_orderPairParams expected reserves, got none (maybe the pool doesn't exist) ${ + from.symbol || from.address + } ${to.symbol || to.address}`, + ); + return null; + } + const fee = (pairState.feeCode + tokenDexTransferFee).toString(); + const pairReversed = + pair.token1.address.toLowerCase() === from.address.toLowerCase(); + if (pairReversed) { + return { + tokenIn: from.address, + tokenOut: to.address, + reservesIn: pairState.reserves1, + reservesOut: pairState.reserves0, + fictiveReservesIn: pairState.fictiveReserves1, + fictiveReservesOut: pairState.fictiveReserves0, + priceAverageIn: pairState.priceAverageOut, + priceAverageOut: pairState.priceAverageIn, + fee, + direction: false, + exchange: pair.exchange, + }; + } + return { + tokenIn: from.address, + tokenOut: to.address, + reservesIn: pairState.reserves0, + reservesOut: pairState.reserves1, + fictiveReservesIn: pairState.fictiveReserves0, + fictiveReservesOut: pairState.fictiveReserves1, + priceAverageIn: pairState.priceAverageIn, + priceAverageOut: pairState.priceAverageOut, + fee, + direction: true, + exchange: pair.exchange, + }; } // Encode params required by the exchange adapter // Used for multiSwap, buy & megaSwap // Hint: abiCoder.encodeParameter() could be useful getAdapterParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, + srcToken: Address, + destToken: Address, + srcAmount: NumberAsString, + toAmount: NumberAsString, // required for buy case data: SmardexData, side: SwapSide, ): AdapterExchangeParam { - // TODO: complete me! - const { exchange } = data; - - // Encode here the payload for adapter - const payload = ''; - + const pools = encodePools(data.pools, this.feeFactor); + const weth = this.getWETHAddress(srcToken, destToken, data.wethAddress); + const payload = this.abiCoder.encodeParameter( + { + ParentStruct: { + weth: 'address', + pools: 'uint256[]', + }, + }, + { pools, weth }, + ); return { - targetExchange: exchange, + targetExchange: data.router, payload, networkFee: '0', }; } - // Encode call data used by simpleSwap like routers - // Used for simpleSwap & simpleBuy - // Hint: this.buildSimpleParamWithoutWETHConversion - // could be useful + getWETHAddress(srcToken: Address, destToken: Address, weth?: Address) { + if (!isETHAddress(srcToken) && !isETHAddress(destToken)) + return NULL_ADDRESS; + return weth || this.dexHelper.config.data.wrappedNativeTokenAddress; + } + async getSimpleParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, + src: Address, + dest: Address, + srcAmount: NumberAsString, + destAmount: NumberAsString, data: SmardexData, side: SwapSide, ): Promise { - // TODO: complete me! - const { exchange } = data; - - // Encode here the transaction arguments - const swapData = ''; - + const pools = encodePools(data.pools, this.feeFactor); + const weth = this.getWETHAddress(src, dest, data.wethAddress); + const swapData = this.exchangeRouterInterface.encodeFunctionData( + side === SwapSide.SELL ? UniswapV2Functions.swap : UniswapV2Functions.buy, + [src, srcAmount, destAmount, weth, pools], + ); return this.buildSimpleParamWithoutWETHConversion( - srcToken, + src, srcAmount, - destToken, + dest, destAmount, swapData, - exchange, + data.router, ); } - // This is called once before getTopPoolsForToken is - // called for multiple tokens. This can be helpful to - // update common state required for calculating - // getTopPoolsForToken. It is optional for a DEX - // to implement this - async updatePoolState(): Promise { - // TODO: complete me! + isLayer1(): boolean { + return this.network === Network.MAINNET; } - // Returns list of top pools based on liquidity. Max - // limit number pools should be returned. async getTopPoolsForToken( tokenAddress: Address, limit: number, ): Promise { - //TODO: complete me! + //TODO: Complete with a query on our subgraph gateway return []; } - - // This is optional function in case if your implementation has acquired any resources - // you need to release for graceful shutdown. For example, it may be any interval timer - releaseResources(): AsyncOrSync { - // TODO: complete me! - } } diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index f2e0843e9..f3da4168b 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -1,22 +1,35 @@ import { Address } from '../../types'; +import { + UniswapV2Data, + UniswapV2PoolOrderedParams, + DexParams as UniswapV2DexParams, + UniswapPool, +} from '../uniswap-v2/types'; +import { UniswapV2Pair } from '../uniswap-v2/uniswap-v2'; +import { SmardexEventPool } from './smardex'; -export type PoolState = { - // TODO: poolState is the state of event - // subscriber. This should be the minimum - // set of parameters required to compute - // pool prices. Complete me! -}; +export interface SmardexPoolState { + reserves0: string; + reserves1: string; + fictiveReserves0: string; + fictiveReserves1: string; + priceAverageIn: string; + priceAverageOut: string; + feeCode: number; +} -export type SmardexData = { - // TODO: SmardexData is the dex data that is - // returned by the API that can be used for - // tx building. The data structure should be minimal. - // Complete me! - exchange: Address; -}; +export type SmardexData = UniswapV2Data; +export type DexParams = UniswapV2DexParams; -export type DexParams = { - // TODO: DexParams is set of parameters the can - // be used to initiate a DEX fork. - // Complete me! -}; +export interface SmardexPoolOrderedParams extends UniswapV2PoolOrderedParams { + fictiveReservesIn: string; + fictiveReservesOut: string; + priceAverageIn: string; + priceAverageOut: string; +} + +export interface SmardexPair extends Omit { + pool?: SmardexEventPool; +} + +export type SmardexPool = UniswapPool; From b3adffc59b591bf1709cd1d42f9318bc01e0fa78 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 1 Sep 2023 16:43:18 +0100 Subject: [PATCH 209/833] 2.33.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5383acecf..a6cce989f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.33.2", + "version": "2.33.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 6418dd1c42d14486938e02751d138e84c3a666dd Mon Sep 17 00:00:00 2001 From: oxSaturn Date: Sat, 2 Sep 2023 11:03:05 +0800 Subject: [PATCH 210/833] add fvm --- src/dex/index.ts | 2 + src/dex/solidly/config.ts | 13 +- src/dex/solidly/forks-override/fvm.ts | 54 +++++++ src/dex/solidly/solidly-e2e.test.ts | 22 +++ src/dex/solidly/solidly-integration.test.ts | 171 ++++++++++++++++++++ src/dex/solidly/solidly.ts | 1 + tests/constants-e2e.ts | 13 ++ 7 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 src/dex/solidly/forks-override/fvm.ts diff --git a/src/dex/index.ts b/src/dex/index.ts index 3aa4e21db..d6d9f3674 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -52,6 +52,7 @@ import { Synthetix } from './synthetix/synthetix'; import { Cone } from './solidly/forks-override/cone'; import { SoliSnek } from './solidly/forks-override/solisnek'; import { Equalizer } from './solidly/forks-override/equalizer'; +import { Fvm } from './solidly/forks-override/fvm'; import { BalancerV1 } from './balancer-v1/balancer-v1'; import { balancerV1Merge } from './balancer-v1/optimizer'; import { CurveV1 } from './curve-v1/curve-v1'; @@ -136,6 +137,7 @@ const Dexes = [ Cone, SoliSnek, Equalizer, + Fvm, Synthetix, CurveV1Factory, SwaapV1, diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index b18dba6d7..c97b03a47 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -158,6 +158,17 @@ export const SolidlyConfig: DexConfigMap = { poolGasCost: 180 * 1000, }, }, + Fvm: { + [Network.FANTOM]: { + factoryAddress: '0x472f3C3c9608fe0aE8d702f3f8A2d12c410C881A', + router: '0x93d2611EB8b85bE4FDEa9D94Ce9913D90072eC0f', + initCode: + '0xac4013aa7118234c1dd1f9cc4cdd3933d5a426224bc691c1bde3d8930a7e6151', // PairFactory.pairCodeHash + feeCode: 0, // dynamic fees + poolGasCost: 180 * 1000, // just same as other forks + // no subgraph + }, + }, }; export const Adapters: Record = { @@ -165,7 +176,7 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'PolygonAdapter02', index: 3 }], // dystopia }, [Network.FANTOM]: { - [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 10 }], // solidly + spiritSwapV2 + Equalizer + [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 10 }], // solidly + spiritSwapV2 + Equalizer + Fvm }, [Network.OPTIMISM]: { [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 8 }], // velodrome diff --git a/src/dex/solidly/forks-override/fvm.ts b/src/dex/solidly/forks-override/fvm.ts new file mode 100644 index 000000000..9ec45bec7 --- /dev/null +++ b/src/dex/solidly/forks-override/fvm.ts @@ -0,0 +1,54 @@ +import { Solidly } from '../solidly'; +import { SolidlyPair } from '../types'; +import { Network } from '../../../constants'; +import { IDexHelper } from '../../../dex-helper'; +import { Interface } from '@ethersproject/abi'; +import { getDexKeysWithNetwork } from '../../../utils'; +import { SolidlyConfig } from '../config'; +import _ from 'lodash'; + +const FvmFactoryABI = [ + { + inputs: [{ internalType: 'bool', name: '_stable', type: 'bool' }], + name: 'getFee', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, +]; + +const fvmFactoryIface = new Interface(FvmFactoryABI); + +export class Fvm extends Solidly { + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(_.pick(SolidlyConfig, ['Fvm'])); + + constructor( + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + ) { + super( + network, + dexKey, + dexHelper, + true, // dynamic fees + ); + } + + protected getFeesMultiCallData(pair: SolidlyPair) { + const callEntry = { + target: this.factoryAddress, + callData: fvmFactoryIface.encodeFunctionData('getFee', [pair.stable]), + }; + const callDecoder = (values: any[]) => + parseInt( + fvmFactoryIface.decodeFunctionResult('getFee', values)[0].toString(), + ); + + return { + callEntry, + callDecoder, + }; + } +} diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index 5395ad36b..1cc127645 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -415,6 +415,28 @@ describe('Solidly E2E', () => { nativeTokenAmount, ); }); + + describe('Fvm', () => { + const dexKey = 'Fvm'; + const network = Network.FANTOM; + + const tokenASymbol: string = 'lzUSDC'; + const tokenBSymbol: string = 'axlUSDC'; + + const tokenAAmount: string = '111110'; + const tokenBAmount: string = '100000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); }); describe('Mainnet', () => { diff --git a/src/dex/solidly/solidly-integration.test.ts b/src/dex/solidly/solidly-integration.test.ts index 73f50a127..451008a4d 100644 --- a/src/dex/solidly/solidly-integration.test.ts +++ b/src/dex/solidly/solidly-integration.test.ts @@ -17,6 +17,7 @@ import { Ramses } from './forks-override/ramses'; import * as util from 'util'; import { VelodromeV2 } from './forks-override/velodromeV2'; import { Equalizer } from './forks-override/equalizer'; +import { Fvm } from './forks-override/fvm'; const amounts18 = [0n, BI_POWS[18], 2000000000000000000n]; const amounts6 = [0n, BI_POWS[6], 2000000n]; @@ -525,6 +526,176 @@ describe('Solidly integration tests', () => { }); }); }); + + describe('Fvm', () => { + const dexKey = 'Fvm'; + const fvm = new Fvm(network, dexKey, dexHelper); + + describe('UniswapV2 like pool', function () { + const TokenASymbol = 'WFTM'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'lzUSDC'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts18; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await fvm.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await fvm.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + + for (const poolPrice of poolPrices || []) { + await checkOnChainPricing( + fvm, + 'getAmountOut', + blocknumber, + poolPrice.prices, + poolPrice.poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + }); + + describe('Curve like stable pool', function () { + const TokenASymbol = 'lzUSDC'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'axlUSDC'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts6; // amounts6; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await fvm.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await fvm.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + for (const poolPrice of poolPrices || []) { + await checkOnChainPricing( + fvm, + 'getAmountOut', + blocknumber, + poolPrice.prices, + poolPrice.poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + }); + + describe('FTM -> FVM', () => { + const TokenASymbol = 'WFTM'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'FVM'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = [0n, 10000000n]; + + console.log('AMOUNTS: ', amounts); + it('getPoolIdentifiers and getPricesVolume', async function () { + // const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const blocknumber = 67666611; + const pools = await fvm.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await fvm.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + for (const poolPrice of poolPrices || []) { + await checkOnChainPricing( + fvm, + 'getAmountOut', + blocknumber, + poolPrice.prices, + poolPrice.poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + }); + }); }); describe('Polygon', () => { diff --git a/src/dex/solidly/solidly.ts b/src/dex/solidly/solidly.ts index 899acd50f..aab0a021c 100644 --- a/src/dex/solidly/solidly.ts +++ b/src/dex/solidly/solidly.ts @@ -75,6 +75,7 @@ export class Solidly extends UniswapV2 { 'Chronos', 'Ramses', 'Equalizer', + 'Fvm', ]), ); diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 7b88aa214..0923ee7e7 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -512,6 +512,18 @@ export const Tokens: { address: '0xe578C856933D8e1082740bf7661e379Aa2A30b26', decimals: 6, }, + axlUSDC: { + address: '0x1B6382DBDEa11d97f24495C9A90b7c88469134a4', + decimals: 6, + }, + lzUSDC: { + address: '0x28a92dde19D9989F39A49905d7C9C2FAc7799bDf', + decimals: 6, + }, + FVM: { + address: '0x07BB65fAaC502d4996532F834A1B7ba5dC32Ff96', + decimals: 18, + }, }, [Network.BSC]: { POPS: { @@ -984,6 +996,7 @@ export const Holders: { GUSDC: '0x894d774a293f8aa3d23d67815d4cadb5319c1094', GDAI: '0x0e2ed73f9c1409e2b36fe6c46e60d4557b7c2ac0', EQUAL: '0x8b187ea19c93091a4d6b426b71871648182b5fac', + FVM: '0x07BB65fAaC502d4996532F834A1B7ba5dC32Ff96', }, [Network.BSC]: { DAI: '0xf68a4b64162906eff0ff6ae34e2bb1cd42fef62d', From 7b4baa9e0bc9060fd7d062b8518f0526be25761c Mon Sep 17 00:00:00 2001 From: julien Date: Tue, 5 Sep 2023 16:20:38 +0200 Subject: [PATCH 211/833] fix: config and SDK --- src/abi/smardex/all/smardex-router.json | 479 ++++++++++++++++++++++++ src/dex/smardex/config.ts | 7 +- src/dex/smardex/smardex-sdk.ts | 36 +- 3 files changed, 500 insertions(+), 22 deletions(-) create mode 100644 src/abi/smardex/all/smardex-router.json diff --git a/src/abi/smardex/all/smardex-router.json b/src/abi/smardex/all/smardex-router.json new file mode 100644 index 000000000..6b6828461 --- /dev/null +++ b/src/abi/smardex/all/smardex-router.json @@ -0,0 +1,479 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "_factory", "type": "address" }, + { "internalType": "address", "name": "_WETH", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "WETH", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_tokenA", "type": "address" }, + { "internalType": "address", "name": "_tokenB", "type": "address" }, + { + "internalType": "uint256", + "name": "_amountADesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amountBDesired", + "type": "uint256" + }, + { "internalType": "uint256", "name": "_amountAMin", "type": "uint256" }, + { "internalType": "uint256", "name": "_amountBMin", "type": "uint256" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" } + ], + "name": "addLiquidity", + "outputs": [ + { "internalType": "uint256", "name": "amountA_", "type": "uint256" }, + { "internalType": "uint256", "name": "amountB_", "type": "uint256" }, + { "internalType": "uint256", "name": "liquidity_", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { + "internalType": "uint256", + "name": "_amountTokenDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amountTokenMin", + "type": "uint256" + }, + { "internalType": "uint256", "name": "_amountETHMin", "type": "uint256" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" } + ], + "name": "addLiquidityETH", + "outputs": [ + { "internalType": "uint256", "name": "amountToken_", "type": "uint256" }, + { "internalType": "uint256", "name": "amountETH_", "type": "uint256" }, + { "internalType": "uint256", "name": "liquidity_", "type": "uint256" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "uint256", "name": "reserveIn", "type": "uint256" }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fictiveReserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fictiveReserveOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priceAverageIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priceAverageOut", + "type": "uint256" + }, + { "internalType": "uint128", "name": "feesLP", "type": "uint128" }, + { "internalType": "uint128", "name": "feesPool", "type": "uint128" } + ], + "internalType": "struct SmardexLibrary.GetAmountParameters", + "name": "_param", + "type": "tuple" + } + ], + "name": "getAmountIn", + "outputs": [ + { "internalType": "uint256", "name": "amountIn_", "type": "uint256" }, + { "internalType": "uint256", "name": "newReserveIn_", "type": "uint256" }, + { + "internalType": "uint256", + "name": "newReserveOut_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newFictiveReserveIn_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newFictiveReserveOut_", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amountOut", "type": "uint256" }, + { "internalType": "address", "name": "_tokenIn", "type": "address" }, + { "internalType": "address", "name": "_tokenOut", "type": "address" } + ], + "name": "getAmountInFromPair", + "outputs": [ + { "internalType": "uint256", "name": "amountIn_", "type": "uint256" }, + { "internalType": "uint256", "name": "newReserveIn_", "type": "uint256" }, + { + "internalType": "uint256", + "name": "newReserveOut_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newFictiveReserveIn_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newFictiveReserveOut_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "uint256", "name": "reserveIn", "type": "uint256" }, + { + "internalType": "uint256", + "name": "reserveOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fictiveReserveIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fictiveReserveOut", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priceAverageIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "priceAverageOut", + "type": "uint256" + }, + { "internalType": "uint128", "name": "feesLP", "type": "uint128" }, + { "internalType": "uint128", "name": "feesPool", "type": "uint128" } + ], + "internalType": "struct SmardexLibrary.GetAmountParameters", + "name": "_param", + "type": "tuple" + } + ], + "name": "getAmountOut", + "outputs": [ + { "internalType": "uint256", "name": "amountOut_", "type": "uint256" }, + { "internalType": "uint256", "name": "newReserveIn_", "type": "uint256" }, + { + "internalType": "uint256", + "name": "newReserveOut_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newFictiveReserveIn_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newFictiveReserveOut_", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amountIn", "type": "uint256" }, + { "internalType": "address", "name": "_tokenIn", "type": "address" }, + { "internalType": "address", "name": "_tokenOut", "type": "address" } + ], + "name": "getAmountOutFromPair", + "outputs": [ + { "internalType": "uint256", "name": "amountOut_", "type": "uint256" }, + { "internalType": "uint256", "name": "newReserveIn_", "type": "uint256" }, + { + "internalType": "uint256", + "name": "newReserveOut_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newFictiveReserveIn_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newFictiveReserveOut_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amountA", "type": "uint256" }, + { "internalType": "uint256", "name": "_reserveA", "type": "uint256" }, + { "internalType": "uint256", "name": "_reserveB", "type": "uint256" } + ], + "name": "quote", + "outputs": [ + { "internalType": "uint256", "name": "amountB_", "type": "uint256" } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_tokenA", "type": "address" }, + { "internalType": "address", "name": "_tokenB", "type": "address" }, + { "internalType": "uint256", "name": "_liquidity", "type": "uint256" }, + { "internalType": "uint256", "name": "_amountAMin", "type": "uint256" }, + { "internalType": "uint256", "name": "_amountBMin", "type": "uint256" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" } + ], + "name": "removeLiquidity", + "outputs": [ + { "internalType": "uint256", "name": "amountA_", "type": "uint256" }, + { "internalType": "uint256", "name": "amountB_", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_liquidity", "type": "uint256" }, + { + "internalType": "uint256", + "name": "_amountTokenMin", + "type": "uint256" + }, + { "internalType": "uint256", "name": "_amountETHMin", "type": "uint256" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" } + ], + "name": "removeLiquidityETH", + "outputs": [ + { "internalType": "uint256", "name": "amountToken_", "type": "uint256" }, + { "internalType": "uint256", "name": "amountETH_", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_token", "type": "address" }, + { "internalType": "uint256", "name": "_liquidity", "type": "uint256" }, + { + "internalType": "uint256", + "name": "_amountTokenMin", + "type": "uint256" + }, + { "internalType": "uint256", "name": "_amountETHMin", "type": "uint256" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" }, + { "internalType": "bool", "name": "_approveMax", "type": "bool" }, + { "internalType": "uint8", "name": "_v", "type": "uint8" }, + { "internalType": "bytes32", "name": "_r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_s", "type": "bytes32" } + ], + "name": "removeLiquidityETHWithPermit", + "outputs": [ + { "internalType": "uint256", "name": "amountToken_", "type": "uint256" }, + { "internalType": "uint256", "name": "amountETH_", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_tokenA", "type": "address" }, + { "internalType": "address", "name": "_tokenB", "type": "address" }, + { "internalType": "uint256", "name": "_liquidity", "type": "uint256" }, + { "internalType": "uint256", "name": "_amountAMin", "type": "uint256" }, + { "internalType": "uint256", "name": "_amountBMin", "type": "uint256" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" }, + { "internalType": "bool", "name": "_approveMax", "type": "bool" }, + { "internalType": "uint8", "name": "_v", "type": "uint8" }, + { "internalType": "bytes32", "name": "_r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_s", "type": "bytes32" } + ], + "name": "removeLiquidityWithPermit", + "outputs": [ + { "internalType": "uint256", "name": "amountA_", "type": "uint256" }, + { "internalType": "uint256", "name": "amountB_", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "token0", "type": "address" }, + { "internalType": "address", "name": "token1", "type": "address" }, + { "internalType": "uint256", "name": "amount0", "type": "uint256" }, + { "internalType": "uint256", "name": "amount1", "type": "uint256" }, + { "internalType": "address", "name": "payer", "type": "address" } + ], + "internalType": "struct ISmardexMintCallback.MintCallbackData", + "name": "_data", + "type": "tuple" + } + ], + "name": "smardexMintCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "int256", "name": "_amount0Delta", "type": "int256" }, + { "internalType": "int256", "name": "_amount1Delta", "type": "int256" }, + { "internalType": "bytes", "name": "_data", "type": "bytes" } + ], + "name": "smardexSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amountOut", "type": "uint256" }, + { "internalType": "address[]", "name": "_path", "type": "address[]" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" } + ], + "name": "swapETHForExactTokens", + "outputs": [ + { "internalType": "uint256", "name": "amountIn_", "type": "uint256" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amountOutMin", "type": "uint256" }, + { "internalType": "address[]", "name": "_path", "type": "address[]" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" } + ], + "name": "swapExactETHForTokens", + "outputs": [ + { "internalType": "uint256", "name": "amountOut_", "type": "uint256" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "_amountOutMin", "type": "uint256" }, + { "internalType": "address[]", "name": "_path", "type": "address[]" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" } + ], + "name": "swapExactTokensForETH", + "outputs": [ + { "internalType": "uint256", "name": "amountOut_", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "_amountOutMin", "type": "uint256" }, + { "internalType": "address[]", "name": "_path", "type": "address[]" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" } + ], + "name": "swapExactTokensForTokens", + "outputs": [ + { "internalType": "uint256", "name": "amountOut_", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amountOut", "type": "uint256" }, + { "internalType": "uint256", "name": "_amountInMax", "type": "uint256" }, + { "internalType": "address[]", "name": "_path", "type": "address[]" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" } + ], + "name": "swapTokensForExactETH", + "outputs": [ + { "internalType": "uint256", "name": "amountIn_", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amountOut", "type": "uint256" }, + { "internalType": "uint256", "name": "_amountInMax", "type": "uint256" }, + { "internalType": "address[]", "name": "_path", "type": "address[]" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" } + ], + "name": "swapTokensForExactTokens", + "outputs": [ + { "internalType": "uint256", "name": "amountIn_", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { "stateMutability": "payable", "type": "receive" } +] diff --git a/src/dex/smardex/config.ts b/src/dex/smardex/config.ts index 7d3ed262d..26a2dc997 100644 --- a/src/dex/smardex/config.ts +++ b/src/dex/smardex/config.ts @@ -1,6 +1,6 @@ import { DexParams } from './types'; import { DexConfigMap, AdapterMappings } from '../../types'; -import { Network, SwapSide } from '../../constants'; +import { Network } from '../../constants'; const gatewaySubgraph = 'https://subgraph.smardex.io/paraswap'; const mainnetInitHash = @@ -42,7 +42,6 @@ export const SmardexConfig: DexConfigMap = { }; export const Adapters: Record = { - // TODO: add adapters for each chain - // This is an example to copy - [Network.MAINNET]: { [SwapSide.SELL]: [{ name: '', index: 0 }] }, + // This is an example + // [Network.MAINNET]: { [SwapSide.SELL]: [{ name: '', index: 0 }] }, }; diff --git a/src/dex/smardex/smardex-sdk.ts b/src/dex/smardex/smardex-sdk.ts index fcb650403..4e415ae27 100644 --- a/src/dex/smardex/smardex-sdk.ts +++ b/src/dex/smardex/smardex-sdk.ts @@ -817,8 +817,8 @@ export function inputOutputComparator( outputB: CurrencyAmount, ): number { // must have same input and output token for comparison - // invariant(inputA.currency === inputB.currency, 'INPUT_CURRENCY'); - // invariant(outputA.currency === outputB.currency, 'OUTPUT_CURRENCY'); + if (inputA.currency !== inputB.currency) throw new Error('INPUT_CURRENCY'); + if (outputA.currency !== outputB.currency) throw new Error('OUTPUT_CURRENCY'); if (outputA.amount.eq(outputB.amount)) { if (inputA.amount.eq(inputB.amount)) { return 0; @@ -931,13 +931,13 @@ function bestTradeExactInInternal( nextAmountIn: CurrencyAmount = currencyAmountIn, bestTrades: Trade[] = [], ): Trade[] { - // invariant(pairs.length > 0, 'PAIRS'); - // invariant(maxHops > 0, 'MAX_HOPS'); - // invariant( - // currencyAmountIn.currency === nextAmountIn.currency || - // currentPairs.length > 0, - // 'INVALID_RECURSION', - // ); + if (pairs.length <= 0) throw new Error('PAIRS'); + if (maxHops <= 0) throw new Error('MAX_HOPS'); + if ( + currencyAmountIn.currency !== nextAmountIn.currency && + currentPairs.length <= 0 + ) + throw new Error('INVALID_RECURSION'); for (let i = 0; i < pairs.length; i += 1) { const pair = { ...pairs[i] }; @@ -1095,13 +1095,13 @@ function bestTradeExactOutInternal( nextAmountOut: CurrencyAmount = currencyAmountOut, bestTrades: Trade[] = [], ): Trade[] { - // invariant(pairs.length > 0, 'PAIRS'); - // invariant(maxHops > 0, 'MAX_HOPS'); - // invariant( - // currencyAmountOut.currency === nextAmountOut.currency || - // currentPairs.length > 0, - // 'INVALID_RECURSION', - // ); + if (pairs.length <= 0) throw new Error('PAIRS'); + if (maxHops <= 0) throw new Error('MAX_HOPS'); + if ( + currencyAmountOut.currency !== nextAmountOut.currency && + currentPairs.length <= 0 + ) + throw new Error('INVALID_RECURSION'); for (let i = 0; i < pairs.length; i += 1) { const pair = { ...pairs[i] }; @@ -1396,9 +1396,9 @@ export function sortedInsert( maxSize: number, comparator: (a: T, b: T) => number, ): T | null { - // invariant(maxSize > 0, 'MAX_SIZE_ZERO'); + if (maxSize <= 0) throw new Error('MAX_SIZE_ZERO'); // this is an invariant because the interface cannot return multiple removed items if items.length exceeds maxSize - // invariant(items.length <= maxSize, 'ITEMS_SIZE'); + if (items.length > maxSize) throw new Error('ITEMS_SIZE'); // short circuit first item add if (items.length === 0) { From f04f2cd660c8a42378803cb25850390ee649e80d Mon Sep 17 00:00:00 2001 From: julien Date: Tue, 5 Sep 2023 16:21:42 +0200 Subject: [PATCH 212/833] wip: added test -> failing bc amount --- src/dex/smardex/smardex-e2e.test.ts | 128 +++++++++++++++------------- src/dex/smardex/smardex.ts | 86 ++++++++++++------- src/dex/smardex/types.ts | 19 ++++- 3 files changed, 142 insertions(+), 91 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index e65cfd2a2..e917dfe05 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -19,41 +19,55 @@ describe('Smardex E2E Mainnet', () => { const dexKey = 'Smardex'; describe('Simpleswap', () => { - it('ETH -> TOKEN', async () => { + it('WETH -> TOKEN', async () => { await testE2E( - tokens.ETH, - tokens.USDC, - holders.ETH, - '7000000000000000000', - SwapSide.SELL, + tokens.WETH, + tokens.USDT, + holders.WETH, + '2000000000000000000', // 2 WETH + SwapSide.SELL, // exact input dexKey, - ContractMethod.swapOnUniswap, + ContractMethod.simpleSwap, network, provider, ); }); - it('TOKEN -> ETH', async () => { - await testE2E( - tokens.USDC, - tokens.ETH, - holders.USDC, - '2000000000', - SwapSide.SELL, - dexKey, - ContractMethod.swapOnUniswap, - network, - provider, - ); - }); - // it('TOKEN -> TOKEN', async () => { + // it('WETH <- TOKEN', async () => { + // await testE2E( + // tokens.WETH, + // tokens.USDT, + // holders.WETH, + // '2000000000000000000', // 2 WETH + // SwapSide.BUY, // exact output + // dexKey, + // ContractMethod.simpleSwap, + // network, + // provider, + // ); + // }); + + // it('ETH -> TOKEN', async () => { // await testE2E( - // tokens.WBTC, - // tokens.BADGER, - // holders.WBTC, - // '20000000', - // SwapSide.SELL, + // tokens.ETH, + // tokens.USDT, + // holders.ETH, + // '7000000000000000000', // 7 ETH + // SwapSide.SELL, // exact input // dexKey, - // ContractMethod., + // ContractMethod.simpleSwap, + // network, + // provider, + // ); + // }); + // it('ETH <- TOKEN', async () => { + // await testE2E( + // tokens.ETH, + // tokens.USDT, + // holders.ETH, + // '7000000000000000000', // 7 ETH + // SwapSide.BUY, // exact output + // dexKey, + // ContractMethod.simpleSwap, // network, // provider, // ); @@ -89,9 +103,9 @@ describe('Smardex E2E Mainnet', () => { // }); // it('TOKEN -> TOKEN', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.WBTC, - // holders.USDC, + // holders.USDT, // '200000000', // SwapSide.SELL, // dexKey, @@ -131,9 +145,9 @@ describe('Smardex E2E Mainnet', () => { // }); // it('TOKEN[USDC] -> ETH', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.ETH, - // holders.USDC, + // holders.USDT, // '200000000', // SwapSide.SELL, // dexKey, @@ -144,9 +158,9 @@ describe('Smardex E2E Mainnet', () => { // }); // it('TOKEN -> TOKEN', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.WBTC, - // holders.USDC, + // holders.USDT, // '200000000', // SwapSide.SELL, // dexKey, @@ -186,9 +200,9 @@ describe('Smardex E2E Mainnet', () => { // }); // it('TOKEN -> TOKEN', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.WBTC, - // holders.USDC, + // holders.USDT, // '200000000', // SwapSide.SELL, // dexKey, @@ -228,9 +242,9 @@ describe('Smardex E2E Mainnet', () => { // }); // it('TOKEN -> TOKEN', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.WBTC, - // holders.USDC, + // holders.USDT, // '200000000', // SwapSide.SELL, // dexKey, @@ -270,9 +284,9 @@ describe('Smardex E2E Mainnet', () => { // }); // it('TOKEN[USDC] -> ETH', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.ETH, - // holders.USDC, + // holders.USDT, // '2000000000000000000', // SwapSide.BUY, // dexKey, @@ -284,9 +298,9 @@ describe('Smardex E2E Mainnet', () => { // it('TOKEN -> TOKEN', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.WBTC, - // holders.USDC, + // holders.USDT, // '200000000', // SwapSide.BUY, // dexKey, @@ -326,9 +340,9 @@ describe('Smardex E2E Mainnet', () => { // }); // it('TOKEN[USDC] -> ETH', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.ETH, - // holders.USDC, + // holders.USDT, // '2000000000000000000', // SwapSide.BUY, // dexKey, @@ -340,9 +354,9 @@ describe('Smardex E2E Mainnet', () => { // it('TOKEN -> TOKEN', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.WBTC, - // holders.USDC, + // holders.USDT, // '200000000', // SwapSide.BUY, // dexKey, @@ -382,9 +396,9 @@ describe('Smardex E2E Mainnet', () => { // }); // it('TOKEN[USDC] -> ETH', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.ETH, - // holders.USDC, + // holders.USDT, // '2000000000000000000', // SwapSide.BUY, // dexKey, @@ -396,9 +410,9 @@ describe('Smardex E2E Mainnet', () => { // it('TOKEN -> TOKEN', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.WBTC, - // holders.USDC, + // holders.USDT, // '200000000', // SwapSide.BUY, // dexKey, @@ -438,9 +452,9 @@ describe('Smardex E2E Mainnet', () => { // }); // it('TOKEN[USDC] -> ETH', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.ETH, - // holders.USDC, + // holders.USDT, // '2000000000000000000', // SwapSide.BUY, // dexKey, @@ -451,9 +465,9 @@ describe('Smardex E2E Mainnet', () => { // }); // it('TOKEN -> TOKEN', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.WBTC, - // holders.USDC, + // holders.USDT, // '20000000', // SwapSide.BUY, // dexKey, @@ -493,9 +507,9 @@ describe('Smardex E2E Mainnet', () => { // }); // it('TOKEN[USDC] -> ETH', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.ETH, - // holders.USDC, + // holders.USDT, // '2000000000000000000', // SwapSide.BUY, // dexKey, @@ -506,9 +520,9 @@ describe('Smardex E2E Mainnet', () => { // }); // it('TOKEN -> TOKEN', async () => { // await testE2E( - // tokens.USDC, + // tokens.USDT, // tokens.WBTC, - // holders.USDC, + // holders.USDT, // '20000000', // SwapSide.BUY, // dexKey, diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 6b513bc02..4699a5c99 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -38,23 +38,21 @@ import SmardexFactoryLayerOneABI from '../../abi/smardex/layer-1/smardex-factory import SmardexFactoryLayerTwoABI from '../../abi/smardex/layer-2/smardex-factory.json'; import SmardexPoolLayerOneABI from '../../abi/smardex/layer-1/smardex-pool.json'; import SmardexPoolLayerTwoABI from '../../abi/smardex/layer-2/smardex-pool.json'; +import SmardexRouterABI from '../../abi/smardex/all/smardex-router.json'; import { DeepReadonly, AsyncOrSync } from 'ts-essentials'; import { SimpleExchange } from '../simple-exchange'; -import { SmardexData } from '../smardex/types'; +import { SmardexData, SmardexRouterFunctions } from '../smardex/types'; import { IDex, StatefulEventSubscriber } from '../..'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { Adapters, SmardexConfig } from './config'; import { Contract } from 'web3-eth-contract'; -import { directUniswapFunctionName } from '../uniswap-v2/uniswap-v2'; import ParaSwapABI from '../../abi/IParaswap.json'; -import UniswapV2ExchangeRouterABI from '../../abi/UniswapV2ExchangeRouter.json'; import { UniswapDataLegacy, UniswapParam, UniswapV2Functions, } from '../uniswap-v2/types'; import { applyTransferFee } from '../../lib/token-transfer-fee'; -import erc20ABI from '../../abi/erc20.json'; import _ from 'lodash'; import { getAmountIn, getAmountOut } from './smardex-sdk'; import { BigNumber } from 'ethers'; @@ -63,12 +61,22 @@ import { BigNumber } from 'ethers'; export const SYNC_EVENT_TOPIC = '0x2a368c7f33bb86e2d999940a3989d849031aff29b750f67947e6b8e8c3d2ffd6'; -const DefaultUniswapV2PoolGasCost = 90 * 1000; +const DefaultSmardexPoolGasCost = 90 * 1000; const smardexPoolL1 = new Interface(SmardexPoolLayerOneABI); const smardexPoolL2 = new Interface(SmardexPoolLayerTwoABI); const coder = new AbiCoder(); + +const directSmardexFunctionName = [ + SmardexRouterFunctions.sellExactEth, + SmardexRouterFunctions.sellExactToken, + SmardexRouterFunctions.swapExactIn, + SmardexRouterFunctions.buyExactEth, + SmardexRouterFunctions.buyExactToken, + SmardexRouterFunctions.swapExactOut, +]; + export class SmardexEventPool extends StatefulEventSubscriber { constructor( protected poolInterface: Interface, @@ -107,8 +115,8 @@ export class SmardexEventPool extends StatefulEventSubscriber reserves1: event.args.reserve1.toString(), fictiveReserves0: event.args.fictiveReserve0.toString(), fictiveReserves1: event.args.fictiveReserve1.toString(), - priceAverageIn: event.args.priceAverageIn.toString(), - priceAverageOut: event.args.priceAverageOut.toString(), + priceAverage0: event.args.priceAverage0.toString(), + priceAverage1: event.args.priceAverage1.toString(), feeCode: state.feeCode, }; } @@ -148,7 +156,7 @@ export class SmardexEventPool extends StatefulEventSubscriber .call({}, blockNumber); const [reserves0, reserves1] = coder.decode( - ['uint112', 'uint112', 'uint32'], + ['uint256', 'uint256'], data.returnData[0], ); @@ -157,7 +165,7 @@ export class SmardexEventPool extends StatefulEventSubscriber data.returnData[1], ); - const [priceAverageIn, priceAverageOut] = coder.decode( + const [priceAverage0, priceAverage1, priceAverageLastTimestamp] = coder.decode( ['uint256', 'uint256', 'uint256'], data.returnData[2], ); @@ -167,8 +175,9 @@ export class SmardexEventPool extends StatefulEventSubscriber reserves1: reserves1.toString(), fictiveReserves0: fictiveReserve0.toString(), fictiveReserves1: fictiveReserve1.toString(), - priceAverageIn: priceAverageIn.toString(), - priceAverageOut: priceAverageOut.toString(), + priceAverage0: priceAverage0.toString(), + priceAverage1: priceAverage1.toString(), + // priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), feeCode: dynamicFees ? this.smardexFeesMulticallDecoder!(data.returnData[3]) : 700, // TODO: Ensure the fees are correct @@ -199,7 +208,7 @@ export class Smardex routerInterface: Interface; exchangeRouterInterface: Interface; - static directFunctionName = directUniswapFunctionName; + static directFunctionName = directSmardexFunctionName; factoryAddress: string; routerAddress: string; @@ -235,11 +244,11 @@ export class Smardex this.factoryAddress, ); this.routerInterface = new Interface(ParaSwapABI); - this.exchangeRouterInterface = new Interface(UniswapV2ExchangeRouterABI); + this.exchangeRouterInterface = new Interface(SmardexRouterABI); } getAdapters(side: SwapSide): { name: string; index: number }[] | null { - return Adapters[this.network][side]; + return Adapters[this.network]?.[side] || null; } async getPoolIdentifiers( @@ -350,6 +359,8 @@ export class Smardex prices: outputsWithFee, unit: unitOutWithFee, data: { + deadline: 3387835836, // TODO make deadline and receiver dynamic ! + receiver: '0x176F3DAb24a159341c0509bB36B833E7fdd0a132', router: this.routerAddress, path: [from.address.toLowerCase(), to.address.toLowerCase()], factory: this.factoryAddress, @@ -365,7 +376,7 @@ export class Smardex }, exchange: this.dexKey, poolIdentifier, - gasCost: DefaultUniswapV2PoolGasCost, + gasCost: DefaultSmardexPoolGasCost, poolAddresses: [pairParam.exchange], }, ]; @@ -506,8 +517,8 @@ export class Smardex pairState.reserves1, pairState.fictiveReserves0, pairState.fictiveReserves1, - pairState.priceAverageIn, - pairState.priceAverageOut, + pairState.priceAverage0, + pairState.priceAverage1, pairState.feeCode, blockNumber, ); @@ -541,8 +552,8 @@ export class Smardex reserves1: string, fictiveReserves0: string, fictiveReserves1: string, - priceAverageIn: string, - priceAverageOut: string, + priceAverage0: string, + priceAverage1: string, feeCode: number, blockNumber: number, ) { @@ -566,8 +577,8 @@ export class Smardex reserves1, fictiveReserves0, fictiveReserves1, - priceAverageIn, - priceAverageOut, + priceAverage0, + priceAverage1, feeCode, }, }); @@ -622,12 +633,15 @@ export class Smardex fictiveReserves1: coder .decode(['uint256', 'uint256'], returnData[i][1])[1] .toString(), - priceAverageIn: coder + priceAverage0: coder .decode(['uint256', 'uint256'], returnData[i][2])[0] .toString(), - priceAverageOut: coder + priceAverage1: coder .decode(['uint256', 'uint256'], returnData[i][2])[1] .toString(), + // priceAverageLastTimestamp: coder + // .decode(['uint256', 'uint256', 'uint256'], returnData[i][2])[2] + // .toString(), feeCode: this.isLayer1() ? 700 : multiCallFeeData[i]!.callDecoder(returnData[i][3]), @@ -755,8 +769,8 @@ export class Smardex reservesOut: pairState.reserves0, fictiveReservesIn: pairState.fictiveReserves1, fictiveReservesOut: pairState.fictiveReserves0, - priceAverageIn: pairState.priceAverageOut, - priceAverageOut: pairState.priceAverageIn, + priceAverageIn: pairState.priceAverage0, + priceAverageOut: pairState.priceAverage1, fee, direction: false, exchange: pair.exchange, @@ -769,8 +783,8 @@ export class Smardex reservesOut: pairState.reserves1, fictiveReservesIn: pairState.fictiveReserves0, fictiveReservesOut: pairState.fictiveReserves1, - priceAverageIn: pairState.priceAverageIn, - priceAverageOut: pairState.priceAverageOut, + priceAverageIn: pairState.priceAverage0, + priceAverageOut: pairState.priceAverage1, fee, direction: true, exchange: pair.exchange, @@ -822,10 +836,20 @@ export class Smardex ): Promise { const pools = encodePools(data.pools, this.feeFactor); const weth = this.getWETHAddress(src, dest, data.wethAddress); - const swapData = this.exchangeRouterInterface.encodeFunctionData( - side === SwapSide.SELL ? UniswapV2Functions.swap : UniswapV2Functions.buy, - [src, srcAmount, destAmount, weth, pools], - ); + + let routerMethod: any; + let routerArgs: any; + if (side === SwapSide.SELL) { + routerMethod = isETHAddress(src) ? SmardexRouterFunctions.sellExactEth : SmardexRouterFunctions.swapExactIn; + routerMethod = isETHAddress(dest) ? SmardexRouterFunctions.sellExactToken : routerMethod; + routerArgs = [srcAmount, BigNumber.from(destAmount).mul(105).div(100).toString(), data.path, data.receiver, data.deadline]; + } else { + routerMethod = isETHAddress(src) ? SmardexRouterFunctions.buyExactToken : SmardexRouterFunctions.swapExactOut; + routerMethod = isETHAddress(dest) ? SmardexRouterFunctions.buyExactEth : routerMethod; + routerArgs = [destAmount, srcAmount, data.path, data.receiver, data.deadline]; + } + + const swapData = this.exchangeRouterInterface.encodeFunctionData(routerMethod, routerArgs); return this.buildSimpleParamWithoutWETHConversion( src, srcAmount, diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index f3da4168b..172d445a4 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -13,12 +13,25 @@ export interface SmardexPoolState { reserves1: string; fictiveReserves0: string; fictiveReserves1: string; - priceAverageIn: string; - priceAverageOut: string; + priceAverage0: string; + priceAverage1: string; feeCode: number; } -export type SmardexData = UniswapV2Data; +export interface SmardexData extends UniswapV2Data { + deadline: number; + receiver: Address; +} + +export enum SmardexRouterFunctions { + sellExactEth = 'swapExactETHForTokens', + sellExactToken = 'swapExactTokensForETH', + swapExactIn = 'swapExactTokensForTokens', + buyExactEth = 'swapTokensForExactETH', + buyExactToken = 'swapETHForExactTokens', + swapExactOut = 'swapTokensForExactTokens', +} + export type DexParams = UniswapV2DexParams; export interface SmardexPoolOrderedParams extends UniswapV2PoolOrderedParams { From 954342ff8a48b767c89117a4875011218f653e85 Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Tue, 5 Sep 2023 19:43:37 +0100 Subject: [PATCH 213/833] feat: add dexalot api key --- src/config.ts | 3 +++ src/dex/dexalot/dexalot.ts | 23 +++++++++++++++++++++++ src/types.ts | 1 + 3 files changed, 27 insertions(+) diff --git a/src/config.ts b/src/config.ts index 45b466f84..f59133c26 100644 --- a/src/config.ts +++ b/src/config.ts @@ -30,6 +30,7 @@ type BaseConfig = { hashFlowAuthToken?: string; hashFlowDisabledMMs: string[]; swaapV2AuthToken?: string; + dexalotAuthToken?: string; forceRpcFallbackDexs: string[]; }; @@ -219,6 +220,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_43114`]?.split(',') || [], + dexalotAuthToken: process.env.API_KEY_DEXALOT_AUTH_TOKEN || '', adapterAddresses: { AvalancheAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9', AvalancheAdapter02: '0xDCf4EE5B700e2a5Fec458e06B763A4a3E3004494', @@ -358,6 +360,7 @@ export function generateConfig(network: number): Config { baseConfig.rpcPollingBlocksBackToTriggerUpdate, hashFlowAuthToken: baseConfig.hashFlowAuthToken, swaapV2AuthToken: baseConfig.swaapV2AuthToken, + dexalotAuthToken: baseConfig.dexalotAuthToken, hashFlowDisabledMMs: baseConfig.hashFlowDisabledMMs, forceRpcFallbackDexs: baseConfig.forceRpcFallbackDexs, }; diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 250d79c97..b9bcc537d 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -64,6 +64,8 @@ export class Dexalot extends SimpleExchange implements IDex { readonly isFeeOnTransferSupported = false; private rateFetcher: RateFetcher; + private dexalotAuthToken: string; + private pricesCacheKey: string; private pairsCacheKey: string; private tokensAddrCacheKey: string; @@ -87,6 +89,13 @@ export class Dexalot extends SimpleExchange implements IDex { super(dexHelper, dexKey); this.logger = dexHelper.getLogger(dexKey); + const authToken = dexHelper.config.data.dexalotAuthToken; + assert( + authToken !== undefined, + 'Dexalot auth token is not specified with env variable', + ); + this.dexalotAuthToken = authToken; + this.pricesCacheKey = `${CACHE_PREFIX}_prices`; this.pairsCacheKey = `${CACHE_PREFIX}_pairs`; this.tokensAddrCacheKey = `${CACHE_PREFIX}_tokens_addr`; @@ -106,15 +115,27 @@ export class Dexalot extends SimpleExchange implements IDex { blacklistIntervalMs: DEXALOT_API_BLACKLIST_POLLING_INTERVAL_MS, pairsReqParams: { url: `${DEXALOT_API_URL}/api/rfq/pairs`, + headers: { + 'x-apikey': this.dexalotAuthToken, + }, }, pricesReqParams: { url: `${DEXALOT_API_URL}/api/rfq/prices`, + headers: { + 'x-apikey': this.dexalotAuthToken, + }, }, tokensReqParams: { url: `${DEXALOT_API_URL}/api/rfq/tokens`, + headers: { + 'x-apikey': this.dexalotAuthToken, + }, }, blacklistReqParams: { url: `${DEXALOT_API_URL}/api/rfq/blacklist`, + headers: { + 'x-apikey': this.dexalotAuthToken, + }, }, pairsCacheKey: this.pairsCacheKey, pairsCacheTTLSecs: DEXALOT_PAIRS_CACHES_TTL_S, @@ -489,6 +510,8 @@ export class Dexalot extends SimpleExchange implements IDex { const rfq: RFQResponse = await this.dexHelper.httpRequest.post( `${DEXALOT_API_URL}/api/rfq/firm`, rfqParams, + undefined, + { 'x-apikey': this.dexalotAuthToken }, ); if (!rfq) { this.generateRFQError( diff --git a/src/types.ts b/src/types.ts index 9d914b038..7ba68d56a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -276,6 +276,7 @@ export type Config = { hashFlowDisabledMMs: string[]; uniswapV3EventLoggingSampleRate?: number; swaapV2AuthToken?: string; + dexalotAuthToken?: string; forceRpcFallbackDexs: string[]; }; From a08c913830949f585b9ec24d48fd3436ddd78d8d Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 6 Sep 2023 10:57:50 +0200 Subject: [PATCH 214/833] 2.34.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a6cce989f..ba58b19a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.33.3", + "version": "2.34.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From bf35ff7e51521b310eae4b008e1d336302c03329 Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Wed, 6 Sep 2023 12:34:47 +0300 Subject: [PATCH 215/833] feat(BACK-1264): add support for uniswapV3 on Base --- src/config.ts | 29 +++++++++++++++++++++++++++++ src/constants.ts | 3 ++- src/dex/uniswap-v3/config.ts | 13 +++++++++++++ src/dex/weth/config.ts | 3 +++ 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index 45b466f84..e35fd6c42 100644 --- a/src/config.ts +++ b/src/config.ts @@ -317,6 +317,35 @@ const baseConfigs: { [network: number]: BaseConfig } = { rpcPollingBlocksBackToTriggerUpdate: 3, forceRpcFallbackDexs: [], }, + [Network.BASE]: { + network: Network.BASE, + networkName: 'Base', + isTestnet: false, + nativeTokenName: 'Ether', + nativeTokenSymbol: 'ETH', + wrappedNativeTokenAddress: '0x4200000000000000000000000000000000000006', + hasEIP1559: false, + augustusAddress: '0x793a0Bb089c6787e84277f08179DAC594eDb9443', + augustusRFQAddress: '0xa003dFBA51C9e1e56C67ae445b852bdEd7aC5EEd', + tokenTransferProxyAddress: '0xCADa28FC80ceB3baF3BEa4C2d7a819e69435907E', + multicallV2Address: '0xeDF6D2a16e8081F777eB623EeB4411466556aF3d', + privateHttpProvider: process.env.HTTP_PROVIDER_8453, + hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', + hashFlowDisabledMMs: + process.env[`HASHFLOW_DISABLED_MMS_10`]?.split(',') || [], + + adapterAddresses: { + BaseAdapter01: '0x9F77bb28e97F093Aa6CbE37cE095C18605d98Af2', + BaseBuyAdapter: '0x8DE036910e34b0d8447Dd0D34C742636de1DDfEb', + }, + uniswapV2ExchangeRouterAddress: + '0x75d199EfB540e47D27D52c62Da3E7daC2B9e834F', + uniswapV3EventLoggingSampleRate: 0, + rfqConfigs: {}, + rpcPollingMaxAllowedStateDelayInBlocks: 5, + rpcPollingBlocksBackToTriggerUpdate: 3, + forceRpcFallbackDexs: [], + }, }; // Should not be used, except by internal test code diff --git a/src/constants.ts b/src/constants.ts index 08c210b0a..d06c902e5 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -21,7 +21,7 @@ export const MAX_BLOCKS_HISTORY = 7; export const SETUP_RETRY_TIMEOUT = 20 * 1000; // 20s -export const FETCH_POOL_IDENTIFIER_TIMEOUT = 1 * 1000; // 1s +export const FETCH_POOL_IDENTIFIER_TIMEOUT = 60 * 1000; // 1s // TODO change once finished testing export const FETCH_POOL_PRICES_TIMEOUT = 3 * 1000; // 3s // How frequently logs wil be printed @@ -38,6 +38,7 @@ export enum Network { FANTOM = 250, ARBITRUM = 42161, OPTIMISM = 10, + BASE = 8453, } export const SUBGRAPH_TIMEOUT = 20 * 1000; diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index 86d0e6163..007d39c04 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -106,6 +106,19 @@ export const UniswapV3Config: DexConfigMap = { subgraphURL: 'https://api.thegraph.com/subgraphs/name/lynnshaoyu/uniswap-v3-avax', }, + [Network.BASE]: { + factory: '0x33128a8fC17869897dcE68Ed026d694621f6FDfD', + quoter: '0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a', + router: '0xaeE2b8d4A154e36f479dAeCe3FB3e6c3c03d396E', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x7160f736c52e1e78e92FD4eE4D73e21A7Cf4F950', + uniswapMulticall: '0x091e99cb1C49331a94dD62755D168E941AbD0693', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/lynnshaoyu/uniswap-v3-base', + }, }, SushiSwapV3: { [Network.MAINNET]: { diff --git a/src/dex/weth/config.ts b/src/dex/weth/config.ts index 3b528ab2d..95d779e20 100644 --- a/src/dex/weth/config.ts +++ b/src/dex/weth/config.ts @@ -25,6 +25,9 @@ export const WethConfig: DexConfigMap = { [Network.ZKEVM]: { poolGasCost: WethGasCost, }, + [Network.BASE]: { + poolGasCost: WethGasCost, + }, }, Wbnb: { [Network.BSC]: { From 138db04fb19fd45c6c8ecceb1af4c334503f6655 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 6 Sep 2023 13:17:22 +0200 Subject: [PATCH 216/833] advance dex-lib version post merge --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f84d00f82..ba58b19a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.31.4-zkevm-revive.13", + "version": "2.34.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e5fc062ae71c8dae1ccd472817c300465c3b4c5c Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 6 Sep 2023 13:19:45 +0200 Subject: [PATCH 217/833] 2.35.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ba58b19a6..9c051de3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.34.0", + "version": "2.35.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From cb74d782f826453458151204c22c8eb121f66ce4 Mon Sep 17 00:00:00 2001 From: julien Date: Wed, 6 Sep 2023 15:45:49 +0200 Subject: [PATCH 218/833] feat:: added working event-test --- src/dex/smardex/smardex-events.test.ts | 99 ++++++++++++++++++++++++++ src/dex/smardex/smardex.ts | 32 +++++---- src/dex/smardex/types.ts | 1 + 3 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 src/dex/smardex/smardex-events.test.ts diff --git a/src/dex/smardex/smardex-events.test.ts b/src/dex/smardex/smardex-events.test.ts new file mode 100644 index 000000000..c41cfbd25 --- /dev/null +++ b/src/dex/smardex/smardex-events.test.ts @@ -0,0 +1,99 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +import { Interface } from '@ethersproject/abi'; +dotenv.config(); + +import SmardexPoolLayerOneABI from '../../abi/smardex/layer-1/smardex-pool.json'; +// import SmardexPoolLayerTwoABI from '../../abi/smardex/layer-2/smardex-pool.json'; +import { SmardexEventPool } from './smardex'; +import { Network } from '../../constants'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { + testEventSubscriber, +} from '../../../tests/utils-events'; +import { + SmardexPoolState, +} from './types'; + +jest.setTimeout(120 * 1000); +const dexKey = 'Smardex'; +const network = Network.MAINNET; +// const config = SmardexConfig[dexKey][network]; + +async function fetchPoolStateFromContractAtBlock( + smardexEventPool: SmardexEventPool, + blockNumber: number, + poolAddress: string, + logger: any, +): Promise { + const message = `Smardex: ${poolAddress} blockNumber ${blockNumber}`; + console.log(`Fetching state ${message}`); + + const state = await smardexEventPool.generateState(blockNumber); + console.log(`Done ${message}`); + + return state; +} + +describe('Smardex Ethereum SDEX-USDT Pool Event', function () { + const poolAddress = '0xd2bf378cea07fe117ffdfd3f5b7e53c2b0b78c05'; // sdex-usdt + const token0 = { address: '0x5de8ab7e27f6e7a1fff3e5b337584aa43961beef', decimals: 18 }; + const token1 = { address: '0xdac17f958d2ee523a2206206994597c13d831ec7', decimals: 6 }; + + const blockNumbers: { [eventName: string]: number[] } = { + ['Swap']: [ + 18064045, + // 18064060, 18064194, 18065266, //18066464, // the last one contains multiple Swap events + ], + // ['Burn']: [1806404500000], + // ['Mint']: [1806404500000], + ['SetFeeProtocol']: [], + ['Sync']: [ + 18064045, + // 18064060, 18064194, 18065266, //18066464, // the last one contains multiple Snyc events + ], + ['Transfer']: [18064025], + }; + + describe('SmardexEventPool ethereum', function () { + Object.keys(blockNumbers).forEach((event: string) => { + blockNumbers[event].forEach((blockNumber: number) => { + it(`${event}:${blockNumber} - should return correct state`, async function () { + const dexHelper = new DummyDexHelper(network); + + const logger = dexHelper.getLogger(dexKey); + + const SmardexPool = new SmardexEventPool( + new Interface(SmardexPoolLayerOneABI), + dexHelper, + poolAddress, + token0, + token1, + logger, + undefined, + undefined, + ); + + // It is done in generateState. But here have to make it manually + // SmardexPool.poolAddress = poolAddress.toLowerCase(); + // SmardexPool.addressesSubscribed[0] = poolAddress.toLowerCase(); + + await testEventSubscriber( + SmardexPool, + SmardexPool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolStateFromContractAtBlock( + SmardexPool, + _blockNumber, + poolAddress, + logger, + ), + blockNumber, + `${dexKey}_${poolAddress}`, + dexHelper.provider, + ); + }); + }); + }); + }); +}); diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 4699a5c99..bed62ebc8 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -1,3 +1,8 @@ +import { AbiCoder, Interface } from '@ethersproject/abi'; +import { BigNumber } from 'ethers'; +import _ from 'lodash'; +import { DeepReadonly, AsyncOrSync } from 'ts-essentials'; +import { Contract } from 'web3-eth-contract'; import { DEST_TOKEN_PARASWAP_TRANSFERS, ETHER_ADDRESS, @@ -21,7 +26,6 @@ import { TxInfo, } from '../../types'; import { IDexHelper } from '../../dex-helper/index'; -import { AbiCoder, Interface } from '@ethersproject/abi'; import { SmardexPair, SmardexPool, @@ -39,13 +43,11 @@ import SmardexFactoryLayerTwoABI from '../../abi/smardex/layer-2/smardex-factory import SmardexPoolLayerOneABI from '../../abi/smardex/layer-1/smardex-pool.json'; import SmardexPoolLayerTwoABI from '../../abi/smardex/layer-2/smardex-pool.json'; import SmardexRouterABI from '../../abi/smardex/all/smardex-router.json'; -import { DeepReadonly, AsyncOrSync } from 'ts-essentials'; import { SimpleExchange } from '../simple-exchange'; import { SmardexData, SmardexRouterFunctions } from '../smardex/types'; import { IDex, StatefulEventSubscriber } from '../..'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { Adapters, SmardexConfig } from './config'; -import { Contract } from 'web3-eth-contract'; import ParaSwapABI from '../../abi/IParaswap.json'; import { UniswapDataLegacy, @@ -53,9 +55,7 @@ import { UniswapV2Functions, } from '../uniswap-v2/types'; import { applyTransferFee } from '../../lib/token-transfer-fee'; -import _ from 'lodash'; import { getAmountIn, getAmountOut } from './smardex-sdk'; -import { BigNumber } from 'ethers'; // event Sync (uint256 reserve0, uint256 reserve1, uint256 fictiveReserve0, uint256 fictiveReserve1, uint256 priceAverage0, uint256 priceAverage1) export const SYNC_EVENT_TOPIC = @@ -106,7 +106,7 @@ export class SmardexEventPool extends StatefulEventSubscriber state: DeepReadonly, log: Readonly, ): AsyncOrSync | null> { - if (log.topics[0] === SYNC_EVENT_TOPIC) return null; + if (log.topics[0] !== SYNC_EVENT_TOPIC) return null; const event = smardexPoolL1.parseLog(log); switch (event.name) { case 'Sync': @@ -117,6 +117,7 @@ export class SmardexEventPool extends StatefulEventSubscriber fictiveReserves1: event.args.fictiveReserve1.toString(), priceAverage0: event.args.priceAverage0.toString(), priceAverage1: event.args.priceAverage1.toString(), + priceAverageLastTimestamp: state.priceAverageLastTimestamp, // should be updated but only on Swap event feeCode: state.feeCode, }; } @@ -177,7 +178,7 @@ export class SmardexEventPool extends StatefulEventSubscriber fictiveReserves1: fictiveReserve1.toString(), priceAverage0: priceAverage0.toString(), priceAverage1: priceAverage1.toString(), - // priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), + priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), feeCode: dynamicFees ? this.smardexFeesMulticallDecoder!(data.returnData[3]) : 700, // TODO: Ensure the fees are correct @@ -360,7 +361,7 @@ export class Smardex unit: unitOutWithFee, data: { deadline: 3387835836, // TODO make deadline and receiver dynamic ! - receiver: '0x176F3DAb24a159341c0509bB36B833E7fdd0a132', + receiver: this.augustusAddress, router: this.routerAddress, path: [from.address.toLowerCase(), to.address.toLowerCase()], factory: this.factoryAddress, @@ -521,6 +522,7 @@ export class Smardex pairState.priceAverage1, pairState.feeCode, blockNumber, + pairState.priceAverageLastTimestamp, ); } else pair.pool.setState(pairState, blockNumber); } @@ -556,6 +558,7 @@ export class Smardex priceAverage1: string, feeCode: number, blockNumber: number, + priceAverageLastTimestamp?: number, ) { const multiCallFeeData = this.getFeesMultiCallData(pair); pair.pool = new SmardexEventPool( @@ -580,6 +583,7 @@ export class Smardex priceAverage0, priceAverage1, feeCode, + priceAverageLastTimestamp, }, }); } @@ -634,14 +638,14 @@ export class Smardex .decode(['uint256', 'uint256'], returnData[i][1])[1] .toString(), priceAverage0: coder - .decode(['uint256', 'uint256'], returnData[i][2])[0] + .decode(['uint256', 'uint256', 'uint256'], returnData[i][2])[0] .toString(), priceAverage1: coder - .decode(['uint256', 'uint256'], returnData[i][2])[1] + .decode(['uint256', 'uint256', 'uint256'], returnData[i][2])[1] + .toString(), + priceAverageLastTimestamp: coder + .decode(['uint256', 'uint256', 'uint256'], returnData[i][2])[2] .toString(), - // priceAverageLastTimestamp: coder - // .decode(['uint256', 'uint256', 'uint256'], returnData[i][2])[2] - // .toString(), feeCode: this.isLayer1() ? 700 : multiCallFeeData[i]!.callDecoder(returnData[i][3]), @@ -842,7 +846,7 @@ export class Smardex if (side === SwapSide.SELL) { routerMethod = isETHAddress(src) ? SmardexRouterFunctions.sellExactEth : SmardexRouterFunctions.swapExactIn; routerMethod = isETHAddress(dest) ? SmardexRouterFunctions.sellExactToken : routerMethod; - routerArgs = [srcAmount, BigNumber.from(destAmount).mul(105).div(100).toString(), data.path, data.receiver, data.deadline]; + routerArgs = [srcAmount, destAmount, data.path, data.receiver, data.deadline]; } else { routerMethod = isETHAddress(src) ? SmardexRouterFunctions.buyExactToken : SmardexRouterFunctions.swapExactOut; routerMethod = isETHAddress(dest) ? SmardexRouterFunctions.buyExactEth : routerMethod; diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index 172d445a4..d6cdb7234 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -15,6 +15,7 @@ export interface SmardexPoolState { fictiveReserves1: string; priceAverage0: string; priceAverage1: string; + priceAverageLastTimestamp?: number; feeCode: number; } From 08125bc537f1c56e785d32f96760149a09c05d04 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 6 Sep 2023 16:53:25 +0200 Subject: [PATCH 219/833] remove capping of price in algebra --- src/dex/algebra/algebra.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 3b1f55ae5..5ea37f7b4 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -817,20 +817,7 @@ export class Algebra extends SimpleExchange implements IDex { return null; } - // TODO buy - let lastNonZeroOutput = 0n; - let lastNonZeroTickCountsOutputs = 0; - for (let i = 0; i < outputsResult.outputs.length; i++) { - // local pricing algo may output 0s at the tail for some out of range amounts, prefer to propagating last amount to appease top algo - if (outputsResult.outputs[i] > 0n) { - lastNonZeroOutput = outputsResult.outputs[i]; - lastNonZeroTickCountsOutputs = outputsResult.tickCounts[i]; - } else { - outputsResult.outputs[i] = lastNonZeroOutput; - outputsResult.tickCounts[i] = lastNonZeroTickCountsOutputs; - } - if (outputsResult.outputs[i] > destTokenBalance) { outputsResult.outputs[i] = 0n; outputsResult.tickCounts[i] = 0; From 325ea57ff78a3155c22d4725b5ef5d1450e99cc3 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 6 Sep 2023 16:55:08 +0200 Subject: [PATCH 220/833] 2.35.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9c051de3a..391dce2b8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.0", + "version": "2.35.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 8bea93a095a1e9163a0dd57165746f8ad340c4d2 Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Wed, 6 Sep 2023 18:17:34 +0300 Subject: [PATCH 221/833] 2.33.4-base-support.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a6cce989f..1eda85122 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.33.3", + "version": "2.33.4-base-support.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From fb0faf8f6dbfac15335e3bc1f592c51ddd3a854b Mon Sep 17 00:00:00 2001 From: julien Date: Thu, 7 Sep 2023 14:47:13 +0200 Subject: [PATCH 222/833] fix: added tests cases --- src/dex/smardex/smardex-events.test.ts | 28 +++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/dex/smardex/smardex-events.test.ts b/src/dex/smardex/smardex-events.test.ts index c41cfbd25..9ed98a128 100644 --- a/src/dex/smardex/smardex-events.test.ts +++ b/src/dex/smardex/smardex-events.test.ts @@ -43,16 +43,34 @@ describe('Smardex Ethereum SDEX-USDT Pool Event', function () { const blockNumbers: { [eventName: string]: number[] } = { ['Swap']: [ 18064045, - // 18064060, 18064194, 18065266, //18066464, // the last one contains multiple Swap events + // 18064060, + // 18064194, + // 18065266, + // 18066464, // the last one contains multiple Swap events ], - // ['Burn']: [1806404500000], - // ['Mint']: [1806404500000], + // ['Burn']: [ + // 17231921, + // 17762042, + // 17762668, + // ], + // ['Mint']: [ + // 17739609, + // 17973926, + // 18062443, + // ], ['SetFeeProtocol']: [], ['Sync']: [ 18064045, - // 18064060, 18064194, 18065266, //18066464, // the last one contains multiple Snyc events + // 18064060, + // 18064194, + // 18065266, + // 18066464, // the last one contains multiple Snyc events + ], + ['Transfer']: [ + 18064025, + 18064045, + // 18065266, ], - ['Transfer']: [18064025], }; describe('SmardexEventPool ethereum', function () { From 1de4f018ba7b88192e7c3ba39bbbedc0063a8d1c Mon Sep 17 00:00:00 2001 From: julien Date: Thu, 7 Sep 2023 16:26:03 +0200 Subject: [PATCH 223/833] fix: remove uniswap types --- src/dex/smardex/smardex.ts | 105 ++++++++++++++++++------------------- src/dex/smardex/types.ts | 26 ++++++++- 2 files changed, 77 insertions(+), 54 deletions(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index bed62ebc8..14ebb282b 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -31,6 +31,7 @@ import { SmardexPool, SmardexPoolOrderedParams, SmardexPoolState, + TOPICS, } from './types'; import { getBigIntPow, @@ -44,23 +45,14 @@ import SmardexPoolLayerOneABI from '../../abi/smardex/layer-1/smardex-pool.json' import SmardexPoolLayerTwoABI from '../../abi/smardex/layer-2/smardex-pool.json'; import SmardexRouterABI from '../../abi/smardex/all/smardex-router.json'; import { SimpleExchange } from '../simple-exchange'; -import { SmardexData, SmardexRouterFunctions } from '../smardex/types'; +import { SmardexData, SmardexParam, SmardexRouterFunctions } from '../smardex/types'; import { IDex, StatefulEventSubscriber } from '../..'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { Adapters, SmardexConfig } from './config'; import ParaSwapABI from '../../abi/IParaswap.json'; -import { - UniswapDataLegacy, - UniswapParam, - UniswapV2Functions, -} from '../uniswap-v2/types'; import { applyTransferFee } from '../../lib/token-transfer-fee'; import { getAmountIn, getAmountOut } from './smardex-sdk'; -// event Sync (uint256 reserve0, uint256 reserve1, uint256 fictiveReserve0, uint256 fictiveReserve1, uint256 priceAverage0, uint256 priceAverage1) -export const SYNC_EVENT_TOPIC = - '0x2a368c7f33bb86e2d999940a3989d849031aff29b750f67947e6b8e8c3d2ffd6'; - const DefaultSmardexPoolGasCost = 90 * 1000; const smardexPoolL1 = new Interface(SmardexPoolLayerOneABI); @@ -106,7 +98,7 @@ export class SmardexEventPool extends StatefulEventSubscriber state: DeepReadonly, log: Readonly, ): AsyncOrSync | null> { - if (log.topics[0] !== SYNC_EVENT_TOPIC) return null; + if (log.topics[0] !== TOPICS.SYNC_EVENT) return null; const event = smardexPoolL1.parseLog(log); switch (event.name) { case 'Sync': @@ -117,7 +109,7 @@ export class SmardexEventPool extends StatefulEventSubscriber fictiveReserves1: event.args.fictiveReserve1.toString(), priceAverage0: event.args.priceAverage0.toString(), priceAverage1: event.args.priceAverage1.toString(), - priceAverageLastTimestamp: state.priceAverageLastTimestamp, // should be updated but only on Swap event + priceAverageLastTimestamp: state.priceAverageLastTimestamp, // TODO should be updated but only on Swap event feeCode: state.feeCode, }; } @@ -201,7 +193,7 @@ function encodePools( export class Smardex extends SimpleExchange - implements IDex + implements IDex { pairs: { [key: string]: SmardexPair } = {}; feeFactor = 10000; @@ -266,7 +258,7 @@ export class Smardex } const tokenAddress = [from.address.toLowerCase(), to.address.toLowerCase()] - .sort((a, b) => (a > b ? 1 : -1)) + .sort((a, b) => (BigInt(a) > BigInt(b) ? 1 : -1)) .join('_'); const poolIdentifier = `${this.dexKey}_${tokenAddress}`; @@ -300,7 +292,7 @@ export class Smardex from.address.toLowerCase(), to.address.toLowerCase(), ] - .sort((a, b) => (a > b ? 1 : -1)) + .sort((a, b) => (BigInt(a) > BigInt(b) ? 1 : -1)) .join('_'); const poolIdentifier = `${this.dexKey}_${tokenAddress}`; @@ -466,7 +458,7 @@ export class Smardex async findPair(from: Token, to: Token) { if (from.address.toLowerCase() === to.address.toLowerCase()) return null; const [token0, token1] = - from.address.toLowerCase() < to.address.toLowerCase() + BigInt(from.address.toLowerCase()) < BigInt(to.address.toLowerCase()) ? [from, to] : [to, from]; @@ -687,56 +679,63 @@ export class Smardex partner: string, beneficiary: string, contractMethod?: string, - ): TxInfo { + ): TxInfo { if (!contractMethod) throw new Error(`contractMethod need to be passed`); if (permit !== '0x') contractMethod += 'WithPermit'; - const swapParams = ((): UniswapParam => { - const data = _data as unknown as UniswapDataLegacy; + const swapParams = ((): SmardexParam => { + const data = _data as unknown as SmardexData; const path = this.fixPath(data.path, srcToken, destToken); switch (contractMethod) { - case UniswapV2Functions.swapOnUniswap: - case UniswapV2Functions.buyOnUniswap: - return [srcAmount, destAmount, path]; - - case UniswapV2Functions.swapOnUniswapFork: - case UniswapV2Functions.buyOnUniswapFork: - return [ - data.factory, - prependWithOx(data.initCode), - srcAmount, - destAmount, - path, - ]; - - case UniswapV2Functions.swapOnUniswapV2Fork: - case UniswapV2Functions.buyOnUniswapV2Fork: return [ - srcToken, - srcAmount, - destAmount, - this.getWETHAddress(srcToken, destToken, _data.wethAddress), - encodePools(_data.pools, this.feeFactor), - ]; - - case UniswapV2Functions.swapOnUniswapV2ForkWithPermit: - case UniswapV2Functions.buyOnUniswapV2ForkWithPermit: - return [ - srcToken, - srcAmount, - destAmount, - this.getWETHAddress(srcToken, destToken, _data.wethAddress), - encodePools(_data.pools, this.feeFactor), - permit, - ]; + case SmardexRouterFunctions.sellExactEth: + case SmardexRouterFunctions.sellExactToken: + case SmardexRouterFunctions.swapExactIn: + return [srcAmount, destAmount, data.path, data.receiver, data.deadline]; + + case SmardexRouterFunctions.buyExactEth: + case SmardexRouterFunctions.buyExactToken: + case SmardexRouterFunctions.swapExactOut: + return [destAmount, srcAmount, data.path, data.receiver, data.deadline]; + + // case UniswapV2Functions.swapOnUniswapFork: + // case UniswapV2Functions.buyOnUniswapFork: + // return [ + // data.factory, + // prependWithOx(data.initCode), + // srcAmount, + // destAmount, + // path, + // ]; + + // case UniswapV2Functions.swapOnUniswapV2Fork: + // case UniswapV2Functions.buyOnUniswapV2Fork: + // return [ + // srcToken, + // srcAmount, + // destAmount, + // this.getWETHAddress(srcToken, destToken, _data.wethAddress), + // encodePools(_data.pools, this.feeFactor), + // ]; + + // case UniswapV2Functions.swapOnUniswapV2ForkWithPermit: + // case UniswapV2Functions.buyOnUniswapV2ForkWithPermit: + // return [ + // srcToken, + // srcAmount, + // destAmount, + // this.getWETHAddress(srcToken, destToken, _data.wethAddress), + // encodePools(_data.pools, this.feeFactor), + // permit, + // ]; default: throw new Error(`contractMethod=${contractMethod} is not supported`); } })(); - const encoder = (...params: UniswapParam) => + const encoder = (...params: SmardexParam) => this.routerInterface.encodeFunctionData(contractMethod!, params); return { params: swapParams, diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index d6cdb7234..7ad41f73a 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -1,9 +1,10 @@ -import { Address } from '../../types'; +import { Address, NumberAsString } from '../../types'; import { UniswapV2Data, UniswapV2PoolOrderedParams, DexParams as UniswapV2DexParams, UniswapPool, + UniswapDataLegacy, } from '../uniswap-v2/types'; import { UniswapV2Pair } from '../uniswap-v2/uniswap-v2'; import { SmardexEventPool } from './smardex'; @@ -19,11 +20,16 @@ export interface SmardexPoolState { feeCode: number; } +// event Sync (uint256 reserve0, uint256 reserve1, uint256 fictiveReserve0, uint256 fictiveReserve1, uint256 priceAverage0, uint256 priceAverage1) +export enum TOPICS { SYNC_EVENT = '0x2a368c7f33bb86e2d999940a3989d849031aff29b750f67947e6b8e8c3d2ffd6' }; + export interface SmardexData extends UniswapV2Data { deadline: number; receiver: Address; } +// export type SmardexDataLegacy = UniswapDataLegacy; + export enum SmardexRouterFunctions { sellExactEth = 'swapExactETHForTokens', sellExactToken = 'swapExactTokensForETH', @@ -33,6 +39,24 @@ export enum SmardexRouterFunctions { swapExactOut = 'swapTokensForExactTokens', } +export type SellOnSmardexParam = [ + amountIn: NumberAsString, + amountOutMin: NumberAsString, + path: Address[], + receiver: Address, + deadline: number, +]; + +export type BuyOnSmardexParam = [ + amountIn: NumberAsString, + amountOutMin: NumberAsString, + path: Address[], + receiver: Address, + deadline: number, +]; + +export type SmardexParam = SellOnSmardexParam | BuyOnSmardexParam; + export type DexParams = UniswapV2DexParams; export interface SmardexPoolOrderedParams extends UniswapV2PoolOrderedParams { From f088a378a62be85e21ddc63f8d9ff3783f8b975a Mon Sep 17 00:00:00 2001 From: julien Date: Thu, 7 Sep 2023 17:31:22 +0200 Subject: [PATCH 224/833] fix: wip --- src/dex/smardex/smardex.ts | 9 ++++++--- src/dex/smardex/types.ts | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 14ebb282b..a9e25148b 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -206,7 +206,8 @@ export class Smardex factoryAddress: string; routerAddress: string; - initCode: string; + protected subgraphURL: string; + protected initCode: string; logger: Logger; @@ -228,6 +229,7 @@ export class Smardex const config = SmardexConfig[dexKey]; this.routerAddress = config[network].router!; this.factoryAddress = config[network].factoryAddress; + this.subgraphURL = config[network].subgraphURL; this.initCode = config[network].initCode; const factoryAbi = this.isLayer1() ? SmardexFactoryLayerOneABI @@ -550,7 +552,7 @@ export class Smardex priceAverage1: string, feeCode: number, blockNumber: number, - priceAverageLastTimestamp?: number, + priceAverageLastTimestamp: number, ) { const multiCallFeeData = this.getFeesMultiCallData(pair); pair.pool = new SmardexEventPool( @@ -688,7 +690,6 @@ export class Smardex const path = this.fixPath(data.path, srcToken, destToken); switch (contractMethod) { - return [ case SmardexRouterFunctions.sellExactEth: case SmardexRouterFunctions.sellExactToken: case SmardexRouterFunctions.swapExactIn: @@ -774,6 +775,7 @@ export class Smardex fictiveReservesOut: pairState.fictiveReserves0, priceAverageIn: pairState.priceAverage0, priceAverageOut: pairState.priceAverage1, + priceAverageLastTimestamp: pairState.priceAverageLastTimestamp, fee, direction: false, exchange: pair.exchange, @@ -788,6 +790,7 @@ export class Smardex fictiveReservesOut: pairState.fictiveReserves1, priceAverageIn: pairState.priceAverage0, priceAverageOut: pairState.priceAverage1, + priceAverageLastTimestamp: pairState.priceAverageLastTimestamp, fee, direction: true, exchange: pair.exchange, diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index 7ad41f73a..ea984904b 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -16,7 +16,7 @@ export interface SmardexPoolState { fictiveReserves1: string; priceAverage0: string; priceAverage1: string; - priceAverageLastTimestamp?: number; + priceAverageLastTimestamp: number; feeCode: number; } @@ -64,6 +64,7 @@ export interface SmardexPoolOrderedParams extends UniswapV2PoolOrderedParams { fictiveReservesOut: string; priceAverageIn: string; priceAverageOut: string; + priceAverageLastTimestamp: number, } export interface SmardexPair extends Omit { From 5716c2b160c71e0b6b17cb3ec7aed3f60c1296c9 Mon Sep 17 00:00:00 2001 From: fireboss777 Date: Thu, 7 Sep 2023 17:51:22 +0200 Subject: [PATCH 225/833] test: e2e pass with wrong values --- src/dex/smardex/smardex-e2e.test.ts | 4 +- src/dex/smardex/smardex-sdk.ts | 1652 +++++++++++++++++---------- src/dex/smardex/smardex.ts | 81 +- src/dex/smardex/types.ts | 8 +- tests/constants-e2e.ts | 4 + 5 files changed, 1122 insertions(+), 627 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index e917dfe05..a95bf2c35 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -19,10 +19,10 @@ describe('Smardex E2E Mainnet', () => { const dexKey = 'Smardex'; describe('Simpleswap', () => { - it('WETH -> TOKEN', async () => { + it('WETH -> SDEX', async () => { await testE2E( tokens.WETH, - tokens.USDT, + tokens.SDEX, holders.WETH, '2000000000000000000', // 2 WETH SwapSide.SELL, // exact input diff --git a/src/dex/smardex/smardex-sdk.ts b/src/dex/smardex/smardex-sdk.ts index 4e415ae27..f423a7d35 100644 --- a/src/dex/smardex/smardex-sdk.ts +++ b/src/dex/smardex/smardex-sdk.ts @@ -66,12 +66,49 @@ export enum TradeType { EXACT_OUTPUT, } // compute first trade amountIn using arbitrage feature +// function computeFirstTradeQtyIn( +// amountIn: BigNumber, +// reserveInFic: BigNumber, +// reserveOutFic: BigNumber, +// priceAverageIn: BigNumber, +// priceAverageOut: BigNumber, +// ): BigNumber { +// // default value +// let firstAmountIn = amountIn; + +// // if trade is in the good direction +// if (reserveOutFic.mul(priceAverageIn).gt(reserveInFic.mul(priceAverageOut))) { +// // pre-compute all operands +// const toSub = reserveInFic.mul( +// FEES_BASE.add(FEES_TOTAL_REVERSED).sub(FEES_POOL), +// ); +// const toDiv = FEES_TOTAL_REVERSED.add(FEES_LP).mul(2); +// const inSqrt = reserveInFic +// .mul(reserveOutFic) +// .mul(4) +// .div(priceAverageOut) +// .mul(priceAverageIn) +// .mul(FEES_TOTAL_REVERSED) +// .mul(FEES_BASE.sub(FEES_POOL)) +// .add(reserveInFic.mul(reserveInFic).mul(FEES_LP).mul(FEES_LP)); + +// // reverse sqrt check to only compute sqrt if really needed +// if (inSqrt.lt(amountIn.mul(toDiv).add(toSub).pow(2))) { +// firstAmountIn = sqrt(inSqrt).sub(toSub).div(toDiv); +// } +// } + +// return firstAmountIn; +// } + function computeFirstTradeQtyIn( amountIn: BigNumber, reserveInFic: BigNumber, reserveOutFic: BigNumber, priceAverageIn: BigNumber, priceAverageOut: BigNumber, + feesLP: BigNumber, + feesPool: BigNumber, ): BigNumber { // default value let firstAmountIn = amountIn; @@ -79,18 +116,22 @@ function computeFirstTradeQtyIn( // if trade is in the good direction if (reserveOutFic.mul(priceAverageIn).gt(reserveInFic.mul(priceAverageOut))) { // pre-compute all operands + const feesTotalReversed = FEES_BASE.sub(feesLP).sub(feesPool); + const toSub = reserveInFic.mul( - FEES_BASE.add(FEES_TOTAL_REVERSED).sub(FEES_POOL), + FEES_BASE.add(feesTotalReversed).sub(feesPool), ); - const toDiv = FEES_TOTAL_REVERSED.add(FEES_LP).mul(2); + + const toDiv = feesTotalReversed.add(feesLP).mul(2); + const inSqrt = reserveInFic .mul(reserveOutFic) .mul(4) .div(priceAverageOut) .mul(priceAverageIn) - .mul(FEES_TOTAL_REVERSED) - .mul(FEES_BASE.sub(FEES_POOL)) - .add(reserveInFic.mul(reserveInFic).mul(FEES_LP).mul(FEES_LP)); + .mul(feesTotalReversed) + .mul(FEES_BASE.sub(feesPool)) + .add(reserveInFic.mul(reserveInFic).mul(feesLP).mul(feesLP)); // reverse sqrt check to only compute sqrt if really needed if (inSqrt.lt(amountIn.mul(toDiv).add(toSub).pow(2))) { @@ -101,6 +142,46 @@ function computeFirstTradeQtyIn( return firstAmountIn; } +// // compute first trade amountOut using arbitrage feature +// function computeFirstTradeQtyOut( +// amountOut: BigNumber, +// reserveInFic: BigNumber, +// reserveOutFic: BigNumber, +// priceAverageIn: BigNumber, +// priceAverageOut: BigNumber, +// ): BigNumber { +// // default value +// let firstAmountOut = amountOut; + +// // if trade is in the good direction +// if (reserveOutFic.mul(priceAverageIn).gt(reserveInFic.mul(priceAverageOut))) { +// // pre-compute all operands +// const reserveOutFicPredictedFees = reserveInFic +// .mul(FEES_LP) +// .mul(priceAverageOut) +// .div(priceAverageIn); +// const toAdd = reserveOutFic +// .mul(FEES_TOTAL_REVERSED) +// .mul(2) +// .add(reserveOutFicPredictedFees); +// const toDiv = FEES_TOTAL_REVERSED.mul(2); +// const inSqrt = reserveOutFic +// .mul(reserveOutFicPredictedFees) +// .mul(4) +// .mul(FEES_TOTAL_REVERSED) +// .mul(FEES_BASE.sub(FEES_POOL)) +// .div(FEES_LP) +// .add(reserveOutFicPredictedFees.pow(2)); + +// // reverse sqrt check to only compute sqrt if really needed +// if (inSqrt.gt(toAdd.sub(amountOut.mul(toDiv)).pow(2))) { +// firstAmountOut = toAdd.sub(sqrt(inSqrt)).div(toDiv); +// } +// } + +// return firstAmountOut; +// } + // compute first trade amountOut using arbitrage feature function computeFirstTradeQtyOut( amountOut: BigNumber, @@ -108,6 +189,8 @@ function computeFirstTradeQtyOut( reserveOutFic: BigNumber, priceAverageIn: BigNumber, priceAverageOut: BigNumber, + feesLP: BigNumber, + feesPool: BigNumber, ): BigNumber { // default value let firstAmountOut = amountOut; @@ -115,21 +198,26 @@ function computeFirstTradeQtyOut( // if trade is in the good direction if (reserveOutFic.mul(priceAverageIn).gt(reserveInFic.mul(priceAverageOut))) { // pre-compute all operands + const feesTotalReversed = FEES_BASE.sub(feesLP).sub(feesPool); + const reserveOutFicPredictedFees = reserveInFic - .mul(FEES_LP) + .mul(feesLP) .mul(priceAverageOut) .div(priceAverageIn); + const toAdd = reserveOutFic - .mul(FEES_TOTAL_REVERSED) + .mul(feesTotalReversed) .mul(2) .add(reserveOutFicPredictedFees); - const toDiv = FEES_TOTAL_REVERSED.mul(2); + + const toDiv = feesTotalReversed.mul(2); + const inSqrt = reserveOutFic .mul(reserveOutFicPredictedFees) .mul(4) - .mul(FEES_TOTAL_REVERSED) - .mul(FEES_BASE.sub(FEES_POOL)) - .div(FEES_LP) + .mul(feesTotalReversed) + .mul(FEES_BASE.sub(feesPool)) + .div(feesLP) .add(reserveOutFicPredictedFees.pow(2)); // reverse sqrt check to only compute sqrt if really needed @@ -149,18 +237,24 @@ function applyKConstRuleOut( reserveOut: BigNumber, reserveInFic: BigNumber, reserveOutFic: BigNumber, + feesLP: BigNumber, + feesPool: BigNumber, ): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { // k const rule - const amountInWithFee = amountIn.mul(FEES_TOTAL_REVERSED); + const feesTotalReversed = FEES_BASE.sub(feesLP).sub(feesPool); + const amountInWithFee = amountIn.mul(feesTotalReversed); const numerator = amountInWithFee.mul(reserveOutFic); const denominator = reserveInFic.mul(FEES_BASE).add(amountInWithFee); - if (denominator.eq(0)) throw new Error('SMARDEX_K_ERROR'); + + if (denominator.eq(0)) { + throw new Error('SMARDEX_K_ERROR'); + } const amountOut = numerator.div(denominator); // update new reserves and add lp-fees to pools const amountInWithFeeLp = amountIn - .mul(FEES_LP) + .mul(feesLP) .add(amountInWithFee) .div(FEES_BASE); const newResIn = reserveIn.add(amountInWithFeeLp); @@ -171,24 +265,87 @@ function applyKConstRuleOut( return [amountOut, newResIn, newResOut, newResInFic, newResOutFic]; } -// apply uniswap k const rule. amountOut -> amountIn -// returns [amountIn, newResIn, newResOut, newResInFic, newResOutFic] +// // apply uniswap k const rule. amountIn -> amountOut +// // return [amountOut, newResIn, newResOut, newResInFic, newResOutFic] +// function applyKConstRuleOut( +// amountIn: BigNumber, +// reserveIn: BigNumber, +// reserveOut: BigNumber, +// reserveInFic: BigNumber, +// reserveOutFic: BigNumber, +// ): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { +// // k const rule +// const amountInWithFee = amountIn.mul(FEES_TOTAL_REVERSED); +// const numerator = amountInWithFee.mul(reserveOutFic); +// const denominator = reserveInFic.mul(FEES_BASE).add(amountInWithFee); +// if (denominator.eq(0)) throw new Error('SMARDEX_K_ERROR'); + +// const amountOut = numerator.div(denominator); + +// // update new reserves and add lp-fees to pools +// const amountInWithFeeLp = amountIn +// .mul(FEES_LP) +// .add(amountInWithFee) +// .div(FEES_BASE); +// const newResIn = reserveIn.add(amountInWithFeeLp); +// const newResInFic = reserveInFic.add(amountInWithFeeLp); +// const newResOut = reserveOut.sub(amountOut); +// const newResOutFic = reserveOutFic.sub(amountOut); + +// return [amountOut, newResIn, newResOut, newResInFic, newResOutFic]; +// } + +// // apply uniswap k const rule. amountOut -> amountIn +// // returns [amountIn, newResIn, newResOut, newResInFic, newResOutFic] +// function applyKConstRuleIn( +// amountOut: BigNumber, +// reserveIn: BigNumber, +// reserveOut: BigNumber, +// reserveInFic: BigNumber, +// reserveOutFic: BigNumber, +// ): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { +// // k const rule +// const numerator = reserveInFic.mul(amountOut).mul(FEES_BASE); +// const denominator = reserveOutFic.sub(amountOut).mul(FEES_TOTAL_REVERSED); +// if (denominator.eq(0)) throw new Error('SMARDEX_K_ERROR'); + +// const amountIn = numerator.div(denominator).add(1); + +// // update new reserves +// const amountInWithFeeLp = FEES_TOTAL_REVERSED.add(FEES_LP) +// .mul(amountIn) +// .div(FEES_BASE); +// const newResIn = reserveIn.add(amountInWithFeeLp); +// const newResInFic = reserveInFic.add(amountInWithFeeLp); +// const newResOut = reserveOut.sub(amountOut); +// const newResOutFic = reserveOutFic.sub(amountOut); + +// return [amountIn, newResIn, newResOut, newResInFic, newResOutFic]; +// } + function applyKConstRuleIn( amountOut: BigNumber, reserveIn: BigNumber, reserveOut: BigNumber, reserveInFic: BigNumber, reserveOutFic: BigNumber, + feesLP: BigNumber, + feesPool: BigNumber, ): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { // k const rule + const feesTotalReversed = FEES_BASE.sub(feesLP).sub(feesPool); const numerator = reserveInFic.mul(amountOut).mul(FEES_BASE); - const denominator = reserveOutFic.sub(amountOut).mul(FEES_TOTAL_REVERSED); - if (denominator.eq(0)) throw new Error('SMARDEX_K_ERROR'); + const denominator = reserveOutFic.sub(amountOut).mul(feesTotalReversed); - const amountIn = numerator.div(denominator).add(1); + if (denominator.eq(0)) { + throw new Error('SMARDEX_K_ERROR'); + } + + const amountIn = numerator.div(denominator.add(1)); // update new reserves - const amountInWithFeeLp = FEES_TOTAL_REVERSED.add(FEES_LP) + const amountInWithFeeLp = feesTotalReversed + .add(feesLP) .mul(amountIn) .div(FEES_BASE); const newResIn = reserveIn.add(amountInWithFeeLp); @@ -252,6 +409,122 @@ export function computeReserveFic( * @param {BigNumber} priceAverageOut the price average of output token. * @returns {Array} [amountOut, newResIn, newResOut, newResInFic, newResOutFic] */ +// export function getAmountOut( +// amountIn: BigNumber, +// reserveIn: BigNumber, +// reserveOut: BigNumber, +// reserveInFic: BigNumber, +// reserveOutFic: BigNumber, +// priceAverageIn: BigNumber, +// priceAverageOut: BigNumber, +// ): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { +// if (amountIn.lt(0)) throw new Error('INSUFFICIENT_INPUT_AMOUNT'); +// if (reserveIn.lt(0) || reserveOut.lt(0)) +// throw new Error('INSUFFICIENT_LIQUIDITY'); +// if (reserveInFic.lt(0) || reserveOutFic.lt(0)) +// throw new Error('INSUFFICIENT_LIQUIDITY'); + +// let reserveInFicUpdated = BigNumber.from(reserveInFic); +// let reserveOutFicUpdated = BigNumber.from(reserveOutFic); + +// const amountWithFees = amountIn.mul(FEES_TOTAL_REVERSED).div(FEES_BASE); +// const firstAmount = computeFirstTradeQtyIn( +// amountWithFees, +// reserveInFic, +// reserveOutFic, +// priceAverageIn, +// priceAverageOut, +// ); + +// // if there are 2 trades: 1st trade mustn't re-compute ReserveFic, 2nd should +// if ( +// firstAmount.eq(amountWithFees) && +// ratioApproxEq(reserveInFic, reserveOutFic, priceAverageIn, priceAverageOut) +// ) { +// [reserveInFicUpdated, reserveOutFicUpdated] = computeReserveFic( +// reserveIn, +// reserveOut, +// reserveInFic, +// reserveOutFic, +// ); +// } + +// // Avoid K constant division by 0 +// if (reserveInFicUpdated.lte('0')) +// return [ +// utils.parseEther('0'), +// reserveIn, +// reserveOut, +// reserveInFicUpdated, +// reserveOutFicUpdated, +// ]; + +// const firstAmountNoFees = firstAmount.mul(FEES_BASE).div(FEES_TOTAL_REVERSED); +// let [amountOut, newResIn, newResOut, newResInFic, newResOutFic] = +// applyKConstRuleOut( +// firstAmountNoFees, +// reserveIn, +// reserveOut, +// reserveInFicUpdated, +// reserveOutFicUpdated, +// ); + +// // if we need a second trade +// if (firstAmount.lt(amountWithFees) && firstAmountNoFees.lt(amountIn)) { +// [newResInFic, newResOutFic] = computeReserveFic( +// newResIn, +// newResOut, +// newResInFic, +// newResOutFic, +// ); + +// // Avoid K constant division by 0 +// if (newResInFic.lte('0')) +// return [ +// utils.parseEther('0'), +// reserveIn, +// reserveOut, +// reserveInFicUpdated, +// reserveOutFicUpdated, +// ]; + +// let secondAmountOutNoFees: BigNumber; +// [secondAmountOutNoFees, newResIn, newResOut, newResInFic, newResOutFic] = +// applyKConstRuleOut( +// amountIn.sub(firstAmountNoFees), +// newResIn, +// newResOut, +// newResInFic, +// newResOutFic, +// ); +// amountOut = amountOut.add(secondAmountOutNoFees); +// } + +// if ( +// newResIn.lte(0) || +// newResOut.lte(0) || +// newResInFic.lte(0) || +// newResOutFic.lte(0) +// ) { +// throw new Error('INSUFFICIENT_LIQUIDITY'); +// } +// return [amountOut, newResIn, newResOut, newResInFic, newResOutFic]; +// } + +/** + * Simulate a full trasaction, if you know the "in" token quantity, provide you the "out" and all reserves change + * Use case: you want to receive exactly amountOut and want to know the exact amountIn to send. + * @param {BigNumber} amountIn the desired input amount of the trade. + * @param {BigNumber} reserveIn the reserves of input token. + * @param {BigNumber} reserveOut the reserves of output token. + * @param {BigNumber} reserveInFic the fictive reserves of input token. + * @param {BigNumber} reserveOutFic the fictive reserves of output token. + * @param {BigNumber} priceAverageIn the price average of input token. + * @param {BigNumber} priceAverageOut the price average of output token. + * @param {BigNumber} feesLP LP fees + * @param {BigNumber} feesPool Pool fees + * @returns {Array} [amountOut, newResIn, newResOut, newResInFic, newResOutFic] + */ export function getAmountOut( amountIn: BigNumber, reserveIn: BigNumber, @@ -260,28 +533,46 @@ export function getAmountOut( reserveOutFic: BigNumber, priceAverageIn: BigNumber, priceAverageOut: BigNumber, + feesLP: BigNumber, + feesPool: BigNumber, ): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { - if (amountIn.lt(0)) throw new Error('INSUFFICIENT_INPUT_AMOUNT'); - if (reserveIn.lt(0) || reserveOut.lt(0)) + // if (amountIn.lte(0)) { + // console.log("amountIn", amountIn) + // throw new Error('INSUFFICIENT_INPUT_AMOUNT'); + // } + + if (reserveIn.lte(0) || reserveOut.lte(0)) { throw new Error('INSUFFICIENT_LIQUIDITY'); - if (reserveInFic.lt(0) || reserveOutFic.lt(0)) + } + + if (reserveInFic.lte(0) || reserveOutFic.lte(0)) { throw new Error('INSUFFICIENT_LIQUIDITY'); + } - let reserveInFicUpdated = BigNumber.from(reserveInFic); - let reserveOutFicUpdated = BigNumber.from(reserveOutFic); + if (priceAverageIn.lte(0) || priceAverageOut.lte(0)) { + throw new Error('INSUFFICIENT_PRICE_AVERAGE'); + } + + let reserveInFicUpdated = reserveInFic; + let reserveOutFicUpdated = reserveOutFic; + + const feesTotalReversed = FEES_BASE.sub(feesLP).sub(feesPool); + + const amountWithFees = amountIn.mul(feesTotalReversed).div(FEES_BASE); - const amountWithFees = amountIn.mul(FEES_TOTAL_REVERSED).div(FEES_BASE); const firstAmount = computeFirstTradeQtyIn( amountWithFees, reserveInFic, reserveOutFic, priceAverageIn, priceAverageOut, + feesLP, + feesPool, ); // if there are 2 trades: 1st trade mustn't re-compute ReserveFic, 2nd should if ( - firstAmount.eq(amountWithFees) && + firstAmount === amountWithFees && ratioApproxEq(reserveInFic, reserveOutFic, priceAverageIn, priceAverageOut) ) { [reserveInFicUpdated, reserveOutFicUpdated] = computeReserveFic( @@ -292,17 +583,19 @@ export function getAmountOut( ); } - // Avoid K constant division by 0 - if (reserveInFicUpdated.lte('0')) + // avoid K constant division by 0 + if (reserveInFicUpdated.lte(0)) { return [ - utils.parseEther('0'), + BigNumber.from(0), reserveIn, reserveOut, reserveInFicUpdated, reserveOutFicUpdated, ]; + } + + const firstAmountNoFees = firstAmount.mul(FEES_BASE).div(feesTotalReversed); - const firstAmountNoFees = firstAmount.mul(FEES_BASE).div(FEES_TOTAL_REVERSED); let [amountOut, newResIn, newResOut, newResInFic, newResOutFic] = applyKConstRuleOut( firstAmountNoFees, @@ -310,6 +603,8 @@ export function getAmountOut( reserveOut, reserveInFicUpdated, reserveOutFicUpdated, + feesLP, + feesPool, ); // if we need a second trade @@ -322,16 +617,18 @@ export function getAmountOut( ); // Avoid K constant division by 0 - if (newResInFic.lte('0')) + if (newResInFic.lte(0)) { return [ - utils.parseEther('0'), + BigNumber.from(0), reserveIn, reserveOut, reserveInFicUpdated, reserveOutFicUpdated, ]; + } let secondAmountOutNoFees: BigNumber; + [secondAmountOutNoFees, newResIn, newResOut, newResInFic, newResOutFic] = applyKConstRuleOut( amountIn.sub(firstAmountNoFees), @@ -339,7 +636,10 @@ export function getAmountOut( newResOut, newResInFic, newResOutFic, + feesLP, + feesPool, ); + amountOut = amountOut.add(secondAmountOutNoFees); } @@ -351,9 +651,123 @@ export function getAmountOut( ) { throw new Error('INSUFFICIENT_LIQUIDITY'); } + return [amountOut, newResIn, newResOut, newResInFic, newResOutFic]; } +// /** +// * Simulate a full transaction, if you know the "out" token quantity, provide you the "in" and all reserves change +// * Use case: you want to receive exactly amountOut and want to know the exact amountIn to send. +// * @param {BigNumber} amountOut the desired output amount of the trade. +// * @param {BigNumber} reserveIn the reserves of input token. +// * @param {BigNumber} reserveOut the reserves of output token. +// * @param {BigNumber} reserveInFic the fictive reserves of input token. +// * @param {BigNumber} reserveOutFic the fictive reserves of output token. +// * @param {BigNumber} priceAverageIn the price average of input token. +// * @param {BigNumber} priceAverageOut the price average of output token. +// * @returns {Array} [amountIn, newResIn, newResOut, newResInFic, newResOutFic] +// */ +// export function getAmountIn( +// amountOut: BigNumber, +// reserveIn: BigNumber, +// reserveOut: BigNumber, +// reserveInFic: BigNumber, +// reserveOutFic: BigNumber, +// priceAverageIn: BigNumber, +// priceAverageOut: BigNumber, +// ): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { +// if (amountOut.lt(0)) throw new Error('INSUFFICIENT_OUTPUT_AMOUNT'); +// if (reserveIn.lt(0) || reserveOut.lt(0)) +// throw new Error('INSUFFICIENT_LIQUIDITY'); +// if (reserveInFic.lt(0) || reserveOutFic.lt(0)) +// throw new Error('INSUFFICIENT_LIQUIDITY'); + +// let reserveInFicUpdated = BigNumber.from(reserveInFic); +// let reserveOutFicUpdated = BigNumber.from(reserveOutFic); + +// const firstAmount = computeFirstTradeQtyOut( +// amountOut, +// reserveInFic, +// reserveOutFic, +// priceAverageIn, +// priceAverageOut, +// ); + +// // if there are 2 trades: 1st trade mustn't re-compute ReserveFic, 2nd should +// if ( +// firstAmount.eq(amountOut) && +// ratioApproxEq(reserveInFic, reserveOutFic, priceAverageIn, priceAverageOut) +// ) { +// [reserveInFicUpdated, reserveOutFicUpdated] = computeReserveFic( +// reserveIn, +// reserveOut, +// reserveInFic, +// reserveOutFic, +// ); +// } + +// // Avoid K constant division by 0 +// if (reserveInFic.lte('0')) +// return [ +// utils.parseEther('0'), +// reserveIn, +// reserveOut, +// reserveInFicUpdated, +// reserveOutFicUpdated, +// ]; + +// let [amountIn, newResIn, newResOut, newResInFic, newResOutFic] = +// applyKConstRuleIn( +// firstAmount, +// reserveIn, +// reserveOut, +// reserveInFicUpdated, +// reserveOutFicUpdated, +// ); + +// // if we need a second trade +// if (firstAmount.lt(amountOut)) { +// // in the second trade ALWAYS recompute fictive reserves +// [newResInFic, newResOutFic] = computeReserveFic( +// newResIn, +// newResOut, +// newResInFic, +// newResOutFic, +// ); + +// // Avoid K constant division by 0 +// if (newResInFic.lte('0')) +// return [ +// utils.parseEther('0'), +// reserveIn, +// reserveOut, +// reserveInFicUpdated, +// reserveOutFicUpdated, +// ]; + +// let secondAmountIn: BigNumber; +// [secondAmountIn, newResIn, newResOut, newResInFic, newResOutFic] = +// applyKConstRuleIn( +// amountOut.sub(firstAmount), +// newResIn, +// newResOut, +// newResInFic, +// newResOutFic, +// ); +// amountIn = amountIn.add(secondAmountIn); +// } + +// if ( +// newResIn.lte(0) || +// newResOut.lte(0) || +// newResInFic.lte(0) || +// newResOutFic.lte(0) +// ) { +// throw new Error('INSUFFICIENT_LIQUIDITY'); +// } +// return [amountIn, newResIn, newResOut, newResInFic, newResOutFic]; +// } + /** * Simulate a full transaction, if you know the "out" token quantity, provide you the "in" and all reserves change * Use case: you want to receive exactly amountOut and want to know the exact amountIn to send. @@ -364,6 +778,8 @@ export function getAmountOut( * @param {BigNumber} reserveOutFic the fictive reserves of output token. * @param {BigNumber} priceAverageIn the price average of input token. * @param {BigNumber} priceAverageOut the price average of output token. + * @param {BigNumber} feesLP LP fees + * @param {BigNumber} feesPool Pool fees * @returns {Array} [amountIn, newResIn, newResOut, newResInFic, newResOutFic] */ export function getAmountIn( @@ -374,15 +790,27 @@ export function getAmountIn( reserveOutFic: BigNumber, priceAverageIn: BigNumber, priceAverageOut: BigNumber, + feesLP: BigNumber, + feesPool: BigNumber, ): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { - if (amountOut.lt(0)) throw new Error('INSUFFICIENT_OUTPUT_AMOUNT'); - if (reserveIn.lt(0) || reserveOut.lt(0)) + if (amountOut.lte(0)) { + throw new Error('INSUFFICIENT_OUTPUT_AMOUNT'); + } + + if (reserveIn.lte(0) || reserveOut.lte(0)) { throw new Error('INSUFFICIENT_LIQUIDITY'); - if (reserveInFic.lt(0) || reserveOutFic.lt(0)) + } + + if (reserveInFic.lte(0) || reserveOutFic.lte(0)) { throw new Error('INSUFFICIENT_LIQUIDITY'); + } - let reserveInFicUpdated = BigNumber.from(reserveInFic); - let reserveOutFicUpdated = BigNumber.from(reserveOutFic); + if (priceAverageIn.lte(0) || priceAverageOut.lte(0)) { + throw new Error('INSUFFICIENT_PRICE_AVERAGE'); + } + + let reserveInFicUpdated = reserveInFic; + let reserveOutFicUpdated = reserveOutFic; const firstAmount = computeFirstTradeQtyOut( amountOut, @@ -390,11 +818,13 @@ export function getAmountIn( reserveOutFic, priceAverageIn, priceAverageOut, + feesLP, + feesPool, ); // if there are 2 trades: 1st trade mustn't re-compute ReserveFic, 2nd should if ( - firstAmount.eq(amountOut) && + firstAmount === amountOut && ratioApproxEq(reserveInFic, reserveOutFic, priceAverageIn, priceAverageOut) ) { [reserveInFicUpdated, reserveOutFicUpdated] = computeReserveFic( @@ -406,14 +836,15 @@ export function getAmountIn( } // Avoid K constant division by 0 - if (reserveInFic.lte('0')) + if (reserveInFic.lte(0)) { return [ - utils.parseEther('0'), + BigNumber.from(0), reserveIn, reserveOut, reserveInFicUpdated, reserveOutFicUpdated, ]; + } let [amountIn, newResIn, newResOut, newResInFic, newResOutFic] = applyKConstRuleIn( @@ -422,10 +853,12 @@ export function getAmountIn( reserveOut, reserveInFicUpdated, reserveOutFicUpdated, + feesLP, + feesPool, ); // if we need a second trade - if (firstAmount.lt(amountOut)) { + if (firstAmount < amountOut) { // in the second trade ALWAYS recompute fictive reserves [newResInFic, newResOutFic] = computeReserveFic( newResIn, @@ -435,16 +868,18 @@ export function getAmountIn( ); // Avoid K constant division by 0 - if (newResInFic.lte('0')) + if (newResInFic.lte(0)) { return [ - utils.parseEther('0'), + BigNumber.from(0), reserveIn, reserveOut, reserveInFicUpdated, reserveOutFicUpdated, ]; + } let secondAmountIn: BigNumber; + [secondAmountIn, newResIn, newResOut, newResInFic, newResOutFic] = applyKConstRuleIn( amountOut.sub(firstAmount), @@ -452,7 +887,10 @@ export function getAmountIn( newResOut, newResInFic, newResOutFic, + feesLP, + feesPool, ); + amountIn = amountIn.add(secondAmountIn); } @@ -464,6 +902,7 @@ export function getAmountIn( ) { throw new Error('INSUFFICIENT_LIQUIDITY'); } + return [amountIn, newResIn, newResOut, newResInFic, newResOutFic]; } @@ -522,242 +961,242 @@ export function getUpdatedPriceAverage( return [priceAverageInRet, priceAverageOutRet]; } -/** - * Computes the amount of tokenOut, at the precision of 1 wei. - * Use case: you want to send an exact amount of tokenIn and know exactly how much you it will give you of tokenOut. - * WARNING: token0 and token1 are pair tokens which addresses hexadecimal's values are sorted as token0 < token1. - * @param {string} token0 the currency address of token0. - * @param {string} token1 the currency address of token1. - * @param {BigNumber} reserve0 the reserves of token0. - * @param {BigNumber} reserve1 the reserves of token1. - * @param {BigNumber} reserve0Fic the fictionnal reserves of token0. - * @param {BigNumber} reserve1Fic the fictionnal reserves of token1. - * @param {BigNumber} tokenAmountIn the input amount of the trade. - * @param {BigNumber} tokenAddressIn address of the input token. - * @param {number} priceAverageLastTimestamp: timestamp in seconds of latest price average. - * @param {BigNumber} priceAverage0 latest price average of token0. - * @param {BigNumber} priceAverage1 latest price average of token1. - * @param {number} forcedPriceAverageTimestamp: current timestamp or timestamp of the trade in seconds. - * @returns {Object} { currency, amount, amountMax, newResIn, newResOut, newResInFic, newResOutFic } - */ -export function computeAmountOut( - token0: string, - token1: string, - reserve0: BigNumber, - reserve1: BigNumber, - reserve0Fic: BigNumber, - reserve1Fic: BigNumber, - tokenAmountIn: BigNumber, - tokenAddressIn: string, - priceAverageLastTimestamp: number, - priceAverage0: BigNumber, - priceAverage1: BigNumber, - forcedPriceAverageTimestamp: number = Math.ceil(Date.now() / 1000) + - LATENCY_OFFSET_SECONDS, -): CurrencyAmount { - if (tokenAddressIn === token0) { - const [newPriceAverage0, newPriceAverage1] = getUpdatedPriceAverage( - reserve0Fic, - reserve1Fic, - priceAverageLastTimestamp, - priceAverage0, - priceAverage1, - forcedPriceAverageTimestamp, - ); - - const [amountOut, newRes0, newRes1, newRes0Fic, newRes1Fic] = getAmountOut( - tokenAmountIn, - reserve0, - reserve1, - reserve0Fic, - reserve1Fic, - newPriceAverage0, - newPriceAverage1, - ); - // const [amountMax] = getAmountOut( - // tokenAmountIn, - // reserve0, - // reserve1, - // reserve0Fic.sub(1).lt(0) ? reserve0Fic : reserve0Fic.sub(1), - // reserve1Fic, - // newPriceAverage0, - // newPriceAverage1, - // ); - - return { - currency: token1, - amount: amountOut, - amountMax: amountOut, // TODO is it still useful ? - newRes0, - newRes1, - newRes0Fic, - newRes1Fic, - newPriceAverage0, - newPriceAverage1, - }; - } - - // token1 is tokenIn - const [newPriceAverage1, newPriceAverage0] = getUpdatedPriceAverage( - reserve1Fic, - reserve0Fic, - priceAverageLastTimestamp, - priceAverage1, - priceAverage0, - forcedPriceAverageTimestamp, - ); - - const [amountOut, newRes1, newRes0, newRes1Fic, newRes0Fic] = getAmountOut( - tokenAmountIn, - reserve1, - reserve0, - reserve1Fic, - reserve0Fic, - newPriceAverage1, - newPriceAverage0, - ); - // const [amountMax] = getAmountOut( - // tokenAmountIn, - // reserve1, - // reserve0, - // reserve1Fic.sub(1).lt(0) ? reserve1Fic : reserve1Fic.sub(1), - // reserve0Fic, - // newPriceAverage1, - // newPriceAverage0, - // ); - - return { - currency: token0, - amount: amountOut, - amountMax: amountOut, // TODO is it still useful ? - newRes0, - newRes1, - newRes0Fic, - newRes1Fic, - newPriceAverage0, - newPriceAverage1, - forcedPriceAverageTimestamp, - }; -} - -/** - * Computes the amount of tokenIn, at the precision of 1 wei. - * Use case: you want to receive exactly tokenOut amount and want to know the exact tokenIn amount to send. - * WARNING: token0 and token1 are pair tokens which addresses hexadecimal's values are sorted as token0 < token1. - * @param {string} token0 the currency address of token0. - * @param {string} token1 the currency address of token1. - * @param {BigNumber} reserve0 the reserves of token0. - * @param {BigNumber} reserve1 the reserves of token1. - * @param {BigNumber} reserve0Fic the fictionnal reserves of token0. - * @param {BigNumber} reserve1Fic the fictionnal reserves of token1. - * @param {BigNumber} tokenAmountOut the output amount of the trade. - * @param {BigNumber} tokenAddressOut address of the output token. - * @param {number} priceAverageLastTimestamp timestamp in seconds of latest price average. - * @param {BigNumber} priceAverage0 latest price average of token0. - * @param {BigNumber} priceAverage1 latest price average of token1. - * @param {number} forcedPriceAverageTimestamp current timestamp or timestamp of the trade in seconds. - * @returns {Object} { currency, amount, amountMax, newResIn, newResOut, newResInFic, newResOutFic } - */ -export function computeAmountIn( - token0: string, - token1: string, - reserve0: BigNumber, - reserve1: BigNumber, - reserve0Fic: BigNumber, - reserve1Fic: BigNumber, - tokenAmountOut: BigNumber, - tokenAddressOut: string, - priceAverageLastTimestamp: number, - priceAverage0: BigNumber, - priceAverage1: BigNumber, - forcedPriceAverageTimestamp: number = Math.ceil(Date.now() / 1000) + - LATENCY_OFFSET_SECONDS, -): CurrencyAmount { - if (tokenAddressOut === token0) { - const [newPriceAverage1, newPriceAverage0] = getUpdatedPriceAverage( - reserve1Fic, - reserve0Fic, - priceAverageLastTimestamp, - priceAverage1, - priceAverage0, - forcedPriceAverageTimestamp, - ); - - const [amountIn, newRes1, newRes0, newRes1Fic, newRes0Fic] = getAmountIn( - tokenAmountOut, - reserve1, - reserve0, - reserve1Fic, - reserve0Fic, - newPriceAverage1, - newPriceAverage0, - ); - // const [amountMax] = getAmountIn( - // tokenAmountOut, - // reserve1, - // reserve0, - // reserve1Fic, - // reserve0Fic.sub(1).lt(0) ? reserve0Fic : reserve0Fic.sub(1), - // newPriceAverage1, - // newPriceAverage0, - // ); - - return { - currency: token1, - amount: amountIn, - amountMax: amountIn, // TODO is it still useful ? - newRes0, - newRes1, - newRes0Fic, - newRes1Fic, - newPriceAverage0, - newPriceAverage1, - }; - } - - // token1 is tokenOut - const [newPriceAverage0, newPriceAverage1] = getUpdatedPriceAverage( - reserve0Fic, - reserve1Fic, - priceAverageLastTimestamp, - priceAverage0, - priceAverage1, - forcedPriceAverageTimestamp, - ); - - const [amountIn, newRes0, newRes1, newRes0Fic, newRes1Fic] = getAmountIn( - tokenAmountOut, - reserve0, - reserve1, - reserve0Fic, - reserve1Fic, - newPriceAverage0, - newPriceAverage1, - ); - - // const [amountMax] = getAmountIn( - // tokenAmountOut, - // reserve0, - // reserve1, - // reserve0Fic, - // reserve1Fic.sub(1).lt(0) ? reserve1Fic : reserve1Fic.sub(1), - // newPriceAverage0, - // newPriceAverage1, - // ); - - return { - currency: token0, - amount: amountIn, - amountMax: amountIn, // TODO is it still useful ? - newRes0, - newRes1, - newRes0Fic, - newRes1Fic, - newPriceAverage0, - newPriceAverage1, - forcedPriceAverageTimestamp, - }; -} +// /** +// * Computes the amount of tokenOut, at the precision of 1 wei. +// * Use case: you want to send an exact amount of tokenIn and know exactly how much you it will give you of tokenOut. +// * WARNING: token0 and token1 are pair tokens which addresses hexadecimal's values are sorted as token0 < token1. +// * @param {string} token0 the currency address of token0. +// * @param {string} token1 the currency address of token1. +// * @param {BigNumber} reserve0 the reserves of token0. +// * @param {BigNumber} reserve1 the reserves of token1. +// * @param {BigNumber} reserve0Fic the fictionnal reserves of token0. +// * @param {BigNumber} reserve1Fic the fictionnal reserves of token1. +// * @param {BigNumber} tokenAmountIn the input amount of the trade. +// * @param {BigNumber} tokenAddressIn address of the input token. +// * @param {number} priceAverageLastTimestamp: timestamp in seconds of latest price average. +// * @param {BigNumber} priceAverage0 latest price average of token0. +// * @param {BigNumber} priceAverage1 latest price average of token1. +// * @param {number} forcedPriceAverageTimestamp: current timestamp or timestamp of the trade in seconds. +// * @returns {Object} { currency, amount, amountMax, newResIn, newResOut, newResInFic, newResOutFic } +// */ +// export function computeAmountOut( +// token0: string, +// token1: string, +// reserve0: BigNumber, +// reserve1: BigNumber, +// reserve0Fic: BigNumber, +// reserve1Fic: BigNumber, +// tokenAmountIn: BigNumber, +// tokenAddressIn: string, +// priceAverageLastTimestamp: number, +// priceAverage0: BigNumber, +// priceAverage1: BigNumber, +// forcedPriceAverageTimestamp: number = Math.ceil(Date.now() / 1000) + +// LATENCY_OFFSET_SECONDS, +// ): CurrencyAmount { +// if (tokenAddressIn === token0) { +// const [newPriceAverage0, newPriceAverage1] = getUpdatedPriceAverage( +// reserve0Fic, +// reserve1Fic, +// priceAverageLastTimestamp, +// priceAverage0, +// priceAverage1, +// forcedPriceAverageTimestamp, +// ); + +// const [amountOut, newRes0, newRes1, newRes0Fic, newRes1Fic] = getAmountOut( +// tokenAmountIn, +// reserve0, +// reserve1, +// reserve0Fic, +// reserve1Fic, +// newPriceAverage0, +// newPriceAverage1, +// ); +// // const [amountMax] = getAmountOut( +// // tokenAmountIn, +// // reserve0, +// // reserve1, +// // reserve0Fic.sub(1).lt(0) ? reserve0Fic : reserve0Fic.sub(1), +// // reserve1Fic, +// // newPriceAverage0, +// // newPriceAverage1, +// // ); + +// return { +// currency: token1, +// amount: amountOut, +// amountMax: amountOut, // TODO is it still useful ? +// newRes0, +// newRes1, +// newRes0Fic, +// newRes1Fic, +// newPriceAverage0, +// newPriceAverage1, +// }; +// } + +// // token1 is tokenIn +// const [newPriceAverage1, newPriceAverage0] = getUpdatedPriceAverage( +// reserve1Fic, +// reserve0Fic, +// priceAverageLastTimestamp, +// priceAverage1, +// priceAverage0, +// forcedPriceAverageTimestamp, +// ); + +// const [amountOut, newRes1, newRes0, newRes1Fic, newRes0Fic] = getAmountOut( +// tokenAmountIn, +// reserve1, +// reserve0, +// reserve1Fic, +// reserve0Fic, +// newPriceAverage1, +// newPriceAverage0, +// ); +// // const [amountMax] = getAmountOut( +// // tokenAmountIn, +// // reserve1, +// // reserve0, +// // reserve1Fic.sub(1).lt(0) ? reserve1Fic : reserve1Fic.sub(1), +// // reserve0Fic, +// // newPriceAverage1, +// // newPriceAverage0, +// // ); + +// return { +// currency: token0, +// amount: amountOut, +// amountMax: amountOut, // TODO is it still useful ? +// newRes0, +// newRes1, +// newRes0Fic, +// newRes1Fic, +// newPriceAverage0, +// newPriceAverage1, +// forcedPriceAverageTimestamp, +// }; +// } + +// /** +// * Computes the amount of tokenIn, at the precision of 1 wei. +// * Use case: you want to receive exactly tokenOut amount and want to know the exact tokenIn amount to send. +// * WARNING: token0 and token1 are pair tokens which addresses hexadecimal's values are sorted as token0 < token1. +// * @param {string} token0 the currency address of token0. +// * @param {string} token1 the currency address of token1. +// * @param {BigNumber} reserve0 the reserves of token0. +// * @param {BigNumber} reserve1 the reserves of token1. +// * @param {BigNumber} reserve0Fic the fictionnal reserves of token0. +// * @param {BigNumber} reserve1Fic the fictionnal reserves of token1. +// * @param {BigNumber} tokenAmountOut the output amount of the trade. +// * @param {BigNumber} tokenAddressOut address of the output token. +// * @param {number} priceAverageLastTimestamp timestamp in seconds of latest price average. +// * @param {BigNumber} priceAverage0 latest price average of token0. +// * @param {BigNumber} priceAverage1 latest price average of token1. +// * @param {number} forcedPriceAverageTimestamp current timestamp or timestamp of the trade in seconds. +// * @returns {Object} { currency, amount, amountMax, newResIn, newResOut, newResInFic, newResOutFic } +// */ +// export function computeAmountIn( +// token0: string, +// token1: string, +// reserve0: BigNumber, +// reserve1: BigNumber, +// reserve0Fic: BigNumber, +// reserve1Fic: BigNumber, +// tokenAmountOut: BigNumber, +// tokenAddressOut: string, +// priceAverageLastTimestamp: number, +// priceAverage0: BigNumber, +// priceAverage1: BigNumber, +// forcedPriceAverageTimestamp: number = Math.ceil(Date.now() / 1000) + +// LATENCY_OFFSET_SECONDS, +// ): CurrencyAmount { +// if (tokenAddressOut === token0) { +// const [newPriceAverage1, newPriceAverage0] = getUpdatedPriceAverage( +// reserve1Fic, +// reserve0Fic, +// priceAverageLastTimestamp, +// priceAverage1, +// priceAverage0, +// forcedPriceAverageTimestamp, +// ); + +// const [amountIn, newRes1, newRes0, newRes1Fic, newRes0Fic] = getAmountIn( +// tokenAmountOut, +// reserve1, +// reserve0, +// reserve1Fic, +// reserve0Fic, +// newPriceAverage1, +// newPriceAverage0, +// ); +// // const [amountMax] = getAmountIn( +// // tokenAmountOut, +// // reserve1, +// // reserve0, +// // reserve1Fic, +// // reserve0Fic.sub(1).lt(0) ? reserve0Fic : reserve0Fic.sub(1), +// // newPriceAverage1, +// // newPriceAverage0, +// // ); + +// return { +// currency: token1, +// amount: amountIn, +// amountMax: amountIn, // TODO is it still useful ? +// newRes0, +// newRes1, +// newRes0Fic, +// newRes1Fic, +// newPriceAverage0, +// newPriceAverage1, +// }; +// } + +// // token1 is tokenOut +// const [newPriceAverage0, newPriceAverage1] = getUpdatedPriceAverage( +// reserve0Fic, +// reserve1Fic, +// priceAverageLastTimestamp, +// priceAverage0, +// priceAverage1, +// forcedPriceAverageTimestamp, +// ); + +// const [amountIn, newRes0, newRes1, newRes0Fic, newRes1Fic] = getAmountIn( +// tokenAmountOut, +// reserve0, +// reserve1, +// reserve0Fic, +// reserve1Fic, +// newPriceAverage0, +// newPriceAverage1, +// ); + +// // const [amountMax] = getAmountIn( +// // tokenAmountOut, +// // reserve0, +// // reserve1, +// // reserve0Fic, +// // reserve1Fic.sub(1).lt(0) ? reserve1Fic : reserve1Fic.sub(1), +// // newPriceAverage0, +// // newPriceAverage1, +// // ); + +// return { +// currency: token0, +// amount: amountIn, +// amountMax: amountIn, // TODO is it still useful ? +// newRes0, +// newRes1, +// newRes0Fic, +// newRes1Fic, +// newPriceAverage0, +// newPriceAverage1, +// forcedPriceAverageTimestamp, +// }; +// } /** * Computes price impact @@ -917,333 +1356,334 @@ export function getPathFromOutput( return path.reverse(); } -// Computes the best trade for the exact amount in, function is used internally with recursion -// extended parameters includes 'tradeTimestamp' which represents the current timestamp in seconds -// other parameters are used by the function internally in for recursion loop -function bestTradeExactInInternal( - pairs: Pair[], - currencyAmountIn: CurrencyAmount, - currencyOut: string, - tradeTimestamp: number, - { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, - // used in recursion. - currentPairs: Pair[] = [], - nextAmountIn: CurrencyAmount = currencyAmountIn, - bestTrades: Trade[] = [], -): Trade[] { - if (pairs.length <= 0) throw new Error('PAIRS'); - if (maxHops <= 0) throw new Error('MAX_HOPS'); - if ( - currencyAmountIn.currency !== nextAmountIn.currency && - currentPairs.length <= 0 - ) - throw new Error('INVALID_RECURSION'); - - for (let i = 0; i < pairs.length; i += 1) { - const pair = { ...pairs[i] }; - - // pair irrelevant - if ( - pair.token0 !== nextAmountIn.currency && - pair.token1 !== nextAmountIn.currency - ) - continue; - if (pair.reserve0.eq(0) || pair.reserve1.eq(0)) continue; - if (pair.reserve0LastFictive.eq(0) || pair.reserve1LastFictive.eq(0)) - continue; - - // breaks arbitrage loops in case config disabled such behaviour - const path = getPathFromInput( - [...currentPairs, pair], - currencyAmountIn.currency, - ); - if ( - !arbitrage && - path.find((token, arrayIndex) => arrayIndex !== path.indexOf(token)) - ) - continue; - - let amountOutData: CurrencyAmount; - try { - amountOutData = computeAmountOut( - pair.token0, - pair.token1, - pair.reserve0, - pair.reserve1, - pair.reserve0LastFictive, - pair.reserve1LastFictive, - nextAmountIn.amount, - nextAmountIn.currency, - pair.priceAverageLastTimestamp, - pair.priceAverage0, - pair.priceAverage1, - pair?.forcedPriceAverageTimestamp, - ); - // Update pair's info - pair.reserve0 = amountOutData.newRes0 || pair.reserve0; - pair.reserve1 = amountOutData.newRes1 || pair.reserve1; - pair.prevReserveFic0 = pair.reserve0LastFictive; - pair.prevReserveFic1 = pair.reserve1LastFictive; - pair.reserve0LastFictive = - amountOutData.newRes0Fic || pair.reserve0LastFictive; - pair.reserve1LastFictive = - amountOutData.newRes1Fic || pair.reserve1LastFictive; - pair.priceAverage0 = amountOutData.newPriceAverage0 || pair.priceAverage0; - pair.priceAverage1 = amountOutData.newPriceAverage1 || pair.priceAverage1; - pair.forcedPriceAverageTimestamp = - amountOutData?.forcedPriceAverageTimestamp || tradeTimestamp; - } catch (error: any) { - if (error.name === 'SmarDexSDK') { - continue; - } - throw error; - } +// // Computes the best trade for the exact amount in, function is used internally with recursion +// // extended parameters includes 'tradeTimestamp' which represents the current timestamp in seconds +// // other parameters are used by the function internally in for recursion loop +// function bestTradeExactInInternal( +// pairs: Pair[], +// currencyAmountIn: CurrencyAmount, +// currencyOut: string, +// tradeTimestamp: number, +// { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, +// // used in recursion. +// currentPairs: Pair[] = [], +// nextAmountIn: CurrencyAmount = currencyAmountIn, +// bestTrades: Trade[] = [], +// ): Trade[] { +// if (pairs.length <= 0) throw new Error('PAIRS'); +// if (maxHops <= 0) throw new Error('MAX_HOPS'); +// if ( +// currencyAmountIn.currency !== nextAmountIn.currency && +// currentPairs.length <= 0 +// ) +// throw new Error('INVALID_RECURSION'); + +// for (let i = 0; i < pairs.length; i += 1) { +// const pair = { ...pairs[i] }; + +// // pair irrelevant +// if ( +// pair.token0 !== nextAmountIn.currency && +// pair.token1 !== nextAmountIn.currency +// ) +// continue; +// if (pair.reserve0.eq(0) || pair.reserve1.eq(0)) continue; +// if (pair.reserve0LastFictive.eq(0) || pair.reserve1LastFictive.eq(0)) +// continue; + +// // breaks arbitrage loops in case config disabled such behaviour +// const path = getPathFromInput( +// [...currentPairs, pair], +// currencyAmountIn.currency, +// ); +// if ( +// !arbitrage && +// path.find((token, arrayIndex) => arrayIndex !== path.indexOf(token)) +// ) +// continue; + +// let amountOutData: CurrencyAmount; +// try { +// amountOutData = computeAmountOut( +// pair.token0, +// pair.token1, +// pair.reserve0, +// pair.reserve1, +// pair.reserve0LastFictive, +// pair.reserve1LastFictive, +// nextAmountIn.amount, +// nextAmountIn.currency, +// pair.priceAverageLastTimestamp, +// pair.priceAverage0, +// pair.priceAverage1, +// pair?.forcedPriceAverageTimestamp, +// ); +// // Update pair's info +// pair.reserve0 = amountOutData.newRes0 || pair.reserve0; +// pair.reserve1 = amountOutData.newRes1 || pair.reserve1; +// pair.prevReserveFic0 = pair.reserve0LastFictive; +// pair.prevReserveFic1 = pair.reserve1LastFictive; +// pair.reserve0LastFictive = +// amountOutData.newRes0Fic || pair.reserve0LastFictive; +// pair.reserve1LastFictive = +// amountOutData.newRes1Fic || pair.reserve1LastFictive; +// pair.priceAverage0 = amountOutData.newPriceAverage0 || pair.priceAverage0; +// pair.priceAverage1 = amountOutData.newPriceAverage1 || pair.priceAverage1; +// pair.forcedPriceAverageTimestamp = +// amountOutData?.forcedPriceAverageTimestamp || tradeTimestamp; +// } catch (error: any) { +// if (error.name === 'SmarDexSDK') { +// continue; +// } +// throw error; +// } + +// const selectedPairs = [...currentPairs, pair]; + +// // we have arrived at the output token, so this is the final trade of one of the paths +// if (amountOutData.currency === currencyOut) { +// sortedInsert( +// bestTrades, +// { +// route: { +// pairs: selectedPairs, +// path, +// input: currencyAmountIn.currency, +// output: currencyOut, +// }, +// amountIn: currencyAmountIn, +// amountOut: amountOutData, +// tradeType: TradeType.EXACT_INPUT, +// priceImpact: computePriceImpact( +// path, +// selectedPairs, +// currencyAmountIn.amount, +// amountOutData.amount, +// ), +// }, +// maxNumResults, +// tradeComparator, +// ); +// } else if (maxHops > 1 && pairs.length > 1) { +// const pairsExcludingThisPair = pairs.filter((_, index) => index !== i); + +// // otherwise, consider all the other paths that lead from this token as long as we have not exceeded maxHops +// bestTradeExactInInternal( +// pairsExcludingThisPair, +// currencyAmountIn, +// currencyOut, +// tradeTimestamp, +// { +// maxNumResults, +// maxHops: maxHops - 1, +// arbitrage, +// }, +// selectedPairs, +// amountOutData, +// bestTrades, +// ); +// } +// } +// return bestTrades; +// } + +// /** +// * Given a list of pairs, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token +// * amount to an output token, making at most `maxHops` hops. +// * Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting +// * the amount in among multiple routes. +// * @param {Pair[]} pairs the pairs to consider in finding the best trade. +// * @param {CurrencyAmount} currencyAmountIn provided currency with exact amount of input provided for thetrade. +// * @param {string} currencyOut address of the desired currency requested in output. +// * @param {Object} [option={maxNumResults=3,maxHops=3,arbitrage=false}] additional options, including: +// * @param {number} option.maxNumResults maximum number of trade results to return. +// * @param {number} option.maxHops maximum number of hops per individual trade, e.g. 1 hop goes through a single pair. +// * @param {boolean} option.arbitrage to enable arbitrage loops in the returned trades (i.e. route can pass multiple times by the same token). +// * @returns {Trade[]} Array of trades ordered by best trade first. +// */ +// export function bestTradeExactIn( +// pairs: Pair[], +// currencyAmountIn: CurrencyAmount, +// currencyOut: string, +// { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, +// ) { +// return bestTradeExactInInternal( +// pairs, +// currencyAmountIn, +// currencyOut, +// Math.ceil(Date.now() / 1000) + LATENCY_OFFSET_SECONDS, +// { +// maxNumResults, +// maxHops, +// arbitrage, +// }, +// ); +// } + +// // Computes the best trade for the exact amount out, function is used internally with recursion +// // extended parameters includes 'tradeTimestamp' which represents the current timestamp in seconds +// // other parameters are used by the function internally in for recursion loop +// function bestTradeExactOutInternal( +// pairs: Pair[], +// currencyIn: string, +// currencyAmountOut: CurrencyAmount, +// tradeTimestamp: number, +// { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, +// // used in recursion. +// currentPairs: Pair[] = [], +// nextAmountOut: CurrencyAmount = currencyAmountOut, +// bestTrades: Trade[] = [], +// ): Trade[] { +// if (pairs.length <= 0) throw new Error('PAIRS'); +// if (maxHops <= 0) throw new Error('MAX_HOPS'); +// if ( +// currencyAmountOut.currency !== nextAmountOut.currency && +// currentPairs.length <= 0 +// ) +// throw new Error('INVALID_RECURSION'); + +// for (let i = 0; i < pairs.length; i += 1) { +// const pair = { ...pairs[i] }; + +// // pair irrelevant +// if ( +// pair.token0 !== nextAmountOut.currency && +// pair.token1 !== nextAmountOut.currency +// ) +// continue; +// if (pair.reserve0.eq(0) || pair.reserve1.eq(0)) continue; +// if (pair.reserve0LastFictive.eq(0) || pair.reserve1LastFictive.eq(0)) +// continue; + +// // breaks arbitrage loops in case config disabled such behaviour +// const path = getPathFromOutput( +// [pair, ...currentPairs], +// currencyAmountOut.currency, +// ); +// if ( +// !arbitrage && +// path.find((token, arrayIndex) => arrayIndex !== path.indexOf(token)) +// ) +// continue; + +// let amountInData: CurrencyAmount; +// try { +// amountInData = computeAmountIn( +// pair.token0, +// pair.token1, +// pair.reserve0, +// pair.reserve1, +// pair.reserve0LastFictive, +// pair.reserve1LastFictive, +// nextAmountOut.amount, +// nextAmountOut.currency, +// pair.priceAverageLastTimestamp, +// pair.priceAverage0, +// pair.priceAverage1, +// pair?.forcedPriceAverageTimestamp, +// ); +// // Update pair's info +// pair.reserve0 = amountInData.newRes0 || pair.reserve0; +// pair.reserve1 = amountInData.newRes1 || pair.reserve1; +// pair.prevReserveFic0 = pair.reserve0LastFictive; +// pair.prevReserveFic1 = pair.reserve1LastFictive; +// pair.reserve0LastFictive = +// amountInData.newRes0Fic || pair.reserve0LastFictive; +// pair.reserve1LastFictive = +// amountInData.newRes1Fic || pair.reserve1LastFictive; +// pair.priceAverage0 = amountInData.newPriceAverage0 || pair.priceAverage0; +// pair.priceAverage1 = amountInData.newPriceAverage1 || pair.priceAverage1; +// pair.forcedPriceAverageTimestamp = +// amountInData?.forcedPriceAverageTimestamp || tradeTimestamp; +// } catch (error: any) { +// if (error.name === 'SmarDexSDK') { +// continue; +// } +// throw error; +// } + +// const selectedPairs = [pair, ...currentPairs]; + +// // we have arrived at the input token, so this is the final trade of one of the paths +// if (amountInData.currency === currencyIn) { +// sortedInsert( +// bestTrades, +// { +// route: { +// pairs: selectedPairs, +// path, +// input: currencyIn, +// output: currencyAmountOut.currency, +// }, +// amountIn: amountInData, +// amountOut: currencyAmountOut, +// tradeType: TradeType.EXACT_OUTPUT, +// priceImpact: computePriceImpact( +// path, +// selectedPairs, +// amountInData.amount, +// currencyAmountOut.amount, +// ), +// }, +// maxNumResults, +// tradeComparator, +// ); +// } else if (maxHops > 1 && pairs.length > 1) { +// const pairsExcludingThisPair = pairs.filter((_, index) => index !== i); + +// // otherwise, consider all the other paths that lead from this token as long as we have not exceeded maxHops +// bestTradeExactOutInternal( +// pairsExcludingThisPair, +// currencyIn, +// currencyAmountOut, +// tradeTimestamp, +// { +// maxNumResults, +// maxHops: maxHops - 1, +// arbitrage, +// }, +// selectedPairs, +// amountInData, +// bestTrades, +// ); +// } +// } +// return bestTrades; +// } + +// /** +// * Given a list of pairs, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token +// * amount to an output token, making at most `maxHops` hops. +// * Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting +// * the amount in among multiple routes. +// * @param {Pair[]} pairs the pairs to consider in finding the best trade. +// * @param {string} currencyIn address of the desired currency requested in input. +// * @param {CurrencyAmount} currencyAmountOut currency with exact amount of output provided for thetrade. +// * @param {Object} [option={maxNumResults=3,maxHops=3,arbitrage=false}] additional options, including: +// * @param {number} option.maxNumResults maximum number of trade results to return. +// * @param {number} option.maxHops maximum number of hops per individual trade, e.g. 1 hop goes through a single pair. +// * @param {boolean} option.arbitrage to enable arbitrage loops in the returned trades (i.e. route can pass multiple times by the same token). +// * @returns {Trade[]} Array of trades ordered by best trade first. +// */ +// export function bestTradeExactOut( +// pairs: Pair[], +// currencyIn: string, +// currencyAmountOut: CurrencyAmount, +// { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, +// ) { +// return bestTradeExactOutInternal( +// pairs, +// currencyIn, +// currencyAmountOut, +// Math.ceil(Date.now() / 1000) + LATENCY_OFFSET_SECONDS, +// { +// maxNumResults, +// maxHops, +// arbitrage, +// }, +// ); +// } - const selectedPairs = [...currentPairs, pair]; - - // we have arrived at the output token, so this is the final trade of one of the paths - if (amountOutData.currency === currencyOut) { - sortedInsert( - bestTrades, - { - route: { - pairs: selectedPairs, - path, - input: currencyAmountIn.currency, - output: currencyOut, - }, - amountIn: currencyAmountIn, - amountOut: amountOutData, - tradeType: TradeType.EXACT_INPUT, - priceImpact: computePriceImpact( - path, - selectedPairs, - currencyAmountIn.amount, - amountOutData.amount, - ), - }, - maxNumResults, - tradeComparator, - ); - } else if (maxHops > 1 && pairs.length > 1) { - const pairsExcludingThisPair = pairs.filter((_, index) => index !== i); - - // otherwise, consider all the other paths that lead from this token as long as we have not exceeded maxHops - bestTradeExactInInternal( - pairsExcludingThisPair, - currencyAmountIn, - currencyOut, - tradeTimestamp, - { - maxNumResults, - maxHops: maxHops - 1, - arbitrage, - }, - selectedPairs, - amountOutData, - bestTrades, - ); - } - } - return bestTrades; -} - -/** - * Given a list of pairs, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token - * amount to an output token, making at most `maxHops` hops. - * Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting - * the amount in among multiple routes. - * @param {Pair[]} pairs the pairs to consider in finding the best trade. - * @param {CurrencyAmount} currencyAmountIn provided currency with exact amount of input provided for thetrade. - * @param {string} currencyOut address of the desired currency requested in output. - * @param {Object} [option={maxNumResults=3,maxHops=3,arbitrage=false}] additional options, including: - * @param {number} option.maxNumResults maximum number of trade results to return. - * @param {number} option.maxHops maximum number of hops per individual trade, e.g. 1 hop goes through a single pair. - * @param {boolean} option.arbitrage to enable arbitrage loops in the returned trades (i.e. route can pass multiple times by the same token). - * @returns {Trade[]} Array of trades ordered by best trade first. - */ -export function bestTradeExactIn( - pairs: Pair[], - currencyAmountIn: CurrencyAmount, - currencyOut: string, - { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, -) { - return bestTradeExactInInternal( - pairs, - currencyAmountIn, - currencyOut, - Math.ceil(Date.now() / 1000) + LATENCY_OFFSET_SECONDS, - { - maxNumResults, - maxHops, - arbitrage, - }, - ); -} - -// Computes the best trade for the exact amount out, function is used internally with recursion -// extended parameters includes 'tradeTimestamp' which represents the current timestamp in seconds -// other parameters are used by the function internally in for recursion loop -function bestTradeExactOutInternal( - pairs: Pair[], - currencyIn: string, - currencyAmountOut: CurrencyAmount, - tradeTimestamp: number, - { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, - // used in recursion. - currentPairs: Pair[] = [], - nextAmountOut: CurrencyAmount = currencyAmountOut, - bestTrades: Trade[] = [], -): Trade[] { - if (pairs.length <= 0) throw new Error('PAIRS'); - if (maxHops <= 0) throw new Error('MAX_HOPS'); - if ( - currencyAmountOut.currency !== nextAmountOut.currency && - currentPairs.length <= 0 - ) - throw new Error('INVALID_RECURSION'); - - for (let i = 0; i < pairs.length; i += 1) { - const pair = { ...pairs[i] }; - - // pair irrelevant - if ( - pair.token0 !== nextAmountOut.currency && - pair.token1 !== nextAmountOut.currency - ) - continue; - if (pair.reserve0.eq(0) || pair.reserve1.eq(0)) continue; - if (pair.reserve0LastFictive.eq(0) || pair.reserve1LastFictive.eq(0)) - continue; - - // breaks arbitrage loops in case config disabled such behaviour - const path = getPathFromOutput( - [pair, ...currentPairs], - currencyAmountOut.currency, - ); - if ( - !arbitrage && - path.find((token, arrayIndex) => arrayIndex !== path.indexOf(token)) - ) - continue; - - let amountInData: CurrencyAmount; - try { - amountInData = computeAmountIn( - pair.token0, - pair.token1, - pair.reserve0, - pair.reserve1, - pair.reserve0LastFictive, - pair.reserve1LastFictive, - nextAmountOut.amount, - nextAmountOut.currency, - pair.priceAverageLastTimestamp, - pair.priceAverage0, - pair.priceAverage1, - pair?.forcedPriceAverageTimestamp, - ); - // Update pair's info - pair.reserve0 = amountInData.newRes0 || pair.reserve0; - pair.reserve1 = amountInData.newRes1 || pair.reserve1; - pair.prevReserveFic0 = pair.reserve0LastFictive; - pair.prevReserveFic1 = pair.reserve1LastFictive; - pair.reserve0LastFictive = - amountInData.newRes0Fic || pair.reserve0LastFictive; - pair.reserve1LastFictive = - amountInData.newRes1Fic || pair.reserve1LastFictive; - pair.priceAverage0 = amountInData.newPriceAverage0 || pair.priceAverage0; - pair.priceAverage1 = amountInData.newPriceAverage1 || pair.priceAverage1; - pair.forcedPriceAverageTimestamp = - amountInData?.forcedPriceAverageTimestamp || tradeTimestamp; - } catch (error: any) { - if (error.name === 'SmarDexSDK') { - continue; - } - throw error; - } - - const selectedPairs = [pair, ...currentPairs]; - - // we have arrived at the input token, so this is the final trade of one of the paths - if (amountInData.currency === currencyIn) { - sortedInsert( - bestTrades, - { - route: { - pairs: selectedPairs, - path, - input: currencyIn, - output: currencyAmountOut.currency, - }, - amountIn: amountInData, - amountOut: currencyAmountOut, - tradeType: TradeType.EXACT_OUTPUT, - priceImpact: computePriceImpact( - path, - selectedPairs, - amountInData.amount, - currencyAmountOut.amount, - ), - }, - maxNumResults, - tradeComparator, - ); - } else if (maxHops > 1 && pairs.length > 1) { - const pairsExcludingThisPair = pairs.filter((_, index) => index !== i); - - // otherwise, consider all the other paths that lead from this token as long as we have not exceeded maxHops - bestTradeExactOutInternal( - pairsExcludingThisPair, - currencyIn, - currencyAmountOut, - tradeTimestamp, - { - maxNumResults, - maxHops: maxHops - 1, - arbitrage, - }, - selectedPairs, - amountInData, - bestTrades, - ); - } - } - return bestTrades; -} - -/** - * Given a list of pairs, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token - * amount to an output token, making at most `maxHops` hops. - * Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting - * the amount in among multiple routes. - * @param {Pair[]} pairs the pairs to consider in finding the best trade. - * @param {string} currencyIn address of the desired currency requested in input. - * @param {CurrencyAmount} currencyAmountOut currency with exact amount of output provided for thetrade. - * @param {Object} [option={maxNumResults=3,maxHops=3,arbitrage=false}] additional options, including: - * @param {number} option.maxNumResults maximum number of trade results to return. - * @param {number} option.maxHops maximum number of hops per individual trade, e.g. 1 hop goes through a single pair. - * @param {boolean} option.arbitrage to enable arbitrage loops in the returned trades (i.e. route can pass multiple times by the same token). - * @returns {Trade[]} Array of trades ordered by best trade first. - */ -export function bestTradeExactOut( - pairs: Pair[], - currencyIn: string, - currencyAmountOut: CurrencyAmount, - { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, -) { - return bestTradeExactOutInternal( - pairs, - currencyIn, - currencyAmountOut, - Math.ceil(Date.now() / 1000) + LATENCY_OFFSET_SECONDS, - { - maxNumResults, - maxHops, - arbitrage, - }, - ); -} // constants to compute approximate equality const APPROX_EQ_PRECISION: BigNumber = BigNumber.from(1); const APPROX_EQ_BASE_PRECISION: BigNumber = BigNumber.from(1000000); diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index a9e25148b..3afa16c05 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -45,7 +45,11 @@ import SmardexPoolLayerOneABI from '../../abi/smardex/layer-1/smardex-pool.json' import SmardexPoolLayerTwoABI from '../../abi/smardex/layer-2/smardex-pool.json'; import SmardexRouterABI from '../../abi/smardex/all/smardex-router.json'; import { SimpleExchange } from '../simple-exchange'; -import { SmardexData, SmardexParam, SmardexRouterFunctions } from '../smardex/types'; +import { + SmardexData, + SmardexParam, + SmardexRouterFunctions, +} from '../smardex/types'; import { IDex, StatefulEventSubscriber } from '../..'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { Adapters, SmardexConfig } from './config'; @@ -158,10 +162,8 @@ export class SmardexEventPool extends StatefulEventSubscriber data.returnData[1], ); - const [priceAverage0, priceAverage1, priceAverageLastTimestamp] = coder.decode( - ['uint256', 'uint256', 'uint256'], - data.returnData[2], - ); + const [priceAverage0, priceAverage1, priceAverageLastTimestamp] = + coder.decode(['uint256', 'uint256', 'uint256'], data.returnData[2]); return { reserves0: reserves0.toString(), @@ -206,11 +208,10 @@ export class Smardex factoryAddress: string; routerAddress: string; - protected subgraphURL: string; + protected subgraphURL: string | undefined; protected initCode: string; logger: Logger; - readonly hasConstantPriceLargeAmounts = false; readonly isFeeOnTransferSupported: boolean = true; readonly SRC_TOKEN_DEX_TRANSFERS = 1; @@ -354,7 +355,7 @@ export class Smardex prices: outputsWithFee, unit: unitOutWithFee, data: { - deadline: 3387835836, // TODO make deadline and receiver dynamic ! + deadline: Math.floor(new Date().getTime()) + 120, receiver: this.augustusAddress, router: this.routerAddress, path: [from.address.toLowerCase(), to.address.toLowerCase()], @@ -419,6 +420,8 @@ export class Smardex BigNumber.from(priceParams.fictiveReservesOut), BigNumber.from(priceParams.priceAverageIn), BigNumber.from(priceParams.priceAverageOut), + BigNumber.from(priceParams.feesLP), + BigNumber.from(priceParams.feesPool), )[0]; return BigInt(amountIn.toString()); } @@ -435,6 +438,8 @@ export class Smardex BigNumber.from(priceParams.fictiveReservesOut), BigNumber.from(priceParams.priceAverageIn), BigNumber.from(priceParams.priceAverageOut), + BigNumber.from(priceParams.feesLP), + BigNumber.from(priceParams.feesPool), )[0]; return BigInt(amountOut.toString()); } @@ -693,12 +698,24 @@ export class Smardex case SmardexRouterFunctions.sellExactEth: case SmardexRouterFunctions.sellExactToken: case SmardexRouterFunctions.swapExactIn: - return [srcAmount, destAmount, data.path, data.receiver, data.deadline]; + return [ + srcAmount, + destAmount, + data.path, + data.receiver, + data.deadline, + ]; case SmardexRouterFunctions.buyExactEth: case SmardexRouterFunctions.buyExactToken: case SmardexRouterFunctions.swapExactOut: - return [destAmount, srcAmount, data.path, data.receiver, data.deadline]; + return [ + destAmount, + srcAmount, + data.path, + data.receiver, + data.deadline, + ]; // case UniswapV2Functions.swapOnUniswapFork: // case UniswapV2Functions.buyOnUniswapFork: @@ -765,8 +782,14 @@ export class Smardex const fee = (pairState.feeCode + tokenDexTransferFee).toString(); const pairReversed = pair.token1.address.toLowerCase() === from.address.toLowerCase(); + + const fees = { + feesLP: '700', + feesPool: '200', + }; if (pairReversed) { return { + ...fees, tokenIn: from.address, tokenOut: to.address, reservesIn: pairState.reserves1, @@ -782,6 +805,7 @@ export class Smardex }; } return { + ...fees, tokenIn: from.address, tokenOut: to.address, reservesIn: pairState.reserves0, @@ -846,16 +870,39 @@ export class Smardex let routerMethod: any; let routerArgs: any; if (side === SwapSide.SELL) { - routerMethod = isETHAddress(src) ? SmardexRouterFunctions.sellExactEth : SmardexRouterFunctions.swapExactIn; - routerMethod = isETHAddress(dest) ? SmardexRouterFunctions.sellExactToken : routerMethod; - routerArgs = [srcAmount, destAmount, data.path, data.receiver, data.deadline]; + routerMethod = isETHAddress(src) + ? SmardexRouterFunctions.sellExactEth + : SmardexRouterFunctions.swapExactIn; + routerMethod = isETHAddress(dest) + ? SmardexRouterFunctions.sellExactToken + : routerMethod; + routerArgs = [ + srcAmount, + destAmount, + data.path, + data.receiver, + data.deadline, + ]; } else { - routerMethod = isETHAddress(src) ? SmardexRouterFunctions.buyExactToken : SmardexRouterFunctions.swapExactOut; - routerMethod = isETHAddress(dest) ? SmardexRouterFunctions.buyExactEth : routerMethod; - routerArgs = [destAmount, srcAmount, data.path, data.receiver, data.deadline]; + routerMethod = isETHAddress(src) + ? SmardexRouterFunctions.buyExactToken + : SmardexRouterFunctions.swapExactOut; + routerMethod = isETHAddress(dest) + ? SmardexRouterFunctions.buyExactEth + : routerMethod; + routerArgs = [ + destAmount, + srcAmount, + data.path, + data.receiver, + data.deadline, + ]; } - const swapData = this.exchangeRouterInterface.encodeFunctionData(routerMethod, routerArgs); + const swapData = this.exchangeRouterInterface.encodeFunctionData( + routerMethod, + routerArgs, + ); return this.buildSimpleParamWithoutWETHConversion( src, srcAmount, diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index ea984904b..56235a961 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -21,7 +21,9 @@ export interface SmardexPoolState { } // event Sync (uint256 reserve0, uint256 reserve1, uint256 fictiveReserve0, uint256 fictiveReserve1, uint256 priceAverage0, uint256 priceAverage1) -export enum TOPICS { SYNC_EVENT = '0x2a368c7f33bb86e2d999940a3989d849031aff29b750f67947e6b8e8c3d2ffd6' }; +export enum TOPICS { + SYNC_EVENT = '0x2a368c7f33bb86e2d999940a3989d849031aff29b750f67947e6b8e8c3d2ffd6', +} export interface SmardexData extends UniswapV2Data { deadline: number; @@ -64,7 +66,9 @@ export interface SmardexPoolOrderedParams extends UniswapV2PoolOrderedParams { fictiveReservesOut: string; priceAverageIn: string; priceAverageOut: string; - priceAverageLastTimestamp: number, + priceAverageLastTimestamp: number; + feesLP?: string; + feesPool?: string; } export interface SmardexPair extends Omit { diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 85df1682c..7b2d216e1 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -61,6 +61,10 @@ export const Tokens: { address: '0xae7ab96520de3a18e5e111b5eaab095312d7fe84', decimals: 18, }, + SDEX: { + address: '0x5DE8ab7E27f6E7A1fFf3E5B337584Aa43961BEeF', + decimals: 18, + }, wstETH: { address: '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0', decimals: 18, From 99a1462a0d6451e3e25922fe5d4b18d563e4c81d Mon Sep 17 00:00:00 2001 From: fireboss777 Date: Thu, 7 Sep 2023 18:28:10 +0200 Subject: [PATCH 226/833] fix: missed some bn calc --- src/dex/smardex/smardex-sdk.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/smardex/smardex-sdk.ts b/src/dex/smardex/smardex-sdk.ts index f423a7d35..90df79034 100644 --- a/src/dex/smardex/smardex-sdk.ts +++ b/src/dex/smardex/smardex-sdk.ts @@ -858,7 +858,7 @@ export function getAmountIn( ); // if we need a second trade - if (firstAmount < amountOut) { + if (firstAmount.lt(amountOut)) { // in the second trade ALWAYS recompute fictive reserves [newResInFic, newResOutFic] = computeReserveFic( newResIn, @@ -926,7 +926,7 @@ export function getUpdatedPriceAverage( priceAverageOut: BigNumber, currentTimestampInSecond: number, ): [BigNumber, BigNumber] { - if (currentTimestampInSecond < priceAverageLastTimestamp) + if (BigNumber.from(currentTimestampInSecond).lt(priceAverageLastTimestamp)) throw new Error('INVALID_TIMESTAMP'); // very first time From 53740839be4f613c0c846ddea742afd587b0f180 Mon Sep 17 00:00:00 2001 From: julien Date: Fri, 8 Sep 2023 08:53:56 +0200 Subject: [PATCH 227/833] fix: added integration fix --- src/dex/smardex/smardex-integration.test.ts | 4 +- src/dex/smardex/smardex.ts | 74 ++++++++++++++++++++- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/dex/smardex/smardex-integration.test.ts b/src/dex/smardex/smardex-integration.test.ts index d2c5fa1c2..627a27f17 100644 --- a/src/dex/smardex/smardex-integration.test.ts +++ b/src/dex/smardex/smardex-integration.test.ts @@ -159,8 +159,8 @@ describe('Smardex', function () { // TODO: Put here token Symbol to check against // Don't forget to update relevant tokens in constant-e2e.ts - const srcTokenSymbol = 'srcTokenSymbol'; - const destTokenSymbol = 'destTokenSymbol'; + const srcTokenSymbol = 'USDT'; + const destTokenSymbol = 'WETH'; const amountsForSell = [ 0n, diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 3afa16c05..ae1322b01 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -73,6 +73,8 @@ const directSmardexFunctionName = [ SmardexRouterFunctions.swapExactOut, ]; +const SUBGRAPH_TIMEOUT = 20 * 1000; + export class SmardexEventPool extends StatefulEventSubscriber { constructor( protected poolInterface: Interface, @@ -921,7 +923,75 @@ export class Smardex tokenAddress: Address, limit: number, ): Promise { - //TODO: Complete with a query on our subgraph gateway - return []; + if (!this.subgraphURL) return []; + const query = ` + query ($token: Bytes!, $limit: Int) { + pools0: pairs(first: $limit, orderBy: reserveUSD, orderDirection: desc, where: {token0: $token, reserve0_gt: 1, reserve1_gt: 1}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + reserveUSD + } + pools1: pairs(first: $limit, orderBy: reserveUSD, orderDirection: desc, where: {token1: $token, reserve0_gt: 1, reserve1_gt: 1}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + reserveUSD + } + }`; + + const { data } = await this.dexHelper.httpRequest.post( + this.subgraphURL, + { + query, + variables: { token: tokenAddress.toLowerCase(), limit }, + }, + SUBGRAPH_TIMEOUT, + { 'x-api-key': process.env.SUBGRAPH_APIKEY! }, + ); + + if (!(data && data.pools0 && data.pools1)) + throw new Error("Couldn't fetch the pools from the subgraph"); + const pools0 = _.map(data.pools0, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token1.id.toLowerCase(), + decimals: parseInt(pool.token1.decimals), + }, + ], + liquidityUSD: parseFloat(pool.reserveUSD), + })); + + const pools1 = _.map(data.pools1, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token0.id.toLowerCase(), + decimals: parseInt(pool.token0.decimals), + }, + ], + liquidityUSD: parseFloat(pool.reserveUSD), + })); + + return _.slice( + _.sortBy(_.concat(pools0, pools1), [pool => -1 * pool.liquidityUSD]), + 0, + limit, + ); } } From de1906289628ab68a54a08e2ce3f2bc183de3340 Mon Sep 17 00:00:00 2001 From: julien Date: Fri, 8 Sep 2023 08:54:06 +0200 Subject: [PATCH 228/833] fix: sdk --- src/dex/smardex/smardex-sdk.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/smardex/smardex-sdk.ts b/src/dex/smardex/smardex-sdk.ts index 90df79034..1bd9971e2 100644 --- a/src/dex/smardex/smardex-sdk.ts +++ b/src/dex/smardex/smardex-sdk.ts @@ -572,7 +572,7 @@ export function getAmountOut( // if there are 2 trades: 1st trade mustn't re-compute ReserveFic, 2nd should if ( - firstAmount === amountWithFees && + firstAmount.eq(amountWithFees) && ratioApproxEq(reserveInFic, reserveOutFic, priceAverageIn, priceAverageOut) ) { [reserveInFicUpdated, reserveOutFicUpdated] = computeReserveFic( @@ -824,7 +824,7 @@ export function getAmountIn( // if there are 2 trades: 1st trade mustn't re-compute ReserveFic, 2nd should if ( - firstAmount === amountOut && + firstAmount.eq(amountOut) && ratioApproxEq(reserveInFic, reserveOutFic, priceAverageIn, priceAverageOut) ) { [reserveInFicUpdated, reserveOutFicUpdated] = computeReserveFic( From 067fd9dc2215ea9001d8e9df5fe944e3632985fe Mon Sep 17 00:00:00 2001 From: fireboss777 Date: Fri, 8 Sep 2023 09:06:26 +0200 Subject: [PATCH 229/833] test: comment removed --- src/dex/smardex/smardex-sdk.ts | 1177 ++++++-------------------------- src/dex/smardex/smardex.ts | 17 +- tests/utils-e2e.ts | 2 + 3 files changed, 208 insertions(+), 988 deletions(-) diff --git a/src/dex/smardex/smardex-sdk.ts b/src/dex/smardex/smardex-sdk.ts index 1bd9971e2..542b70075 100644 --- a/src/dex/smardex/smardex-sdk.ts +++ b/src/dex/smardex/smardex-sdk.ts @@ -32,7 +32,7 @@ export interface CurrencyAmount { newRes1Fic?: BigNumber; newPriceAverage0?: BigNumber; newPriceAverage1?: BigNumber; - forcedPriceAverageTimestamp?: number; + forcedPriceAverageTimestamp?: BigNumber; } export interface BestTradeOptions { @@ -65,41 +65,6 @@ export enum TradeType { EXACT_INPUT, EXACT_OUTPUT, } -// compute first trade amountIn using arbitrage feature -// function computeFirstTradeQtyIn( -// amountIn: BigNumber, -// reserveInFic: BigNumber, -// reserveOutFic: BigNumber, -// priceAverageIn: BigNumber, -// priceAverageOut: BigNumber, -// ): BigNumber { -// // default value -// let firstAmountIn = amountIn; - -// // if trade is in the good direction -// if (reserveOutFic.mul(priceAverageIn).gt(reserveInFic.mul(priceAverageOut))) { -// // pre-compute all operands -// const toSub = reserveInFic.mul( -// FEES_BASE.add(FEES_TOTAL_REVERSED).sub(FEES_POOL), -// ); -// const toDiv = FEES_TOTAL_REVERSED.add(FEES_LP).mul(2); -// const inSqrt = reserveInFic -// .mul(reserveOutFic) -// .mul(4) -// .div(priceAverageOut) -// .mul(priceAverageIn) -// .mul(FEES_TOTAL_REVERSED) -// .mul(FEES_BASE.sub(FEES_POOL)) -// .add(reserveInFic.mul(reserveInFic).mul(FEES_LP).mul(FEES_LP)); - -// // reverse sqrt check to only compute sqrt if really needed -// if (inSqrt.lt(amountIn.mul(toDiv).add(toSub).pow(2))) { -// firstAmountIn = sqrt(inSqrt).sub(toSub).div(toDiv); -// } -// } - -// return firstAmountIn; -// } function computeFirstTradeQtyIn( amountIn: BigNumber, @@ -142,46 +107,6 @@ function computeFirstTradeQtyIn( return firstAmountIn; } -// // compute first trade amountOut using arbitrage feature -// function computeFirstTradeQtyOut( -// amountOut: BigNumber, -// reserveInFic: BigNumber, -// reserveOutFic: BigNumber, -// priceAverageIn: BigNumber, -// priceAverageOut: BigNumber, -// ): BigNumber { -// // default value -// let firstAmountOut = amountOut; - -// // if trade is in the good direction -// if (reserveOutFic.mul(priceAverageIn).gt(reserveInFic.mul(priceAverageOut))) { -// // pre-compute all operands -// const reserveOutFicPredictedFees = reserveInFic -// .mul(FEES_LP) -// .mul(priceAverageOut) -// .div(priceAverageIn); -// const toAdd = reserveOutFic -// .mul(FEES_TOTAL_REVERSED) -// .mul(2) -// .add(reserveOutFicPredictedFees); -// const toDiv = FEES_TOTAL_REVERSED.mul(2); -// const inSqrt = reserveOutFic -// .mul(reserveOutFicPredictedFees) -// .mul(4) -// .mul(FEES_TOTAL_REVERSED) -// .mul(FEES_BASE.sub(FEES_POOL)) -// .div(FEES_LP) -// .add(reserveOutFicPredictedFees.pow(2)); - -// // reverse sqrt check to only compute sqrt if really needed -// if (inSqrt.gt(toAdd.sub(amountOut.mul(toDiv)).pow(2))) { -// firstAmountOut = toAdd.sub(sqrt(inSqrt)).div(toDiv); -// } -// } - -// return firstAmountOut; -// } - // compute first trade amountOut using arbitrage feature function computeFirstTradeQtyOut( amountOut: BigNumber, @@ -265,64 +190,6 @@ function applyKConstRuleOut( return [amountOut, newResIn, newResOut, newResInFic, newResOutFic]; } -// // apply uniswap k const rule. amountIn -> amountOut -// // return [amountOut, newResIn, newResOut, newResInFic, newResOutFic] -// function applyKConstRuleOut( -// amountIn: BigNumber, -// reserveIn: BigNumber, -// reserveOut: BigNumber, -// reserveInFic: BigNumber, -// reserveOutFic: BigNumber, -// ): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { -// // k const rule -// const amountInWithFee = amountIn.mul(FEES_TOTAL_REVERSED); -// const numerator = amountInWithFee.mul(reserveOutFic); -// const denominator = reserveInFic.mul(FEES_BASE).add(amountInWithFee); -// if (denominator.eq(0)) throw new Error('SMARDEX_K_ERROR'); - -// const amountOut = numerator.div(denominator); - -// // update new reserves and add lp-fees to pools -// const amountInWithFeeLp = amountIn -// .mul(FEES_LP) -// .add(amountInWithFee) -// .div(FEES_BASE); -// const newResIn = reserveIn.add(amountInWithFeeLp); -// const newResInFic = reserveInFic.add(amountInWithFeeLp); -// const newResOut = reserveOut.sub(amountOut); -// const newResOutFic = reserveOutFic.sub(amountOut); - -// return [amountOut, newResIn, newResOut, newResInFic, newResOutFic]; -// } - -// // apply uniswap k const rule. amountOut -> amountIn -// // returns [amountIn, newResIn, newResOut, newResInFic, newResOutFic] -// function applyKConstRuleIn( -// amountOut: BigNumber, -// reserveIn: BigNumber, -// reserveOut: BigNumber, -// reserveInFic: BigNumber, -// reserveOutFic: BigNumber, -// ): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { -// // k const rule -// const numerator = reserveInFic.mul(amountOut).mul(FEES_BASE); -// const denominator = reserveOutFic.sub(amountOut).mul(FEES_TOTAL_REVERSED); -// if (denominator.eq(0)) throw new Error('SMARDEX_K_ERROR'); - -// const amountIn = numerator.div(denominator).add(1); - -// // update new reserves -// const amountInWithFeeLp = FEES_TOTAL_REVERSED.add(FEES_LP) -// .mul(amountIn) -// .div(FEES_BASE); -// const newResIn = reserveIn.add(amountInWithFeeLp); -// const newResInFic = reserveInFic.add(amountInWithFeeLp); -// const newResOut = reserveOut.sub(amountOut); -// const newResOutFic = reserveOutFic.sub(amountOut); - -// return [amountIn, newResIn, newResOut, newResInFic, newResOutFic]; -// } - function applyKConstRuleIn( amountOut: BigNumber, reserveIn: BigNumber, @@ -397,120 +264,6 @@ export function computeReserveFic( return [newResFicIn.div(4), newResFicOut.div(4)]; } -/** - * Simulate a full trasaction, if you know the "in" token quantity, provide you the "out" and all reserves change - * Use case: you want to receive exactly amountOut and want to know the exact amountIn to send. - * @param {BigNumber} amountIn the desired input amount of the trade. - * @param {BigNumber} reserveIn the reserves of input token. - * @param {BigNumber} reserveOut the reserves of output token. - * @param {BigNumber} reserveInFic the fictive reserves of input token. - * @param {BigNumber} reserveOutFic the fictive reserves of output token. - * @param {BigNumber} priceAverageIn the price average of input token. - * @param {BigNumber} priceAverageOut the price average of output token. - * @returns {Array} [amountOut, newResIn, newResOut, newResInFic, newResOutFic] - */ -// export function getAmountOut( -// amountIn: BigNumber, -// reserveIn: BigNumber, -// reserveOut: BigNumber, -// reserveInFic: BigNumber, -// reserveOutFic: BigNumber, -// priceAverageIn: BigNumber, -// priceAverageOut: BigNumber, -// ): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { -// if (amountIn.lt(0)) throw new Error('INSUFFICIENT_INPUT_AMOUNT'); -// if (reserveIn.lt(0) || reserveOut.lt(0)) -// throw new Error('INSUFFICIENT_LIQUIDITY'); -// if (reserveInFic.lt(0) || reserveOutFic.lt(0)) -// throw new Error('INSUFFICIENT_LIQUIDITY'); - -// let reserveInFicUpdated = BigNumber.from(reserveInFic); -// let reserveOutFicUpdated = BigNumber.from(reserveOutFic); - -// const amountWithFees = amountIn.mul(FEES_TOTAL_REVERSED).div(FEES_BASE); -// const firstAmount = computeFirstTradeQtyIn( -// amountWithFees, -// reserveInFic, -// reserveOutFic, -// priceAverageIn, -// priceAverageOut, -// ); - -// // if there are 2 trades: 1st trade mustn't re-compute ReserveFic, 2nd should -// if ( -// firstAmount.eq(amountWithFees) && -// ratioApproxEq(reserveInFic, reserveOutFic, priceAverageIn, priceAverageOut) -// ) { -// [reserveInFicUpdated, reserveOutFicUpdated] = computeReserveFic( -// reserveIn, -// reserveOut, -// reserveInFic, -// reserveOutFic, -// ); -// } - -// // Avoid K constant division by 0 -// if (reserveInFicUpdated.lte('0')) -// return [ -// utils.parseEther('0'), -// reserveIn, -// reserveOut, -// reserveInFicUpdated, -// reserveOutFicUpdated, -// ]; - -// const firstAmountNoFees = firstAmount.mul(FEES_BASE).div(FEES_TOTAL_REVERSED); -// let [amountOut, newResIn, newResOut, newResInFic, newResOutFic] = -// applyKConstRuleOut( -// firstAmountNoFees, -// reserveIn, -// reserveOut, -// reserveInFicUpdated, -// reserveOutFicUpdated, -// ); - -// // if we need a second trade -// if (firstAmount.lt(amountWithFees) && firstAmountNoFees.lt(amountIn)) { -// [newResInFic, newResOutFic] = computeReserveFic( -// newResIn, -// newResOut, -// newResInFic, -// newResOutFic, -// ); - -// // Avoid K constant division by 0 -// if (newResInFic.lte('0')) -// return [ -// utils.parseEther('0'), -// reserveIn, -// reserveOut, -// reserveInFicUpdated, -// reserveOutFicUpdated, -// ]; - -// let secondAmountOutNoFees: BigNumber; -// [secondAmountOutNoFees, newResIn, newResOut, newResInFic, newResOutFic] = -// applyKConstRuleOut( -// amountIn.sub(firstAmountNoFees), -// newResIn, -// newResOut, -// newResInFic, -// newResOutFic, -// ); -// amountOut = amountOut.add(secondAmountOutNoFees); -// } - -// if ( -// newResIn.lte(0) || -// newResOut.lte(0) || -// newResInFic.lte(0) || -// newResOutFic.lte(0) -// ) { -// throw new Error('INSUFFICIENT_LIQUIDITY'); -// } -// return [amountOut, newResIn, newResOut, newResInFic, newResOutFic]; -// } - /** * Simulate a full trasaction, if you know the "in" token quantity, provide you the "out" and all reserves change * Use case: you want to receive exactly amountOut and want to know the exact amountIn to send. @@ -523,7 +276,7 @@ export function computeReserveFic( * @param {BigNumber} priceAverageOut the price average of output token. * @param {BigNumber} feesLP LP fees * @param {BigNumber} feesPool Pool fees - * @returns {Array} [amountOut, newResIn, newResOut, newResInFic, newResOutFic] + * @returns {BigNumber[]} [amountOut, newResIn, newResOut, newResInFic, newResOutFic] */ export function getAmountOut( amountIn: BigNumber, @@ -655,119 +408,6 @@ export function getAmountOut( return [amountOut, newResIn, newResOut, newResInFic, newResOutFic]; } -// /** -// * Simulate a full transaction, if you know the "out" token quantity, provide you the "in" and all reserves change -// * Use case: you want to receive exactly amountOut and want to know the exact amountIn to send. -// * @param {BigNumber} amountOut the desired output amount of the trade. -// * @param {BigNumber} reserveIn the reserves of input token. -// * @param {BigNumber} reserveOut the reserves of output token. -// * @param {BigNumber} reserveInFic the fictive reserves of input token. -// * @param {BigNumber} reserveOutFic the fictive reserves of output token. -// * @param {BigNumber} priceAverageIn the price average of input token. -// * @param {BigNumber} priceAverageOut the price average of output token. -// * @returns {Array} [amountIn, newResIn, newResOut, newResInFic, newResOutFic] -// */ -// export function getAmountIn( -// amountOut: BigNumber, -// reserveIn: BigNumber, -// reserveOut: BigNumber, -// reserveInFic: BigNumber, -// reserveOutFic: BigNumber, -// priceAverageIn: BigNumber, -// priceAverageOut: BigNumber, -// ): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { -// if (amountOut.lt(0)) throw new Error('INSUFFICIENT_OUTPUT_AMOUNT'); -// if (reserveIn.lt(0) || reserveOut.lt(0)) -// throw new Error('INSUFFICIENT_LIQUIDITY'); -// if (reserveInFic.lt(0) || reserveOutFic.lt(0)) -// throw new Error('INSUFFICIENT_LIQUIDITY'); - -// let reserveInFicUpdated = BigNumber.from(reserveInFic); -// let reserveOutFicUpdated = BigNumber.from(reserveOutFic); - -// const firstAmount = computeFirstTradeQtyOut( -// amountOut, -// reserveInFic, -// reserveOutFic, -// priceAverageIn, -// priceAverageOut, -// ); - -// // if there are 2 trades: 1st trade mustn't re-compute ReserveFic, 2nd should -// if ( -// firstAmount.eq(amountOut) && -// ratioApproxEq(reserveInFic, reserveOutFic, priceAverageIn, priceAverageOut) -// ) { -// [reserveInFicUpdated, reserveOutFicUpdated] = computeReserveFic( -// reserveIn, -// reserveOut, -// reserveInFic, -// reserveOutFic, -// ); -// } - -// // Avoid K constant division by 0 -// if (reserveInFic.lte('0')) -// return [ -// utils.parseEther('0'), -// reserveIn, -// reserveOut, -// reserveInFicUpdated, -// reserveOutFicUpdated, -// ]; - -// let [amountIn, newResIn, newResOut, newResInFic, newResOutFic] = -// applyKConstRuleIn( -// firstAmount, -// reserveIn, -// reserveOut, -// reserveInFicUpdated, -// reserveOutFicUpdated, -// ); - -// // if we need a second trade -// if (firstAmount.lt(amountOut)) { -// // in the second trade ALWAYS recompute fictive reserves -// [newResInFic, newResOutFic] = computeReserveFic( -// newResIn, -// newResOut, -// newResInFic, -// newResOutFic, -// ); - -// // Avoid K constant division by 0 -// if (newResInFic.lte('0')) -// return [ -// utils.parseEther('0'), -// reserveIn, -// reserveOut, -// reserveInFicUpdated, -// reserveOutFicUpdated, -// ]; - -// let secondAmountIn: BigNumber; -// [secondAmountIn, newResIn, newResOut, newResInFic, newResOutFic] = -// applyKConstRuleIn( -// amountOut.sub(firstAmount), -// newResIn, -// newResOut, -// newResInFic, -// newResOutFic, -// ); -// amountIn = amountIn.add(secondAmountIn); -// } - -// if ( -// newResIn.lte(0) || -// newResOut.lte(0) || -// newResInFic.lte(0) || -// newResOutFic.lte(0) -// ) { -// throw new Error('INSUFFICIENT_LIQUIDITY'); -// } -// return [amountIn, newResIn, newResOut, newResInFic, newResOutFic]; -// } - /** * Simulate a full transaction, if you know the "out" token quantity, provide you the "in" and all reserves change * Use case: you want to receive exactly amountOut and want to know the exact amountIn to send. @@ -780,7 +420,7 @@ export function getAmountOut( * @param {BigNumber} priceAverageOut the price average of output token. * @param {BigNumber} feesLP LP fees * @param {BigNumber} feesPool Pool fees - * @returns {Array} [amountIn, newResIn, newResOut, newResInFic, newResOutFic] + * @returns {BigNumber[]} [amountIn, newResIn, newResOut, newResInFic, newResOutFic] */ export function getAmountIn( amountOut: BigNumber, @@ -906,298 +546,6 @@ export function getAmountIn( return [amountIn, newResIn, newResOut, newResInFic, newResOutFic]; } -/** - * Computes the priceAverageIn and priceAverageOut. - * Use case: you want to send an exact amount of tokenIn and know exactly how much you it will give you of tokenOut. - * Price averages are modified only if current timestamp does not match last timestamp - * @param {BigNumber} reserveFicIn the fictuve reserves of input token. - * @param {BigNumber} reserveFicOut the fictuve reserves of output token. - * @param {number} priceAverageLastTimestamp last timestamp in seconds of price average values. - * @param {BigNumber} priceAverageIn the latest price average of input token. - * @param {BigNumber} priceAverageOut the latest price average of output token. - * @param {number} currentTimestampInSecond current timestamp in seconds. - * @returns {Array} [priceAverageIn, priceAverageOut] - */ -export function getUpdatedPriceAverage( - reserveFicIn: BigNumber, - reserveFicOut: BigNumber, - priceAverageLastTimestamp: number, - priceAverageIn: BigNumber, - priceAverageOut: BigNumber, - currentTimestampInSecond: number, -): [BigNumber, BigNumber] { - if (BigNumber.from(currentTimestampInSecond).lt(priceAverageLastTimestamp)) - throw new Error('INVALID_TIMESTAMP'); - - // very first time - if ( - priceAverageLastTimestamp === 0 || - priceAverageIn.eq(0) || - priceAverageOut.eq(0) - ) { - return [reserveFicIn, reserveFicOut]; - } - - // another tx has been done in the same block - if (priceAverageLastTimestamp === currentTimestampInSecond) { - return [priceAverageIn, priceAverageOut]; - } - - // need to compute new linear-average price - // compute new price: - const timeDiff = Math.min( - currentTimestampInSecond - priceAverageLastTimestamp, - MAX_BLOCK_DIFF_SECONDS, - ); - - const priceAverageInRet = reserveFicIn; - const priceAverageOutRet = priceAverageOut - .mul(priceAverageInRet) - .mul(MAX_BLOCK_DIFF_SECONDS - timeDiff) - .div(priceAverageIn) - .add(reserveFicOut.mul(timeDiff)) - .div(MAX_BLOCK_DIFF_SECONDS); - - return [priceAverageInRet, priceAverageOutRet]; -} - -// /** -// * Computes the amount of tokenOut, at the precision of 1 wei. -// * Use case: you want to send an exact amount of tokenIn and know exactly how much you it will give you of tokenOut. -// * WARNING: token0 and token1 are pair tokens which addresses hexadecimal's values are sorted as token0 < token1. -// * @param {string} token0 the currency address of token0. -// * @param {string} token1 the currency address of token1. -// * @param {BigNumber} reserve0 the reserves of token0. -// * @param {BigNumber} reserve1 the reserves of token1. -// * @param {BigNumber} reserve0Fic the fictionnal reserves of token0. -// * @param {BigNumber} reserve1Fic the fictionnal reserves of token1. -// * @param {BigNumber} tokenAmountIn the input amount of the trade. -// * @param {BigNumber} tokenAddressIn address of the input token. -// * @param {number} priceAverageLastTimestamp: timestamp in seconds of latest price average. -// * @param {BigNumber} priceAverage0 latest price average of token0. -// * @param {BigNumber} priceAverage1 latest price average of token1. -// * @param {number} forcedPriceAverageTimestamp: current timestamp or timestamp of the trade in seconds. -// * @returns {Object} { currency, amount, amountMax, newResIn, newResOut, newResInFic, newResOutFic } -// */ -// export function computeAmountOut( -// token0: string, -// token1: string, -// reserve0: BigNumber, -// reserve1: BigNumber, -// reserve0Fic: BigNumber, -// reserve1Fic: BigNumber, -// tokenAmountIn: BigNumber, -// tokenAddressIn: string, -// priceAverageLastTimestamp: number, -// priceAverage0: BigNumber, -// priceAverage1: BigNumber, -// forcedPriceAverageTimestamp: number = Math.ceil(Date.now() / 1000) + -// LATENCY_OFFSET_SECONDS, -// ): CurrencyAmount { -// if (tokenAddressIn === token0) { -// const [newPriceAverage0, newPriceAverage1] = getUpdatedPriceAverage( -// reserve0Fic, -// reserve1Fic, -// priceAverageLastTimestamp, -// priceAverage0, -// priceAverage1, -// forcedPriceAverageTimestamp, -// ); - -// const [amountOut, newRes0, newRes1, newRes0Fic, newRes1Fic] = getAmountOut( -// tokenAmountIn, -// reserve0, -// reserve1, -// reserve0Fic, -// reserve1Fic, -// newPriceAverage0, -// newPriceAverage1, -// ); -// // const [amountMax] = getAmountOut( -// // tokenAmountIn, -// // reserve0, -// // reserve1, -// // reserve0Fic.sub(1).lt(0) ? reserve0Fic : reserve0Fic.sub(1), -// // reserve1Fic, -// // newPriceAverage0, -// // newPriceAverage1, -// // ); - -// return { -// currency: token1, -// amount: amountOut, -// amountMax: amountOut, // TODO is it still useful ? -// newRes0, -// newRes1, -// newRes0Fic, -// newRes1Fic, -// newPriceAverage0, -// newPriceAverage1, -// }; -// } - -// // token1 is tokenIn -// const [newPriceAverage1, newPriceAverage0] = getUpdatedPriceAverage( -// reserve1Fic, -// reserve0Fic, -// priceAverageLastTimestamp, -// priceAverage1, -// priceAverage0, -// forcedPriceAverageTimestamp, -// ); - -// const [amountOut, newRes1, newRes0, newRes1Fic, newRes0Fic] = getAmountOut( -// tokenAmountIn, -// reserve1, -// reserve0, -// reserve1Fic, -// reserve0Fic, -// newPriceAverage1, -// newPriceAverage0, -// ); -// // const [amountMax] = getAmountOut( -// // tokenAmountIn, -// // reserve1, -// // reserve0, -// // reserve1Fic.sub(1).lt(0) ? reserve1Fic : reserve1Fic.sub(1), -// // reserve0Fic, -// // newPriceAverage1, -// // newPriceAverage0, -// // ); - -// return { -// currency: token0, -// amount: amountOut, -// amountMax: amountOut, // TODO is it still useful ? -// newRes0, -// newRes1, -// newRes0Fic, -// newRes1Fic, -// newPriceAverage0, -// newPriceAverage1, -// forcedPriceAverageTimestamp, -// }; -// } - -// /** -// * Computes the amount of tokenIn, at the precision of 1 wei. -// * Use case: you want to receive exactly tokenOut amount and want to know the exact tokenIn amount to send. -// * WARNING: token0 and token1 are pair tokens which addresses hexadecimal's values are sorted as token0 < token1. -// * @param {string} token0 the currency address of token0. -// * @param {string} token1 the currency address of token1. -// * @param {BigNumber} reserve0 the reserves of token0. -// * @param {BigNumber} reserve1 the reserves of token1. -// * @param {BigNumber} reserve0Fic the fictionnal reserves of token0. -// * @param {BigNumber} reserve1Fic the fictionnal reserves of token1. -// * @param {BigNumber} tokenAmountOut the output amount of the trade. -// * @param {BigNumber} tokenAddressOut address of the output token. -// * @param {number} priceAverageLastTimestamp timestamp in seconds of latest price average. -// * @param {BigNumber} priceAverage0 latest price average of token0. -// * @param {BigNumber} priceAverage1 latest price average of token1. -// * @param {number} forcedPriceAverageTimestamp current timestamp or timestamp of the trade in seconds. -// * @returns {Object} { currency, amount, amountMax, newResIn, newResOut, newResInFic, newResOutFic } -// */ -// export function computeAmountIn( -// token0: string, -// token1: string, -// reserve0: BigNumber, -// reserve1: BigNumber, -// reserve0Fic: BigNumber, -// reserve1Fic: BigNumber, -// tokenAmountOut: BigNumber, -// tokenAddressOut: string, -// priceAverageLastTimestamp: number, -// priceAverage0: BigNumber, -// priceAverage1: BigNumber, -// forcedPriceAverageTimestamp: number = Math.ceil(Date.now() / 1000) + -// LATENCY_OFFSET_SECONDS, -// ): CurrencyAmount { -// if (tokenAddressOut === token0) { -// const [newPriceAverage1, newPriceAverage0] = getUpdatedPriceAverage( -// reserve1Fic, -// reserve0Fic, -// priceAverageLastTimestamp, -// priceAverage1, -// priceAverage0, -// forcedPriceAverageTimestamp, -// ); - -// const [amountIn, newRes1, newRes0, newRes1Fic, newRes0Fic] = getAmountIn( -// tokenAmountOut, -// reserve1, -// reserve0, -// reserve1Fic, -// reserve0Fic, -// newPriceAverage1, -// newPriceAverage0, -// ); -// // const [amountMax] = getAmountIn( -// // tokenAmountOut, -// // reserve1, -// // reserve0, -// // reserve1Fic, -// // reserve0Fic.sub(1).lt(0) ? reserve0Fic : reserve0Fic.sub(1), -// // newPriceAverage1, -// // newPriceAverage0, -// // ); - -// return { -// currency: token1, -// amount: amountIn, -// amountMax: amountIn, // TODO is it still useful ? -// newRes0, -// newRes1, -// newRes0Fic, -// newRes1Fic, -// newPriceAverage0, -// newPriceAverage1, -// }; -// } - -// // token1 is tokenOut -// const [newPriceAverage0, newPriceAverage1] = getUpdatedPriceAverage( -// reserve0Fic, -// reserve1Fic, -// priceAverageLastTimestamp, -// priceAverage0, -// priceAverage1, -// forcedPriceAverageTimestamp, -// ); - -// const [amountIn, newRes0, newRes1, newRes0Fic, newRes1Fic] = getAmountIn( -// tokenAmountOut, -// reserve0, -// reserve1, -// reserve0Fic, -// reserve1Fic, -// newPriceAverage0, -// newPriceAverage1, -// ); - -// // const [amountMax] = getAmountIn( -// // tokenAmountOut, -// // reserve0, -// // reserve1, -// // reserve0Fic, -// // reserve1Fic.sub(1).lt(0) ? reserve1Fic : reserve1Fic.sub(1), -// // newPriceAverage0, -// // newPriceAverage1, -// // ); - -// return { -// currency: token0, -// amount: amountIn, -// amountMax: amountIn, // TODO is it still useful ? -// newRes0, -// newRes1, -// newRes0Fic, -// newRes1Fic, -// newPriceAverage0, -// newPriceAverage1, -// forcedPriceAverageTimestamp, -// }; -// } - /** * Computes price impact * you can manually verify the values using https://www.calculatorsoup.com/calculators/algebra/percent-change-calculator.php @@ -1356,334 +704,6 @@ export function getPathFromOutput( return path.reverse(); } -// // Computes the best trade for the exact amount in, function is used internally with recursion -// // extended parameters includes 'tradeTimestamp' which represents the current timestamp in seconds -// // other parameters are used by the function internally in for recursion loop -// function bestTradeExactInInternal( -// pairs: Pair[], -// currencyAmountIn: CurrencyAmount, -// currencyOut: string, -// tradeTimestamp: number, -// { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, -// // used in recursion. -// currentPairs: Pair[] = [], -// nextAmountIn: CurrencyAmount = currencyAmountIn, -// bestTrades: Trade[] = [], -// ): Trade[] { -// if (pairs.length <= 0) throw new Error('PAIRS'); -// if (maxHops <= 0) throw new Error('MAX_HOPS'); -// if ( -// currencyAmountIn.currency !== nextAmountIn.currency && -// currentPairs.length <= 0 -// ) -// throw new Error('INVALID_RECURSION'); - -// for (let i = 0; i < pairs.length; i += 1) { -// const pair = { ...pairs[i] }; - -// // pair irrelevant -// if ( -// pair.token0 !== nextAmountIn.currency && -// pair.token1 !== nextAmountIn.currency -// ) -// continue; -// if (pair.reserve0.eq(0) || pair.reserve1.eq(0)) continue; -// if (pair.reserve0LastFictive.eq(0) || pair.reserve1LastFictive.eq(0)) -// continue; - -// // breaks arbitrage loops in case config disabled such behaviour -// const path = getPathFromInput( -// [...currentPairs, pair], -// currencyAmountIn.currency, -// ); -// if ( -// !arbitrage && -// path.find((token, arrayIndex) => arrayIndex !== path.indexOf(token)) -// ) -// continue; - -// let amountOutData: CurrencyAmount; -// try { -// amountOutData = computeAmountOut( -// pair.token0, -// pair.token1, -// pair.reserve0, -// pair.reserve1, -// pair.reserve0LastFictive, -// pair.reserve1LastFictive, -// nextAmountIn.amount, -// nextAmountIn.currency, -// pair.priceAverageLastTimestamp, -// pair.priceAverage0, -// pair.priceAverage1, -// pair?.forcedPriceAverageTimestamp, -// ); -// // Update pair's info -// pair.reserve0 = amountOutData.newRes0 || pair.reserve0; -// pair.reserve1 = amountOutData.newRes1 || pair.reserve1; -// pair.prevReserveFic0 = pair.reserve0LastFictive; -// pair.prevReserveFic1 = pair.reserve1LastFictive; -// pair.reserve0LastFictive = -// amountOutData.newRes0Fic || pair.reserve0LastFictive; -// pair.reserve1LastFictive = -// amountOutData.newRes1Fic || pair.reserve1LastFictive; -// pair.priceAverage0 = amountOutData.newPriceAverage0 || pair.priceAverage0; -// pair.priceAverage1 = amountOutData.newPriceAverage1 || pair.priceAverage1; -// pair.forcedPriceAverageTimestamp = -// amountOutData?.forcedPriceAverageTimestamp || tradeTimestamp; -// } catch (error: any) { -// if (error.name === 'SmarDexSDK') { -// continue; -// } -// throw error; -// } - -// const selectedPairs = [...currentPairs, pair]; - -// // we have arrived at the output token, so this is the final trade of one of the paths -// if (amountOutData.currency === currencyOut) { -// sortedInsert( -// bestTrades, -// { -// route: { -// pairs: selectedPairs, -// path, -// input: currencyAmountIn.currency, -// output: currencyOut, -// }, -// amountIn: currencyAmountIn, -// amountOut: amountOutData, -// tradeType: TradeType.EXACT_INPUT, -// priceImpact: computePriceImpact( -// path, -// selectedPairs, -// currencyAmountIn.amount, -// amountOutData.amount, -// ), -// }, -// maxNumResults, -// tradeComparator, -// ); -// } else if (maxHops > 1 && pairs.length > 1) { -// const pairsExcludingThisPair = pairs.filter((_, index) => index !== i); - -// // otherwise, consider all the other paths that lead from this token as long as we have not exceeded maxHops -// bestTradeExactInInternal( -// pairsExcludingThisPair, -// currencyAmountIn, -// currencyOut, -// tradeTimestamp, -// { -// maxNumResults, -// maxHops: maxHops - 1, -// arbitrage, -// }, -// selectedPairs, -// amountOutData, -// bestTrades, -// ); -// } -// } -// return bestTrades; -// } - -// /** -// * Given a list of pairs, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token -// * amount to an output token, making at most `maxHops` hops. -// * Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting -// * the amount in among multiple routes. -// * @param {Pair[]} pairs the pairs to consider in finding the best trade. -// * @param {CurrencyAmount} currencyAmountIn provided currency with exact amount of input provided for thetrade. -// * @param {string} currencyOut address of the desired currency requested in output. -// * @param {Object} [option={maxNumResults=3,maxHops=3,arbitrage=false}] additional options, including: -// * @param {number} option.maxNumResults maximum number of trade results to return. -// * @param {number} option.maxHops maximum number of hops per individual trade, e.g. 1 hop goes through a single pair. -// * @param {boolean} option.arbitrage to enable arbitrage loops in the returned trades (i.e. route can pass multiple times by the same token). -// * @returns {Trade[]} Array of trades ordered by best trade first. -// */ -// export function bestTradeExactIn( -// pairs: Pair[], -// currencyAmountIn: CurrencyAmount, -// currencyOut: string, -// { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, -// ) { -// return bestTradeExactInInternal( -// pairs, -// currencyAmountIn, -// currencyOut, -// Math.ceil(Date.now() / 1000) + LATENCY_OFFSET_SECONDS, -// { -// maxNumResults, -// maxHops, -// arbitrage, -// }, -// ); -// } - -// // Computes the best trade for the exact amount out, function is used internally with recursion -// // extended parameters includes 'tradeTimestamp' which represents the current timestamp in seconds -// // other parameters are used by the function internally in for recursion loop -// function bestTradeExactOutInternal( -// pairs: Pair[], -// currencyIn: string, -// currencyAmountOut: CurrencyAmount, -// tradeTimestamp: number, -// { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, -// // used in recursion. -// currentPairs: Pair[] = [], -// nextAmountOut: CurrencyAmount = currencyAmountOut, -// bestTrades: Trade[] = [], -// ): Trade[] { -// if (pairs.length <= 0) throw new Error('PAIRS'); -// if (maxHops <= 0) throw new Error('MAX_HOPS'); -// if ( -// currencyAmountOut.currency !== nextAmountOut.currency && -// currentPairs.length <= 0 -// ) -// throw new Error('INVALID_RECURSION'); - -// for (let i = 0; i < pairs.length; i += 1) { -// const pair = { ...pairs[i] }; - -// // pair irrelevant -// if ( -// pair.token0 !== nextAmountOut.currency && -// pair.token1 !== nextAmountOut.currency -// ) -// continue; -// if (pair.reserve0.eq(0) || pair.reserve1.eq(0)) continue; -// if (pair.reserve0LastFictive.eq(0) || pair.reserve1LastFictive.eq(0)) -// continue; - -// // breaks arbitrage loops in case config disabled such behaviour -// const path = getPathFromOutput( -// [pair, ...currentPairs], -// currencyAmountOut.currency, -// ); -// if ( -// !arbitrage && -// path.find((token, arrayIndex) => arrayIndex !== path.indexOf(token)) -// ) -// continue; - -// let amountInData: CurrencyAmount; -// try { -// amountInData = computeAmountIn( -// pair.token0, -// pair.token1, -// pair.reserve0, -// pair.reserve1, -// pair.reserve0LastFictive, -// pair.reserve1LastFictive, -// nextAmountOut.amount, -// nextAmountOut.currency, -// pair.priceAverageLastTimestamp, -// pair.priceAverage0, -// pair.priceAverage1, -// pair?.forcedPriceAverageTimestamp, -// ); -// // Update pair's info -// pair.reserve0 = amountInData.newRes0 || pair.reserve0; -// pair.reserve1 = amountInData.newRes1 || pair.reserve1; -// pair.prevReserveFic0 = pair.reserve0LastFictive; -// pair.prevReserveFic1 = pair.reserve1LastFictive; -// pair.reserve0LastFictive = -// amountInData.newRes0Fic || pair.reserve0LastFictive; -// pair.reserve1LastFictive = -// amountInData.newRes1Fic || pair.reserve1LastFictive; -// pair.priceAverage0 = amountInData.newPriceAverage0 || pair.priceAverage0; -// pair.priceAverage1 = amountInData.newPriceAverage1 || pair.priceAverage1; -// pair.forcedPriceAverageTimestamp = -// amountInData?.forcedPriceAverageTimestamp || tradeTimestamp; -// } catch (error: any) { -// if (error.name === 'SmarDexSDK') { -// continue; -// } -// throw error; -// } - -// const selectedPairs = [pair, ...currentPairs]; - -// // we have arrived at the input token, so this is the final trade of one of the paths -// if (amountInData.currency === currencyIn) { -// sortedInsert( -// bestTrades, -// { -// route: { -// pairs: selectedPairs, -// path, -// input: currencyIn, -// output: currencyAmountOut.currency, -// }, -// amountIn: amountInData, -// amountOut: currencyAmountOut, -// tradeType: TradeType.EXACT_OUTPUT, -// priceImpact: computePriceImpact( -// path, -// selectedPairs, -// amountInData.amount, -// currencyAmountOut.amount, -// ), -// }, -// maxNumResults, -// tradeComparator, -// ); -// } else if (maxHops > 1 && pairs.length > 1) { -// const pairsExcludingThisPair = pairs.filter((_, index) => index !== i); - -// // otherwise, consider all the other paths that lead from this token as long as we have not exceeded maxHops -// bestTradeExactOutInternal( -// pairsExcludingThisPair, -// currencyIn, -// currencyAmountOut, -// tradeTimestamp, -// { -// maxNumResults, -// maxHops: maxHops - 1, -// arbitrage, -// }, -// selectedPairs, -// amountInData, -// bestTrades, -// ); -// } -// } -// return bestTrades; -// } - -// /** -// * Given a list of pairs, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token -// * amount to an output token, making at most `maxHops` hops. -// * Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting -// * the amount in among multiple routes. -// * @param {Pair[]} pairs the pairs to consider in finding the best trade. -// * @param {string} currencyIn address of the desired currency requested in input. -// * @param {CurrencyAmount} currencyAmountOut currency with exact amount of output provided for thetrade. -// * @param {Object} [option={maxNumResults=3,maxHops=3,arbitrage=false}] additional options, including: -// * @param {number} option.maxNumResults maximum number of trade results to return. -// * @param {number} option.maxHops maximum number of hops per individual trade, e.g. 1 hop goes through a single pair. -// * @param {boolean} option.arbitrage to enable arbitrage loops in the returned trades (i.e. route can pass multiple times by the same token). -// * @returns {Trade[]} Array of trades ordered by best trade first. -// */ -// export function bestTradeExactOut( -// pairs: Pair[], -// currencyIn: string, -// currencyAmountOut: CurrencyAmount, -// { maxNumResults = 3, maxHops = 3, arbitrage = false }: BestTradeOptions = {}, -// ) { -// return bestTradeExactOutInternal( -// pairs, -// currencyIn, -// currencyAmountOut, -// Math.ceil(Date.now() / 1000) + LATENCY_OFFSET_SECONDS, -// { -// maxNumResults, -// maxHops, -// arbitrage, -// }, -// ); -// } - // constants to compute approximate equality const APPROX_EQ_PRECISION: BigNumber = BigNumber.from(1); const APPROX_EQ_BASE_PRECISION: BigNumber = BigNumber.from(1000000); @@ -1867,3 +887,194 @@ export function sortedInsert( items.splice(lo, 0, add); return isFull ? items.pop()! : null; } + +/** + * Computes the amount of tokenOut, at the precision of 1 wei. + * Use case: you want to send an exact amount of tokenIn and know exactly how much you it will give you of tokenOut. + * WARNING: token0 and token1 are pair tokens which addresses hexadecimal's values are sorted as token0 < token1. + * @param {string} token0 the currency address of token0. + * @param {string} token1 the currency address of token1. + * @param {bigint} reserve0 the reserves of token0. + * @param {bigint} reserve1 the reserves of token1. + * @param {bigint} reserve0Fic the fictionnal reserves of token0. + * @param {bigint} reserve1Fic the fictionnal reserves of token1. + * @param {bigint} tokenAmountIn the input amount of the trade. + * @param {bigint} tokenAddressIn address of the input token. + * @param {number} priceAverageLastTimestamp: timestamp in seconds of the latest price average. + * @param {bigint} priceAverage0 latest price average of token0. + * @param {bigint} priceAverage1 latest price average of token1. + * @param {bigint} feesLP LP fees + * @param {bigint} feesPool Pool fees + * @param {number} forcedPriceAverageTimestamp: current timestamp or timestamp of the trade in seconds. + * @param {number} maxBlockDiffSeconds: Max block difference in seconds + * @returns {Object} { currency, amount, amountMax, newResIn, newResOut, newResInFic, newResOutFic } + */ +export function computeAmountOut( + token0: string, + token1: string, + reserve0: BigNumber, + reserve1: BigNumber, + reserve0Fic: BigNumber, + reserve1Fic: BigNumber, + tokenAmountIn: BigNumber, + tokenAddressIn: string, + priceAverageLastTimestamp: BigNumber, + priceAverage0: BigNumber, + priceAverage1: BigNumber, + feesLP: BigNumber, + feesPool: BigNumber, + forcedPriceAverageTimestamp: BigNumber = BigNumber.from( + Math.ceil(Date.now() / 1000) + LATENCY_OFFSET_SECONDS, + ), + maxBlockDiffSeconds = BigNumber.from(300), +): CurrencyAmount { + if (tokenAddressIn === token0) { + const [newPriceAverage0, newPriceAverage1] = getUpdatedPriceAverage( + reserve0Fic, + reserve1Fic, + priceAverageLastTimestamp, + priceAverage0, + priceAverage1, + forcedPriceAverageTimestamp, + maxBlockDiffSeconds, + ); + + const [amountOut, newRes0, newRes1, newRes0Fic, newRes1Fic] = getAmountOut( + tokenAmountIn, + reserve0, + reserve1, + reserve0Fic, + reserve1Fic, + newPriceAverage0, + newPriceAverage1, + feesLP, + feesPool, + ); + // const [amountMax] = getAmountOut( + // tokenAmountIn, + // reserve0, + // reserve1, + // reserve0Fic.sub(1).lt(0) ? reserve0Fic : reserve0Fic.sub(1), + // reserve1Fic, + // newPriceAverage0, + // newPriceAverage1, + // ); + + return { + currency: token1, + amount: amountOut, + amountMax: amountOut, // TODO is it still useful ? + newRes0, + newRes1, + newRes0Fic, + newRes1Fic, + newPriceAverage0, + newPriceAverage1, + }; + } + + // token1 is tokenIn + const [newPriceAverage1, newPriceAverage0] = getUpdatedPriceAverage( + reserve1Fic, + reserve0Fic, + priceAverageLastTimestamp, + priceAverage1, + priceAverage0, + forcedPriceAverageTimestamp, + maxBlockDiffSeconds, + ); + + const [amountOut, newRes1, newRes0, newRes1Fic, newRes0Fic] = getAmountOut( + tokenAmountIn, + reserve1, + reserve0, + reserve1Fic, + reserve0Fic, + newPriceAverage1, + newPriceAverage0, + feesLP, + feesPool, + ); + // const [amountMax] = getAmountOut( + // tokenAmountIn, + // reserve1, + // reserve0, + // reserve1Fic.sub(1).lt(0) ? reserve1Fic : reserve1Fic.sub(1), + // reserve0Fic, + // newPriceAverage1, + // newPriceAverage0, + // ); + + return { + currency: token0, + amount: amountOut, + amountMax: amountOut, // TODO is it still useful ? + newRes0, + newRes1, + newRes0Fic, + newRes1Fic, + newPriceAverage0, + newPriceAverage1, + forcedPriceAverageTimestamp, + }; +} + +/** + * Computes the priceAverageIn and priceAverageOut. + * Use case: you want to send an exact amount of tokenIn and know exactly how much you it will give you of tokenOut. + * Price averages are modified only if current timestamp does not match last timestamp + * @param {BigNumber} reserveFicIn the fictuve reserves of input token. + * @param {BigNumber} reserveFicOut the fictuve reserves of output token. + * @param {BigNumber} priceAverageLastTimestamp last timestamp in seconds of price average values. + * @param {BigNumber} priceAverageIn the latest price average of input token. + * @param {BigNumber} priceAverageOut the latest price average of output token. + * @param {BigNumber} currentTimestampInSecond current timestamp in seconds. + * @param {BigNumber} maxBlockDiffSeconds: Max block difference in seconds + * @returns {Array} [priceAverageIn, priceAverageOut] + */ +export function getUpdatedPriceAverage( + reserveFicIn: BigNumber, + reserveFicOut: BigNumber, + priceAverageLastTimestamp: BigNumber, + priceAverageIn: BigNumber, + priceAverageOut: BigNumber, + currentTimestampInSecond: BigNumber, + maxBlockDiffSeconds: BigNumber, +): [BigNumber, BigNumber] { + if (currentTimestampInSecond.lt(priceAverageLastTimestamp)) { + throw new Error('INVALID_TIMESTAMP'); + } + + // very first time + if ( + priceAverageLastTimestamp.eq(0) || + priceAverageIn.eq(0) || + priceAverageOut.eq(0) + ) { + return [reserveFicIn, reserveFicOut]; + } + + // another tx has been done in the same block + if (priceAverageLastTimestamp.eq(currentTimestampInSecond)) { + return [priceAverageIn, priceAverageOut]; + } + + // need to compute new linear-average price + // compute new price: + const timeDiff = currentTimestampInSecond + .sub(priceAverageLastTimestamp) + .lte(maxBlockDiffSeconds) + ? currentTimestampInSecond.sub(priceAverageLastTimestamp) + : maxBlockDiffSeconds; + + const priceAverageInRet = reserveFicIn; + + const priceAverageOutRet = priceAverageOut + .mul(priceAverageInRet) + .mul(maxBlockDiffSeconds.sub(timeDiff)) + .div(priceAverageIn) + .add(reserveFicOut.mul(timeDiff)) + .div(maxBlockDiffSeconds); + + return [priceAverageInRet, priceAverageOutRet]; +} diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index ae1322b01..b01588494 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -1,5 +1,5 @@ import { AbiCoder, Interface } from '@ethersproject/abi'; -import { BigNumber } from 'ethers'; +import { BigNumber, utils } from 'ethers'; import _ from 'lodash'; import { DeepReadonly, AsyncOrSync } from 'ts-essentials'; import { Contract } from 'web3-eth-contract'; @@ -55,7 +55,7 @@ import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { Adapters, SmardexConfig } from './config'; import ParaSwapABI from '../../abi/IParaswap.json'; import { applyTransferFee } from '../../lib/token-transfer-fee'; -import { getAmountIn, getAmountOut } from './smardex-sdk'; +import { getAmountIn, getAmountOut, computeAmountOut } from './smardex-sdk'; const DefaultSmardexPoolGasCost = 90 * 1000; @@ -432,17 +432,24 @@ export class Smardex priceParams: SmardexPoolOrderedParams, srcAmount: bigint, ): Promise { - const amountOut = getAmountOut( - BigNumber.from(srcAmount), + const amountOut = computeAmountOut( + priceParams.tokenIn, + priceParams.tokenOut, BigNumber.from(priceParams.reservesIn), BigNumber.from(priceParams.reservesOut), BigNumber.from(priceParams.fictiveReservesIn), BigNumber.from(priceParams.fictiveReservesOut), + BigNumber.from(srcAmount), + priceParams.tokenIn, + BigNumber.from(priceParams.priceAverageLastTimestamp), BigNumber.from(priceParams.priceAverageIn), BigNumber.from(priceParams.priceAverageOut), BigNumber.from(priceParams.feesLP), BigNumber.from(priceParams.feesPool), - )[0]; + ).amount; + // uncomment to get rate + // console.log("srcAmount.", utils.formatEther(srcAmount.toString())) + // console.log("amountOut", utils.formatEther(amountOut.toString())) return BigInt(amountOut.toString()); } diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index 12143c4dc..a2d00ffc3 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -368,6 +368,8 @@ export async function testE2E( poolIdentifiers, transferFees, ); + // uncomment to avoid tenderly simulation + // process.exit() expect(parseFloat(priceRoute.destAmount)).toBeGreaterThan(0); // Calculate slippage. Default is 1% From 92ef47e7fceda9792b57a51985f2416de4daf541 Mon Sep 17 00:00:00 2001 From: fireboss777 Date: Fri, 8 Sep 2023 10:39:52 +0200 Subject: [PATCH 230/833] fix: original sdk --- src/dex/smardex/smardex-sdk.ts | 1077 +++++++++++++------------------- src/dex/smardex/smardex.ts | 106 ++-- src/dex/smardex/types.ts | 21 +- src/dex/smardex/utils.ts | 126 ++++ 4 files changed, 637 insertions(+), 693 deletions(-) create mode 100644 src/dex/smardex/utils.ts diff --git a/src/dex/smardex/smardex-sdk.ts b/src/dex/smardex/smardex-sdk.ts index 542b70075..bcc38a85f 100644 --- a/src/dex/smardex/smardex-sdk.ts +++ b/src/dex/smardex/smardex-sdk.ts @@ -1,38 +1,36 @@ -import { BigNumber, constants, utils } from 'ethers/lib/ethers'; - // Protocol's fees constants -export const FEES_LP = BigNumber.from(500); -export const FEES_POOL = BigNumber.from(200); -export const FEES_TOTAL = FEES_LP.add(FEES_POOL); -export const FEES_BASE = BigNumber.from(1000); -export const FEES_TOTAL_REVERSED = FEES_BASE.sub(FEES_TOTAL); +export const FEES_LP = BigInt(500); +export const FEES_POOL = BigInt(200); +export const FEES_TOTAL = FEES_LP + FEES_POOL; +export const FEES_BASE = BigInt(1000); +export const FEES_TOTAL_REVERSED = FEES_BASE - FEES_TOTAL; export interface Pair { address?: string; token0: string; token1: string; - reserve0: BigNumber; - reserve1: BigNumber; - reserve0LastFictive: BigNumber; - reserve1LastFictive: BigNumber; + reserve0: bigint; + reserve1: bigint; + reserve0LastFictive: bigint; + reserve1LastFictive: bigint; priceAverageLastTimestamp: number; - priceAverage0: BigNumber; - priceAverage1: BigNumber; + priceAverage0: bigint; + priceAverage1: bigint; forcedPriceAverageTimestamp?: number; - prevReserveFic0?: BigNumber; - prevReserveFic1?: BigNumber; + prevReserveFic0?: bigint; + prevReserveFic1?: bigint; } export interface CurrencyAmount { currency: string; - amount: BigNumber; - amountMax?: BigNumber; - newRes0?: BigNumber; - newRes1?: BigNumber; - newRes0Fic?: BigNumber; - newRes1Fic?: BigNumber; - newPriceAverage0?: BigNumber; - newPriceAverage1?: BigNumber; - forcedPriceAverageTimestamp?: BigNumber; + amount: bigint; + amountMax?: bigint; + newRes0?: bigint; + newRes1?: bigint; + newRes0Fic?: bigint; + newRes1Fic?: bigint; + newPriceAverage0?: bigint; + newPriceAverage1?: bigint; + forcedPriceAverageTimestamp?: number; } export interface BestTradeOptions { @@ -53,7 +51,7 @@ export interface Trade { amountIn: CurrencyAmount; amountOut: CurrencyAmount; tradeType: TradeType; - priceImpact?: BigNumber; // defined only after calling bestTradeExactIn or bestTradeExactOut + priceImpact?: bigint; // defined only after calling bestTradeExactIn or bestTradeExactOut } // constant for function 'updatePriceAverage' export const MAX_BLOCK_DIFF_SECONDS = process.env.SDK_MAX_BLOCK_DIFF_SECONDS @@ -66,41 +64,37 @@ export enum TradeType { EXACT_OUTPUT, } +import { ratioApproxEq, sqrt } from './utils'; + +// compute first trade amountIn using arbitrage feature function computeFirstTradeQtyIn( - amountIn: BigNumber, - reserveInFic: BigNumber, - reserveOutFic: BigNumber, - priceAverageIn: BigNumber, - priceAverageOut: BigNumber, - feesLP: BigNumber, - feesPool: BigNumber, -): BigNumber { + amountIn: bigint, + reserveInFic: bigint, + reserveOutFic: bigint, + priceAverageIn: bigint, + priceAverageOut: bigint, + feesLP: bigint, + feesPool: bigint, +): bigint { // default value let firstAmountIn = amountIn; // if trade is in the good direction - if (reserveOutFic.mul(priceAverageIn).gt(reserveInFic.mul(priceAverageOut))) { + if (reserveOutFic * priceAverageIn > reserveInFic * priceAverageOut) { // pre-compute all operands - const feesTotalReversed = FEES_BASE.sub(feesLP).sub(feesPool); - - const toSub = reserveInFic.mul( - FEES_BASE.add(feesTotalReversed).sub(feesPool), - ); - - const toDiv = feesTotalReversed.add(feesLP).mul(2); - - const inSqrt = reserveInFic - .mul(reserveOutFic) - .mul(4) - .div(priceAverageOut) - .mul(priceAverageIn) - .mul(feesTotalReversed) - .mul(FEES_BASE.sub(feesPool)) - .add(reserveInFic.mul(reserveInFic).mul(feesLP).mul(feesLP)); + const feesTotalReversed = FEES_BASE - feesLP - feesPool; + const toSub = reserveInFic * (FEES_BASE + feesTotalReversed - feesPool); + const toDiv = (feesTotalReversed + feesLP) * 2n; + const inSqrt = + ((reserveInFic * reserveOutFic * 4n) / priceAverageOut) * + priceAverageIn * + feesTotalReversed * + (FEES_BASE - feesPool) + + reserveInFic * reserveInFic * feesLP * feesLP; // reverse sqrt check to only compute sqrt if really needed - if (inSqrt.lt(amountIn.mul(toDiv).add(toSub).pow(2))) { - firstAmountIn = sqrt(inSqrt).sub(toSub).div(toDiv); + if (inSqrt < (amountIn * toDiv + toSub) ** 2n) { + firstAmountIn = (sqrt(inSqrt) - toSub) / toDiv; } } @@ -109,45 +103,38 @@ function computeFirstTradeQtyIn( // compute first trade amountOut using arbitrage feature function computeFirstTradeQtyOut( - amountOut: BigNumber, - reserveInFic: BigNumber, - reserveOutFic: BigNumber, - priceAverageIn: BigNumber, - priceAverageOut: BigNumber, - feesLP: BigNumber, - feesPool: BigNumber, -): BigNumber { + amountOut: bigint, + reserveInFic: bigint, + reserveOutFic: bigint, + priceAverageIn: bigint, + priceAverageOut: bigint, + feesLP: bigint, + feesPool: bigint, +): bigint { // default value let firstAmountOut = amountOut; // if trade is in the good direction - if (reserveOutFic.mul(priceAverageIn).gt(reserveInFic.mul(priceAverageOut))) { + if (reserveOutFic * priceAverageIn > reserveInFic * priceAverageOut) { // pre-compute all operands - const feesTotalReversed = FEES_BASE.sub(feesLP).sub(feesPool); - - const reserveOutFicPredictedFees = reserveInFic - .mul(feesLP) - .mul(priceAverageOut) - .div(priceAverageIn); - - const toAdd = reserveOutFic - .mul(feesTotalReversed) - .mul(2) - .add(reserveOutFicPredictedFees); - - const toDiv = feesTotalReversed.mul(2); - - const inSqrt = reserveOutFic - .mul(reserveOutFicPredictedFees) - .mul(4) - .mul(feesTotalReversed) - .mul(FEES_BASE.sub(feesPool)) - .div(feesLP) - .add(reserveOutFicPredictedFees.pow(2)); + const feesTotalReversed = FEES_BASE - feesLP - feesPool; + const reserveOutFicPredictedFees = + (reserveInFic * feesLP * priceAverageOut) / priceAverageIn; + const toAdd = + reserveOutFic * feesTotalReversed * 2n + reserveOutFicPredictedFees; + const toDiv = feesTotalReversed * 2n; + const inSqrt = + (reserveOutFic * + reserveOutFicPredictedFees * + 4n * + feesTotalReversed * + (FEES_BASE - feesPool)) / + feesLP + + reserveOutFicPredictedFees ** 2n; // reverse sqrt check to only compute sqrt if really needed - if (inSqrt.gt(toAdd.sub(amountOut.mul(toDiv)).pow(2))) { - firstAmountOut = toAdd.sub(sqrt(inSqrt)).div(toDiv); + if (inSqrt > (toAdd - amountOut * toDiv) ** 2n) { + firstAmountOut = (toAdd - sqrt(inSqrt)) / toDiv; } } @@ -157,68 +144,65 @@ function computeFirstTradeQtyOut( // apply uniswap k const rule. amountIn -> amountOut // return [amountOut, newResIn, newResOut, newResInFic, newResOutFic] function applyKConstRuleOut( - amountIn: BigNumber, - reserveIn: BigNumber, - reserveOut: BigNumber, - reserveInFic: BigNumber, - reserveOutFic: BigNumber, - feesLP: BigNumber, - feesPool: BigNumber, -): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { + amountIn: bigint, + reserveIn: bigint, + reserveOut: bigint, + reserveInFic: bigint, + reserveOutFic: bigint, + feesLP: bigint, + feesPool: bigint, +): [bigint, bigint, bigint, bigint, bigint] { // k const rule - const feesTotalReversed = FEES_BASE.sub(feesLP).sub(feesPool); - const amountInWithFee = amountIn.mul(feesTotalReversed); - const numerator = amountInWithFee.mul(reserveOutFic); - const denominator = reserveInFic.mul(FEES_BASE).add(amountInWithFee); + const feesTotalReversed = FEES_BASE - feesLP - feesPool; + const amountInWithFee = amountIn * feesTotalReversed; + const numerator = amountInWithFee * reserveOutFic; + const denominator = reserveInFic * FEES_BASE + amountInWithFee; - if (denominator.eq(0)) { + if (denominator === 0n) { throw new Error('SMARDEX_K_ERROR'); } - const amountOut = numerator.div(denominator); + const amountOut = numerator / denominator; // update new reserves and add lp-fees to pools - const amountInWithFeeLp = amountIn - .mul(feesLP) - .add(amountInWithFee) - .div(FEES_BASE); - const newResIn = reserveIn.add(amountInWithFeeLp); - const newResInFic = reserveInFic.add(amountInWithFeeLp); - const newResOut = reserveOut.sub(amountOut); - const newResOutFic = reserveOutFic.sub(amountOut); + const amountInWithFeeLp = (amountIn * feesLP + amountInWithFee) / FEES_BASE; + const newResIn = reserveIn + amountInWithFeeLp; + const newResInFic = reserveInFic + amountInWithFeeLp; + const newResOut = reserveOut - amountOut; + const newResOutFic = reserveOutFic - amountOut; return [amountOut, newResIn, newResOut, newResInFic, newResOutFic]; } +// apply uniswap k const rule. amountOut -> amountIn +// returns [amountIn, newResIn, newResOut, newResInFic, newResOutFic] function applyKConstRuleIn( - amountOut: BigNumber, - reserveIn: BigNumber, - reserveOut: BigNumber, - reserveInFic: BigNumber, - reserveOutFic: BigNumber, - feesLP: BigNumber, - feesPool: BigNumber, -): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { + amountOut: bigint, + reserveIn: bigint, + reserveOut: bigint, + reserveInFic: bigint, + reserveOutFic: bigint, + feesLP: bigint, + feesPool: bigint, +): [bigint, bigint, bigint, bigint, bigint] { // k const rule - const feesTotalReversed = FEES_BASE.sub(feesLP).sub(feesPool); - const numerator = reserveInFic.mul(amountOut).mul(FEES_BASE); - const denominator = reserveOutFic.sub(amountOut).mul(feesTotalReversed); + const feesTotalReversed = FEES_BASE - feesLP - feesPool; + const numerator = reserveInFic * amountOut * FEES_BASE; + const denominator = (reserveOutFic - amountOut) * feesTotalReversed; - if (denominator.eq(0)) { + if (denominator === 0n) { throw new Error('SMARDEX_K_ERROR'); } - const amountIn = numerator.div(denominator.add(1)); + const amountIn = numerator / denominator + 1n; // update new reserves - const amountInWithFeeLp = feesTotalReversed - .add(feesLP) - .mul(amountIn) - .div(FEES_BASE); - const newResIn = reserveIn.add(amountInWithFeeLp); - const newResInFic = reserveInFic.add(amountInWithFeeLp); - const newResOut = reserveOut.sub(amountOut); - const newResOutFic = reserveOutFic.sub(amountOut); + const amountInWithFeeLp = + ((feesTotalReversed + feesLP) * amountIn) / FEES_BASE; + const newResIn = reserveIn + amountInWithFeeLp; + const newResInFic = reserveInFic + amountInWithFeeLp; + const newResOut = reserveOut - amountOut; + const newResOutFic = reserveOutFic - amountOut; return [amountIn, newResIn, newResOut, newResInFic, newResOutFic]; } @@ -226,93 +210,81 @@ function applyKConstRuleIn( /** * Compute fictive reserves based on current reserves state * - * @param {BigNumber} reserveIn the reserves of input token. - * @param {BigNumber} reserveOut the reserves of output token. - * @param {BigNumber} reserveInFic the fictive reserves of input token. - * @param {BigNumber} reserveOutFic the fictive reserves of output token. + * @param {bigint} reserveIn the reserves of input token. + * @param {bigint} reserveOut the reserves of output token. + * @param {bigint} reserveInFic the fictive reserves of input token. + * @param {bigint} reserveOutFic the fictive reserves of output token. * @returns {Array} [ficIn, ficOut] */ export function computeReserveFic( - reserveIn: BigNumber, - reserveOut: BigNumber, - reserveInFic: BigNumber, - reserveOutFic: BigNumber, -): [BigNumber, BigNumber] { - if (reserveOut.mul(reserveInFic).lt(reserveIn.mul(reserveOutFic))) { - const temp = reserveOut - .mul(reserveOut) - .div(reserveOutFic) - .mul(reserveInFic) - .div(reserveIn); - const newResFicIn = temp - .mul(reserveInFic) - .div(reserveOutFic) - .add(reserveOut.mul(reserveInFic).div(reserveOutFic)); - const newResFicOut = reserveOut.add(temp); - - return [newResFicIn.div(4), newResFicOut.div(4)]; - } - const newResFicIn = reserveInFic - .mul(reserveOut) - .div(reserveOutFic) - .add(reserveIn); - const newResFicOut = reserveIn - .mul(reserveOutFic) - .div(reserveInFic) - .add(reserveOut); - - return [newResFicIn.div(4), newResFicOut.div(4)]; + reserveIn: bigint, + reserveOut: bigint, + reserveInFic: bigint, + reserveOutFic: bigint, +): [bigint, bigint] { + if (reserveOut * reserveInFic < reserveIn * reserveOutFic) { + const temp = + (((reserveOut * reserveOut) / reserveOutFic) * reserveInFic) / reserveIn; + const newResFicIn = + (temp * reserveInFic) / reserveOutFic + + (reserveOut * reserveInFic) / reserveOutFic; + const newResFicOut = reserveOut + temp; + + return [newResFicIn / 4n, newResFicOut / 4n]; + } + + const newResFicIn = (reserveInFic * reserveOut) / reserveOutFic + reserveIn; + const newResFicOut = (reserveIn * reserveOutFic) / reserveInFic + reserveOut; + + return [newResFicIn / 4n, newResFicOut / 4n]; } /** * Simulate a full trasaction, if you know the "in" token quantity, provide you the "out" and all reserves change * Use case: you want to receive exactly amountOut and want to know the exact amountIn to send. - * @param {BigNumber} amountIn the desired input amount of the trade. - * @param {BigNumber} reserveIn the reserves of input token. - * @param {BigNumber} reserveOut the reserves of output token. - * @param {BigNumber} reserveInFic the fictive reserves of input token. - * @param {BigNumber} reserveOutFic the fictive reserves of output token. - * @param {BigNumber} priceAverageIn the price average of input token. - * @param {BigNumber} priceAverageOut the price average of output token. - * @param {BigNumber} feesLP LP fees - * @param {BigNumber} feesPool Pool fees - * @returns {BigNumber[]} [amountOut, newResIn, newResOut, newResInFic, newResOutFic] + * @param {bigint} amountIn the desired input amount of the trade. + * @param {bigint} reserveIn the reserves of input token. + * @param {bigint} reserveOut the reserves of output token. + * @param {bigint} reserveInFic the fictive reserves of input token. + * @param {bigint} reserveOutFic the fictive reserves of output token. + * @param {bigint} priceAverageIn the price average of input token. + * @param {bigint} priceAverageOut the price average of output token. + * @param {bigint} feesLP LP fees + * @param {bigint} feesPool Pool fees + * @returns {Array} [amountOut, newResIn, newResOut, newResInFic, newResOutFic] */ export function getAmountOut( - amountIn: BigNumber, - reserveIn: BigNumber, - reserveOut: BigNumber, - reserveInFic: BigNumber, - reserveOutFic: BigNumber, - priceAverageIn: BigNumber, - priceAverageOut: BigNumber, - feesLP: BigNumber, - feesPool: BigNumber, -): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { - // if (amountIn.lte(0)) { - // console.log("amountIn", amountIn) + amountIn: bigint, + reserveIn: bigint, + reserveOut: bigint, + reserveInFic: bigint, + reserveOutFic: bigint, + priceAverageIn: bigint, + priceAverageOut: bigint, + feesLP: bigint, + feesPool: bigint, +): [bigint, bigint, bigint, bigint, bigint] { + // if (amountIn <= 0n) { // throw new Error('INSUFFICIENT_INPUT_AMOUNT'); // } - if (reserveIn.lte(0) || reserveOut.lte(0)) { + if (reserveIn <= 0n || reserveOut <= 0n) { throw new Error('INSUFFICIENT_LIQUIDITY'); } - if (reserveInFic.lte(0) || reserveOutFic.lte(0)) { + if (reserveInFic <= 0n || reserveOutFic <= 0n) { throw new Error('INSUFFICIENT_LIQUIDITY'); } - if (priceAverageIn.lte(0) || priceAverageOut.lte(0)) { + if (priceAverageIn <= 0n || priceAverageOut <= 0n) { throw new Error('INSUFFICIENT_PRICE_AVERAGE'); } let reserveInFicUpdated = reserveInFic; let reserveOutFicUpdated = reserveOutFic; - const feesTotalReversed = FEES_BASE.sub(feesLP).sub(feesPool); - - const amountWithFees = amountIn.mul(feesTotalReversed).div(FEES_BASE); - + const feesTotalReversed = FEES_BASE - feesLP - feesPool; + const amountWithFees = (amountIn * feesTotalReversed) / FEES_BASE; const firstAmount = computeFirstTradeQtyIn( amountWithFees, reserveInFic, @@ -325,7 +297,7 @@ export function getAmountOut( // if there are 2 trades: 1st trade mustn't re-compute ReserveFic, 2nd should if ( - firstAmount.eq(amountWithFees) && + firstAmount === amountWithFees && ratioApproxEq(reserveInFic, reserveOutFic, priceAverageIn, priceAverageOut) ) { [reserveInFicUpdated, reserveOutFicUpdated] = computeReserveFic( @@ -337,9 +309,9 @@ export function getAmountOut( } // avoid K constant division by 0 - if (reserveInFicUpdated.lte(0)) { + if (reserveInFicUpdated <= 0n) { return [ - BigNumber.from(0), + 0n, reserveIn, reserveOut, reserveInFicUpdated, @@ -347,7 +319,7 @@ export function getAmountOut( ]; } - const firstAmountNoFees = firstAmount.mul(FEES_BASE).div(feesTotalReversed); + const firstAmountNoFees = (firstAmount * FEES_BASE) / feesTotalReversed; let [amountOut, newResIn, newResOut, newResInFic, newResOutFic] = applyKConstRuleOut( @@ -361,7 +333,7 @@ export function getAmountOut( ); // if we need a second trade - if (firstAmount.lt(amountWithFees) && firstAmountNoFees.lt(amountIn)) { + if (firstAmount < amountWithFees && firstAmountNoFees < amountIn) { [newResInFic, newResOutFic] = computeReserveFic( newResIn, newResOut, @@ -370,9 +342,9 @@ export function getAmountOut( ); // Avoid K constant division by 0 - if (newResInFic.lte(0)) { + if (newResInFic <= 0n) { return [ - BigNumber.from(0), + 0n, reserveIn, reserveOut, reserveInFicUpdated, @@ -380,11 +352,11 @@ export function getAmountOut( ]; } - let secondAmountOutNoFees: BigNumber; + let secondAmountOutNoFees: bigint; [secondAmountOutNoFees, newResIn, newResOut, newResInFic, newResOutFic] = applyKConstRuleOut( - amountIn.sub(firstAmountNoFees), + amountIn - firstAmountNoFees, newResIn, newResOut, newResInFic, @@ -393,14 +365,14 @@ export function getAmountOut( feesPool, ); - amountOut = amountOut.add(secondAmountOutNoFees); + amountOut += secondAmountOutNoFees; } if ( - newResIn.lte(0) || - newResOut.lte(0) || - newResInFic.lte(0) || - newResOutFic.lte(0) + newResIn <= 0n || + newResOut <= 0n || + newResInFic <= 0n || + newResOutFic <= 0n ) { throw new Error('INSUFFICIENT_LIQUIDITY'); } @@ -411,41 +383,41 @@ export function getAmountOut( /** * Simulate a full transaction, if you know the "out" token quantity, provide you the "in" and all reserves change * Use case: you want to receive exactly amountOut and want to know the exact amountIn to send. - * @param {BigNumber} amountOut the desired output amount of the trade. - * @param {BigNumber} reserveIn the reserves of input token. - * @param {BigNumber} reserveOut the reserves of output token. - * @param {BigNumber} reserveInFic the fictive reserves of input token. - * @param {BigNumber} reserveOutFic the fictive reserves of output token. - * @param {BigNumber} priceAverageIn the price average of input token. - * @param {BigNumber} priceAverageOut the price average of output token. - * @param {BigNumber} feesLP LP fees - * @param {BigNumber} feesPool Pool fees - * @returns {BigNumber[]} [amountIn, newResIn, newResOut, newResInFic, newResOutFic] + * @param {bigint} amountOut the desired output amount of the trade. + * @param {bigint} reserveIn the reserves of input token. + * @param {bigint} reserveOut the reserves of output token. + * @param {bigint} reserveInFic the fictive reserves of input token. + * @param {bigint} reserveOutFic the fictive reserves of output token. + * @param {bigint} priceAverageIn the price average of input token. + * @param {bigint} priceAverageOut the price average of output token. + * @param {bigint} feesLP LP fees + * @param {bigint} feesPool Pool fees + * @returns {Array} [amountIn, newResIn, newResOut, newResInFic, newResOutFic] */ export function getAmountIn( - amountOut: BigNumber, - reserveIn: BigNumber, - reserveOut: BigNumber, - reserveInFic: BigNumber, - reserveOutFic: BigNumber, - priceAverageIn: BigNumber, - priceAverageOut: BigNumber, - feesLP: BigNumber, - feesPool: BigNumber, -): [BigNumber, BigNumber, BigNumber, BigNumber, BigNumber] { - if (amountOut.lte(0)) { + amountOut: bigint, + reserveIn: bigint, + reserveOut: bigint, + reserveInFic: bigint, + reserveOutFic: bigint, + priceAverageIn: bigint, + priceAverageOut: bigint, + feesLP: bigint, + feesPool: bigint, +): [bigint, bigint, bigint, bigint, bigint] { + if (amountOut <= 0n) { throw new Error('INSUFFICIENT_OUTPUT_AMOUNT'); } - if (reserveIn.lte(0) || reserveOut.lte(0)) { + if (reserveIn <= 0n || reserveOut <= 0n) { throw new Error('INSUFFICIENT_LIQUIDITY'); } - if (reserveInFic.lte(0) || reserveOutFic.lte(0)) { + if (reserveInFic <= 0n || reserveOutFic <= 0n) { throw new Error('INSUFFICIENT_LIQUIDITY'); } - if (priceAverageIn.lte(0) || priceAverageOut.lte(0)) { + if (priceAverageIn <= 0n || priceAverageOut <= 0n) { throw new Error('INSUFFICIENT_PRICE_AVERAGE'); } @@ -464,7 +436,7 @@ export function getAmountIn( // if there are 2 trades: 1st trade mustn't re-compute ReserveFic, 2nd should if ( - firstAmount.eq(amountOut) && + firstAmount === amountOut && ratioApproxEq(reserveInFic, reserveOutFic, priceAverageIn, priceAverageOut) ) { [reserveInFicUpdated, reserveOutFicUpdated] = computeReserveFic( @@ -476,9 +448,9 @@ export function getAmountIn( } // Avoid K constant division by 0 - if (reserveInFic.lte(0)) { + if (reserveInFic <= 0n) { return [ - BigNumber.from(0), + BigInt(0), reserveIn, reserveOut, reserveInFicUpdated, @@ -498,7 +470,7 @@ export function getAmountIn( ); // if we need a second trade - if (firstAmount.lt(amountOut)) { + if (firstAmount < amountOut) { // in the second trade ALWAYS recompute fictive reserves [newResInFic, newResOutFic] = computeReserveFic( newResIn, @@ -508,9 +480,9 @@ export function getAmountIn( ); // Avoid K constant division by 0 - if (newResInFic.lte(0)) { + if (newResInFic <= 0n) { return [ - BigNumber.from(0), + BigInt(0), reserveIn, reserveOut, reserveInFicUpdated, @@ -518,11 +490,11 @@ export function getAmountIn( ]; } - let secondAmountIn: BigNumber; + let secondAmountIn: bigint; [secondAmountIn, newResIn, newResOut, newResInFic, newResOutFic] = applyKConstRuleIn( - amountOut.sub(firstAmount), + amountOut - firstAmount, newResIn, newResOut, newResInFic, @@ -531,14 +503,14 @@ export function getAmountIn( feesPool, ); - amountIn = amountIn.add(secondAmountIn); + amountIn += secondAmountIn; } if ( - newResIn.lte(0) || - newResOut.lte(0) || - newResInFic.lte(0) || - newResOutFic.lte(0) + newResIn <= 0n || + newResOut <= 0n || + newResInFic <= 0n || + newResOutFic <= 0n ) { throw new Error('INSUFFICIENT_LIQUIDITY'); } @@ -547,345 +519,62 @@ export function getAmountIn( } /** - * Computes price impact - * you can manually verify the values using https://www.calculatorsoup.com/calculators/algebra/percent-change-calculator.php - * @param {string[]} path array of token addresses composing the trade (reverse order for EXACT_OUTPUT). - * @param {Pair[]} pairs array of pairs composing the trade (reverse order for EXACT_OUTPUT). - * @param {BigNumber} inputAmount the input amount of the trade. - * @param {BigNumber} outputAmount the output amount of the trade, calculated with computeAmountOut. - * @returns {BigNumber} the percent change (not difference) between the mid price and the execution price, i.e. price impact. - */ -export function computePriceImpact( - path: string[], - pairs: Pair[], - inputAmount: BigNumber, - outputAmount: BigNumber, -): BigNumber { - // Intermediate results are not exact relative to tokens decimals but the returned result is independant of decimals differences - let initalPrice = utils.parseEther('1'); - const midPrice = priceRatio(outputAmount, inputAmount); - - // returns 100% price impact - if (midPrice.lte(0)) return utils.parseEther('1'); - - for (let i = 0; i < pairs.length; i += 1) { - if ( - !pairs[i].prevReserveFic1 || - !pairs[i].prevReserveFic0 || - pairs[i].prevReserveFic1?.eq(0) || - pairs[i].prevReserveFic0?.eq(0) - ) { - return utils.parseEther('1'); - } - - const refIsToken0 = path[i] === pairs[i].token0; - initalPrice = initalPrice - .mul(refIsToken0 ? pairs[i].prevReserveFic1! : pairs[i].prevReserveFic0!) - .div(refIsToken0 ? pairs[i].prevReserveFic0! : pairs[i].prevReserveFic1!); - } - return priceRatio(initalPrice.sub(midPrice).abs(), initalPrice); -} - -/** - * Comparator function to sort best trades - * Trades are sorted by their output amounts in decreasing order, first - * Then they are sorted by their input amounts in increasing order - * i.e. the best trades have the most outputs for the least inputs and are sorted first. - * @param {CurrencyAmount} inputA trade A input amount. - * @param {CurrencyAmount} outputA trade B input amount. - * @param {CurrencyAmount} inputB trade A input amount. - * @param {CurrencyAmount} outputB trade A input amount. - * @return {number} 1 when 'trade B' is better than 'trade A', -1 when 'trade A' is better than 'B', 0 when trades are equal. - */ -export function inputOutputComparator( - inputA: CurrencyAmount, - outputA: CurrencyAmount, - inputB: CurrencyAmount, - outputB: CurrencyAmount, -): number { - // must have same input and output token for comparison - if (inputA.currency !== inputB.currency) throw new Error('INPUT_CURRENCY'); - if (outputA.currency !== outputB.currency) throw new Error('OUTPUT_CURRENCY'); - if (outputA.amount.eq(outputB.amount)) { - if (inputA.amount.eq(inputB.amount)) { - return 0; - } - // trade A requires less input than trade B, so A should come first - if (inputA.amount.lt(inputB.amount)) { - return -1; - } - return 1; - } - // tradeA has less output than trade B, so should come second - if (outputA.amount.lt(outputB.amount)) { - return 1; - } - return -1; -} - -/** - * Compares trades extending inputOutputComparator ranking with price impact and path length - * @param {Trade} a trade A to compare - * @param {Trade} b trade B to compare - * @return {number} 1 when 'b' is better than 'a', -1 when 'a' is better than 'b', 0 when trades are equal - */ -export function tradeComparator(a: Trade, b: Trade): number { - const ioComp = inputOutputComparator( - a.amountIn, - a.amountOut, - b.amountIn, - b.amountOut, - ); - if (ioComp !== 0) { - return ioComp; - } - - // consider lowest priceImpact next, since these are less likely to fail - if (a.priceImpact!.lt(b.priceImpact!)) { - return -1; - } - if (a.priceImpact!.gt(b.priceImpact!)) { - return 1; - } - - // finally consider the number of hops since each hop costs gas - return a.route.path.length - b.route.path.length; -} - -/** - * Extracts the token addresses composing the route ordered in the route's direction starting with inputCurrency. - * @param {Pair[]} pairs array of pairs composing the trade. - * @param {string} inputCurrency the currency from which the route starts. - * @return {string[]} Array of token addresses composing the route ordered in the route's direction starting with inputCurrency. - */ -export function getPathFromInput( - pairs: Pair[], - inputCurrency: string, -): string[] { - const path: string[] = []; - for (let i = 0; i < pairs.length; i += 1) { - const pairCurrencyIn = - path.length === 0 ? inputCurrency : path[path.length - 1]; - const [tokenIn, tokenOut] = - pairCurrencyIn === pairs[i].token0 - ? [pairs[i].token0, pairs[i].token1] - : [pairs[i].token1, pairs[i].token0]; - if (path.length === 0) { - path.push(tokenIn); - } - path.push(tokenOut); - } - return path; -} - -/** - * Extracts the token addresses composing the route ordered in the route's direction ending with outputCurrency. - * @param {Pair[]} pairs array of pairs composing the trade. - * @param {string} outputCurrency the currency for which the route finishes. - * @return {string[]} Array of token addresses composing the route ordered in the route's direction ending with outputCurrency. - */ -export function getPathFromOutput( - pairs: Pair[], - outputCurrency: string, -): string[] { - const path: string[] = []; - for (let i = pairs.length - 1; i >= 0; i -= 1) { - const pairCurrencyOut = - path.length === 0 ? outputCurrency : path[path.length - 1]; - const [tokenOut, tokenIn] = - pairCurrencyOut === pairs[i].token0 - ? [pairs[i].token0, pairs[i].token1] - : [pairs[i].token1, pairs[i].token0]; - if (path.length === 0) { - path.push(tokenOut); - } - path.push(tokenIn); - } - return path.reverse(); -} - -// constants to compute approximate equality -const APPROX_EQ_PRECISION: BigNumber = BigNumber.from(1); -const APPROX_EQ_BASE_PRECISION: BigNumber = BigNumber.from(1000000); - -/** - * Computes logarithm in base 2 for a given positive number. Result is rounded down - * - * @param {BigNumber} value - value to compute the log2 - * @returns {BigNumber} the log in base 2 of the value, 0 if given 0. + * Computes the priceAverageIn and priceAverageOut. + * Use case: you want to send an exact amount of tokenIn and know exactly how much you it will give you of tokenOut. + * Price averages are modified only if current timestamp does not match last timestamp + * @param {bigint} reserveFicIn the fictuve reserves of input token. + * @param {bigint} reserveFicOut the fictuve reserves of output token. + * @param {number} priceAverageLastTimestamp last timestamp in seconds of price average values. + * @param {bigint} priceAverageIn the latest price average of input token. + * @param {bigint} priceAverageOut the latest price average of output token. + * @param {number} currentTimestampInSecond current timestamp in seconds. + * @param {number} maxBlockDiffSeconds: Max block difference in seconds + * @returns {Array} [priceAverageIn, priceAverageOut] */ -export function log2(value: BigNumber): BigNumber { - let result = constants.Zero; - if (value.shr(128).gt(0)) { - // eslint-disable-next-line no-param-reassign - value = value.shr(128); - result = result.add(128); - } - if (value.shr(64).gt(0)) { - // eslint-disable-next-line no-param-reassign - value = value.shr(64); - result = result.add(64); - } - if (value.shr(32).gt(0)) { - // eslint-disable-next-line no-param-reassign - value = value.shr(32); - result = result.add(32); - } - if (value.shr(16).gt(0)) { - // eslint-disable-next-line no-param-reassign - value = value.shr(16); - result = result.add(16); - } - if (value.shr(8).gt(0)) { - // eslint-disable-next-line no-param-reassign - value = value.shr(8); - result = result.add(8); - } - if (value.shr(4).gt(0)) { - // eslint-disable-next-line no-param-reassign - value = value.shr(4); - result = result.add(4); - } - if (value.shr(2).gt(0)) { - // eslint-disable-next-line no-param-reassign - value = value.shr(2); - result = result.add(2); - } - if (value.shr(1).gt(0)) { - result = result.add(1); +export function getUpdatedPriceAverage( + reserveFicIn: bigint, + reserveFicOut: bigint, + priceAverageLastTimestamp: number, + priceAverageIn: bigint, + priceAverageOut: bigint, + currentTimestampInSecond: number, + maxBlockDiffSeconds: number, +): [bigint, bigint] { + if (currentTimestampInSecond < priceAverageLastTimestamp) { + throw new Error('INVALID_TIMESTAMP'); } - return result; -} -/** - * Computes the square root of a number. If the number is not a perfect square, the value is rounded down. - * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). - * - * @param {BigNumber} value - value to compute the square root - * @returns {BigNumber} the square root of the value - */ -export function sqrt(a: BigNumber): BigNumber { - if (a.eq(constants.Zero)) { - return constants.Zero; + // very first time + if ( + priceAverageLastTimestamp === 0 || + priceAverageIn === 0n || + priceAverageOut === 0n + ) { + return [reserveFicIn, reserveFicOut]; } - // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. - // - // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have - // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. - // - // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` - // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` - // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` - // - // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. - let result = constants.One.shl(log2(a).div(2).toNumber()); - - // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, - // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at - // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision - // into the expected uint128 result. - result = result.add(a.div(result)).shr(1); - result = result.add(a.div(result)).shr(1); - result = result.add(a.div(result)).shr(1); - result = result.add(a.div(result)).shr(1); - result = result.add(a.div(result)).shr(1); - result = result.add(a.div(result)).shr(1); - result = result.add(a.div(result)).shr(1); - return result.lt(a.div(result)) ? result : a.div(result); -} - -/** - * Evaluates the equality of two numbers at a precision of 1/1_000_000 - * - * @param {BigNumber} x - value to compare - * @param {BigNumber} y - value to compare - * @returns {boolean} true if numbers are approximatively equal at 1/1_000_000, false otherwise - */ -export function approxEq(x: BigNumber, y: BigNumber): true | false { - return x.gt(y) - ? x.lt(y.add(y.mul(APPROX_EQ_PRECISION).div(APPROX_EQ_BASE_PRECISION))) - : y.lt(x.add(x.mul(APPROX_EQ_PRECISION).div(APPROX_EQ_BASE_PRECISION))); -} - -/** - * Evaluates the equality of two ratio numbers at a precision of 1/1_000_000. xNum / xDen ~= yNum / yDen - * - * @param {BigNumber} _xNum - first number numerator - * @param {BigNumber} _xDen - first number denominator - * @param {BigNumber} _yNum - second number numerator - * @param {BigNumber} _yDen - second number denominator - * @returns {boolean} true if the two ratios are approximatively equal at 1/1_000_000, false otherwise - */ -export function ratioApproxEq( - _xNum: BigNumber, - _xDen: BigNumber, - _yNum: BigNumber, - _yDen: BigNumber, -): true | false { - return approxEq(_xNum.mul(_yDen), _xDen.mul(_yNum)); -} - -/** - * Computes the ratio of two numbers - * - * @param {BigNumber} numerator - numerator number - * @param {BigNumber} denominator - denominator number - * @returns {BigNumber} ratio of the two numbers. returns 0 if denominator is 0 - */ -export function priceRatio(numerator: BigNumber, denominator: BigNumber) { - if (denominator.eq(0)) return BigNumber.from(0); - return utils.parseEther(numerator.toString()).div(denominator); -} - -/** - * Given an array of items sorted by `comparator` function, insert an item into its sort index and constrain - * the size to `maxSize` by removing the last item - * WARNING: This function mutates the input array ! - * Inspired by Uniswap V2: https://github.com/Uniswap/sdk-core/blob/main/src/utils/sortedInsert.ts - * - * @param {T[]} items - array of items to insert result into - * @param {T} add - item to insert - * @param {number} maxSize - maximum size of the desired array - * @param {(a: T, b: T) => number} comparator - comparator function to sort the array - * @returns {T | null} the item which was removed from the array, or null if no item was removed - */ -export function sortedInsert( - items: T[], - add: T, - maxSize: number, - comparator: (a: T, b: T) => number, -): T | null { - if (maxSize <= 0) throw new Error('MAX_SIZE_ZERO'); - // this is an invariant because the interface cannot return multiple removed items if items.length exceeds maxSize - if (items.length > maxSize) throw new Error('ITEMS_SIZE'); - - // short circuit first item add - if (items.length === 0) { - items.push(add); - return null; + // another tx has been done in the same block + if (priceAverageLastTimestamp === currentTimestampInSecond) { + return [priceAverageIn, priceAverageOut]; } - const isFull = items.length === maxSize; - // short circuit if full and the additional item does not come before the last item - if (isFull && comparator(items[items.length - 1], add) <= 0) { - return add; - } + // need to compute new linear-average price + // compute new price: + const timeDiff = Math.min( + currentTimestampInSecond - priceAverageLastTimestamp, + maxBlockDiffSeconds, + ); - let lo = 0; - let hi = items.length; + const priceAverageInRet = reserveFicIn; + const priceAverageOutRet = + ((priceAverageOut * + priceAverageInRet * + BigInt(maxBlockDiffSeconds - timeDiff)) / + priceAverageIn + + reserveFicOut * BigInt(timeDiff)) / + BigInt(maxBlockDiffSeconds); - while (lo < hi) { - // eslint-disable-next-line no-bitwise - const mid = (lo + hi) >>> 1; - if (comparator(items[mid], add) <= 0) { - lo = mid + 1; - } else { - hi = mid; - } - } - items.splice(lo, 0, add); - return isFull ? items.pop()! : null; + return [priceAverageInRet, priceAverageOutRet]; } /** @@ -912,21 +601,20 @@ export function sortedInsert( export function computeAmountOut( token0: string, token1: string, - reserve0: BigNumber, - reserve1: BigNumber, - reserve0Fic: BigNumber, - reserve1Fic: BigNumber, - tokenAmountIn: BigNumber, + reserve0: bigint, + reserve1: bigint, + reserve0Fic: bigint, + reserve1Fic: bigint, + tokenAmountIn: bigint, tokenAddressIn: string, - priceAverageLastTimestamp: BigNumber, - priceAverage0: BigNumber, - priceAverage1: BigNumber, - feesLP: BigNumber, - feesPool: BigNumber, - forcedPriceAverageTimestamp: BigNumber = BigNumber.from( - Math.ceil(Date.now() / 1000) + LATENCY_OFFSET_SECONDS, - ), - maxBlockDiffSeconds = BigNumber.from(300), + priceAverageLastTimestamp: number, + priceAverage0: bigint, + priceAverage1: bigint, + feesLP: bigint, + feesPool: bigint, + forcedPriceAverageTimestamp: number = Math.ceil(Date.now() / 1000) + + LATENCY_OFFSET_SECONDS, + maxBlockDiffSeconds = 300, ): CurrencyAmount { if (tokenAddressIn === token0) { const [newPriceAverage0, newPriceAverage1] = getUpdatedPriceAverage( @@ -1020,61 +708,184 @@ export function computeAmountOut( } /** - * Computes the priceAverageIn and priceAverageOut. - * Use case: you want to send an exact amount of tokenIn and know exactly how much you it will give you of tokenOut. - * Price averages are modified only if current timestamp does not match last timestamp - * @param {BigNumber} reserveFicIn the fictuve reserves of input token. - * @param {BigNumber} reserveFicOut the fictuve reserves of output token. - * @param {BigNumber} priceAverageLastTimestamp last timestamp in seconds of price average values. - * @param {BigNumber} priceAverageIn the latest price average of input token. - * @param {BigNumber} priceAverageOut the latest price average of output token. - * @param {BigNumber} currentTimestampInSecond current timestamp in seconds. - * @param {BigNumber} maxBlockDiffSeconds: Max block difference in seconds - * @returns {Array} [priceAverageIn, priceAverageOut] + * Computes the amount of tokenIn, at the precision of 1 wei. + * Use case: you want to receive exactly tokenOut amount and want to know the exact tokenIn amount to send. + * WARNING: token0 and token1 are pair tokens which addresses hexadecimal's values are sorted as token0 < token1. + * @param {string} token0 the currency address of token0. + * @param {string} token1 the currency address of token1. + * @param {bigint} reserve0 the reserves of token0. + * @param {bigint} reserve1 the reserves of token1. + * @param {bigint} reserve0Fic the fictionnal reserves of token0. + * @param {bigint} reserve1Fic the fictionnal reserves of token1. + * @param {bigint} tokenAmountOut the output amount of the trade. + * @param {bigint} tokenAddressOut address of the output token. + * @param {number} priceAverageLastTimestamp timestamp in seconds of the latest price average. + * @param {bigint} priceAverage0 latest price average of token0. + * @param {bigint} priceAverage1 latest price average of token1. + * @param {bigint} feesLP LP fees + * @param {bigint} feesPool Pool fees + * @param {number} forcedPriceAverageTimestamp current timestamp or timestamp of the trade in seconds. + * @param {number} maxBlockDiffSeconds: Max block difference in seconds + * @returns {Object} { currency, amount, amountMax, newResIn, newResOut, newResInFic, newResOutFic } */ -export function getUpdatedPriceAverage( - reserveFicIn: BigNumber, - reserveFicOut: BigNumber, - priceAverageLastTimestamp: BigNumber, - priceAverageIn: BigNumber, - priceAverageOut: BigNumber, - currentTimestampInSecond: BigNumber, - maxBlockDiffSeconds: BigNumber, -): [BigNumber, BigNumber] { - if (currentTimestampInSecond.lt(priceAverageLastTimestamp)) { - throw new Error('INVALID_TIMESTAMP'); - } +export function computeAmountIn( + token0: string, + token1: string, + reserve0: bigint, + reserve1: bigint, + reserve0Fic: bigint, + reserve1Fic: bigint, + tokenAmountOut: bigint, + tokenAddressOut: string, + priceAverageLastTimestamp: number, + priceAverage0: bigint, + priceAverage1: bigint, + feesLP: bigint, + feesPool: bigint, + forcedPriceAverageTimestamp: number = Math.ceil(Date.now() / 1000) + + LATENCY_OFFSET_SECONDS, + maxBlockDiffSeconds = 300, +): CurrencyAmount { + if (tokenAddressOut === token0) { + const [newPriceAverage1, newPriceAverage0] = getUpdatedPriceAverage( + reserve1Fic, + reserve0Fic, + priceAverageLastTimestamp, + priceAverage1, + priceAverage0, + forcedPriceAverageTimestamp, + maxBlockDiffSeconds, + ); - // very first time - if ( - priceAverageLastTimestamp.eq(0) || - priceAverageIn.eq(0) || - priceAverageOut.eq(0) - ) { - return [reserveFicIn, reserveFicOut]; - } + const [amountIn, newRes1, newRes0, newRes1Fic, newRes0Fic] = getAmountIn( + tokenAmountOut, + reserve1, + reserve0, + reserve1Fic, + reserve0Fic, + newPriceAverage1, + newPriceAverage0, + feesLP, + feesPool, + ); + // const [amountMax] = getAmountIn( + // tokenAmountOut, + // reserve1, + // reserve0, + // reserve1Fic, + // reserve0Fic.sub(1).lt(0) ? reserve0Fic : reserve0Fic.sub(1), + // newPriceAverage1, + // newPriceAverage0, + // ); - // another tx has been done in the same block - if (priceAverageLastTimestamp.eq(currentTimestampInSecond)) { - return [priceAverageIn, priceAverageOut]; + return { + currency: token1, + amount: amountIn, + amountMax: amountIn, // TODO is it still useful ? + newRes0, + newRes1, + newRes0Fic, + newRes1Fic, + newPriceAverage0, + newPriceAverage1, + }; } - // need to compute new linear-average price - // compute new price: - const timeDiff = currentTimestampInSecond - .sub(priceAverageLastTimestamp) - .lte(maxBlockDiffSeconds) - ? currentTimestampInSecond.sub(priceAverageLastTimestamp) - : maxBlockDiffSeconds; + // token1 is tokenOut + const [newPriceAverage0, newPriceAverage1] = getUpdatedPriceAverage( + reserve0Fic, + reserve1Fic, + priceAverageLastTimestamp, + priceAverage0, + priceAverage1, + forcedPriceAverageTimestamp, + maxBlockDiffSeconds, + ); - const priceAverageInRet = reserveFicIn; + const [amountIn, newRes0, newRes1, newRes0Fic, newRes1Fic] = getAmountIn( + tokenAmountOut, + reserve0, + reserve1, + reserve0Fic, + reserve1Fic, + newPriceAverage0, + newPriceAverage1, + feesLP, + feesPool, + ); - const priceAverageOutRet = priceAverageOut - .mul(priceAverageInRet) - .mul(maxBlockDiffSeconds.sub(timeDiff)) - .div(priceAverageIn) - .add(reserveFicOut.mul(timeDiff)) - .div(maxBlockDiffSeconds); + // const [amountMax] = getAmountIn( + // tokenAmountOut, + // reserve0, + // reserve1, + // reserve0Fic, + // reserve1Fic.sub(1).lt(0) ? reserve1Fic : reserve1Fic.sub(1), + // newPriceAverage0, + // newPriceAverage1, + // ); - return [priceAverageInRet, priceAverageOutRet]; + return { + currency: token0, + amount: amountIn, + amountMax: amountIn, // TODO is it still useful ? + newRes0, + newRes1, + newRes0Fic, + newRes1Fic, + newPriceAverage0, + newPriceAverage1, + forcedPriceAverageTimestamp, + }; +} + +/** + * Extracts the token addresses composing the route ordered in the route's direction starting with inputCurrency. + * @param {Pair[]} pairs array of pairs composing the trade. + * @param {string} inputCurrency the currency from which the route starts. + * @return {string[]} Array of token addresses composing the route ordered in the route's direction starting with inputCurrency. + */ +export function getPathFromInput( + pairs: Pair[], + inputCurrency: string, +): string[] { + const path: string[] = []; + for (let i = 0; i < pairs.length; i += 1) { + const pairCurrencyIn = + path.length === 0 ? inputCurrency : path[path.length - 1]; + const [tokenIn, tokenOut] = + pairCurrencyIn === pairs[i].token0 + ? [pairs[i].token0, pairs[i].token1] + : [pairs[i].token1, pairs[i].token0]; + if (path.length === 0) { + path.push(tokenIn); + } + path.push(tokenOut); + } + return path; +} + +/** + * Extracts the token addresses composing the route ordered in the route's direction ending with outputCurrency. + * @param {Pair[]} pairs array of pairs composing the trade. + * @param {string} outputCurrency the currency for which the route finishes. + * @return {string[]} Array of token addresses composing the route ordered in the route's direction ending with outputCurrency. + */ +export function getPathFromOutput( + pairs: Pair[], + outputCurrency: string, +): string[] { + const path: string[] = []; + for (let i = pairs.length - 1; i >= 0; i -= 1) { + const pairCurrencyOut = + path.length === 0 ? outputCurrency : path[path.length - 1]; + const [tokenOut, tokenIn] = + pairCurrencyOut === pairs[i].token0 + ? [pairs[i].token0, pairs[i].token1] + : [pairs[i].token1, pairs[i].token0]; + if (path.length === 0) { + path.push(tokenOut); + } + path.push(tokenIn); + } + return path.reverse(); } diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index b01588494..6beaa7ff2 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -415,15 +415,15 @@ export class Smardex destAmount: bigint, ): Promise { const amountIn = getAmountIn( - BigNumber.from(destAmount), - BigNumber.from(priceParams.reservesIn), - BigNumber.from(priceParams.reservesOut), - BigNumber.from(priceParams.fictiveReservesIn), - BigNumber.from(priceParams.fictiveReservesOut), - BigNumber.from(priceParams.priceAverageIn), - BigNumber.from(priceParams.priceAverageOut), - BigNumber.from(priceParams.feesLP), - BigNumber.from(priceParams.feesPool), + BigInt(destAmount), + BigInt(priceParams.reserves0), + BigInt(priceParams.reserves1), + BigInt(priceParams.fictiveReserves0), + BigInt(priceParams.fictiveReserves1), + BigInt(priceParams.priceAverage0), + BigInt(priceParams.priceAverage1), + BigInt(priceParams.feesLP || '700'), + BigInt(priceParams.feesPool || '200'), )[0]; return BigInt(amountIn.toString()); } @@ -433,19 +433,39 @@ export class Smardex srcAmount: bigint, ): Promise { const amountOut = computeAmountOut( - priceParams.tokenIn, - priceParams.tokenOut, - BigNumber.from(priceParams.reservesIn), - BigNumber.from(priceParams.reservesOut), - BigNumber.from(priceParams.fictiveReservesIn), - BigNumber.from(priceParams.fictiveReservesOut), - BigNumber.from(srcAmount), - priceParams.tokenIn, - BigNumber.from(priceParams.priceAverageLastTimestamp), - BigNumber.from(priceParams.priceAverageIn), - BigNumber.from(priceParams.priceAverageOut), - BigNumber.from(priceParams.feesLP), - BigNumber.from(priceParams.feesPool), + priceParams.direction ? priceParams.token0 : priceParams.token1, + priceParams.direction ? priceParams.token1 : priceParams.token0, + BigInt( + priceParams.direction ? priceParams.reserves0 : priceParams.reserves1, + ), + BigInt( + priceParams.direction ? priceParams.reserves1 : priceParams.reserves0, + ), + BigInt( + priceParams.direction + ? priceParams.fictiveReserves0 + : priceParams.fictiveReserves1, + ), + BigInt( + priceParams.direction + ? priceParams.fictiveReserves1 + : priceParams.fictiveReserves0, + ), + BigInt(srcAmount), + priceParams.direction ? priceParams.token0 : priceParams.token1, + +priceParams.priceAverageLastTimestamp, + BigInt( + priceParams.direction + ? priceParams.priceAverage0 + : priceParams.priceAverage1, + ), + BigInt( + priceParams.direction + ? priceParams.priceAverage1 + : priceParams.priceAverage1, + ), + BigInt(priceParams.feesLP || '700'), + BigInt(priceParams.feesPool || '200'), ).amount; // uncomment to get rate // console.log("srcAmount.", utils.formatEther(srcAmount.toString())) @@ -792,41 +812,21 @@ export class Smardex const pairReversed = pair.token1.address.toLowerCase() === from.address.toLowerCase(); - const fees = { - feesLP: '700', - feesPool: '200', - }; - if (pairReversed) { - return { - ...fees, - tokenIn: from.address, - tokenOut: to.address, - reservesIn: pairState.reserves1, - reservesOut: pairState.reserves0, - fictiveReservesIn: pairState.fictiveReserves1, - fictiveReservesOut: pairState.fictiveReserves0, - priceAverageIn: pairState.priceAverage0, - priceAverageOut: pairState.priceAverage1, - priceAverageLastTimestamp: pairState.priceAverageLastTimestamp, - fee, - direction: false, - exchange: pair.exchange, - }; - } return { - ...fees, - tokenIn: from.address, - tokenOut: to.address, - reservesIn: pairState.reserves0, - reservesOut: pairState.reserves1, - fictiveReservesIn: pairState.fictiveReserves0, - fictiveReservesOut: pairState.fictiveReserves1, - priceAverageIn: pairState.priceAverage0, - priceAverageOut: pairState.priceAverage1, + token0: pair.token0.address, + token1: pair.token1.address, + reserves0: pairState.reserves0, + reserves1: pairState.reserves1, + fictiveReserves0: pairState.fictiveReserves0, + fictiveReserves1: pairState.fictiveReserves1, + priceAverage0: pairState.priceAverage0, + priceAverage1: pairState.priceAverage1, priceAverageLastTimestamp: pairState.priceAverageLastTimestamp, fee, - direction: true, + direction: !pairReversed, exchange: pair.exchange, + feesLP: '700', + feesPool: '200', }; } diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index 56235a961..0fd82fdae 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -61,14 +61,21 @@ export type SmardexParam = SellOnSmardexParam | BuyOnSmardexParam; export type DexParams = UniswapV2DexParams; -export interface SmardexPoolOrderedParams extends UniswapV2PoolOrderedParams { - fictiveReservesIn: string; - fictiveReservesOut: string; - priceAverageIn: string; - priceAverageOut: string; +export interface SmardexPoolOrderedParams { + token0: string; + token1: string; + reserves0: string; + reserves1: string; + fictiveReserves0: string; + fictiveReserves1: string; + priceAverage0: string; + priceAverage1: string; priceAverageLastTimestamp: number; - feesLP?: string; - feesPool?: string; + fee: string; + direction: boolean; + exchange: string; + feesLP: string; + feesPool: string; } export interface SmardexPair extends Omit { diff --git a/src/dex/smardex/utils.ts b/src/dex/smardex/utils.ts new file mode 100644 index 000000000..0eb8c6d2b --- /dev/null +++ b/src/dex/smardex/utils.ts @@ -0,0 +1,126 @@ +// Constants to compute approximate equality +const APPROX_EQ_PRECISION = 1n; +const APPROX_EQ_BASE_PRECISION = 1000000n; + +/** + * Computes logarithm in base 2 for a given positive number. + * Result is rounded down. + * + * @param {bigint} value - value to compute the log2 + * @returns {bigint} the log in base 2 of the value, 0 if given 0. + */ +/* eslint-disable no-param-reassign */ +export function log2(value: bigint): bigint { + let result = 0n; + + if (value >> 128n > 0n) { + value >>= 128n; + result += 128n; + } + + if (value >> 64n > 0n) { + value >>= 64n; + result += 64n; + } + + if (value >> 32n > 0n) { + value >>= 32n; + result += 32n; + } + + if (value >> 16n > 0n) { + value >>= 16n; + result += 16n; + } + + if (value >> 8n > 0n) { + value >>= 8n; + result += 8n; + } + + if (value >> 4n > 0n) { + value >>= 4n; + result += 4n; + } + + if (value >> 2n > 0n) { + value >>= 2n; + result += 2n; + } + + if (value >> 1n > 0n) { + result += 1n; + } + + return result; +} + +/** + * Computes the square root of a number. If the number is not a perfect square, the value is rounded down. + * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). + * + * @param {bigint} value - value to compute the square root + * @returns {bigint} the square root of the value + */ +export function sqrt(value: bigint): bigint { + if (value === 0n) { + return 0n; + } + + // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. + // + // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have + // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. + // + // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` + // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` + // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` + // + // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. + let result = 1n << (log2(value) / 2n); + + // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, + // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at + // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision + // into the expected uint128 result. + result = (result + value / result) >> 1n; + result = (result + value / result) >> 1n; + result = (result + value / result) >> 1n; + result = (result + value / result) >> 1n; + result = (result + value / result) >> 1n; + result = (result + value / result) >> 1n; + result = (result + value / result) >> 1n; + + return result < value / result ? result : value / result; +} + +/** + * Evaluates the equality of two numbers at a precision of 1/1_000_000 + * + * @param {bigint} x - value to compare + * @param {bigint} y - value to compare + * @returns {boolean} true if numbers are approximatively equal at 1/1_000_000, false otherwise + */ +export function approxEq(x: bigint, y: bigint): true | false { + return x > y + ? x < y + (y * APPROX_EQ_PRECISION) / APPROX_EQ_BASE_PRECISION + : y < x + (x * APPROX_EQ_PRECISION) / APPROX_EQ_BASE_PRECISION; +} + +/** + * Evaluates the equality of two ratio numbers at a precision of 1/1_000_000. xNum / xDen ~= yNum / yDen + * + * @param {bigint} _xNum - first number numerator + * @param {bigint} _xDen - first number denominator + * @param {bigint} _yNum - second number numerator + * @param {bigint} _yDen - second number denominator + * @returns {boolean} true if the two ratios are approximatively equal at 1/1_000_000, false otherwise + */ +export function ratioApproxEq( + _xNum: bigint, + _xDen: bigint, + _yNum: bigint, + _yDen: bigint, +): true | false { + return approxEq(_xNum * _yDen, _xDen * _yNum); +} From 7d9bae35017f99183ac7e2598903e292d07dfb3d Mon Sep 17 00:00:00 2001 From: julien Date: Fri, 8 Sep 2023 11:25:43 +0200 Subject: [PATCH 231/833] fix: compute amount --- src/dex/smardex/smardex.ts | 97 ++++++++++++++++---------------------- src/dex/smardex/types.ts | 19 ++++---- 2 files changed, 50 insertions(+), 66 deletions(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 6beaa7ff2..347da2f8b 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -55,7 +55,7 @@ import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { Adapters, SmardexConfig } from './config'; import ParaSwapABI from '../../abi/IParaswap.json'; import { applyTransferFee } from '../../lib/token-transfer-fee'; -import { getAmountIn, getAmountOut, computeAmountOut } from './smardex-sdk'; +import { computeAmountIn, computeAmountOut } from './smardex-sdk'; const DefaultSmardexPoolGasCost = 90 * 1000; @@ -368,7 +368,7 @@ export class Smardex { address: pairParam.exchange, fee: parseInt(pairParam.fee), - direction: pairParam.direction, + direction: pairParam.tokenIn.toLocaleLowerCase() === pairParam.token0.toLocaleLowerCase(), }, ], }, @@ -414,17 +414,21 @@ export class Smardex priceParams: SmardexPoolOrderedParams, destAmount: bigint, ): Promise { - const amountIn = getAmountIn( - BigInt(destAmount), - BigInt(priceParams.reserves0), - BigInt(priceParams.reserves1), - BigInt(priceParams.fictiveReserves0), - BigInt(priceParams.fictiveReserves1), - BigInt(priceParams.priceAverage0), - BigInt(priceParams.priceAverage1), - BigInt(priceParams.feesLP || '700'), - BigInt(priceParams.feesPool || '200'), - )[0]; + const amountIn = computeAmountIn( + priceParams.token0, + priceParams.token1, + priceParams.reserves0, + priceParams.reserves1, + priceParams.fictiveReserves0, + priceParams.fictiveReserves1, + destAmount, + priceParams.tokenOut, + +priceParams.priceAverageLastTimestamp, + priceParams.priceAverage0, + priceParams.priceAverage1, + priceParams.feesLP, + priceParams.feesPool, + ).amount; return BigInt(amountIn.toString()); } @@ -433,39 +437,19 @@ export class Smardex srcAmount: bigint, ): Promise { const amountOut = computeAmountOut( - priceParams.direction ? priceParams.token0 : priceParams.token1, - priceParams.direction ? priceParams.token1 : priceParams.token0, - BigInt( - priceParams.direction ? priceParams.reserves0 : priceParams.reserves1, - ), - BigInt( - priceParams.direction ? priceParams.reserves1 : priceParams.reserves0, - ), - BigInt( - priceParams.direction - ? priceParams.fictiveReserves0 - : priceParams.fictiveReserves1, - ), - BigInt( - priceParams.direction - ? priceParams.fictiveReserves1 - : priceParams.fictiveReserves0, - ), - BigInt(srcAmount), - priceParams.direction ? priceParams.token0 : priceParams.token1, + priceParams.token0, + priceParams.token1, + priceParams.reserves0, + priceParams.reserves1, + priceParams.fictiveReserves0, + priceParams.fictiveReserves1, + srcAmount, + priceParams.tokenIn, +priceParams.priceAverageLastTimestamp, - BigInt( - priceParams.direction - ? priceParams.priceAverage0 - : priceParams.priceAverage1, - ), - BigInt( - priceParams.direction - ? priceParams.priceAverage1 - : priceParams.priceAverage1, - ), - BigInt(priceParams.feesLP || '700'), - BigInt(priceParams.feesPool || '200'), + priceParams.priceAverage0, + priceParams.priceAverage1, + priceParams.feesLP, + priceParams.feesPool, ).amount; // uncomment to get rate // console.log("srcAmount.", utils.formatEther(srcAmount.toString())) @@ -809,24 +793,23 @@ export class Smardex return null; } const fee = (pairState.feeCode + tokenDexTransferFee).toString(); - const pairReversed = - pair.token1.address.toLowerCase() === from.address.toLowerCase(); return { token0: pair.token0.address, token1: pair.token1.address, - reserves0: pairState.reserves0, - reserves1: pairState.reserves1, - fictiveReserves0: pairState.fictiveReserves0, - fictiveReserves1: pairState.fictiveReserves1, - priceAverage0: pairState.priceAverage0, - priceAverage1: pairState.priceAverage1, + reserves0: BigInt(pairState.reserves0), + reserves1: BigInt(pairState.reserves1), + fictiveReserves0: BigInt(pairState.fictiveReserves0), + fictiveReserves1: BigInt(pairState.fictiveReserves1), + priceAverage0: BigInt(pairState.priceAverage0), + priceAverage1: BigInt(pairState.priceAverage1), priceAverageLastTimestamp: pairState.priceAverageLastTimestamp, fee, - direction: !pairReversed, + tokenIn: from.address, + tokenOut: to.address, exchange: pair.exchange, - feesLP: '700', - feesPool: '200', + feesLP: 700n, + feesPool: 200n, }; } @@ -966,7 +949,7 @@ export class Smardex variables: { token: tokenAddress.toLowerCase(), limit }, }, SUBGRAPH_TIMEOUT, - { 'x-api-key': process.env.SUBGRAPH_APIKEY! }, + { 'x-api-key': process.env.SDEX_SUBGRAPH_APIKEY! }, ); if (!(data && data.pools0 && data.pools1)) diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index 0fd82fdae..3fe7b2359 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -64,18 +64,19 @@ export type DexParams = UniswapV2DexParams; export interface SmardexPoolOrderedParams { token0: string; token1: string; - reserves0: string; - reserves1: string; - fictiveReserves0: string; - fictiveReserves1: string; - priceAverage0: string; - priceAverage1: string; + reserves0: bigint; + reserves1: bigint; + fictiveReserves0: bigint; + fictiveReserves1: bigint; + priceAverage0: bigint; + priceAverage1: bigint; priceAverageLastTimestamp: number; fee: string; - direction: boolean; + tokenIn: string; + tokenOut: string; exchange: string; - feesLP: string; - feesPool: string; + feesLP: bigint; + feesPool: bigint; } export interface SmardexPair extends Omit { From f874a2bcfe5b6f1db19b28fede3fb95b8411a7ec Mon Sep 17 00:00:00 2001 From: julien Date: Fri, 8 Sep 2023 14:15:01 +0200 Subject: [PATCH 232/833] fix: move constant in file --- src/dex/smardex/constants.ts | 29 +++++++++++++++++++++++++++++ src/dex/smardex/smardex.ts | 26 +++++++------------------- src/dex/smardex/types.ts | 22 ++-------------------- 3 files changed, 38 insertions(+), 39 deletions(-) create mode 100644 src/dex/smardex/constants.ts diff --git a/src/dex/smardex/constants.ts b/src/dex/smardex/constants.ts new file mode 100644 index 000000000..3f59d0e95 --- /dev/null +++ b/src/dex/smardex/constants.ts @@ -0,0 +1,29 @@ +// event Sync (uint256 reserve0, uint256 reserve1, uint256 fictiveReserve0, uint256 fictiveReserve1, uint256 priceAverage0, uint256 priceAverage1) +export enum TOPICS { + SYNC_EVENT = '0x2a368c7f33bb86e2d999940a3989d849031aff29b750f67947e6b8e8c3d2ffd6', + SWAP_EVENT = '0xa4228e1eb11eb9b31069d9ed20e7af9a010ca1a02d4855cee54e08e188fcc32c', + FEES_EVENT = '0x64f84976d9c917a44796104a59950fdbd9b3c16a5dd348b546d738301f6bd068', + // PAIR_CREATED_EVENT = '0x0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9', +} + +export enum SmardexRouterFunctions { + sellExactEth = 'swapExactETHForTokens', + sellExactToken = 'swapExactTokensForETH', + swapExactIn = 'swapExactTokensForTokens', + buyExactEth = 'swapTokensForExactETH', + buyExactToken = 'swapETHForExactTokens', + swapExactOut = 'swapTokensForExactTokens', +} + +export const directSmardexFunctionName = [ + SmardexRouterFunctions.sellExactEth, + SmardexRouterFunctions.sellExactToken, + SmardexRouterFunctions.swapExactIn, + SmardexRouterFunctions.buyExactEth, + SmardexRouterFunctions.buyExactToken, + SmardexRouterFunctions.swapExactOut, +]; + +export const SUBGRAPH_TIMEOUT = 20 * 1000; + +export const DefaultSmardexPoolGasCost = 90 * 1000; diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 347da2f8b..57df60629 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -31,7 +31,6 @@ import { SmardexPool, SmardexPoolOrderedParams, SmardexPoolState, - TOPICS, } from './types'; import { getBigIntPow, @@ -46,10 +45,13 @@ import SmardexPoolLayerTwoABI from '../../abi/smardex/layer-2/smardex-pool.json' import SmardexRouterABI from '../../abi/smardex/all/smardex-router.json'; import { SimpleExchange } from '../simple-exchange'; import { - SmardexData, - SmardexParam, SmardexRouterFunctions, -} from '../smardex/types'; + directSmardexFunctionName, + TOPICS, + DefaultSmardexPoolGasCost, + SUBGRAPH_TIMEOUT, +} from '../smardex/constants'; +import { SmardexData, SmardexParam } from '../smardex/types'; import { IDex, StatefulEventSubscriber } from '../..'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { Adapters, SmardexConfig } from './config'; @@ -57,24 +59,11 @@ import ParaSwapABI from '../../abi/IParaswap.json'; import { applyTransferFee } from '../../lib/token-transfer-fee'; import { computeAmountIn, computeAmountOut } from './smardex-sdk'; -const DefaultSmardexPoolGasCost = 90 * 1000; - const smardexPoolL1 = new Interface(SmardexPoolLayerOneABI); const smardexPoolL2 = new Interface(SmardexPoolLayerTwoABI); const coder = new AbiCoder(); -const directSmardexFunctionName = [ - SmardexRouterFunctions.sellExactEth, - SmardexRouterFunctions.sellExactToken, - SmardexRouterFunctions.swapExactIn, - SmardexRouterFunctions.buyExactEth, - SmardexRouterFunctions.buyExactToken, - SmardexRouterFunctions.swapExactOut, -]; - -const SUBGRAPH_TIMEOUT = 20 * 1000; - export class SmardexEventPool extends StatefulEventSubscriber { constructor( protected poolInterface: Interface, @@ -104,7 +93,7 @@ export class SmardexEventPool extends StatefulEventSubscriber state: DeepReadonly, log: Readonly, ): AsyncOrSync | null> { - if (log.topics[0] !== TOPICS.SYNC_EVENT) return null; + if (!Object.keys(TOPICS).includes(log.topics[0])) return null; const event = smardexPoolL1.parseLog(log); switch (event.name) { case 'Sync': @@ -139,7 +128,6 @@ export class SmardexEventPool extends StatefulEventSubscriber [], ), }, - { target: this.poolAddress, callData: this.poolInterface.encodeFunctionData('getPriceAverage', []), diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index 3fe7b2359..4da319bea 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -1,13 +1,11 @@ import { Address, NumberAsString } from '../../types'; import { UniswapV2Data, - UniswapV2PoolOrderedParams, DexParams as UniswapV2DexParams, UniswapPool, - UniswapDataLegacy, } from '../uniswap-v2/types'; import { UniswapV2Pair } from '../uniswap-v2/uniswap-v2'; -import { SmardexEventPool } from './smardex'; +import { type SmardexEventPool } from './smardex'; export interface SmardexPoolState { reserves0: string; @@ -20,27 +18,11 @@ export interface SmardexPoolState { feeCode: number; } -// event Sync (uint256 reserve0, uint256 reserve1, uint256 fictiveReserve0, uint256 fictiveReserve1, uint256 priceAverage0, uint256 priceAverage1) -export enum TOPICS { - SYNC_EVENT = '0x2a368c7f33bb86e2d999940a3989d849031aff29b750f67947e6b8e8c3d2ffd6', -} - -export interface SmardexData extends UniswapV2Data { +export interface SmardexData extends Omit{ deadline: number; receiver: Address; } -// export type SmardexDataLegacy = UniswapDataLegacy; - -export enum SmardexRouterFunctions { - sellExactEth = 'swapExactETHForTokens', - sellExactToken = 'swapExactTokensForETH', - swapExactIn = 'swapExactTokensForTokens', - buyExactEth = 'swapTokensForExactETH', - buyExactToken = 'swapETHForExactTokens', - swapExactOut = 'swapTokensForExactTokens', -} - export type SellOnSmardexParam = [ amountIn: NumberAsString, amountOutMin: NumberAsString, From 88f3ebb0cd8592dd54f90b6561c26d201030dcde Mon Sep 17 00:00:00 2001 From: julien Date: Fri, 8 Sep 2023 14:16:55 +0200 Subject: [PATCH 233/833] fix: TOPICS condition --- src/dex/smardex/smardex.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 57df60629..851580ec3 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -93,7 +93,7 @@ export class SmardexEventPool extends StatefulEventSubscriber state: DeepReadonly, log: Readonly, ): AsyncOrSync | null> { - if (!Object.keys(TOPICS).includes(log.topics[0])) return null; + if (!Object.values(TOPICS).includes(log.topics[0] as TOPICS)) return null; const event = smardexPoolL1.parseLog(log); switch (event.name) { case 'Sync': From 94b26a478f65c36408f8e2b4c3d2c6fe3f9faa03 Mon Sep 17 00:00:00 2001 From: fireboss777 Date: Fri, 8 Sep 2023 15:29:06 +0200 Subject: [PATCH 234/833] fix: merged --- src/dex/smardex/sdk/constants.ts | 10 ++ .../smardex/{smardex-sdk.ts => sdk/core.ts} | 104 +++-------- src/dex/smardex/sdk/errors.ts | 18 ++ src/dex/smardex/sdk/types.ts | 68 ++++++++ src/dex/smardex/sdk/utils.ts | 156 +++++++++++++++++ src/dex/smardex/smardex-e2e.test.ts | 164 ++++++++++++------ src/dex/smardex/smardex.ts | 54 +++--- src/dex/smardex/types.ts | 4 +- tests/constants-e2e.ts | 1 + tsconfig.json | 2 +- 10 files changed, 422 insertions(+), 159 deletions(-) create mode 100644 src/dex/smardex/sdk/constants.ts rename src/dex/smardex/{smardex-sdk.ts => sdk/core.ts} (90%) create mode 100644 src/dex/smardex/sdk/errors.ts create mode 100644 src/dex/smardex/sdk/types.ts create mode 100644 src/dex/smardex/sdk/utils.ts diff --git a/src/dex/smardex/sdk/constants.ts b/src/dex/smardex/sdk/constants.ts new file mode 100644 index 000000000..d8d61944f --- /dev/null +++ b/src/dex/smardex/sdk/constants.ts @@ -0,0 +1,10 @@ +// Protocol's fees constants +export const FEES_BASE = 1000000n; + +// constant for function 'updatePriceAverage' +export const LATENCY_OFFSET_SECONDS = 20; + +export enum TradeType { + EXACT_INPUT, + EXACT_OUTPUT, +} diff --git a/src/dex/smardex/smardex-sdk.ts b/src/dex/smardex/sdk/core.ts similarity index 90% rename from src/dex/smardex/smardex-sdk.ts rename to src/dex/smardex/sdk/core.ts index bcc38a85f..1cfef637a 100644 --- a/src/dex/smardex/smardex-sdk.ts +++ b/src/dex/smardex/sdk/core.ts @@ -1,70 +1,8 @@ -// Protocol's fees constants -export const FEES_LP = BigInt(500); -export const FEES_POOL = BigInt(200); -export const FEES_TOTAL = FEES_LP + FEES_POOL; -export const FEES_BASE = BigInt(1000); -export const FEES_TOTAL_REVERSED = FEES_BASE - FEES_TOTAL; -export interface Pair { - address?: string; - token0: string; - token1: string; - reserve0: bigint; - reserve1: bigint; - reserve0LastFictive: bigint; - reserve1LastFictive: bigint; - priceAverageLastTimestamp: number; - priceAverage0: bigint; - priceAverage1: bigint; - forcedPriceAverageTimestamp?: number; - prevReserveFic0?: bigint; - prevReserveFic1?: bigint; -} - -export interface CurrencyAmount { - currency: string; - amount: bigint; - amountMax?: bigint; - newRes0?: bigint; - newRes1?: bigint; - newRes0Fic?: bigint; - newRes1Fic?: bigint; - newPriceAverage0?: bigint; - newPriceAverage1?: bigint; - forcedPriceAverageTimestamp?: number; -} - -export interface BestTradeOptions { - maxNumResults?: number; // how many results to return - maxHops?: number; // the maximum number of hops for the swap - arbitrage?: boolean; // consider arbitrage loops or not -} - -export interface Route { - pairs: Pair[]; - path: string[]; - input: string; - output: string; -} - -export interface Trade { - route: Route; - amountIn: CurrencyAmount; - amountOut: CurrencyAmount; - tradeType: TradeType; - priceImpact?: bigint; // defined only after calling bestTradeExactIn or bestTradeExactOut -} -// constant for function 'updatePriceAverage' -export const MAX_BLOCK_DIFF_SECONDS = process.env.SDK_MAX_BLOCK_DIFF_SECONDS - ? Number(process.env.SDK_MAX_BLOCK_DIFF_SECONDS) - : 300; -export const LATENCY_OFFSET_SECONDS = 20; - -export enum TradeType { - EXACT_INPUT, - EXACT_OUTPUT, -} - +import { parseEther, parseUnits } from 'ethers/lib/utils'; +import { FEES_BASE, LATENCY_OFFSET_SECONDS, TradeType } from './constants'; import { ratioApproxEq, sqrt } from './utils'; +import SmardexError from './errors'; +import type { BestTradeOptions, CurrencyAmount, Pair, Trade } from './types'; // compute first trade amountIn using arbitrage feature function computeFirstTradeQtyIn( @@ -159,7 +97,7 @@ function applyKConstRuleOut( const denominator = reserveInFic * FEES_BASE + amountInWithFee; if (denominator === 0n) { - throw new Error('SMARDEX_K_ERROR'); + throw new SmardexError('SMARDEX_K_ERROR'); } const amountOut = numerator / denominator; @@ -191,7 +129,7 @@ function applyKConstRuleIn( const denominator = (reserveOutFic - amountOut) * feesTotalReversed; if (denominator === 0n) { - throw new Error('SMARDEX_K_ERROR'); + throw new SmardexError('SMARDEX_K_ERROR'); } const amountIn = numerator / denominator + 1n; @@ -265,19 +203,19 @@ export function getAmountOut( feesPool: bigint, ): [bigint, bigint, bigint, bigint, bigint] { // if (amountIn <= 0n) { - // throw new Error('INSUFFICIENT_INPUT_AMOUNT'); + // throw new SmardexError('INSUFFICIENT_INPUT_AMOUNT'); // } if (reserveIn <= 0n || reserveOut <= 0n) { - throw new Error('INSUFFICIENT_LIQUIDITY'); + throw new SmardexError('INSUFFICIENT_LIQUIDITY'); } if (reserveInFic <= 0n || reserveOutFic <= 0n) { - throw new Error('INSUFFICIENT_LIQUIDITY'); + throw new SmardexError('INSUFFICIENT_LIQUIDITY'); } if (priceAverageIn <= 0n || priceAverageOut <= 0n) { - throw new Error('INSUFFICIENT_PRICE_AVERAGE'); + throw new SmardexError('INSUFFICIENT_PRICE_AVERAGE'); } let reserveInFicUpdated = reserveInFic; @@ -374,7 +312,7 @@ export function getAmountOut( newResInFic <= 0n || newResOutFic <= 0n ) { - throw new Error('INSUFFICIENT_LIQUIDITY'); + throw new SmardexError('INSUFFICIENT_LIQUIDITY'); } return [amountOut, newResIn, newResOut, newResInFic, newResOutFic]; @@ -405,20 +343,20 @@ export function getAmountIn( feesLP: bigint, feesPool: bigint, ): [bigint, bigint, bigint, bigint, bigint] { - if (amountOut <= 0n) { - throw new Error('INSUFFICIENT_OUTPUT_AMOUNT'); - } + // if (amountOut <= 0n) { + // throw new SmardexError('INSUFFICIENT_OUTPUT_AMOUNT'); + // } if (reserveIn <= 0n || reserveOut <= 0n) { - throw new Error('INSUFFICIENT_LIQUIDITY'); + throw new SmardexError('INSUFFICIENT_LIQUIDITY'); } if (reserveInFic <= 0n || reserveOutFic <= 0n) { - throw new Error('INSUFFICIENT_LIQUIDITY'); + throw new SmardexError('INSUFFICIENT_LIQUIDITY'); } if (priceAverageIn <= 0n || priceAverageOut <= 0n) { - throw new Error('INSUFFICIENT_PRICE_AVERAGE'); + throw new SmardexError('INSUFFICIENT_PRICE_AVERAGE'); } let reserveInFicUpdated = reserveInFic; @@ -450,7 +388,7 @@ export function getAmountIn( // Avoid K constant division by 0 if (reserveInFic <= 0n) { return [ - BigInt(0), + BigInt('0'), reserveIn, reserveOut, reserveInFicUpdated, @@ -482,7 +420,7 @@ export function getAmountIn( // Avoid K constant division by 0 if (newResInFic <= 0n) { return [ - BigInt(0), + BigInt('0'), reserveIn, reserveOut, reserveInFicUpdated, @@ -512,7 +450,7 @@ export function getAmountIn( newResInFic <= 0n || newResOutFic <= 0n ) { - throw new Error('INSUFFICIENT_LIQUIDITY'); + throw new SmardexError('INSUFFICIENT_LIQUIDITY'); } return [amountIn, newResIn, newResOut, newResInFic, newResOutFic]; @@ -541,7 +479,7 @@ export function getUpdatedPriceAverage( maxBlockDiffSeconds: number, ): [bigint, bigint] { if (currentTimestampInSecond < priceAverageLastTimestamp) { - throw new Error('INVALID_TIMESTAMP'); + throw new SmardexError('INVALID_TIMESTAMP', 'SmarDexError'); } // very first time diff --git a/src/dex/smardex/sdk/errors.ts b/src/dex/smardex/sdk/errors.ts new file mode 100644 index 000000000..7898fa965 --- /dev/null +++ b/src/dex/smardex/sdk/errors.ts @@ -0,0 +1,18 @@ +/** + * SmardexError class + * + * @class SmardexError extends Error + */ +export default class SmardexError extends Error { + /** + * Create SmardexError object + * + * @param {string} message - error message + * @param {string} [errorName=SmarDexSDK] - identifier for the error + * @returns {SmardexError} SmarDex Error object + */ + constructor(message: string, errorName = 'SmarDexSDK') { + super(message); + this.name = errorName; + } +} diff --git a/src/dex/smardex/sdk/types.ts b/src/dex/smardex/sdk/types.ts new file mode 100644 index 000000000..2a91c164e --- /dev/null +++ b/src/dex/smardex/sdk/types.ts @@ -0,0 +1,68 @@ +import { TradeType } from './constants'; + +export interface Pair { + address?: string; + token0: string; + token1: string; + reserve0: bigint; + reserve1: bigint; + reserve0LastFictive: bigint; + reserve1LastFictive: bigint; + priceAverageLastTimestamp: number; + priceAverage0: bigint; + priceAverage1: bigint; + forcedPriceAverageTimestamp?: number; + prevReserveFic0?: bigint; + prevReserveFic1?: bigint; + feesLP: bigint; + feesPool: bigint; +} + +export interface CurrencyAmount { + currency: string; + amount: bigint; + amountMax?: bigint; + newRes0?: bigint; + newRes1?: bigint; + newRes0Fic?: bigint; + newRes1Fic?: bigint; + newPriceAverage0?: bigint; + newPriceAverage1?: bigint; + forcedPriceAverageTimestamp?: number; +} + +export interface BestTradeOptions { + maxNumResults?: number; // how many results to return + maxHops?: number; // the maximum number of hops for the swap + arbitrage?: boolean; // consider arbitrage loops or not +} + +export interface Route { + pairs: Pair[]; + path: string[]; + input: string; + output: string; +} + +export interface Trade { + route: Route; + amountIn: CurrencyAmount; + amountOut: CurrencyAmount; + tradeType: TradeType; + priceImpact?: bigint; + gasFeesUSD?: bigint; + amountInUSD?: bigint; + amountOutUSD?: bigint; +} + +export interface GasEstimateData { + gasPrice: bigint; + gasQuantitiesFirstHop: number; + gasQuantitiesAdditionalHop: number; + nativeTokenPrice: bigint; + nativeTokenDecimals: number; + inputTokenPrice: bigint; + inputTokenDecimals: number; + outputTokenPrice: bigint; + outputTokenDecimals: number; +} diff --git a/src/dex/smardex/sdk/utils.ts b/src/dex/smardex/sdk/utils.ts new file mode 100644 index 000000000..c8627b5f0 --- /dev/null +++ b/src/dex/smardex/sdk/utils.ts @@ -0,0 +1,156 @@ +import { parseUnits } from 'ethers/lib/utils'; + +import { CurrencyAmount, Trade } from './types'; + +// Constants to compute approximate equality +const APPROX_EQ_PRECISION = 1n; +const APPROX_EQ_BASE_PRECISION = 1000000n; + +/** + * Computes logarithm in base 2 for a given positive number. + * Result is rounded down. + * + * @param {bigint} value - value to compute the log2 + * @returns {bigint} the log in base 2 of the value, 0 if given 0. + */ +/* eslint-disable no-param-reassign */ +export function log2(value: bigint): bigint { + let result = 0n; + + if (value >> 128n > 0n) { + value >>= 128n; + result += 128n; + } + + if (value >> 64n > 0n) { + value >>= 64n; + result += 64n; + } + + if (value >> 32n > 0n) { + value >>= 32n; + result += 32n; + } + + if (value >> 16n > 0n) { + value >>= 16n; + result += 16n; + } + + if (value >> 8n > 0n) { + value >>= 8n; + result += 8n; + } + + if (value >> 4n > 0n) { + value >>= 4n; + result += 4n; + } + + if (value >> 2n > 0n) { + value >>= 2n; + result += 2n; + } + + if (value >> 1n > 0n) { + result += 1n; + } + + return result; +} + +/** + * Computes the square root of a number. If the number is not a perfect square, the value is rounded down. + * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). + * + * @param {bigint} value - value to compute the square root + * @returns {bigint} the square root of the value + */ +export function sqrt(value: bigint): bigint { + if (value === 0n) { + return 0n; + } + + // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. + // + // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have + // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. + // + // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` + // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` + // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` + // + // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. + let result = 1n << (log2(value) / 2n); + + // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, + // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at + // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision + // into the expected uint128 result. + result = (result + value / result) >> 1n; + result = (result + value / result) >> 1n; + result = (result + value / result) >> 1n; + result = (result + value / result) >> 1n; + result = (result + value / result) >> 1n; + result = (result + value / result) >> 1n; + result = (result + value / result) >> 1n; + + return result < value / result ? result : value / result; +} + +/** + * Evaluates the equality of two numbers at a precision of 1/1_000_000 + * + * @param {bigint} x - value to compare + * @param {bigint} y - value to compare + * @returns {boolean} true if numbers are approximatively equal at 1/1_000_000, false otherwise + */ +export function approxEq(x: bigint, y: bigint): true | false { + return x > y + ? x < y + (y * APPROX_EQ_PRECISION) / APPROX_EQ_BASE_PRECISION + : y < x + (x * APPROX_EQ_PRECISION) / APPROX_EQ_BASE_PRECISION; +} + +/** + * Evaluates the equality of two ratio numbers at a precision of 1/1_000_000. xNum / xDen ~= yNum / yDen + * + * @param {bigint} _xNum - first number numerator + * @param {bigint} _xDen - first number denominator + * @param {bigint} _yNum - second number numerator + * @param {bigint} _yDen - second number denominator + * @returns {boolean} true if the two ratios are approximatively equal at 1/1_000_000, false otherwise + */ +export function ratioApproxEq( + _xNum: bigint, + _xDen: bigint, + _yNum: bigint, + _yDen: bigint, +): true | false { + return approxEq(_xNum * _yDen, _xDen * _yNum); +} + +/** + * Computes the ratio of two numbers + * + * @param {bigint} numerator - numerator number + * @param {bigint} denominator - denominator number + * @param {number} decimals - decimals + * @returns {bigint} ratio of the two numbers. returns 0 if denominator is 0 + */ +export function priceRatio( + numerator: bigint, + denominator: bigint, + decimals = 18, +) { + if (denominator === 0n) { + return 0n; + } + + return ( + BigInt(parseUnits(numerator.toString(), decimals).toString()) / denominator + ); +} + +export function abs(value: bigint) { + return value === -0n || value < 0n ? -value : value; +} diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index a95bf2c35..f3c31d3ff 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -19,59 +19,121 @@ describe('Smardex E2E Mainnet', () => { const dexKey = 'Smardex'; describe('Simpleswap', () => { - it('WETH -> SDEX', async () => { - await testE2E( - tokens.WETH, - tokens.SDEX, - holders.WETH, - '2000000000000000000', // 2 WETH - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); + describe('SELL', () => { + it('WETH -> SDEX', async () => { + await testE2E( + tokens.WETH, + tokens.SDEX, + holders.WETH, + '2000000000000000000', // 2 WETH + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('SDEX -> WETH', async () => { + await testE2E( + tokens.SDEX, + tokens.WETH, + holders.SDEX, + '300000000000000000000000', // 300K SDEX + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('USDT -> SDEX', async () => { + await testE2E( + tokens.USDT, + tokens.SDEX, + holders.USDT, + '200000000', // 200 USDT + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('SDEX -> USDT', async () => { + await testE2E( + tokens.SDEX, + tokens.USDT, + holders.SDEX, + '30000000000000000000000', // 30K SDEX + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); }); - // it('WETH <- TOKEN', async () => { - // await testE2E( - // tokens.WETH, - // tokens.USDT, - // holders.WETH, - // '2000000000000000000', // 2 WETH - // SwapSide.BUY, // exact output - // dexKey, - // ContractMethod.simpleSwap, - // network, - // provider, - // ); - // }); - // it('ETH -> TOKEN', async () => { - // await testE2E( - // tokens.ETH, - // tokens.USDT, - // holders.ETH, - // '7000000000000000000', // 7 ETH - // SwapSide.SELL, // exact input - // dexKey, - // ContractMethod.simpleSwap, - // network, - // provider, - // ); - // }); - // it('ETH <- TOKEN', async () => { - // await testE2E( - // tokens.ETH, - // tokens.USDT, - // holders.ETH, - // '7000000000000000000', // 7 ETH - // SwapSide.BUY, // exact output - // dexKey, - // ContractMethod.simpleSwap, - // network, - // provider, - // ); - // }); + describe('BUY', () => { + it('WETH -> SDEX', async () => { + await testE2E( + tokens.WETH, + tokens.SDEX, + holders.WETH, + '300000000000000000000000', // 300K SDEX + SwapSide.BUY, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('SDEX -> WETH', async () => { + await testE2E( + tokens.SDEX, + tokens.WETH, + holders.SDEX, + '2000000000000000000', // 2 ETH + SwapSide.BUY, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('USDT -> SDEX', async () => { + await testE2E( + tokens.USDT, + tokens.SDEX, + holders.USDT, + '30000000000000000000000', // 30K SDEX + SwapSide.BUY, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it.skip('SDEX -> USDT', async () => { + await testE2E( + tokens.SDEX, + tokens.USDT, + holders.SDEX, + '1000000', // 200 USDT + SwapSide.BUY, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + }); }); // describe('Multiswap', () => { diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 851580ec3..44bfa8a7b 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -57,7 +57,7 @@ import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { Adapters, SmardexConfig } from './config'; import ParaSwapABI from '../../abi/IParaswap.json'; import { applyTransferFee } from '../../lib/token-transfer-fee'; -import { computeAmountIn, computeAmountOut } from './smardex-sdk'; +import { computeAmountIn, computeAmountOut } from './sdk/core'; const smardexPoolL1 = new Interface(SmardexPoolLayerOneABI); const smardexPoolL2 = new Interface(SmardexPoolLayerTwoABI); @@ -351,12 +351,13 @@ export class Smardex path: [from.address.toLowerCase(), to.address.toLowerCase()], factory: this.factoryAddress, initCode: this.initCode, - feeFactor: this.feeFactor, pools: [ { address: pairParam.exchange, fee: parseInt(pairParam.fee), - direction: pairParam.tokenIn.toLocaleLowerCase() === pairParam.token0.toLocaleLowerCase(), + direction: + pairParam.tokenIn.toLocaleLowerCase() === + pairParam.token0.toLocaleLowerCase(), }, ], }, @@ -405,18 +406,22 @@ export class Smardex const amountIn = computeAmountIn( priceParams.token0, priceParams.token1, - priceParams.reserves0, - priceParams.reserves1, - priceParams.fictiveReserves0, - priceParams.fictiveReserves1, - destAmount, - priceParams.tokenOut, + BigInt(priceParams.reserves0), + BigInt(priceParams.reserves1), + BigInt(priceParams.fictiveReserves0), + BigInt(priceParams.fictiveReserves1), + BigInt(destAmount), + priceParams.to, +priceParams.priceAverageLastTimestamp, - priceParams.priceAverage0, - priceParams.priceAverage1, - priceParams.feesLP, - priceParams.feesPool, + BigInt(priceParams.priceAverage0), + BigInt(priceParams.priceAverage1), + BigInt(priceParams.feesLP || '700'), + BigInt(priceParams.feesPool || '200'), ).amount; + + // console.log("destAmount.", utils.formatEther(destAmount.toString())) + // console.log("amountIn", utils.formatEther(amountIn.toString())) + return BigInt(amountIn.toString()); } @@ -427,18 +432,19 @@ export class Smardex const amountOut = computeAmountOut( priceParams.token0, priceParams.token1, - priceParams.reserves0, - priceParams.reserves1, - priceParams.fictiveReserves0, - priceParams.fictiveReserves1, - srcAmount, - priceParams.tokenIn, + BigInt(priceParams.reserves0), + BigInt(priceParams.reserves1), + BigInt(priceParams.fictiveReserves0), + BigInt(priceParams.fictiveReserves1), + BigInt(srcAmount), + priceParams.from, +priceParams.priceAverageLastTimestamp, - priceParams.priceAverage0, - priceParams.priceAverage1, - priceParams.feesLP, - priceParams.feesPool, + BigInt(priceParams.priceAverage0), + BigInt(priceParams.priceAverage1), + BigInt(priceParams.feesLP || '700'), + BigInt(priceParams.feesPool || '200'), ).amount; + // uncomment to get rate // console.log("srcAmount.", utils.formatEther(srcAmount.toString())) // console.log("amountOut", utils.formatEther(amountOut.toString())) @@ -783,6 +789,8 @@ export class Smardex const fee = (pairState.feeCode + tokenDexTransferFee).toString(); return { + from: from.address, + to: to.address, token0: pair.token0.address, token1: pair.token1.address, reserves0: BigInt(pairState.reserves0), diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index 4da319bea..8a5bcddd6 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -18,7 +18,7 @@ export interface SmardexPoolState { feeCode: number; } -export interface SmardexData extends Omit{ +export interface SmardexData extends Omit { deadline: number; receiver: Address; } @@ -44,6 +44,8 @@ export type SmardexParam = SellOnSmardexParam | BuyOnSmardexParam; export type DexParams = UniswapV2DexParams; export interface SmardexPoolOrderedParams { + from: string; + to: string; token0: string; token1: string; reserves0: bigint; diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 7b2d216e1..ae011b0d9 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -868,6 +868,7 @@ export const Holders: { } = { [Network.MAINNET]: { ETH: '0x176F3DAb24a159341c0509bB36B833E7fdd0a132', + SDEX: '0xE03c726340ccB2FbBAF6ca91533Ab64e64Fb9d4A', USDC: '0x79E2Ba942B0e8fDB6ff3d406e930289d10B49ADe', WBTC: '0x1cb17a66dc606a52785f69f08f4256526abd4943', sBTC: '0xA2e3475D13776C6E42ff37B47286827d959B2195', diff --git a/tsconfig.json b/tsconfig.json index 6318f0667..1511b7216 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,7 @@ "module": "commonjs", "noImplicitAny": true, "outDir": "build", - "rootDir": "src", + // "rootDir": "src", "preserveConstEnums": true, "strictNullChecks": true, "strict": true, From 226bb895a68488e1f7b6c6863eabdee0276ed0a3 Mon Sep 17 00:00:00 2001 From: julien Date: Fri, 8 Sep 2023 15:41:01 +0200 Subject: [PATCH 235/833] fix: conflict --- src/dex/smardex/smardex.ts | 45 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 44bfa8a7b..7144f2ac8 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -306,6 +306,7 @@ export class Smardex const unitAmount = getBigIntPow(isSell ? from.decimals : to.decimals); + // TODO SMARDEX does not support FoT const [unitVolumeWithFee, ...amountsWithFee] = applyTransferFee( [unitAmount, ...amounts], side, @@ -354,10 +355,8 @@ export class Smardex pools: [ { address: pairParam.exchange, - fee: parseInt(pairParam.fee), - direction: - pairParam.tokenIn.toLocaleLowerCase() === - pairParam.token0.toLocaleLowerCase(), + fee: 0, // Smardex does not support Fees on Transfer Tokens + direction: pairParam.fromToken.toLocaleLowerCase() === pairParam.token0.toLocaleLowerCase(), }, ], }, @@ -406,17 +405,17 @@ export class Smardex const amountIn = computeAmountIn( priceParams.token0, priceParams.token1, - BigInt(priceParams.reserves0), - BigInt(priceParams.reserves1), - BigInt(priceParams.fictiveReserves0), - BigInt(priceParams.fictiveReserves1), - BigInt(destAmount), + priceParams.reserves0, + priceParams.reserves1, + priceParams.fictiveReserves0, + priceParams.fictiveReserves1, + destAmount, priceParams.to, +priceParams.priceAverageLastTimestamp, - BigInt(priceParams.priceAverage0), - BigInt(priceParams.priceAverage1), - BigInt(priceParams.feesLP || '700'), - BigInt(priceParams.feesPool || '200'), + priceParams.priceAverage0, + priceParams.priceAverage1, + priceParams.feesLp, + priceParams.feesPool, ).amount; // console.log("destAmount.", utils.formatEther(destAmount.toString())) @@ -432,17 +431,17 @@ export class Smardex const amountOut = computeAmountOut( priceParams.token0, priceParams.token1, - BigInt(priceParams.reserves0), - BigInt(priceParams.reserves1), - BigInt(priceParams.fictiveReserves0), - BigInt(priceParams.fictiveReserves1), - BigInt(srcAmount), - priceParams.from, + priceParams.reserves0, + priceParams.reserves1, + priceParams.fictiveReserves0, + priceParams.fictiveReserves1, + srcAmount, + priceParams.fromToken, +priceParams.priceAverageLastTimestamp, - BigInt(priceParams.priceAverage0), - BigInt(priceParams.priceAverage1), - BigInt(priceParams.feesLP || '700'), - BigInt(priceParams.feesPool || '200'), + priceParams.priceAverage0, + priceParams.priceAverage1, + priceParams.feesLp, + priceParams.feesPool, ).amount; // uncomment to get rate From d47a2771624263cdee2deafd932bd6fa13adbcd8 Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Fri, 8 Sep 2023 16:42:18 +0300 Subject: [PATCH 236/833] feat(BACK-1264): add adapters for UniswapV3 Base --- src/dex/uniswap-v3/config.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index 007d39c04..4a503e9f4 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -296,4 +296,8 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 5 }], [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 6 }], }, + [Network.BASE]: { + [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 1 }], + [SwapSide.BUY]: [{ name: 'BaseBuyAdapter', index: 1 }], + }, }; From e5faf3e8c0f863e83d8a1833f2b30554c7af6cb5 Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Fri, 8 Sep 2023 16:44:16 +0300 Subject: [PATCH 237/833] feat(BACK-1264): update dev version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1eda85122..29b7326d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.33.4-base-support.0", + "version": "2.33.4-base-support.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 3db7e14bc9e1d103d8e26c7bfd7b4cd733d97205 Mon Sep 17 00:00:00 2001 From: fireboss777 Date: Fri, 8 Sep 2023 15:48:16 +0200 Subject: [PATCH 238/833] fix: minor types --- src/dex/smardex/smardex.ts | 12 +++++++----- src/dex/smardex/types.ts | 6 +++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 7144f2ac8..20f9c3319 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -356,7 +356,9 @@ export class Smardex { address: pairParam.exchange, fee: 0, // Smardex does not support Fees on Transfer Tokens - direction: pairParam.fromToken.toLocaleLowerCase() === pairParam.token0.toLocaleLowerCase(), + direction: + pairParam.fromToken.toLocaleLowerCase() === + pairParam.token0.toLocaleLowerCase(), }, ], }, @@ -410,7 +412,7 @@ export class Smardex priceParams.fictiveReserves0, priceParams.fictiveReserves1, destAmount, - priceParams.to, + priceParams.toToken, +priceParams.priceAverageLastTimestamp, priceParams.priceAverage0, priceParams.priceAverage1, @@ -788,8 +790,8 @@ export class Smardex const fee = (pairState.feeCode + tokenDexTransferFee).toString(); return { - from: from.address, - to: to.address, + fromToken: from.address, + toToken: to.address, token0: pair.token0.address, token1: pair.token1.address, reserves0: BigInt(pairState.reserves0), @@ -803,7 +805,7 @@ export class Smardex tokenIn: from.address, tokenOut: to.address, exchange: pair.exchange, - feesLP: 700n, + feesLp: 700n, feesPool: 200n, }; } diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index 8a5bcddd6..b470c6714 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -44,8 +44,8 @@ export type SmardexParam = SellOnSmardexParam | BuyOnSmardexParam; export type DexParams = UniswapV2DexParams; export interface SmardexPoolOrderedParams { - from: string; - to: string; + fromToken: string; + toToken: string; token0: string; token1: string; reserves0: bigint; @@ -59,7 +59,7 @@ export interface SmardexPoolOrderedParams { tokenIn: string; tokenOut: string; exchange: string; - feesLP: bigint; + feesLp: bigint; feesPool: bigint; } From d46c88d36519b563f02f28b6125bd8a2c5ff62ec Mon Sep 17 00:00:00 2001 From: julien Date: Fri, 8 Sep 2023 16:29:44 +0200 Subject: [PATCH 239/833] fix: rm useless --- src/dex/smardex/sdk/core.ts | 5 +- src/dex/smardex/smardex.ts | 31 --------- src/dex/smardex/types.ts | 12 ++-- src/dex/smardex/utils.ts | 126 ------------------------------------ 4 files changed, 8 insertions(+), 166 deletions(-) delete mode 100644 src/dex/smardex/utils.ts diff --git a/src/dex/smardex/sdk/core.ts b/src/dex/smardex/sdk/core.ts index 1cfef637a..2bffdb67c 100644 --- a/src/dex/smardex/sdk/core.ts +++ b/src/dex/smardex/sdk/core.ts @@ -1,8 +1,7 @@ -import { parseEther, parseUnits } from 'ethers/lib/utils'; -import { FEES_BASE, LATENCY_OFFSET_SECONDS, TradeType } from './constants'; +import { FEES_BASE, LATENCY_OFFSET_SECONDS } from './constants'; import { ratioApproxEq, sqrt } from './utils'; import SmardexError from './errors'; -import type { BestTradeOptions, CurrencyAmount, Pair, Trade } from './types'; +import type { CurrencyAmount, Pair } from './types'; // compute first trade amountIn using arbitrage feature function computeFirstTradeQtyIn( diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 20f9c3319..d4b75d20f 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -725,37 +725,6 @@ export class Smardex data.deadline, ]; - // case UniswapV2Functions.swapOnUniswapFork: - // case UniswapV2Functions.buyOnUniswapFork: - // return [ - // data.factory, - // prependWithOx(data.initCode), - // srcAmount, - // destAmount, - // path, - // ]; - - // case UniswapV2Functions.swapOnUniswapV2Fork: - // case UniswapV2Functions.buyOnUniswapV2Fork: - // return [ - // srcToken, - // srcAmount, - // destAmount, - // this.getWETHAddress(srcToken, destToken, _data.wethAddress), - // encodePools(_data.pools, this.feeFactor), - // ]; - - // case UniswapV2Functions.swapOnUniswapV2ForkWithPermit: - // case UniswapV2Functions.buyOnUniswapV2ForkWithPermit: - // return [ - // srcToken, - // srcAmount, - // destAmount, - // this.getWETHAddress(srcToken, destToken, _data.wethAddress), - // encodePools(_data.pools, this.feeFactor), - // permit, - // ]; - default: throw new Error(`contractMethod=${contractMethod} is not supported`); } diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index b470c6714..7e3c28b3a 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -15,10 +15,13 @@ export interface SmardexPoolState { priceAverage0: string; priceAverage1: string; priceAverageLastTimestamp: number; - feeCode: number; + feesLp: number; + feesPool: number; } -export interface SmardexData extends Omit { +// export interface SmardexData extends Omit { +export interface SmardexData extends UniswapV2Data { + deadline: number; receiver: Address; } @@ -41,7 +44,7 @@ export type BuyOnSmardexParam = [ export type SmardexParam = SellOnSmardexParam | BuyOnSmardexParam; -export type DexParams = UniswapV2DexParams; +export type DexParams = Omit; export interface SmardexPoolOrderedParams { fromToken: string; @@ -55,9 +58,6 @@ export interface SmardexPoolOrderedParams { priceAverage0: bigint; priceAverage1: bigint; priceAverageLastTimestamp: number; - fee: string; - tokenIn: string; - tokenOut: string; exchange: string; feesLp: bigint; feesPool: bigint; diff --git a/src/dex/smardex/utils.ts b/src/dex/smardex/utils.ts deleted file mode 100644 index 0eb8c6d2b..000000000 --- a/src/dex/smardex/utils.ts +++ /dev/null @@ -1,126 +0,0 @@ -// Constants to compute approximate equality -const APPROX_EQ_PRECISION = 1n; -const APPROX_EQ_BASE_PRECISION = 1000000n; - -/** - * Computes logarithm in base 2 for a given positive number. - * Result is rounded down. - * - * @param {bigint} value - value to compute the log2 - * @returns {bigint} the log in base 2 of the value, 0 if given 0. - */ -/* eslint-disable no-param-reassign */ -export function log2(value: bigint): bigint { - let result = 0n; - - if (value >> 128n > 0n) { - value >>= 128n; - result += 128n; - } - - if (value >> 64n > 0n) { - value >>= 64n; - result += 64n; - } - - if (value >> 32n > 0n) { - value >>= 32n; - result += 32n; - } - - if (value >> 16n > 0n) { - value >>= 16n; - result += 16n; - } - - if (value >> 8n > 0n) { - value >>= 8n; - result += 8n; - } - - if (value >> 4n > 0n) { - value >>= 4n; - result += 4n; - } - - if (value >> 2n > 0n) { - value >>= 2n; - result += 2n; - } - - if (value >> 1n > 0n) { - result += 1n; - } - - return result; -} - -/** - * Computes the square root of a number. If the number is not a perfect square, the value is rounded down. - * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). - * - * @param {bigint} value - value to compute the square root - * @returns {bigint} the square root of the value - */ -export function sqrt(value: bigint): bigint { - if (value === 0n) { - return 0n; - } - - // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. - // - // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have - // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. - // - // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` - // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` - // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` - // - // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. - let result = 1n << (log2(value) / 2n); - - // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, - // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at - // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision - // into the expected uint128 result. - result = (result + value / result) >> 1n; - result = (result + value / result) >> 1n; - result = (result + value / result) >> 1n; - result = (result + value / result) >> 1n; - result = (result + value / result) >> 1n; - result = (result + value / result) >> 1n; - result = (result + value / result) >> 1n; - - return result < value / result ? result : value / result; -} - -/** - * Evaluates the equality of two numbers at a precision of 1/1_000_000 - * - * @param {bigint} x - value to compare - * @param {bigint} y - value to compare - * @returns {boolean} true if numbers are approximatively equal at 1/1_000_000, false otherwise - */ -export function approxEq(x: bigint, y: bigint): true | false { - return x > y - ? x < y + (y * APPROX_EQ_PRECISION) / APPROX_EQ_BASE_PRECISION - : y < x + (x * APPROX_EQ_PRECISION) / APPROX_EQ_BASE_PRECISION; -} - -/** - * Evaluates the equality of two ratio numbers at a precision of 1/1_000_000. xNum / xDen ~= yNum / yDen - * - * @param {bigint} _xNum - first number numerator - * @param {bigint} _xDen - first number denominator - * @param {bigint} _yNum - second number numerator - * @param {bigint} _yDen - second number denominator - * @returns {boolean} true if the two ratios are approximatively equal at 1/1_000_000, false otherwise - */ -export function ratioApproxEq( - _xNum: bigint, - _xDen: bigint, - _yNum: bigint, - _yDen: bigint, -): true | false { - return approxEq(_xNum * _yDen, _xDen * _yNum); -} From 50c35c7e93731da8216034a5b25b1b421a921cc4 Mon Sep 17 00:00:00 2001 From: fireboss777 Date: Fri, 8 Sep 2023 16:42:37 +0200 Subject: [PATCH 240/833] fix: buy tests --- src/dex/smardex/smardex-e2e.test.ts | 16 ++++++++-------- src/dex/smardex/smardex.ts | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index f3c31d3ff..316e0412a 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -86,7 +86,7 @@ describe('Smardex E2E Mainnet', () => { '300000000000000000000000', // 300K SDEX SwapSide.BUY, // exact input dexKey, - ContractMethod.simpleSwap, + ContractMethod.simpleBuy, network, provider, ); @@ -97,10 +97,10 @@ describe('Smardex E2E Mainnet', () => { tokens.SDEX, tokens.WETH, holders.SDEX, - '2000000000000000000', // 2 ETH + '2000000000000000000', SwapSide.BUY, // exact input dexKey, - ContractMethod.simpleSwap, + ContractMethod.simpleBuy, network, provider, ); @@ -111,24 +111,24 @@ describe('Smardex E2E Mainnet', () => { tokens.USDT, tokens.SDEX, holders.USDT, - '30000000000000000000000', // 30K SDEX + '30000000000000000000000', SwapSide.BUY, // exact input dexKey, - ContractMethod.simpleSwap, + ContractMethod.simpleBuy, network, provider, ); }); - it.skip('SDEX -> USDT', async () => { + it('SDEX -> USDT', async () => { await testE2E( tokens.SDEX, tokens.USDT, holders.SDEX, - '1000000', // 200 USDT + '3000000000', // 3K USDT SwapSide.BUY, // exact input dexKey, - ContractMethod.simpleSwap, + ContractMethod.simpleBuy, network, provider, ); diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 20f9c3319..c51dc1dac 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -420,6 +420,7 @@ export class Smardex priceParams.feesPool, ).amount; + // uncomment to log rates // console.log("destAmount.", utils.formatEther(destAmount.toString())) // console.log("amountIn", utils.formatEther(amountIn.toString())) @@ -446,7 +447,7 @@ export class Smardex priceParams.feesPool, ).amount; - // uncomment to get rate + // uncomment to log rates // console.log("srcAmount.", utils.formatEther(srcAmount.toString())) // console.log("amountOut", utils.formatEther(amountOut.toString())) return BigInt(amountOut.toString()); From ac4dd6e40e17a391264b531d8f0797d8ae99b52b Mon Sep 17 00:00:00 2001 From: julien Date: Fri, 8 Sep 2023 17:34:44 +0200 Subject: [PATCH 241/833] fix: fees and fees default values --- src/dex/smardex/config.ts | 8 +-- src/dex/smardex/smardex.ts | 125 +++++++++++++++++++++++++++++-------- src/dex/smardex/types.ts | 5 +- 3 files changed, 104 insertions(+), 34 deletions(-) diff --git a/src/dex/smardex/config.ts b/src/dex/smardex/config.ts index 26a2dc997..35291c0da 100644 --- a/src/dex/smardex/config.ts +++ b/src/dex/smardex/config.ts @@ -15,28 +15,28 @@ export const SmardexConfig: DexConfigMap = { router: '0xEf2f9b48d7EC80440Ab4573dF1A2aBDBE06D3f60', initCode: mainnetInitHash, subgraphURL: `${gatewaySubgraph}/ethereum`, - feeCode: 0, + // feeCode: 0, // this is ignored as Smardex uses dynamic fees }, [Network.ARBITRUM]: { factoryAddress: '0x41A00e3FbE7F479A99bA6822704d9c5dEB611F22', router: '0xdd4536dD9636564D891c919416880a3e250f975A', initCode: layer2InitHash, subgraphURL: `${gatewaySubgraph}/arbitrum`, - feeCode: 0, + // feeCode: 0, // this is ignored as Smardex uses dynamic fees }, [Network.BSC]: { factoryAddress: '0xA8EF6FEa013034E62E2C4A9Ec1CDb059fE23Af33', router: '0x391BeCc8DAaf32b9ba8e602e9527Bf9DA04C8deb', initCode: layer2InitHash, subgraphURL: `${gatewaySubgraph}/bsc`, - feeCode: 0, + // feeCode: 0, // this is ignored as Smardex uses dynamic fees }, [Network.POLYGON]: { factoryAddress: '0x9A1e1681f6D59Ca051776410465AfAda6384398f', router: '0xA8EF6FEa013034E62E2C4A9Ec1CDb059fE23Af33', initCode: layer2InitHash, subgraphURL: `${gatewaySubgraph}/polygon`, - feeCode: 0, + // feeCode: 0, // this is ignored as Smardex uses dynamic fees }, }, }; diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 6f301cb10..4477f63c0 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -1,7 +1,7 @@ import { AbiCoder, Interface } from '@ethersproject/abi'; import { BigNumber, utils } from 'ethers'; import _ from 'lodash'; -import { DeepReadonly, AsyncOrSync } from 'ts-essentials'; +import { DeepReadonly } from 'ts-essentials'; import { Contract } from 'web3-eth-contract'; import { DEST_TOKEN_PARASWAP_TRANSFERS, @@ -89,14 +89,52 @@ export class SmardexEventPool extends StatefulEventSubscriber ); } - protected processLog( + async fetchPairFeesAndLastTimestamp(blockNumber: number): Promise<{ + feesLp: number; + feesPool: number; + priceAverageLastTimestamp: number; + }> { + const dynamicFees = !!this.smardexFeesMultiCallEntry; + let calldata = [ + { + target: this.poolAddress, + callData: this.poolInterface.encodeFunctionData('getPriceAverage', []), + }, + ]; + if (dynamicFees) { + calldata.push(this.smardexFeesMultiCallEntry!); + } + + const data: { returnData: any[] } = + await this.dexHelper.multiContract.methods + .aggregate(calldata) + .call({}, blockNumber); + + const priceAverageLastTimestamp = coder.decode(['uint256', 'uint256', 'uint256'], data.returnData[0])[2]; + + return { + feesLp: dynamicFees + ? this.smardexFeesMulticallDecoder!(data.returnData[1][0]) + : 500, + feesPool: dynamicFees + ? this.smardexFeesMulticallDecoder!(data.returnData[1][1]) + : 200, + priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), + }; + } + + // This methode overrides previous state with new state. + // Problem: Smardex Pair state is updated partially on different events + // This is why we must fetch pair's missing state in Events + protected async processLog( state: DeepReadonly, log: Readonly, - ): AsyncOrSync | null> { + ): Promise | null> { if (!Object.values(TOPICS).includes(log.topics[0] as TOPICS)) return null; const event = smardexPoolL1.parseLog(log); switch (event.name) { case 'Sync': + const fetchedSync = await this.fetchPairFeesAndLastTimestamp(log.blockNumber); return { reserves0: event.args.reserve0.toString(), reserves1: event.args.reserve1.toString(), @@ -104,9 +142,35 @@ export class SmardexEventPool extends StatefulEventSubscriber fictiveReserves1: event.args.fictiveReserve1.toString(), priceAverage0: event.args.priceAverage0.toString(), priceAverage1: event.args.priceAverage1.toString(), - priceAverageLastTimestamp: state.priceAverageLastTimestamp, // TODO should be updated but only on Swap event - feeCode: state.feeCode, + priceAverageLastTimestamp: fetchedSync.priceAverageLastTimestamp, + feesLp: fetchedSync.feesLp, + feesPool: fetchedSync.feesPool, + }; + case 'FeesChanged': // only triggerd on L2 + return { + reserves0: state.reserves0, + reserves1: state.reserves1, + fictiveReserves0: state.fictiveReserves0, + fictiveReserves1: state.fictiveReserves1, + priceAverage0: state.priceAverage0, + priceAverage1: state.priceAverage1, + priceAverageLastTimestamp: state.priceAverageLastTimestamp, + feesLp: event.args.feesLp.toNumber(), + feesPool: event.args.feesPool.toNumber(), }; + // case 'Swap': + // const fetchedSwap = await this.fetchPairFeesAndLastTimestamp(log.blockNumber); + // return { + // reserves0: state.reserves0, + // reserves1: state.reserves1, + // fictiveReserves0: state.fictiveReserves0, + // fictiveReserves1: state.fictiveReserves1, + // priceAverage0: state.priceAverage0, + // priceAverage1: state.priceAverage1, + // priceAverageLastTimestamp: fetchedSwap.priceAverageLastTimestamp, + // feesLp: fetchedSwap.feesLp, + // feesPool: fetchedSwap.feesPool, + // }; } return null; } @@ -163,20 +227,23 @@ export class SmardexEventPool extends StatefulEventSubscriber priceAverage0: priceAverage0.toString(), priceAverage1: priceAverage1.toString(), priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), - feeCode: dynamicFees - ? this.smardexFeesMulticallDecoder!(data.returnData[3]) - : 700, // TODO: Ensure the fees are correct + feesLp: dynamicFees + ? this.smardexFeesMulticallDecoder!(data.returnData[3][0]) + : 500, + feesPool: dynamicFees + ? this.smardexFeesMulticallDecoder!(data.returnData[3][1]) + : 200, }; } } function encodePools( pools: SmardexPool[], - feeFactor: number, + // feeFactor: number, ): NumberAsString[] { return pools.map(({ fee, direction, address }) => { return ( - (BigInt(feeFactor - fee) << 161n) + + (BigInt(fee) << 161n) + ((direction ? 0n : 1n) << 160n) + BigInt(address) ).toString(); @@ -188,7 +255,7 @@ export class Smardex implements IDex { pairs: { [key: string]: SmardexPair } = {}; - feeFactor = 10000; + // feeFactor = 10000; factory: Contract; routerInterface: Interface; @@ -306,7 +373,7 @@ export class Smardex const unitAmount = getBigIntPow(isSell ? from.decimals : to.decimals); - // TODO SMARDEX does not support FoT + // TODO SMARDEX does not support Fees on Transfer Tokens const [unitVolumeWithFee, ...amountsWithFee] = applyTransferFee( [unitAmount, ...amounts], side, @@ -352,6 +419,7 @@ export class Smardex path: [from.address.toLowerCase(), to.address.toLowerCase()], factory: this.factoryAddress, initCode: this.initCode, + // feeFactor: this.feeFactor, pools: [ { address: pairParam.exchange, @@ -528,7 +596,8 @@ export class Smardex pairState.fictiveReserves1, pairState.priceAverage0, pairState.priceAverage1, - pairState.feeCode, + pairState.feesLp, + pairState.feesPool, blockNumber, pairState.priceAverageLastTimestamp, ); @@ -547,7 +616,7 @@ export class Smardex }; const callDecoder = (values: any[]) => parseInt( - smardexPoolL2.decodeFunctionResult('getPairFees', values)[0].toString(), + smardexPoolL2.decodeFunctionResult('getPairFees', values).toString(), ); return { @@ -564,7 +633,8 @@ export class Smardex fictiveReserves1: string, priceAverage0: string, priceAverage1: string, - feeCode: number, + feesLp: number, + feesPool: number, blockNumber: number, priceAverageLastTimestamp: number, ) { @@ -590,7 +660,8 @@ export class Smardex fictiveReserves1, priceAverage0, priceAverage1, - feeCode, + feesLp, + feesPool, priceAverageLastTimestamp, }, }); @@ -654,9 +725,12 @@ export class Smardex priceAverageLastTimestamp: coder .decode(['uint256', 'uint256', 'uint256'], returnData[i][2])[2] .toString(), - feeCode: this.isLayer1() - ? 700 - : multiCallFeeData[i]!.callDecoder(returnData[i][3]), + feesLp: this.isLayer1() + ? 500 + : multiCallFeeData[i]!.callDecoder(returnData[i][3][0]), + feesPool: this.isLayer1() + ? 200 + : multiCallFeeData[i]!.callDecoder(returnData[i][3][1]), })); } catch (e) { this.logger.error( @@ -757,7 +831,7 @@ export class Smardex ); return null; } - const fee = (pairState.feeCode + tokenDexTransferFee).toString(); + // const fee = (pairState.feesPool + tokenDexTransferFee).toString(); return { fromToken: from.address, @@ -771,12 +845,9 @@ export class Smardex priceAverage0: BigInt(pairState.priceAverage0), priceAverage1: BigInt(pairState.priceAverage1), priceAverageLastTimestamp: pairState.priceAverageLastTimestamp, - fee, - tokenIn: from.address, - tokenOut: to.address, exchange: pair.exchange, - feesLp: 700n, - feesPool: 200n, + feesLp: BigInt(pairState.feesLp), + feesPool: BigInt(pairState.feesPool), }; } @@ -791,7 +862,7 @@ export class Smardex data: SmardexData, side: SwapSide, ): AdapterExchangeParam { - const pools = encodePools(data.pools, this.feeFactor); + const pools = encodePools(data.pools); const weth = this.getWETHAddress(srcToken, destToken, data.wethAddress); const payload = this.abiCoder.encodeParameter( { @@ -823,7 +894,7 @@ export class Smardex data: SmardexData, side: SwapSide, ): Promise { - const pools = encodePools(data.pools, this.feeFactor); + const pools = encodePools(data.pools); const weth = this.getWETHAddress(src, dest, data.wethAddress); let routerMethod: any; diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index 7e3c28b3a..c1a11b750 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -19,9 +19,8 @@ export interface SmardexPoolState { feesPool: number; } -// export interface SmardexData extends Omit { -export interface SmardexData extends UniswapV2Data { - +// export interface SmardexData extends UniswapV2Data { +export interface SmardexData extends Omit { deadline: number; receiver: Address; } From 61b4213f2ad490684ba6bad88098ae4ea7ec318d Mon Sep 17 00:00:00 2001 From: julien Date: Fri, 8 Sep 2023 17:57:12 +0200 Subject: [PATCH 242/833] fix: events test --> PASSING !!! --- src/dex/smardex/smardex-events.test.ts | 59 +++++++++++--------------- src/dex/smardex/smardex.ts | 17 +++++--- 2 files changed, 36 insertions(+), 40 deletions(-) diff --git a/src/dex/smardex/smardex-events.test.ts b/src/dex/smardex/smardex-events.test.ts index 9ed98a128..52e625de0 100644 --- a/src/dex/smardex/smardex-events.test.ts +++ b/src/dex/smardex/smardex-events.test.ts @@ -8,12 +8,8 @@ import SmardexPoolLayerOneABI from '../../abi/smardex/layer-1/smardex-pool.json' import { SmardexEventPool } from './smardex'; import { Network } from '../../constants'; import { DummyDexHelper } from '../../dex-helper/index'; -import { - testEventSubscriber, -} from '../../../tests/utils-events'; -import { - SmardexPoolState, -} from './types'; +import { testEventSubscriber } from '../../../tests/utils-events'; +import { SmardexPoolState } from './types'; jest.setTimeout(120 * 1000); const dexKey = 'Smardex'; @@ -37,42 +33,37 @@ async function fetchPoolStateFromContractAtBlock( describe('Smardex Ethereum SDEX-USDT Pool Event', function () { const poolAddress = '0xd2bf378cea07fe117ffdfd3f5b7e53c2b0b78c05'; // sdex-usdt - const token0 = { address: '0x5de8ab7e27f6e7a1fff3e5b337584aa43961beef', decimals: 18 }; - const token1 = { address: '0xdac17f958d2ee523a2206206994597c13d831ec7', decimals: 6 }; + const token0 = { + address: '0x5de8ab7e27f6e7a1fff3e5b337584aa43961beef', + decimals: 18, + }; + const token1 = { + address: '0xdac17f958d2ee523a2206206994597c13d831ec7', + decimals: 6, + }; const blockNumbers: { [eventName: string]: number[] } = { ['Swap']: [ 18064045, - // 18064060, - // 18064194, - // 18065266, - // 18066464, // the last one contains multiple Swap events + 18064060, + 18064194, + 18065266, + 18066464, // the last one contains multiple Swap events ], - // ['Burn']: [ - // 17231921, - // 17762042, - // 17762668, - // ], - // ['Mint']: [ - // 17739609, - // 17973926, - // 18062443, - // ], - ['SetFeeProtocol']: [], + ['Burn']: [17231921, 17762042, 17762668], + ['Mint']: [17739609, 17973926, 18062443], + // ['FeesChanged']: [], // none on L1 ['Sync']: [ 18064045, - // 18064060, - // 18064194, - // 18065266, - // 18066464, // the last one contains multiple Snyc events - ], - ['Transfer']: [ - 18064025, - 18064045, - // 18065266, + 18064060, + 18064194, + 18065266, + 18066464, // the last one contains multiple Snyc events ], + ['Transfer']: [18064025, 18064045, 18065266], }; + // events in the same block must update the same element describe('SmardexEventPool ethereum', function () { Object.keys(blockNumbers).forEach((event: string) => { blockNumbers[event].forEach((blockNumber: number) => { @@ -93,8 +84,8 @@ describe('Smardex Ethereum SDEX-USDT Pool Event', function () { ); // It is done in generateState. But here have to make it manually - // SmardexPool.poolAddress = poolAddress.toLowerCase(); - // SmardexPool.addressesSubscribed[0] = poolAddress.toLowerCase(); + SmardexPool.poolAddress = poolAddress.toLowerCase(); + SmardexPool.addressesSubscribed[0] = poolAddress.toLowerCase(); await testEventSubscriber( SmardexPool, diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 4477f63c0..0bc1d5380 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -68,7 +68,7 @@ export class SmardexEventPool extends StatefulEventSubscriber constructor( protected poolInterface: Interface, protected dexHelper: IDexHelper, - private poolAddress: Address, + public poolAddress: Address, token0: Token, token1: Token, logger: Logger, @@ -106,11 +106,14 @@ export class SmardexEventPool extends StatefulEventSubscriber } const data: { returnData: any[] } = - await this.dexHelper.multiContract.methods - .aggregate(calldata) - .call({}, blockNumber); + await this.dexHelper.multiContract.methods + .aggregate(calldata) + .call({}, blockNumber); - const priceAverageLastTimestamp = coder.decode(['uint256', 'uint256', 'uint256'], data.returnData[0])[2]; + const priceAverageLastTimestamp = coder.decode( + ['uint256', 'uint256', 'uint256'], + data.returnData[0], + )[2]; return { feesLp: dynamicFees @@ -134,7 +137,9 @@ export class SmardexEventPool extends StatefulEventSubscriber const event = smardexPoolL1.parseLog(log); switch (event.name) { case 'Sync': - const fetchedSync = await this.fetchPairFeesAndLastTimestamp(log.blockNumber); + const fetchedSync = await this.fetchPairFeesAndLastTimestamp( + log.blockNumber, + ); return { reserves0: event.args.reserve0.toString(), reserves1: event.args.reserve1.toString(), From 22b98eab7a54c8059b79a28f7731608dec1c13fe Mon Sep 17 00:00:00 2001 From: fireboss777 Date: Fri, 8 Sep 2023 18:39:21 +0200 Subject: [PATCH 243/833] fix: ETH buy sell --- src/dex/smardex/smardex-e2e.test.ts | 55 +++++++++++++++++++++++++++++ src/dex/smardex/smardex.ts | 22 +++++------- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index 316e0412a..5b0717b53 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -20,6 +20,33 @@ describe('Smardex E2E Mainnet', () => { describe('Simpleswap', () => { describe('SELL', () => { + it('ETH -> SDEX', async () => { + await testE2E( + tokens.ETH, + tokens.SDEX, + holders.ETH, + '2000000000000000000', // 2 WETH + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('SDEX -> ETH', async () => { + await testE2E( + tokens.SDEX, + tokens.ETH, + holders.SDEX, + '300000000000000000000000', // 300K SDEX + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); it('WETH -> SDEX', async () => { await testE2E( tokens.WETH, @@ -78,6 +105,34 @@ describe('Smardex E2E Mainnet', () => { }); describe('BUY', () => { + it('ETH -> SDEX', async () => { + await testE2E( + tokens.ETH, + tokens.SDEX, + holders.ETH, + '300000000000000000000000', // 300K SDEX + SwapSide.BUY, // exact input + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + + it('SDEX -> ETH', async () => { + await testE2E( + tokens.SDEX, + tokens.ETH, + holders.SDEX, + '2000000000000000000', // 2 WETH + SwapSide.BUY, // exact input + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + it('WETH -> SDEX', async () => { await testE2E( tokens.WETH, diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 0bc1d5380..55edfbae2 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -911,13 +911,10 @@ export class Smardex routerMethod = isETHAddress(dest) ? SmardexRouterFunctions.sellExactToken : routerMethod; - routerArgs = [ - srcAmount, - destAmount, - data.path, - data.receiver, - data.deadline, - ]; + + routerArgs = isETHAddress(src) + ? [destAmount, data.path, data.receiver, data.deadline] + : [srcAmount, destAmount, data.path, data.receiver, data.deadline]; } else { routerMethod = isETHAddress(src) ? SmardexRouterFunctions.buyExactToken @@ -925,13 +922,10 @@ export class Smardex routerMethod = isETHAddress(dest) ? SmardexRouterFunctions.buyExactEth : routerMethod; - routerArgs = [ - destAmount, - srcAmount, - data.path, - data.receiver, - data.deadline, - ]; + + routerArgs = isETHAddress(src) + ? [destAmount, data.path, data.receiver, data.deadline] + : [destAmount, srcAmount, data.path, data.receiver, data.deadline]; } const swapData = this.exchangeRouterInterface.encodeFunctionData( From 45bb025394b05f855ba4f2e7ae272958390923d3 Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Fri, 8 Sep 2023 19:59:50 +0300 Subject: [PATCH 244/833] feat(BACK-1264): implement tests for UniswapV3 Base integration --- src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 95 +++++++++++++++++++++++ tests/constants-e2e.ts | 17 ++++ 2 files changed, 112 insertions(+) diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index 4d097abc7..af9829d9f 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -403,6 +403,101 @@ describe('UniswapV3 E2E', () => { ); }); + describe('UniswapV3 Base', () => { + const network = Network.BASE; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'PRIME'; + const tokenBSymbol: string = 'WETH'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '1000000000000000000'; + const tokenBAmount: string = '1000000000000000000'; + const nativeTokenAmount = '1000000000000000000'; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + // ContractMethod.simpleSwap, + ContractMethod.multiSwap, + // ContractMethod.megaSwap, + ], + ], + [ + SwapSide.BUY, + [ + // ContractMethod.simpleBuy, + // ContractMethod.buy + ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenBSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[tokenBSymbol], + tokens[tokenASymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenBAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); + describe('UniswapV3 Avalanche', () => { const network = Network.AVALANCHE; const tokens = Tokens[network]; diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index fc6584a09..069890872 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -883,6 +883,17 @@ export const Tokens: { decimals: 6, }, }, + [Network.BASE]: { + PRIME: { + address: '0xfA980cEd6895AC314E7dE34Ef1bFAE90a5AdD21b', + decimals: 18, + }, + WETH: { + address: '0x4200000000000000000000000000000000000006', + decimals: 18, + }, + ETH: { address: ETHER_ADDRESS, decimals: 18 }, + }, }; export const Holders: { @@ -1102,6 +1113,11 @@ export const Holders: { WBTC: '0x99b31498b0a1dae01fc3433e3cb60f095340935c', USDC: '0x99b31498b0a1dae01fc3433e3cb60f095340935c', }, + [Network.BASE]: { + WETH: '0x4bb6b2efe7036020ba6f02a05602546c9f25bf28', + PRIME: '0x956bcc6b56c99db382d9d97a30ba5f1402144b3e', + ETH: '0xdd9176ea3e7559d6b68b537ef555d3e89403f742', + }, }; export const SmartTokens = Object.keys(Tokens).reduce((acc, _network) => { @@ -1126,4 +1142,5 @@ export const NativeTokenSymbols: { [network: number]: string } = { [Network.FANTOM]: 'FTM', [Network.ARBITRUM]: 'ETH', [Network.OPTIMISM]: 'ETH', + [Network.BASE]: 'ETH', }; From ba07e11b7495c78743a06ca4002f53d8951fbd3d Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Fri, 8 Sep 2023 20:01:11 +0300 Subject: [PATCH 245/833] 2.35.2-base-support.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 391dce2b8..3d23408cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.1", + "version": "2.35.2-base-support.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e6e5a357f7809d14f1822305fc54f2ab176084b5 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 8 Sep 2023 21:51:12 +0200 Subject: [PATCH 246/833] override non exisiting pool by dex - cmaelotV3 --- src/dex/algebra/algebra.ts | 7 +++++-- src/dex/algebra/config.ts | 1 + src/dex/algebra/types.ts | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 5ea37f7b4..30f16f34f 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -126,10 +126,13 @@ export class Algebra extends SimpleExchange implements IDex { } async initializePricing(blockNumber: number) { + const cleanNonExistingPoolTTLMs = + this.config.cleanExistingPoolTTLMs || + ALGEBRA_CLEAN_NOT_EXISTING_POOL_TTL_MS; + if (!this.dexHelper.config.isSlave) { const cleanExpiredNotExistingPoolsKeys = async () => { - const maxTimestamp = - Date.now() - ALGEBRA_CLEAN_NOT_EXISTING_POOL_TTL_MS; + const maxTimestamp = Date.now() - cleanNonExistingPoolTTLMs; await this.dexHelper.cache.zremrangebyscore( this.notExistingPoolSetKey, 0, diff --git a/src/dex/algebra/config.ts b/src/dex/algebra/config.ts index 5809d2037..daa761097 100644 --- a/src/dex/algebra/config.ts +++ b/src/dex/algebra/config.ts @@ -83,6 +83,7 @@ export const AlgebraConfig: DexConfigMap = { uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', deployer: '0x6dd3fb9653b10e806650f107c3b5a0a6ff974f65', version: 'v1.9', + cleanExistingPoolTTLMs: 20 * 60 * 1000, }, }, }; diff --git a/src/dex/algebra/types.ts b/src/dex/algebra/types.ts index 891983100..27ca978e1 100644 --- a/src/dex/algebra/types.ts +++ b/src/dex/algebra/types.ts @@ -73,6 +73,7 @@ export type DexParams = { version: 'v1.1' | 'v1.9'; forceRPC?: boolean; forceManualStateGenerate?: boolean; + cleanExistingPoolTTLMs?: number; }; export type IAlgebraPoolState = PoolStateV1_1 | PoolState_v1_9; From 16c16b35e7ae0342b132ac50fadbe834c5ff0050 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 8 Sep 2023 21:53:05 +0200 Subject: [PATCH 247/833] 2.35.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 391dce2b8..55739ce6e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.1", + "version": "2.35.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 988841b530cdb40c4771f9b6016b49153bd36a28 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 9 Sep 2023 14:17:26 +0200 Subject: [PATCH 248/833] Revert "override non exisiting pool by dex - cmaelotV3" This reverts commit e6e5a357f7809d14f1822305fc54f2ab176084b5. --- src/dex/algebra/algebra.ts | 7 ++----- src/dex/algebra/config.ts | 1 - src/dex/algebra/types.ts | 1 - 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 30f16f34f..5ea37f7b4 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -126,13 +126,10 @@ export class Algebra extends SimpleExchange implements IDex { } async initializePricing(blockNumber: number) { - const cleanNonExistingPoolTTLMs = - this.config.cleanExistingPoolTTLMs || - ALGEBRA_CLEAN_NOT_EXISTING_POOL_TTL_MS; - if (!this.dexHelper.config.isSlave) { const cleanExpiredNotExistingPoolsKeys = async () => { - const maxTimestamp = Date.now() - cleanNonExistingPoolTTLMs; + const maxTimestamp = + Date.now() - ALGEBRA_CLEAN_NOT_EXISTING_POOL_TTL_MS; await this.dexHelper.cache.zremrangebyscore( this.notExistingPoolSetKey, 0, diff --git a/src/dex/algebra/config.ts b/src/dex/algebra/config.ts index daa761097..5809d2037 100644 --- a/src/dex/algebra/config.ts +++ b/src/dex/algebra/config.ts @@ -83,7 +83,6 @@ export const AlgebraConfig: DexConfigMap = { uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', deployer: '0x6dd3fb9653b10e806650f107c3b5a0a6ff974f65', version: 'v1.9', - cleanExistingPoolTTLMs: 20 * 60 * 1000, }, }, }; diff --git a/src/dex/algebra/types.ts b/src/dex/algebra/types.ts index 27ca978e1..891983100 100644 --- a/src/dex/algebra/types.ts +++ b/src/dex/algebra/types.ts @@ -73,7 +73,6 @@ export type DexParams = { version: 'v1.1' | 'v1.9'; forceRPC?: boolean; forceManualStateGenerate?: boolean; - cleanExistingPoolTTLMs?: number; }; export type IAlgebraPoolState = PoolStateV1_1 | PoolState_v1_9; From 918f11ce06093f944f7276a6af23f59d0e02618c Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 9 Sep 2023 15:00:47 +0200 Subject: [PATCH 249/833] expose zrem for mark pools as existing flow --- src/dex-helper/dummy-dex-helper.ts | 4 ++ src/dex-helper/icache.ts | 2 + src/dex/algebra/algebra-factory.ts | 65 ++++++++++++++++++++++++++++++ src/dex/algebra/algebra.ts | 35 +++++++++++++++- 4 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 src/dex/algebra/algebra-factory.ts diff --git a/src/dex-helper/dummy-dex-helper.ts b/src/dex-helper/dummy-dex-helper.ts index 69be935b8..c805c5556 100644 --- a/src/dex-helper/dummy-dex-helper.ts +++ b/src/dex-helper/dummy-dex-helper.ts @@ -112,6 +112,10 @@ class DummyCache implements ICache { return 0; } + async zrem(key: string, membersKeys: string[]): Promise { + return 0; + } + async zadd(key: string, bulkItemsToAdd: (number | string)[], option?: 'NX') { return 0; } diff --git a/src/dex-helper/icache.ts b/src/dex-helper/icache.ts index edaa1536d..4aa725ee6 100644 --- a/src/dex-helper/icache.ts +++ b/src/dex-helper/icache.ts @@ -46,6 +46,8 @@ export interface ICache { zremrangebyscore(key: string, min: number, max: number): Promise; + zrem(key: string, membersKeys: string[]): Promise; + zscore(setKey: string, key: string): Promise; sismember(setKey: string, key: string): Promise; diff --git a/src/dex/algebra/algebra-factory.ts b/src/dex/algebra/algebra-factory.ts new file mode 100644 index 000000000..328936431 --- /dev/null +++ b/src/dex/algebra/algebra-factory.ts @@ -0,0 +1,65 @@ +import { Interface } from '@ethersproject/abi'; +import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; +import FactoryABI from '../../abi/algebra/AlgebraFactory-v1_1.abi.json'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { Address, Log, Logger } from '../../types'; + +export type OnPoolCreatedCallback = ({ + token0, + token1, +}: { + token0: string; + token1: string; +}) => AsyncOrSync; + +/* + * Stateless event subscriber in order to capture "Pool" event on new pools created. + */ +export class AlgebraFactory extends StatefulEventSubscriber { + handlers: { + [event: string]: (event: any) => DeepReadonly | null; + } = {}; + + logDecoder: (log: Log) => any; + + public readonly factoryIface = new Interface(FactoryABI); + + constructor( + readonly dexHelper: IDexHelper, + parentName: string, + protected readonly factoryAddress: Address, + logger: Logger, + protected readonly onPoolCreated: OnPoolCreatedCallback, + mapKey: string = '', + ) { + super(parentName, `factory`, dexHelper, logger, true, mapKey); + + this.addressesSubscribed = [factoryAddress]; + + this.logDecoder = (log: Log) => this.factoryIface.parseLog(log); + + this.handlers['Pool'] = this.handleNewPool.bind(this); + } + + generateState(): AsyncOrSync {} + + protected processLog( + _: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + const event = this.logDecoder(log); + if (event.name in this.handlers) { + this.handlers[event.name](event); + } + + return null; + } + + handleNewPool(event: any) { + const token0 = event.args.token0; + const token1 = event.args.token1; + + this.onPoolCreated({ token0, token1 }); + } +} diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 5ea37f7b4..69de19639 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -38,14 +38,15 @@ import { import { AlgebraMath } from './lib/AlgebraMath'; import { AlgebraEventPoolV1_1 } from './algebra-pool-v1_1'; import { AlgebraEventPoolV1_9 } from './algebra-pool-v1_9'; +import { AlgebraFactory, OnPoolCreatedCallback } from './algebra-factory'; type PoolPairsInfo = { token0: Address; token1: Address; }; -const ALGEBRA_CLEAN_NOT_EXISTING_POOL_TTL_MS = 3 * 60 * 60 * 1000; // 3 hours -const ALGEBRA_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 30 * 60 * 1000; // Once in 30 minutes +const ALGEBRA_CLEAN_NOT_EXISTING_POOL_TTL_MS = 3 * 24 * 60 * 60 * 1000; // 3 days +const ALGEBRA_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 24 * 60 * 60 * 1000; // Once in a day const ALGEBRA_EFFICIENCY_FACTOR = 3; const ALGEBRA_TICK_GAS_COST = 24_000; // Ceiled const ALGEBRA_TICK_BASE_OVERHEAD = 75_000; @@ -114,6 +115,14 @@ export class Algebra extends SimpleExchange implements IDex { this.AlgebraPoolImplem = config.version === 'v1.1' ? AlgebraEventPoolV1_1 : AlgebraEventPoolV1_9; + + new AlgebraFactory( + dexHelper, + dexKey, + this.config.factory, + this.logger, + this.onPoolCreatedDeleteFromNonExistingSet, + ); } getAdapters(side: SwapSide): { name: string; index: number }[] | null { @@ -144,6 +153,28 @@ export class Algebra extends SimpleExchange implements IDex { } } + /* + * When a non exisiting pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls + * Once the pool is created, it gets immediately flagged + */ + onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ + token0, + token1, + }) => { + const [_token0, _token1] = this._sortTokens(token0, token1); + const poolKey = `${token0}_${token1}`.toLowerCase(); + + // consider doing it only from master pool for less calls to distant cache + + try { + // delete pool record from set + await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); + } catch (e) {} + + // delete entry locally to let local instance discover the pool + delete this.eventPools[this.getPoolIdentifier(_token0, _token1)]; + }; + async getPool( srcAddress: Address, destAddress: Address, From 5da620b2494f0ea722b6e332abe4f5f5080dc0ce Mon Sep 17 00:00:00 2001 From: Verisana Date: Mon, 11 Sep 2023 12:41:50 +0100 Subject: [PATCH 250/833] feat: implement new proxy quering --- src/abi/api3-proxy.json | 7 +++ src/dex/quick-perps/pool.ts | 48 ++++++++++++++++--- .../quick-perps/quick-perps-events.test.ts | 1 - src/lib/api3-feed.ts | 35 ++++++++++++++ 4 files changed, 83 insertions(+), 8 deletions(-) diff --git a/src/abi/api3-proxy.json b/src/abi/api3-proxy.json index 41ce3c43e..ec343f133 100644 --- a/src/abi/api3-proxy.json +++ b/src/abi/api3-proxy.json @@ -42,5 +42,12 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [], + "name": "dapiNameHash", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" } ] diff --git a/src/dex/quick-perps/pool.ts b/src/dex/quick-perps/pool.ts index 8b922b236..022686655 100644 --- a/src/dex/quick-perps/pool.ts +++ b/src/dex/quick-perps/pool.ts @@ -283,7 +283,8 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { for (let priceFeed of priceFeeds) { const api3ServerAddressCallData = Api3FeedSubscriber.getApi3ServerV1MultiCallInput(priceFeed); - const dataFeedIdCallData = Api3FeedSubscriber.getDataFeedId(priceFeed); + const dataFeedIdCallData = + Api3FeedSubscriber.getDapiNameHashMultiCallInput(priceFeed); multiCallData.push(...[api3ServerAddressCallData, dataFeedIdCallData]); multicallSlices.push([i, i + 2]); i += 2; @@ -315,24 +316,31 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { await multiContract.methods.aggregate(multiCallData).call({}, blockNumber) ).returnData; - const api3ServerV1: { + const api3ServerV1Prep: { [address: string]: { proxy: Address; api3ServerV1: Address; - dataFeedId: string; }; } = {}; + const getFeedIdRequests: MultiCallInput[] = []; + for (let token of tokens) { - const [api3ServerAddressRes, dataFeedIdRes] = configResults.slice( + const [api3ServerAddressRes, dapiNameHashRes] = configResults.slice( ...multicallSlices.shift()!, ); const serverV1Address = Api3FeedSubscriber.decodeApi3ServerV1Result(api3ServerAddressRes); - const dataFeedId = Api3FeedSubscriber.decodeDataFeedId(dataFeedIdRes); - api3ServerV1[token] = { + const dapiNameHash = + Api3FeedSubscriber.decodeDapiNameHash(dapiNameHashRes); + getFeedIdRequests.push( + Api3FeedSubscriber.getFeedIdFromDapiNameHash( + serverV1Address, + dapiNameHash, + ), + ); + api3ServerV1Prep[token] = { proxy: priceFeeds.shift(), api3ServerV1: serverV1Address, - dataFeedId, }; } @@ -355,6 +363,32 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { const vaultConfigResults = configResults.slice(...multicallSlices.shift()!); const vaultConfig = Vault.getConfig(vaultConfigResults, tokens); + const feedIdResults = ( + await multiContract.methods + .aggregate(getFeedIdRequests) + .call({}, blockNumber) + ).returnData; + + const api3ServerV1: { + [address: string]: { + proxy: Address; + api3ServerV1: Address; + dataFeedId: string; + }; + } = {}; + for (let [i, token] of tokens.entries()) { + const { proxy, api3ServerV1: api3ServerAddress } = + api3ServerV1Prep[token]; + const dataFeedId = Api3FeedSubscriber.decodeFeedIdFromDapiNameHash( + feedIdResults[i], + ); + api3ServerV1[token] = { + proxy, + api3ServerV1: api3ServerAddress, + dataFeedId, + }; + } + return { vaultAddress: dexParams.vault, readerAddress: dexParams.reader, diff --git a/src/dex/quick-perps/quick-perps-events.test.ts b/src/dex/quick-perps/quick-perps-events.test.ts index f3d4999e2..16cf510aa 100644 --- a/src/dex/quick-perps/quick-perps-events.test.ts +++ b/src/dex/quick-perps/quick-perps-events.test.ts @@ -81,7 +81,6 @@ describe('QuickPerps Event', function () { dexKey, network, dexHelper, - logger, config, ); await testEventSubscriber( diff --git a/src/lib/api3-feed.ts b/src/lib/api3-feed.ts index 588204372..c0a7b90e8 100644 --- a/src/lib/api3-feed.ts +++ b/src/lib/api3-feed.ts @@ -51,6 +51,14 @@ export class Api3FeedSubscriber extends PartialEventSubscriber< }; } + static getDapiNameHashMultiCallInput(proxy: Address): MultiCallInput { + return { + target: proxy, + callData: + Api3FeedSubscriber.proxyInterface.encodeFunctionData('dapiNameHash'), + }; + } + static getDataFeedId(proxy: Address): MultiCallInput { return { target: proxy, @@ -59,6 +67,33 @@ export class Api3FeedSubscriber extends PartialEventSubscriber< }; } + static getFeedIdFromDapiNameHash( + api3Server: Address, + dapiNameHash: string, + ): MultiCallInput { + return { + target: api3Server, + callData: Api3FeedSubscriber.api3ServerV1Iface.encodeFunctionData( + 'dapiNameHashToDataFeedId', + [dapiNameHash], + ), + }; + } + + static decodeFeedIdFromDapiNameHash(multicallOutput: MultiCallOutput) { + return Api3FeedSubscriber.api3ServerV1Iface.decodeFunctionResult( + 'dapiNameHashToDataFeedId', + multicallOutput, + )[0]; + } + + static decodeDapiNameHash(multicallOutput: MultiCallOutput) { + return Api3FeedSubscriber.proxyInterface.decodeFunctionResult( + 'dapiNameHash', + multicallOutput, + )[0]; + } + static decodeDataFeedId(multicallOutput: MultiCallOutput) { return Api3FeedSubscriber.proxyInterface.decodeFunctionResult( 'dataFeedId', From 48b5bbf3adb83c2f78e39e0c896a418b630de887 Mon Sep 17 00:00:00 2001 From: julien Date: Mon, 11 Sep 2023 13:52:40 +0200 Subject: [PATCH 251/833] fix: e2e test consistency --- src/dex/smardex/smardex-e2e.test.ts | 333 ++++++++++++++++++++++++++-- 1 file changed, 309 insertions(+), 24 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index 5b0717b53..cb6c6bc69 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -19,13 +19,13 @@ describe('Smardex E2E Mainnet', () => { const dexKey = 'Smardex'; describe('Simpleswap', () => { - describe('SELL', () => { + describe('SELL small amounts', () => { it('ETH -> SDEX', async () => { await testE2E( tokens.ETH, tokens.SDEX, holders.ETH, - '2000000000000000000', // 2 WETH + '2000000000000000000', // 2 ETH SwapSide.SELL, // exact input dexKey, ContractMethod.simpleSwap, @@ -47,12 +47,13 @@ describe('Smardex E2E Mainnet', () => { provider, ); }); + it('WETH -> SDEX', async () => { await testE2E( tokens.WETH, tokens.SDEX, holders.WETH, - '2000000000000000000', // 2 WETH + '1500000000000000000', // 1.5 WETH SwapSide.SELL, // exact input dexKey, ContractMethod.simpleSwap, @@ -66,7 +67,7 @@ describe('Smardex E2E Mainnet', () => { tokens.SDEX, tokens.WETH, holders.SDEX, - '300000000000000000000000', // 300K SDEX + '250000000000000000000000', // 250K SDEX SwapSide.SELL, // exact input dexKey, ContractMethod.simpleSwap, @@ -80,7 +81,7 @@ describe('Smardex E2E Mainnet', () => { tokens.USDT, tokens.SDEX, holders.USDT, - '200000000', // 200 USDT + '1200000000', // 1200 USDT SwapSide.SELL, // exact input dexKey, ContractMethod.simpleSwap, @@ -94,7 +95,63 @@ describe('Smardex E2E Mainnet', () => { tokens.SDEX, tokens.USDT, holders.SDEX, - '30000000000000000000000', // 30K SDEX + '300000000000000000000000', // 300K SDEX + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('WBTC -> WETH', async () => { + await testE2E( + tokens.WBTC, + tokens.WETH, + holders.WBTC, + '30000000', // 0.3 WBTC + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('WETH -> WBTC', async () => { + await testE2E( + tokens.WETH, + tokens.WBTC, + holders.WETH, + '2500000000000000000', // 2.5 ETH + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('USDT -> ETH', async () => { + await testE2E( + tokens.USDT, + tokens.ETH, + holders.USDT, + '5000000000', // 5000 USDT + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('ETH -> USDT', async () => { + await testE2E( + tokens.ETH, + tokens.USDT, + holders.ETH, + '2500000000000000000', // 2.5K ETH SwapSide.SELL, // exact input dexKey, ContractMethod.simpleSwap, @@ -104,16 +161,16 @@ describe('Smardex E2E Mainnet', () => { }); }); - describe('BUY', () => { + describe('SELL big amounts', () => { it('ETH -> SDEX', async () => { await testE2E( tokens.ETH, tokens.SDEX, holders.ETH, - '300000000000000000000000', // 300K SDEX - SwapSide.BUY, // exact input + '18000000000000000000', // 18 ETH + SwapSide.SELL, // exact input dexKey, - ContractMethod.simpleBuy, + ContractMethod.simpleSwap, network, provider, ); @@ -124,10 +181,10 @@ describe('Smardex E2E Mainnet', () => { tokens.SDEX, tokens.ETH, holders.SDEX, - '2000000000000000000', // 2 WETH - SwapSide.BUY, // exact input + '30000000000000000000000000', // 30M SDEX + SwapSide.SELL, // exact input dexKey, - ContractMethod.simpleBuy, + ContractMethod.simpleSwap, network, provider, ); @@ -138,8 +195,108 @@ describe('Smardex E2E Mainnet', () => { tokens.WETH, tokens.SDEX, holders.WETH, + '42000000000000000000', // 42 WETH + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('SDEX -> WETH', async () => { + await testE2E( + tokens.SDEX, + tokens.WETH, + holders.SDEX, + '32000000000000000000000000', // 32M SDEX + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('USDT -> SDEX', async () => { + await testE2E( + tokens.USDT, + tokens.SDEX, + holders.USDT, + '200000000000', // 200K USDT + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('SDEX -> USDT', async () => { + await testE2E( + tokens.SDEX, + tokens.USDT, + holders.SDEX, + '30000000000000000000000000', // 30M SDEX + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('WBTC -> WETH', async () => { + await testE2E( + tokens.WBTC, + tokens.WETH, + holders.WBTC, + '500000000', // 5 WBTC + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('WETH -> WBTC', async () => { + await testE2E( + tokens.WETH, + tokens.WBTC, + holders.WETH, + '42000000000000000000', // 42 ETH + SwapSide.SELL, // exact input + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + }); + + describe('BUY small amounts', () => { + it('SDEX <- ETH', async () => { + await testE2E( + tokens.SDEX, + tokens.ETH, + holders.SDEX, + '2000000000000000000', // 2 WETH + SwapSide.BUY, // exact output + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + + it('ETH <- SDEX', async () => { + await testE2E( + tokens.ETH, + tokens.SDEX, + holders.ETH, '300000000000000000000000', // 300K SDEX - SwapSide.BUY, // exact input + SwapSide.BUY, // exact output dexKey, ContractMethod.simpleBuy, network, @@ -147,13 +304,13 @@ describe('Smardex E2E Mainnet', () => { ); }); - it('SDEX -> WETH', async () => { + it('SDEX <- WETH', async () => { await testE2E( tokens.SDEX, tokens.WETH, holders.SDEX, - '2000000000000000000', - SwapSide.BUY, // exact input + '1500000000000000000', // 1.5 WETH + SwapSide.BUY, // exact output dexKey, ContractMethod.simpleBuy, network, @@ -161,13 +318,41 @@ describe('Smardex E2E Mainnet', () => { ); }); - it('USDT -> SDEX', async () => { + it('WETH <- SDEX', async () => { + await testE2E( + tokens.WETH, + tokens.SDEX, + holders.WETH, + '250000000000000000000000', // 250K SDEX + SwapSide.BUY, // exact output + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + + it('SDEX <- USDT', async () => { + await testE2E( + tokens.SDEX, + tokens.USDT, + holders.SDEX, + '1200000000', // 1200 USDT + SwapSide.BUY, // exact output + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + + it('USDT <- SDEX', async () => { await testE2E( tokens.USDT, tokens.SDEX, holders.USDT, - '30000000000000000000000', - SwapSide.BUY, // exact input + '300000000000000000000000', // 300k SDEX + SwapSide.BUY, // exact output dexKey, ContractMethod.simpleBuy, network, @@ -175,13 +360,113 @@ describe('Smardex E2E Mainnet', () => { ); }); - it('SDEX -> USDT', async () => { + it('WETH <- WBTC', async () => { + await testE2E( + tokens.WETH, + tokens.WBTC, + holders.WETH, + '30000000', // 0.3 WBTC + SwapSide.BUY, // exact output + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + + it('WBTC <- WETH', async () => { + await testE2E( + tokens.WBTC, + tokens.WETH, + holders.WBTC, + '2500000000000000000', // 2.5 ETH + SwapSide.BUY, // exact output + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + }); + + describe('BUY big amounts', () => { + it('SDEX <- ETH', async () => { + await testE2E( + tokens.SDEX, + tokens.ETH, + holders.SDEX, + '18000000000000000000', // 18 WETH + SwapSide.BUY, // exact output + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + + it('ETH <- SDEX', async () => { + await testE2E( + tokens.ETH, + tokens.SDEX, + holders.ETH, + '30000000000000000000000000', // 30M SDEX + SwapSide.BUY, // exact output + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + + it('SDEX <- WETH', async () => { + await testE2E( + tokens.SDEX, + tokens.WETH, + holders.SDEX, + '42000000000000000000', // 42 WETH + SwapSide.BUY, // exact output + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + + it('WETH <- SDEX', async () => { + await testE2E( + tokens.WETH, + tokens.SDEX, + holders.WETH, + '20000000000000000000000000', // 20M SDEX + SwapSide.BUY, // exact output + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + + it('USDT <- SDEX', async () => { + await testE2E( + tokens.USDT, + tokens.SDEX, + holders.USDT, + '20000000000000000000000000', // 20M SDEX + SwapSide.BUY, // exact output + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + + it('SDEX <- USDT', async () => { await testE2E( tokens.SDEX, tokens.USDT, holders.SDEX, - '3000000000', // 3K USDT - SwapSide.BUY, // exact input + '200000000000', // 200K USDT + SwapSide.BUY, // exact output dexKey, ContractMethod.simpleBuy, network, @@ -197,7 +482,7 @@ describe('Smardex E2E Mainnet', () => { // tokens.ETH, // tokens.WBTC, // holders.ETH, - // '7000000000000000', + // '2000000000000000000', // 2 ETH // SwapSide.SELL, // dexKey, // ContractMethod.multiSwap, From 0ebe5a8b44b7824c2400eac873824319d942bb80 Mon Sep 17 00:00:00 2001 From: Esteban Date: Mon, 11 Sep 2023 16:21:50 +0200 Subject: [PATCH 252/833] fix(core): avoid finding amountIn for 0 amountOut --- src/dex/smardex/sdk/core.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/dex/smardex/sdk/core.ts b/src/dex/smardex/sdk/core.ts index 2bffdb67c..8dd0ac9bc 100644 --- a/src/dex/smardex/sdk/core.ts +++ b/src/dex/smardex/sdk/core.ts @@ -384,8 +384,12 @@ export function getAmountIn( ); } - // Avoid K constant division by 0 - if (reserveInFic <= 0n) { + if ( + // Avoid K constant division by 0 + reserveInFic <= 0n || + // Avoid finding an amountIn for an exact amountOut that is equal to 0 + amountOut <= 0n + ) { return [ BigInt('0'), reserveIn, From b0d39fe3579732c2f5c1af1c541cdbd53adb0747 Mon Sep 17 00:00:00 2001 From: Esteban Date: Mon, 11 Sep 2023 16:22:32 +0200 Subject: [PATCH 253/833] test(smardex): implementation of integration tests --- src/dex/smardex/smardex-integration.test.ts | 330 +++++++------------- 1 file changed, 107 insertions(+), 223 deletions(-) diff --git a/src/dex/smardex/smardex-integration.test.ts b/src/dex/smardex/smardex-integration.test.ts index 627a27f17..e8dc8265e 100644 --- a/src/dex/smardex/smardex-integration.test.ts +++ b/src/dex/smardex/smardex-integration.test.ts @@ -2,244 +2,128 @@ import dotenv from 'dotenv'; dotenv.config(); -import { Interface, Result } from '@ethersproject/abi'; import { DummyDexHelper } from '../../dex-helper/index'; import { Network, SwapSide } from '../../constants'; import { BI_POWS } from '../../bigint-constants'; import { Smardex } from './smardex'; -import { - checkPoolPrices, - checkPoolsLiquidity, - checkConstantPoolPrices, -} from '../../../tests/utils'; +import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; -/* - README - ====== - - This test script adds tests for Smardex general integration - with the DEX interface. The test cases below are example tests. - It is recommended to add tests which cover Smardex specific - logic. - - You can run this individual test script by running: - `npx jest src/dex//-integration.test.ts` - - (This comment should be removed from the final implementation) -*/ - -function getReaderCalldata( - exchangeAddress: string, - readerIface: Interface, - amounts: bigint[], - funcName: string, - // TODO: Put here additional arguments you need -) { - return amounts.map(amount => ({ - target: exchangeAddress, - callData: readerIface.encodeFunctionData(funcName, [ - // TODO: Put here additional arguments to encode them - amount, - ]), - })); -} - -function decodeReaderResult( - results: Result, - readerIface: Interface, - funcName: string, -) { - // TODO: Adapt this function for your needs - return results.map(result => { - const parsed = readerIface.decodeFunctionResult(funcName, result); - return BigInt(parsed[0]._hex); - }); -} - -async function checkOnChainPricing( - smardex: Smardex, - funcName: string, - blockNumber: number, - prices: bigint[], - amounts: bigint[], -) { - const exchangeAddress = ''; // TODO: Put here the real exchange address - - // TODO: Replace dummy interface with the real one - // Normally you can get it from smardex.Iface or from eventPool. - // It depends on your implementation - const readerIface = new Interface(''); - - const readerCallData = getReaderCalldata( - exchangeAddress, - readerIface, - amounts.slice(1), - funcName, - ); - const readerResult = ( - await smardex.dexHelper.multiContract.methods - .aggregate(readerCallData) - .call({}, blockNumber) - ).returnData; - - const expectedPrices = [0n].concat( - decodeReaderResult(readerResult, readerIface, funcName), - ); - - expect(prices).toEqual(expectedPrices); -} - -async function testPricingOnNetwork( - smardex: Smardex, - network: Network, - dexKey: string, - blockNumber: number, - srcTokenSymbol: string, - destTokenSymbol: string, - side: SwapSide, - amounts: bigint[], - funcNameToCheck: string, -) { - const networkTokens = Tokens[network]; - - const pools = await smardex.getPoolIdentifiers( - networkTokens[srcTokenSymbol], - networkTokens[destTokenSymbol], - side, - blockNumber, - ); - console.log( - `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `, - pools, - ); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await smardex.getPricesVolume( - networkTokens[srcTokenSymbol], - networkTokens[destTokenSymbol], - amounts, - side, - blockNumber, - pools, - ); - console.log( - `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `, - poolPrices, - ); - - expect(poolPrices).not.toBeNull(); - if (smardex.hasConstantPriceLargeAmounts) { - checkConstantPoolPrices(poolPrices!, amounts, dexKey); - } else { - checkPoolPrices(poolPrices!, amounts, side, dexKey); - } - - // Check if onchain pricing equals to calculated ones - await checkOnChainPricing( - smardex, - funcNameToCheck, - blockNumber, - poolPrices![0].prices, - amounts, - ); -} - describe('Smardex', function () { const dexKey = 'Smardex'; - let blockNumber: number; - let smardex: Smardex; - - describe('Mainnet', () => { - const network = Network.MAINNET; - const dexHelper = new DummyDexHelper(network); - - const tokens = Tokens[network]; - - // TODO: Put here token Symbol to check against - // Don't forget to update relevant tokens in constant-e2e.ts - const srcTokenSymbol = 'USDT'; - const destTokenSymbol = 'WETH'; + const network = Network.MAINNET; + const tokens = Tokens[network]; - const amountsForSell = [ - 0n, - 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - 10n * BI_POWS[tokens[srcTokenSymbol].decimals], - ]; + describe('Ethereum', () => { + let dexHelper: DummyDexHelper; + let blocknumber: number; - const amountsForBuy = [ - 0n, - 1n * BI_POWS[tokens[destTokenSymbol].decimals], - 2n * BI_POWS[tokens[destTokenSymbol].decimals], - 3n * BI_POWS[tokens[destTokenSymbol].decimals], - 4n * BI_POWS[tokens[destTokenSymbol].decimals], - 5n * BI_POWS[tokens[destTokenSymbol].decimals], - 6n * BI_POWS[tokens[destTokenSymbol].decimals], - 7n * BI_POWS[tokens[destTokenSymbol].decimals], - 8n * BI_POWS[tokens[destTokenSymbol].decimals], - 9n * BI_POWS[tokens[destTokenSymbol].decimals], - 10n * BI_POWS[tokens[destTokenSymbol].decimals], - ]; - - beforeAll(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - smardex = new Smardex(network, dexKey, dexHelper); + beforeEach(async () => { + dexHelper = new DummyDexHelper(network); + blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); }); - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - await testPricingOnNetwork( - smardex, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.SELL, - amountsForSell, - '', // TODO: Put here proper function name to check pricing + // Token pairs to test + const tokenPairs = [ + { src: 'SDEX', dest: 'USDT' }, + { src: 'SDEX', dest: 'WETH' }, + { src: 'SDEX', dest: 'ETH' }, + ] as { src: string; dest: string }[]; + + /** + * Allow to generate amounts for a pair of tokens according to the decimals of each token + * Note: The amounts must increase at the same interval (e.g. 1000, 2000, 3000, 4000) + */ + const generateAmountsForPair = ( + sellToken: string, + buyToken: string, + sellMultipliers: number[], + buyMultipliers: number[], + ) => { + const sell = sellMultipliers.map( + multiplier => BigInt(multiplier) * BI_POWS[tokens[sellToken].decimals], ); - }); - - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - await testPricingOnNetwork( - smardex, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.BUY, - amountsForBuy, - '', // TODO: Put here proper function name to check pricing + const buy = buyMultipliers.map( + multiplier => BigInt(multiplier) * BI_POWS[tokens[buyToken].decimals], ); - }); - - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - const newSmardex = new Smardex(network, dexKey, dexHelper); - const poolLiquidity = await newSmardex.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, + return { sell, buy }; + }; + + const amounts = { + 'SDEX-USDT': generateAmountsForPair( + 'SDEX', + 'USDT', + [0, 10_000, 20_000, 30_000], + [0, 1_000, 2_000, 3_000], + ), + 'SDEX-WETH': generateAmountsForPair( + 'SDEX', + 'WETH', + [0, 100_000, 200_000, 300_000], + [0, 1, 2, 3], + ), + 'SDEX-ETH': generateAmountsForPair( + 'SDEX', + 'WETH', + [0, 100_000, 200_000, 300_000], + [0, 1, 2, 3], + ), + } as { [key: string]: { sell: bigint[]; buy: bigint[] } }; + + // Help us to test the pool prices and volume for a given amount of tokens to swap + const testPoolPricesVolume = async (swapSide: SwapSide, pair: any) => { + const smardex = new Smardex(network, dexKey, dexHelper); + const currentAmounts = + swapSide === SwapSide.SELL + ? amounts[`${pair.src}-${pair.dest}`].sell + : amounts[`${pair.src}-${pair.dest}`].buy; + + const pools = await smardex.getPoolIdentifiers( + tokens[pair.src], + tokens[pair.dest], + swapSide, + blocknumber, ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - - if (!newSmardex.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, - dexKey, - ); - } + console.log(`${pair.src} <> ${pair.dest} Pool Identifiers: `, pools); + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await smardex.getPricesVolume( + tokens[pair.src], + tokens[pair.dest], + currentAmounts, + swapSide, + blocknumber, + pools, + ); + console.log(`${pair.src} <> ${pair.dest} Pool Prices: `, poolPrices); + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, currentAmounts, swapSide, dexKey); + }; + + /** + * For each token pair, test: + * - Compute pool identifiers and prices for a given amount of tokens to swap (SELL and BUY) + * - Get top pools for a token + */ + tokenPairs.forEach(pair => { + describe(`${pair.src} <> ${pair.dest}`, () => { + it('SELL: Compute pool identiers and prices', async () => { + await testPoolPricesVolume(SwapSide.SELL, pair); + }); + + it('BUY: Compute pool identiers and prices', async () => { + await testPoolPricesVolume(SwapSide.BUY, pair); + }); + + it('getTopPoolsForToken', async () => { + const smardex = new Smardex(network, dexKey, dexHelper); + const poolLiquidity = await smardex.getTopPoolsForToken( + tokens[pair.src].address, + 10, + ); + checkPoolsLiquidity(poolLiquidity, tokens[pair.src].address, dexKey); + }); + }); }); }); }); From 5e68347920e929ccb56570289092c173dd2ffa96 Mon Sep 17 00:00:00 2001 From: Esteban Date: Mon, 11 Sep 2023 16:40:37 +0200 Subject: [PATCH 254/833] test: query top pool for each token --- src/dex/smardex/smardex-integration.test.ts | 31 ++++++++++++++------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/dex/smardex/smardex-integration.test.ts b/src/dex/smardex/smardex-integration.test.ts index e8dc8265e..d4b103de0 100644 --- a/src/dex/smardex/smardex-integration.test.ts +++ b/src/dex/smardex/smardex-integration.test.ts @@ -3,7 +3,7 @@ import dotenv from 'dotenv'; dotenv.config(); import { DummyDexHelper } from '../../dex-helper/index'; -import { Network, SwapSide } from '../../constants'; +import { ETHER_ADDRESS, Network, SwapSide } from '../../constants'; import { BI_POWS } from '../../bigint-constants'; import { Smardex } from './smardex'; import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; @@ -114,16 +114,27 @@ describe('Smardex', function () { it('BUY: Compute pool identiers and prices', async () => { await testPoolPricesVolume(SwapSide.BUY, pair); }); - - it('getTopPoolsForToken', async () => { - const smardex = new Smardex(network, dexKey, dexHelper); - const poolLiquidity = await smardex.getTopPoolsForToken( - tokens[pair.src].address, - 10, - ); - checkPoolsLiquidity(poolLiquidity, tokens[pair.src].address, dexKey); - }); }); }); + + it('getTopPoolsForToken', async () => { + const smardex = new Smardex(network, dexKey, dexHelper); + // Get all distinct tokens of the pairs + const distinctTokens = tokenPairs + .reduce((acc, pair) => [...acc, pair.src, pair.dest], [] as string[]) + .filter((value, index, self) => self.indexOf(value) === index) + // Native token doesn't have a pool, avoid it + .filter(token => tokens[token].address !== ETHER_ADDRESS); + // Get top pools for each token and check liquidity + await Promise.all( + distinctTokens.map(async token => + checkPoolsLiquidity( + await smardex.getTopPoolsForToken(tokens[token].address, 10), + tokens[token].address, + dexKey, + ), + ), + ); + }); }); }); From d0ecaee171e56632b990175db793fb515efbc622 Mon Sep 17 00:00:00 2001 From: Esteban Date: Mon, 11 Sep 2023 16:57:21 +0200 Subject: [PATCH 255/833] tests: add wbtc-weth in integration tests --- src/dex/smardex/smardex-integration.test.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/dex/smardex/smardex-integration.test.ts b/src/dex/smardex/smardex-integration.test.ts index d4b103de0..fdbde1167 100644 --- a/src/dex/smardex/smardex-integration.test.ts +++ b/src/dex/smardex/smardex-integration.test.ts @@ -28,6 +28,7 @@ describe('Smardex', function () { { src: 'SDEX', dest: 'USDT' }, { src: 'SDEX', dest: 'WETH' }, { src: 'SDEX', dest: 'ETH' }, + { src: 'WETH', dest: 'WBTC' }, ] as { src: string; dest: string }[]; /** @@ -68,6 +69,12 @@ describe('Smardex', function () { [0, 100_000, 200_000, 300_000], [0, 1, 2, 3], ), + 'WETH-WBTC': generateAmountsForPair( + 'WETH', + 'WBTC', + [0, 2, 4, 6], + [0, 1, 2, 3], + ), } as { [key: string]: { sell: bigint[]; buy: bigint[] } }; // Help us to test the pool prices and volume for a given amount of tokens to swap From 5dfdac93952dd6df69c52052b55b72b6fa70570c Mon Sep 17 00:00:00 2001 From: julien Date: Tue, 12 Sep 2023 10:39:13 +0200 Subject: [PATCH 256/833] fix: pool gas cost --- src/dex/smardex/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/smardex/constants.ts b/src/dex/smardex/constants.ts index 3f59d0e95..ddfcf015d 100644 --- a/src/dex/smardex/constants.ts +++ b/src/dex/smardex/constants.ts @@ -26,4 +26,4 @@ export const directSmardexFunctionName = [ export const SUBGRAPH_TIMEOUT = 20 * 1000; -export const DefaultSmardexPoolGasCost = 90 * 1000; +export const DefaultSmardexPoolGasCost = 130 * 1000; From e6f7b558f18695d786de5d6e34ffb9bd9d73fcea Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 12 Sep 2023 10:56:34 +0200 Subject: [PATCH 257/833] tests: multichain implementation --- src/dex/smardex/smardex-integration.test.ts | 220 ++++++++++++++------ 1 file changed, 159 insertions(+), 61 deletions(-) diff --git a/src/dex/smardex/smardex-integration.test.ts b/src/dex/smardex/smardex-integration.test.ts index fdbde1167..2a83866e9 100644 --- a/src/dex/smardex/smardex-integration.test.ts +++ b/src/dex/smardex/smardex-integration.test.ts @@ -9,12 +9,158 @@ import { Smardex } from './smardex'; import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; -describe('Smardex', function () { - const dexKey = 'Smardex'; - const network = Network.MAINNET; - const tokens = Tokens[network]; +interface NetworkConfig { + name: 'ethereum' | 'bsc' | 'polygon' | 'arbitrum'; + network: Network; + tokens: typeof Tokens[Network]; + tokenPairs: { src: string; dest: string; sell: number[]; buy: number[] }[]; +} + +const networkConfigs: Array = [ + { + name: 'ethereum', + network: Network.MAINNET, + tokens: Tokens[Network.MAINNET], + tokenPairs: [ + { + src: 'SDEX', + dest: 'USDT', + sell: [0, 10_000, 20_000, 30_000], + buy: [0, 1_000, 2_000], + }, + { + src: 'SDEX', + dest: 'WETH', + sell: [0, 100_000, 200_000, 300_000], + buy: [0, 1, 2, 3], + }, + { + src: 'SDEX', + dest: 'ETH', + sell: [0, 100_000, 200_000, 300_000], + buy: [0, 1, 2, 3], + }, + { src: 'WETH', dest: 'WBTC', sell: [0, 2, 4, 6], buy: [0, 1, 2, 3] }, + ], + }, + { + name: 'arbitrum', + network: Network.ARBITRUM, + tokens: Tokens[Network.ARBITRUM], + tokenPairs: [ + { + src: 'SDEX', + dest: 'USDC', + sell: [0, 10_000, 20_000, 30_000], + buy: [0, 1_000, 2_000], + }, + { + src: 'SDEX', + dest: 'WETH', + sell: [0, 100_000, 200_000, 300_000], + buy: [0, 1, 2, 3], + }, + { + src: 'SDEX', + dest: 'ETH', + sell: [0, 100_000, 200_000, 300_000], + buy: [0, 1, 2, 3], + }, + { + src: 'SDEX', + dest: 'WBTC', + sell: [0, 100_000, 200_000, 300_000], + buy: [0, 1, 2, 3], + }, + { + src: 'ARB', + dest: 'USDC', + sell: [0, 2_000, 4_000, 6_000], + buy: [0, 1_000, 2_000], + }, + ], + }, + { + name: 'bsc', + network: Network.BSC, + tokens: Tokens[Network.BSC], + tokenPairs: [ + { + src: 'SDEX', + dest: 'USDT', + sell: [0, 10_000, 20_000, 30_000], + buy: [0, 1_000, 2_000], + }, + { + src: 'bBTC', + dest: 'SDEX', + sell: [0, 100_000, 200_000, 300_000], + buy: [0, 1, 2, 3], + }, + { + src: 'USDT', + dest: 'WBNB', + sell: [0, 100_000, 200_000, 300_000], + buy: [0, 10, 20, 30], + }, + { src: 'ETH', dest: 'SDEX', sell: [0, 2, 4, 6], buy: [0, 1, 2, 3] }, + { + src: 'USDT', + dest: 'BNB', + sell: [0, 2_000, 4_000, 6_000], + buy: [0, 10, 20, 30], + }, + { + src: 'RVF', + dest: 'SDEX', + sell: [0, 2_000, 4_000, 6_000], + buy: [0, 1_000, 2_000], + }, + ], + }, + { + name: 'polygon', + network: Network.POLYGON, + tokens: Tokens[Network.POLYGON], + tokenPairs: [ + { + src: 'USDC', + dest: 'SDEX', + sell: [0, 10_000, 20_000, 30_000], + buy: [0, 100_000, 200_000], + }, + { + src: 'SDEX', + dest: 'WETH', + sell: [0, 100_000, 200_000, 300_000], + buy: [0, 2, 4, 6, 8, 10], + }, + { + src: 'USDC', + dest: 'WMATIC', + sell: [0, 100_000, 200_000, 300_000], + buy: [0, 20_000, 40_000, 60_000], + }, + { + src: 'USDC', + dest: 'MATIC', + sell: [0, 100_000, 200_000, 300_000], + buy: [0, 20_000, 40_000, 60_000], + }, + { + src: 'WBTC', + dest: 'SDEX', + sell: [0, 1, 2, 3], + buy: [0, 500_000, 1_000_000, 1_500_000], + }, + ], + }, +]; + +networkConfigs.forEach(({ name, network, tokens, tokenPairs }) => { + describe(`Smardex Integration Tests on ${name}`, () => { + const dexKey = 'Smardex'; - describe('Ethereum', () => { let dexHelper: DummyDexHelper; let blocknumber: number; @@ -23,67 +169,19 @@ describe('Smardex', function () { blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); }); - // Token pairs to test - const tokenPairs = [ - { src: 'SDEX', dest: 'USDT' }, - { src: 'SDEX', dest: 'WETH' }, - { src: 'SDEX', dest: 'ETH' }, - { src: 'WETH', dest: 'WBTC' }, - ] as { src: string; dest: string }[]; - - /** - * Allow to generate amounts for a pair of tokens according to the decimals of each token - * Note: The amounts must increase at the same interval (e.g. 1000, 2000, 3000, 4000) - */ - const generateAmountsForPair = ( - sellToken: string, - buyToken: string, - sellMultipliers: number[], - buyMultipliers: number[], - ) => { - const sell = sellMultipliers.map( - multiplier => BigInt(multiplier) * BI_POWS[tokens[sellToken].decimals], - ); - const buy = buyMultipliers.map( - multiplier => BigInt(multiplier) * BI_POWS[tokens[buyToken].decimals], - ); - return { sell, buy }; - }; - - const amounts = { - 'SDEX-USDT': generateAmountsForPair( - 'SDEX', - 'USDT', - [0, 10_000, 20_000, 30_000], - [0, 1_000, 2_000, 3_000], - ), - 'SDEX-WETH': generateAmountsForPair( - 'SDEX', - 'WETH', - [0, 100_000, 200_000, 300_000], - [0, 1, 2, 3], - ), - 'SDEX-ETH': generateAmountsForPair( - 'SDEX', - 'WETH', - [0, 100_000, 200_000, 300_000], - [0, 1, 2, 3], - ), - 'WETH-WBTC': generateAmountsForPair( - 'WETH', - 'WBTC', - [0, 2, 4, 6], - [0, 1, 2, 3], - ), - } as { [key: string]: { sell: bigint[]; buy: bigint[] } }; - // Help us to test the pool prices and volume for a given amount of tokens to swap const testPoolPricesVolume = async (swapSide: SwapSide, pair: any) => { const smardex = new Smardex(network, dexKey, dexHelper); const currentAmounts = swapSide === SwapSide.SELL - ? amounts[`${pair.src}-${pair.dest}`].sell - : amounts[`${pair.src}-${pair.dest}`].buy; + ? pair.sell.map( + (amount: number) => + BigInt(amount) * BI_POWS[tokens[pair.src].decimals], + ) + : pair.buy.map( + (amount: number) => + BigInt(amount) * BI_POWS[tokens[pair.dest].decimals], + ); const pools = await smardex.getPoolIdentifiers( tokens[pair.src], From ae52b405c648e1087628ea23a8cb4f5d9b0cf0b3 Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 12 Sep 2023 10:57:15 +0200 Subject: [PATCH 258/833] chore(multichain): add sdex token to constants --- tests/constants-e2e.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index ae011b0d9..0b47906ef 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -445,6 +445,10 @@ export const Tokens: { address: '0xa3fa99a148fa48d14ed51d610c367c61876997f1', decimals: 18, }, + SDEX: { + address: '0x6899fAcE15c14348E1759371049ab64A3a06bFA6', + decimals: 18, + }, }, [Network.FANTOM]: { FTM: { address: ETHER_ADDRESS, decimals: 18 }, @@ -571,6 +575,14 @@ export const Tokens: { address: '0x4268B8F0B87b6Eae5d897996E6b845ddbD99Adf3', decimals: 6, }, + SDEX: { + address: '0xFdc66A08B0d0Dc44c17bbd471B88f49F50CdD20F', + decimals: 18, + }, + RVF: { + address: '0x872a34Ebb2d54Af86827810EeBC7b9dC6B2144aA', + decimals: 18, + }, }, [Network.AVALANCHE]: { USDCe: { @@ -809,6 +821,10 @@ export const Tokens: { address: '0x3d9907f9a368ad0a51be60f7da3b97cf940982d8', decimals: 18, }, + SDEX: { + address: '0xabD587f2607542723b17f14d00d99b987C29b074', + decimals: 18, + }, }, [Network.OPTIMISM]: { DAI: { From af59087f6c015e3488b700befbb44b4bca1a619c Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 12 Sep 2023 10:57:57 +0200 Subject: [PATCH 259/833] fix: fees on layer two --- src/dex/smardex/smardex.ts | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 55edfbae2..6a4828286 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -76,7 +76,7 @@ export class SmardexEventPool extends StatefulEventSubscriber target: string; callData: string; }, - protected smardexFeesMulticallDecoder?: (values: any[]) => number, + protected smardexFeesMulticallDecoder?: (values: any[]) => number[], ) { super( 'Smardex', @@ -117,10 +117,10 @@ export class SmardexEventPool extends StatefulEventSubscriber return { feesLp: dynamicFees - ? this.smardexFeesMulticallDecoder!(data.returnData[1][0]) + ? this.smardexFeesMulticallDecoder!(data.returnData[1])[0] : 500, feesPool: dynamicFees - ? this.smardexFeesMulticallDecoder!(data.returnData[1][1]) + ? this.smardexFeesMulticallDecoder!(data.returnData[1])[1] : 200, priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), }; @@ -233,10 +233,10 @@ export class SmardexEventPool extends StatefulEventSubscriber priceAverage1: priceAverage1.toString(), priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), feesLp: dynamicFees - ? this.smardexFeesMulticallDecoder!(data.returnData[3][0]) + ? this.smardexFeesMulticallDecoder!(data.returnData[3])[0] : 500, feesPool: dynamicFees - ? this.smardexFeesMulticallDecoder!(data.returnData[3][1]) + ? this.smardexFeesMulticallDecoder!(data.returnData[3])[1] : 200, }; } @@ -619,10 +619,8 @@ export class Smardex target: pair.exchange!, callData: smardexPoolL2.encodeFunctionData('getPairFees'), }; - const callDecoder = (values: any[]) => - parseInt( - smardexPoolL2.decodeFunctionResult('getPairFees', values).toString(), - ); + const callDecoder = (values: any[]): number[] => + smardexPoolL2.decodeFunctionResult('getPairFees', values) as number[]; return { callEntry, @@ -707,7 +705,7 @@ export class Smardex .aggregate(calldata) .call({}, blockNumber); - const returnData = _.chunk(data.returnData, 3); + const returnData = _.chunk(data.returnData, 4); return pairs.map((_pair: SmardexPair, i) => ({ reserves0: coder .decode(['uint256', 'uint256'], returnData[i][0])[0] @@ -732,10 +730,10 @@ export class Smardex .toString(), feesLp: this.isLayer1() ? 500 - : multiCallFeeData[i]!.callDecoder(returnData[i][3][0]), + : multiCallFeeData[i]!.callDecoder(returnData[i][3])[0], feesPool: this.isLayer1() ? 200 - : multiCallFeeData[i]!.callDecoder(returnData[i][3][1]), + : multiCallFeeData[i]!.callDecoder(returnData[i][3])[1], })); } catch (e) { this.logger.error( From 736bed4220b7e3fa5a2f98b8c6dd23b1d070ecd8 Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 12 Sep 2023 11:49:13 +0200 Subject: [PATCH 260/833] chore: remove rvf token --- src/dex/smardex/smardex-integration.test.ts | 6 ------ tests/constants-e2e.ts | 4 ---- 2 files changed, 10 deletions(-) diff --git a/src/dex/smardex/smardex-integration.test.ts b/src/dex/smardex/smardex-integration.test.ts index 2a83866e9..d7e415ba4 100644 --- a/src/dex/smardex/smardex-integration.test.ts +++ b/src/dex/smardex/smardex-integration.test.ts @@ -110,12 +110,6 @@ const networkConfigs: Array = [ sell: [0, 2_000, 4_000, 6_000], buy: [0, 10, 20, 30], }, - { - src: 'RVF', - dest: 'SDEX', - sell: [0, 2_000, 4_000, 6_000], - buy: [0, 1_000, 2_000], - }, ], }, { diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 0b47906ef..23453baae 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -579,10 +579,6 @@ export const Tokens: { address: '0xFdc66A08B0d0Dc44c17bbd471B88f49F50CdD20F', decimals: 18, }, - RVF: { - address: '0x872a34Ebb2d54Af86827810EeBC7b9dC6B2144aA', - decimals: 18, - }, }, [Network.AVALANCHE]: { USDCe: { From dde6fea2140a3fded918caff271e19cb76eb5342 Mon Sep 17 00:00:00 2001 From: julien Date: Tue, 12 Sep 2023 12:06:49 +0200 Subject: [PATCH 261/833] refactor: e2e test for better lisibility --- src/dex/smardex/smardex-e2e.test.ts | 1073 +++------------------------ 1 file changed, 114 insertions(+), 959 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index cb6c6bc69..5267eba34 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -15,966 +15,121 @@ describe('Smardex E2E Mainnet', () => { generateConfig(network).privateHttpProvider, network, ); - describe('Smardex', () => { - const dexKey = 'Smardex'; - - describe('Simpleswap', () => { - describe('SELL small amounts', () => { - it('ETH -> SDEX', async () => { - await testE2E( - tokens.ETH, - tokens.SDEX, - holders.ETH, - '2000000000000000000', // 2 ETH - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('SDEX -> ETH', async () => { - await testE2E( - tokens.SDEX, - tokens.ETH, - holders.SDEX, - '300000000000000000000000', // 300K SDEX - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('WETH -> SDEX', async () => { - await testE2E( - tokens.WETH, - tokens.SDEX, - holders.WETH, - '1500000000000000000', // 1.5 WETH - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('SDEX -> WETH', async () => { - await testE2E( - tokens.SDEX, - tokens.WETH, - holders.SDEX, - '250000000000000000000000', // 250K SDEX - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('USDT -> SDEX', async () => { - await testE2E( - tokens.USDT, - tokens.SDEX, - holders.USDT, - '1200000000', // 1200 USDT - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('SDEX -> USDT', async () => { - await testE2E( - tokens.SDEX, - tokens.USDT, - holders.SDEX, - '300000000000000000000000', // 300K SDEX - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('WBTC -> WETH', async () => { - await testE2E( - tokens.WBTC, - tokens.WETH, - holders.WBTC, - '30000000', // 0.3 WBTC - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('WETH -> WBTC', async () => { - await testE2E( - tokens.WETH, - tokens.WBTC, - holders.WETH, - '2500000000000000000', // 2.5 ETH - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('USDT -> ETH', async () => { - await testE2E( - tokens.USDT, - tokens.ETH, - holders.USDT, - '5000000000', // 5000 USDT - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('ETH -> USDT', async () => { - await testE2E( - tokens.ETH, - tokens.USDT, - holders.ETH, - '2500000000000000000', // 2.5K ETH - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - }); - - describe('SELL big amounts', () => { - it('ETH -> SDEX', async () => { - await testE2E( - tokens.ETH, - tokens.SDEX, - holders.ETH, - '18000000000000000000', // 18 ETH - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('SDEX -> ETH', async () => { - await testE2E( - tokens.SDEX, - tokens.ETH, - holders.SDEX, - '30000000000000000000000000', // 30M SDEX - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('WETH -> SDEX', async () => { - await testE2E( - tokens.WETH, - tokens.SDEX, - holders.WETH, - '42000000000000000000', // 42 WETH - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('SDEX -> WETH', async () => { - await testE2E( - tokens.SDEX, - tokens.WETH, - holders.SDEX, - '32000000000000000000000000', // 32M SDEX - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('USDT -> SDEX', async () => { - await testE2E( - tokens.USDT, - tokens.SDEX, - holders.USDT, - '200000000000', // 200K USDT - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('SDEX -> USDT', async () => { - await testE2E( - tokens.SDEX, - tokens.USDT, - holders.SDEX, - '30000000000000000000000000', // 30M SDEX - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('WBTC -> WETH', async () => { - await testE2E( - tokens.WBTC, - tokens.WETH, - holders.WBTC, - '500000000', // 5 WBTC - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('WETH -> WBTC', async () => { - await testE2E( - tokens.WETH, - tokens.WBTC, - holders.WETH, - '42000000000000000000', // 42 ETH - SwapSide.SELL, // exact input - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - }); - - describe('BUY small amounts', () => { - it('SDEX <- ETH', async () => { - await testE2E( - tokens.SDEX, - tokens.ETH, - holders.SDEX, - '2000000000000000000', // 2 WETH - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - it('ETH <- SDEX', async () => { - await testE2E( - tokens.ETH, - tokens.SDEX, - holders.ETH, - '300000000000000000000000', // 300K SDEX - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - - it('SDEX <- WETH', async () => { - await testE2E( - tokens.SDEX, - tokens.WETH, - holders.SDEX, - '1500000000000000000', // 1.5 WETH - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - - it('WETH <- SDEX', async () => { - await testE2E( - tokens.WETH, - tokens.SDEX, - holders.WETH, - '250000000000000000000000', // 250K SDEX - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - - it('SDEX <- USDT', async () => { - await testE2E( - tokens.SDEX, - tokens.USDT, - holders.SDEX, - '1200000000', // 1200 USDT - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - - it('USDT <- SDEX', async () => { - await testE2E( - tokens.USDT, - tokens.SDEX, - holders.USDT, - '300000000000000000000000', // 300k SDEX - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - - it('WETH <- WBTC', async () => { - await testE2E( - tokens.WETH, - tokens.WBTC, - holders.WETH, - '30000000', // 0.3 WBTC - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - - it('WBTC <- WETH', async () => { - await testE2E( - tokens.WBTC, - tokens.WETH, - holders.WBTC, - '2500000000000000000', // 2.5 ETH - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - }); - - describe('BUY big amounts', () => { - it('SDEX <- ETH', async () => { - await testE2E( - tokens.SDEX, - tokens.ETH, - holders.SDEX, - '18000000000000000000', // 18 WETH - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - - it('ETH <- SDEX', async () => { - await testE2E( - tokens.ETH, - tokens.SDEX, - holders.ETH, - '30000000000000000000000000', // 30M SDEX - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - - it('SDEX <- WETH', async () => { - await testE2E( - tokens.SDEX, - tokens.WETH, - holders.SDEX, - '42000000000000000000', // 42 WETH - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - - it('WETH <- SDEX', async () => { - await testE2E( - tokens.WETH, - tokens.SDEX, - holders.WETH, - '20000000000000000000000000', // 20M SDEX - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - - it('USDT <- SDEX', async () => { - await testE2E( - tokens.USDT, - tokens.SDEX, - holders.USDT, - '20000000000000000000000000', // 20M SDEX - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - - it('SDEX <- USDT', async () => { - await testE2E( - tokens.SDEX, - tokens.USDT, - holders.SDEX, - '200000000000', // 200K USDT - SwapSide.BUY, // exact output - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - }); - }); - - // describe('Multiswap', () => { - // it('ETH -> TOKEN', async () => { - // await testE2E( - // tokens.ETH, - // tokens.WBTC, - // holders.ETH, - // '2000000000000000000', // 2 ETH - // SwapSide.SELL, - // dexKey, - // ContractMethod.multiSwap, - // network, - // provider, - // ); - // }); - // it('TOKEN -> ETH', async () => { - // await testE2E( - // tokens.BADGER, - // tokens.ETH, - // holders.BADGER, - // '700000000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.multiSwap, - // network, - // provider, - // ); - // }); - // it('TOKEN -> TOKEN', async () => { - // await testE2E( - // tokens.USDT, - // tokens.WBTC, - // holders.USDT, - // '200000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.multiSwap, - // network, - // provider, - // ); - // }); - // }); - - // describe('swapOnUniswap', () => { - // it('ETH -> TOKEN', async () => { - // await testE2E( - // tokens.ETH, - // tokens.WBTC, - // holders.ETH, - // '7000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.swapOnUniswap, - // network, - // provider, - // ); - // }); - // it('TOKEN[BADGER] -> ETH', async () => { - // await testE2E( - // tokens.BADGER, - // tokens.ETH, - // holders.BADGER, - // '700000000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.swapOnUniswap, - // network, - // provider, - // ); - // }); - // it('TOKEN[USDC] -> ETH', async () => { - // await testE2E( - // tokens.USDT, - // tokens.ETH, - // holders.USDT, - // '200000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.swapOnUniswap, - // network, - // provider, - // ); - // }); - // it('TOKEN -> TOKEN', async () => { - // await testE2E( - // tokens.USDT, - // tokens.WBTC, - // holders.USDT, - // '200000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.swapOnUniswap, - // network, - // provider, - // ); - // }); - // }); - - // describe('swapOnUniswapFork', () => { - // it('ETH -> TOKEN', async () => { - // await testE2E( - // tokens.ETH, - // tokens.WBTC, - // holders.ETH, - // '7000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.swapOnUniswapFork, - // network, - // provider, - // ); - // }); - // it('TOKEN -> ETH', async () => { - // await testE2E( - // tokens.BADGER, - // tokens.ETH, - // holders.BADGER, - // '700000000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.swapOnUniswapFork, - // network, - // provider, - // ); - // }); - // it('TOKEN -> TOKEN', async () => { - // await testE2E( - // tokens.USDT, - // tokens.WBTC, - // holders.USDT, - // '200000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.swapOnUniswapFork, - // network, - // provider, - // ); - // }); - // }); - - // describe('swapOnUniswapV2Fork', () => { - // it('ETH -> TOKEN', async () => { - // await testE2E( - // tokens.ETH, - // tokens.WBTC, - // holders.ETH, - // '7000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.swapOnUniswapV2Fork, - // network, - // provider, - // ); - // }); - // it('TOKEN -> ETH', async () => { - // await testE2E( - // tokens.BADGER, - // tokens.ETH, - // holders.BADGER, - // '700000000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.swapOnUniswapV2Fork, - // network, - // provider, - // ); - // }); - // it('TOKEN -> TOKEN', async () => { - // await testE2E( - // tokens.USDT, - // tokens.WBTC, - // holders.USDT, - // '200000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.swapOnUniswapV2Fork, - // network, - // provider, - // ); - // }); - // }); - - // describe('buyOnUniswap', () => { - // it('TOKEN -> ETH', async () => { - // await testE2E( - // tokens.USDT, - // tokens.ETH, - // holders.USDT, - // '700000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buyOnUniswap, - // network, - // provider, - // ); - // }); - // it('ETH -> TOKEN[BADGER]', async () => { - // await testE2E( - // tokens.ETH, - // tokens.BADGER, - // holders.ETH, - // '700000000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buyOnUniswap, - // network, - // provider, - // ); - // }); - // it('TOKEN[USDC] -> ETH', async () => { - // await testE2E( - // tokens.USDT, - // tokens.ETH, - // holders.USDT, - // '2000000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buyOnUniswap, - // network, - // provider, - // ); - // }); - - // it('TOKEN -> TOKEN', async () => { - // await testE2E( - // tokens.USDT, - // tokens.WBTC, - // holders.USDT, - // '200000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buyOnUniswap, - // network, - // provider, - // ); - // }); - // }); - - // describe('buyOnUniswapFork', () => { - // it('TOKEN -> ETH', async () => { - // await testE2E( - // tokens.USDT, - // tokens.ETH, - // holders.USDT, - // '700000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buyOnUniswapFork, - // network, - // provider, - // ); - // }); - // it('ETH -> TOKEN[BADGER]', async () => { - // await testE2E( - // tokens.ETH, - // tokens.BADGER, - // holders.ETH, - // '700000000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buyOnUniswapFork, - // network, - // provider, - // ); - // }); - // it('TOKEN[USDC] -> ETH', async () => { - // await testE2E( - // tokens.USDT, - // tokens.ETH, - // holders.USDT, - // '2000000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buyOnUniswapFork, - // network, - // provider, - // ); - // }); - - // it('TOKEN -> TOKEN', async () => { - // await testE2E( - // tokens.USDT, - // tokens.WBTC, - // holders.USDT, - // '200000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buyOnUniswapFork, - // network, - // provider, - // ); - // }); - // }); - - // describe('buyOnUniswapV2Fork', () => { - // it('TOKEN -> ETH', async () => { - // await testE2E( - // tokens.USDT, - // tokens.ETH, - // holders.USDT, - // '700000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buyOnUniswapV2Fork, - // network, - // provider, - // ); - // }); - // it('ETH -> TOKEN[BADGER]', async () => { - // await testE2E( - // tokens.ETH, - // tokens.BADGER, - // holders.ETH, - // '700000000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buyOnUniswapV2Fork, - // network, - // provider, - // ); - // }); - // it('TOKEN[USDC] -> ETH', async () => { - // await testE2E( - // tokens.USDT, - // tokens.ETH, - // holders.USDT, - // '2000000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buyOnUniswapV2Fork, - // network, - // provider, - // ); - // }); - - // it('TOKEN -> TOKEN', async () => { - // await testE2E( - // tokens.USDT, - // tokens.WBTC, - // holders.USDT, - // '200000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buyOnUniswapV2Fork, - // network, - // provider, - // ); - // }); - // }); - - // describe('simpleBuy', () => { - // it('TOKEN -> ETH', async () => { - // await testE2E( - // tokens.USDT, - // tokens.ETH, - // holders.USDT, - // '700000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.simpleBuy, - // network, - // provider, - // ); - // }); - // it('ETH -> TOKEN[BADGER]', async () => { - // await testE2E( - // tokens.ETH, - // tokens.BADGER, - // holders.ETH, - // '700000000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.simpleBuy, - // network, - // provider, - // ); - // }); - // it('TOKEN[USDC] -> ETH', async () => { - // await testE2E( - // tokens.USDT, - // tokens.ETH, - // holders.USDT, - // '2000000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.simpleBuy, - // network, - // provider, - // ); - // }); - // it('TOKEN -> TOKEN', async () => { - // await testE2E( - // tokens.USDT, - // tokens.WBTC, - // holders.USDT, - // '20000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.simpleBuy, - // network, - // provider, - // ); - // }); - // }); - - // describe('BuyMethod', () => { - // it('TOKEN -> ETH', async () => { - // await testE2E( - // tokens.USDT, - // tokens.ETH, - // holders.USDT, - // '700000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buy, - // network, - // provider, - // ); - // }); - // it('ETH -> TOKEN[BADGER]', async () => { - // await testE2E( - // tokens.ETH, - // tokens.BADGER, - // holders.ETH, - // '700000000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buy, - // network, - // provider, - // ); - // }); - // it('TOKEN[USDC] -> ETH', async () => { - // await testE2E( - // tokens.USDT, - // tokens.ETH, - // holders.USDT, - // '2000000000000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buy, - // network, - // provider, - // ); - // }); - // it('TOKEN -> TOKEN', async () => { - // await testE2E( - // tokens.USDT, - // tokens.WBTC, - // holders.USDT, - // '20000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.buy, - // network, - // provider, - // ); - // }); - // }); + describe('Smardex Swap', () => { + const dexKey = 'Smardex'; - // describe('STETH->ETH', () => { - // it('simpleSwap', async () => { - // await testE2E( - // tokens.STETH, - // tokens.ETH, - // holders.STETH, - // '1000000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.simpleSwap, - // network, - // provider, - // ); - // }); - // it('multiSwap', async () => { - // await testE2E( - // tokens.STETH, - // tokens.ETH, - // holders.STETH, - // '1000000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.multiSwap, - // network, - // provider, - // ); - // }); - // it('megaSwap', async () => { - // await testE2E( - // tokens.STETH, - // tokens.ETH, - // holders.STETH, - // '1000000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.megaSwap, - // network, - // provider, - // ); - // }); - // }); + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, // TODO: uncomment when Adapter is ready to enable Multiswap + // ContractMethod.megaSwap, // TODO: uncomment when Adapter is ready to enable Megaswap + ], + ], + // [SwapSide.BUY, [ContractMethod.simpleBuy]], + ]); + + const pairsSmallAmount: { name: string; sellAmount: string; buyAmount: string }[][] = [ + [ + { + name: 'ETH', + sellAmount: '2000000000000000000', // 2 ETH + buyAmount: '300000000000000000000000', // 300K SDEX + }, + { + name: 'SDEX', + sellAmount: '300000000000000000000000', // 300K SDEX + buyAmount: '2000000000000000000', // 2 ETH + }, + ], + [ + { + name: 'WETH', + sellAmount: '1500000000000000000', // 1.5 WETH + buyAmount: '250000000000000000000000', // 250K SDEX + }, + { + name: 'SDEX', + sellAmount: '250000000000000000000000', // 250K SDEX + buyAmount: '1500000000000000000', // 1.5 WETH + }, + ], + [ + { + name: 'USDT', + sellAmount: '1200000000', // 1200 USDT + buyAmount: '300000000000000000000000', // 300K SDEX + }, + { + name: 'SDEX', + sellAmount: '300000000000000000000000', // 300K SDEX + buyAmount: '1200000000', // 1200 USDT + }, + ], + [ + { + name: 'WBTC', + sellAmount: '30000000', // 0.3 WBTC + buyAmount: '2500000000000000000', // 2.5 WETH + }, + { + name: 'WETH', + sellAmount: '2500000000000000000', // 2.5 WETH + buyAmount: '30000000', // 0.3 WBTC + }, + ], + ]; + + // multiply all amounts by 10 + const pairsBigAmount: { name: string; sellAmount: string; buyAmount: string }[][] = + pairsSmallAmount.map((pair) => + pair.map((token) => ({ ...token, sellAmount: token.sellAmount + '0', buyAmount: token.buyAmount + '0' })), + ); + + // copy smallAmount and bigAmount into the same array alternatively to get same pairs together + const pairs = pairsSmallAmount.map((small, index) => ([small, pairsBigAmount[index]])).flat(1); + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }); + }), + ); }); }); From cb518cbe73b58e53703c9df9360c8f702408c066 Mon Sep 17 00:00:00 2001 From: julien Date: Tue, 12 Sep 2023 12:06:59 +0200 Subject: [PATCH 262/833] rm: useless --- src/dex/smardex/smardex.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 6a4828286..02dc2ba0a 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -855,7 +855,7 @@ export class Smardex } // Encode params required by the exchange adapter - // Used for multiSwap, buy & megaSwap + // Used for multiSwap & megaSwap // Hint: abiCoder.encodeParameter() could be useful getAdapterParam( srcToken: Address, @@ -897,9 +897,6 @@ export class Smardex data: SmardexData, side: SwapSide, ): Promise { - const pools = encodePools(data.pools); - const weth = this.getWETHAddress(src, dest, data.wethAddress); - let routerMethod: any; let routerArgs: any; if (side === SwapSide.SELL) { From 12629d476eef8837fbca6f57a23e6251494bd5a7 Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Tue, 12 Sep 2023 14:04:35 +0300 Subject: [PATCH 263/833] fix(BACK-1264): fix small issues related to Base config --- src/config.ts | 4 +--- src/constants.ts | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/config.ts b/src/config.ts index c92d0546a..ef6b679cd 100644 --- a/src/config.ts +++ b/src/config.ts @@ -360,9 +360,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { multicallV2Address: '0xeDF6D2a16e8081F777eB623EeB4411466556aF3d', privateHttpProvider: process.env.HTTP_PROVIDER_8453, hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', - hashFlowDisabledMMs: - process.env[`HASHFLOW_DISABLED_MMS_10`]?.split(',') || [], - + hashFlowDisabledMMs: [], adapterAddresses: { BaseAdapter01: '0x9F77bb28e97F093Aa6CbE37cE095C18605d98Af2', BaseBuyAdapter: '0x8DE036910e34b0d8447Dd0D34C742636de1DDfEb', diff --git a/src/constants.ts b/src/constants.ts index d06c902e5..3c0bf6b9a 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -21,7 +21,7 @@ export const MAX_BLOCKS_HISTORY = 7; export const SETUP_RETRY_TIMEOUT = 20 * 1000; // 20s -export const FETCH_POOL_IDENTIFIER_TIMEOUT = 60 * 1000; // 1s // TODO change once finished testing +export const FETCH_POOL_IDENTIFIER_TIMEOUT = 1 * 1000; // 1s export const FETCH_POOL_PRICES_TIMEOUT = 3 * 1000; // 3s // How frequently logs wil be printed From e7b4785a8ae9aa1c64bc12f07ddb2eb35092d666 Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Tue, 12 Sep 2023 14:06:40 +0300 Subject: [PATCH 264/833] 2.35.3-base-support.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 55739ce6e..311c8f8e4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.2", + "version": "2.35.3-base-support.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1f1523cacb67042cf1a8c5fb41ff55dc29c7617c Mon Sep 17 00:00:00 2001 From: julien Date: Tue, 12 Sep 2023 14:36:34 +0200 Subject: [PATCH 265/833] feat: setup e2e multichain --- src/dex/smardex/smardex-e2e.test.ts | 315 +++++++++++++++++++++------- 1 file changed, 245 insertions(+), 70 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index 5267eba34..634e47257 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -7,31 +7,17 @@ import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; -describe('Smardex E2E Mainnet', () => { - const network = Network.MAINNET; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - describe('Smardex Swap', () => { - const dexKey = 'Smardex'; +interface SmardexE2ePairToken { + name: string; + sellAmount: string; + buyAmount: string; +} +type SmardexE2ePair = SmardexE2ePairToken[]; - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - // ContractMethod.multiSwap, // TODO: uncomment when Adapter is ready to enable Multiswap - // ContractMethod.megaSwap, // TODO: uncomment when Adapter is ready to enable Megaswap - ], - ], - // [SwapSide.BUY, [ContractMethod.simpleBuy]], - ]); - - const pairsSmallAmount: { name: string; sellAmount: string; buyAmount: string }[][] = [ +describe('Smardex E2E', () => { + // Generate pairs for each network twice: each time with small and big swap amount (x10) + const allPairs: { [key: number]: SmardexE2ePair[] } = { + [Network.MAINNET]: [ [ { name: 'ETH', @@ -80,56 +66,245 @@ describe('Smardex E2E Mainnet', () => { buyAmount: '30000000', // 0.3 WBTC }, ], - ]; + ] + .map((pair, i, arr) => [ + [pair], + [ + arr[i].map(token => ({ + ...token, + sellAmount: token.sellAmount + '0', + buyAmount: token.buyAmount + '0', + })), + ], + ]) + .flat(2), + // [Network.ARBITRUM]: [ + // [ + // { + // name: 'WETH', + // sellAmount: '1500000000000000000', // 1.5 WETH + // buyAmount: '250000000000000000000000', // 250K SDEX + // }, + // { + // name: 'SDEX', + // sellAmount: '250000000000000000000000', // 250K SDEX + // buyAmount: '1500000000000000000', // 1.5 WETH + // }, + // ], + // [ + // { + // name: 'USDT', + // sellAmount: '1200000000', // 1200 USDT + // buyAmount: '300000000000000000000000', // 300K SDEX + // }, + // { + // name: 'SDEX', + // sellAmount: '300000000000000000000000', // 300K SDEX + // buyAmount: '1200000000', // 1200 USDT + // }, + // ], + // [ + // { + // name: 'WBTC', + // sellAmount: '30000000', // 0.3 WBTC + // buyAmount: '2500000000000000000', // 2.5 WETH + // }, + // { + // name: 'WETH', + // sellAmount: '2500000000000000000', // 2.5 WETH + // buyAmount: '30000000', // 0.3 WBTC + // }, + // ], + // ] + // .map((pair, i, arr) => [ + // [pair], + // [ + // arr[i].map(token => ({ + // ...token, + // sellAmount: token.sellAmount + '0', + // buyAmount: token.buyAmount + '0', + // })), + // ], + // ]) + // .flat(2), + // [Network.BSC]: [ + // [ + // { + // name: 'USDT', + // sellAmount: '1200000000', // 1200 USDT + // buyAmount: '300000000000000000000000', // 300K SDEX + // }, + // { + // name: 'SDEX', + // sellAmount: '300000000000000000000000', // 300K SDEX + // buyAmount: '1200000000', // 1200 USDT + // }, + // ], + // [ + // { + // name: 'SDEX', + // sellAmount: '5000000', // 005 WBTC + // buyAmount: '300000000000000000000000', // 300K SDEX + // }, + // { + // name: 'bBTC', + // sellAmount: '300000000000000000000000', // 300K SDEX + // buyAmount: '5000000', // 0.05 WBTC + // }, + // ], + // [ + // { + // name: 'USDT', + // sellAmount: '1500000000', // 1500 USDT + // buyAmount: '20000000000000000000', // 20 BNB + // }, + // { + // name: 'BNB', + // sellAmount: '20000000000000000000', // 20 BNB + // buyAmount: '1500000000', // 1500 USDT + // }, + // ], + // ] + // .map((pair, i, arr) => [ + // [pair], + // [ + // arr[i].map(token => ({ + // ...token, + // sellAmount: token.sellAmount + '0', + // buyAmount: token.buyAmount + '0', + // })), + // ], + // ]) + // .flat(2), + // [Network.POLYGON]: [ + // [ + // { + // name: 'WETH', + // sellAmount: '1500000000000000000', // 1.5 WETH + // buyAmount: '250000000000000000000000', // 250K SDEX + // }, + // { + // name: 'SDEX', + // sellAmount: '250000000000000000000000', // 250K SDEX + // buyAmount: '1500000000000000000', // 1.5 WETH + // }, + // ], + // [ + // { + // name: 'USDC', + // sellAmount: '2500000000', // 2500 USDC + // buyAmount: '300000000000000000000000', // 300K SDEX + // }, + // { + // name: 'SDEX', + // sellAmount: '300000000000000000000000', // 300K SDEX + // buyAmount: '2500000000', // 2500 USDC + // }, + // ], + // [ + // { + // name: 'USDC', + // sellAmount: '2500000000', // 2500 USDC + // buyAmount: '8000000000000000000000', // 8000 MATIC + // }, + // { + // name: 'MATIC', + // sellAmount: '8000000000000000000000', // 8000 MATIC + // buyAmount: '2500000000', // 2500 USDC + // }, + // ], + // [ + // { + // name: 'SDEX', + // sellAmount: '9000000', // 0.09 WBTC + // buyAmount: '190000000000000000000000', // 190K SDEX + // }, + // { + // name: 'WBTC', + // sellAmount: '190000000000000000000000', // 190K SDEX + // buyAmount: '9000000', // 0.09 WBTC + // }, + // ], + // ] + // .map((pair, i, arr) => [ + // [pair], + // [ + // arr[i].map(token => ({ + // ...token, + // sellAmount: token.sellAmount + '0', + // buyAmount: token.buyAmount + '0', + // })), + // ], + // ]) + // .flat(2), + }; - // multiply all amounts by 10 - const pairsBigAmount: { name: string; sellAmount: string; buyAmount: string }[][] = - pairsSmallAmount.map((pair) => - pair.map((token) => ({ ...token, sellAmount: token.sellAmount + '0', buyAmount: token.buyAmount + '0' })), + // TODO add Base network when available + Object.keys(allPairs).forEach( + netKey => { + const network = Number(netKey); + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, ); + describe(`Smardex Swap on Chain ${network}`, () => { + const dexKey = 'Smardex'; - // copy smallAmount and bigAmount into the same array alternatively to get same pairs together - const pairs = pairsSmallAmount.map((small, index) => ([small, pairsBigAmount[index]])).flat(1); + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, // TODO: uncomment when Adapter is ready to enable Multiswap + // ContractMethod.megaSwap, // TODO: uncomment when Adapter is ready to enable Megaswap + ], + ], + [SwapSide.BUY, [ContractMethod.simpleBuy]], + ]); - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - contractMethods.forEach((contractMethod: ContractMethod) => { - pairs.forEach(pair => { - describe(`${contractMethod}`, () => { - it(`${pair[0].name} -> ${pair[1].name}`, async () => { - await testE2E( - tokens[pair[0].name], - tokens[pair[1].name], - holders[pair[0].name], - side === SwapSide.SELL - ? pair[0].sellAmount - : pair[0].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${pair[1].name} -> ${pair[0].name}`, async () => { - await testE2E( - tokens[pair[1].name], - tokens[pair[0].name], - holders[pair[1].name], - side === SwapSide.SELL - ? pair[1].sellAmount - : pair[1].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + allPairs[network].forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); }); }); - }); - }); - }), - ); - }); + }), + ); + }); + }, + ); }); From e09a426e79e0de60f8b887b412e357f8ee190e72 Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 12 Sep 2023 14:37:06 +0200 Subject: [PATCH 266/833] tests: multichain tests on ethereum and polygon --- src/dex/smardex/smardex-events.test.ts | 189 ++++++++++++++++--------- 1 file changed, 119 insertions(+), 70 deletions(-) diff --git a/src/dex/smardex/smardex-events.test.ts b/src/dex/smardex/smardex-events.test.ts index 52e625de0..33c6ca603 100644 --- a/src/dex/smardex/smardex-events.test.ts +++ b/src/dex/smardex/smardex-events.test.ts @@ -1,11 +1,12 @@ /* eslint-disable no-console */ import dotenv from 'dotenv'; import { Interface } from '@ethersproject/abi'; +import { Tokens } from '../../../tests/constants-e2e'; dotenv.config(); import SmardexPoolLayerOneABI from '../../abi/smardex/layer-1/smardex-pool.json'; -// import SmardexPoolLayerTwoABI from '../../abi/smardex/layer-2/smardex-pool.json'; -import { SmardexEventPool } from './smardex'; +import SmardexPoolLayerTwoABI from '../../abi/smardex/layer-2/smardex-pool.json'; +import { Smardex, SmardexEventPool } from './smardex'; import { Network } from '../../constants'; import { DummyDexHelper } from '../../dex-helper/index'; import { testEventSubscriber } from '../../../tests/utils-events'; @@ -13,8 +14,74 @@ import { SmardexPoolState } from './types'; jest.setTimeout(120 * 1000); const dexKey = 'Smardex'; -const network = Network.MAINNET; -// const config = SmardexConfig[dexKey][network]; + +type NetworkConfig = { + name: 'ethereum' | 'polygon' | 'bsc' | 'arbitrum'; + network: Network; + tokens: typeof Tokens[Network]; + pools: Array<{ + address: string; + symbol0: string; + symbol1: string; + events: { + [event: string]: number[]; + }; + }>; +}; + +const NETWORK_CONFIGS: NetworkConfig[] = [ + { + name: 'ethereum', + network: Network.MAINNET, + tokens: Tokens[Network.MAINNET], + pools: [ + { + address: '0xd2bf378cea07fe117ffdfd3f5b7e53c2b0b78c05', + symbol0: 'SDEX', + symbol1: 'USDT', + events: { + ['Swap']: [ + 18064045, + 18064060, + 18064194, + 18065266, + 18066464, // the last one contains multiple Swap events + ], + ['Burn']: [17231921, 17762042, 17762668], + ['Mint']: [17739609, 17973926, 18062443], + // ['FeesChanged']: [], // none on L1 + ['Sync']: [ + 18064045, + 18064060, + 18064194, + 18065266, + 18066464, // the last one contains multiple Snyc events + ], + ['Transfer']: [18064025, 18064045, 18065266], + }, + }, + ], + }, + { + name: 'polygon', + network: Network.POLYGON, + tokens: Tokens[Network.POLYGON], + pools: [ + { + address: '0x77476148B72ECB4E9f6A3cDDC5dd437Df1F003F3', + symbol0: 'USDC', + symbol1: 'SDEX', + events: { + ['Swap']: [47436997, 47437089, 47437096, 47445056, 47445066], + ['Burn']: [47423778, 47334674, 46807911], + ['Mint']: [47417315, 47414686, 47288517], + ['FeesChanged']: [45861051], + ['Sync']: [47436997, 47437089, 47437096, 47445056, 47445066], + }, + }, + ], + }, +]; async function fetchPoolStateFromContractAtBlock( smardexEventPool: SmardexEventPool, @@ -31,76 +98,58 @@ async function fetchPoolStateFromContractAtBlock( return state; } -describe('Smardex Ethereum SDEX-USDT Pool Event', function () { - const poolAddress = '0xd2bf378cea07fe117ffdfd3f5b7e53c2b0b78c05'; // sdex-usdt - const token0 = { - address: '0x5de8ab7e27f6e7a1fff3e5b337584aa43961beef', - decimals: 18, - }; - const token1 = { - address: '0xdac17f958d2ee523a2206206994597c13d831ec7', - decimals: 6, - }; - - const blockNumbers: { [eventName: string]: number[] } = { - ['Swap']: [ - 18064045, - 18064060, - 18064194, - 18065266, - 18066464, // the last one contains multiple Swap events - ], - ['Burn']: [17231921, 17762042, 17762668], - ['Mint']: [17739609, 17973926, 18062443], - // ['FeesChanged']: [], // none on L1 - ['Sync']: [ - 18064045, - 18064060, - 18064194, - 18065266, - 18066464, // the last one contains multiple Snyc events - ], - ['Transfer']: [18064025, 18064045, 18065266], - }; +NETWORK_CONFIGS.forEach(({ name, network, pools, tokens }) => { + describe(`Events Tests on ${name}`, function () { + pools.forEach(({ address, events, symbol0, symbol1 }) => { + describe(`${symbol0} <> ${symbol1}`, function () { + const poolAddress = address; + const token0 = tokens[symbol0]; + const token1 = tokens[symbol1]; + // events in the same block must update the same element + Object.keys(events).forEach((event: string) => { + events[event].forEach((blockNumber: number) => { + it(`${event}:${blockNumber} - should return correct state`, async function () { + const dexHelper = new DummyDexHelper(network); - // events in the same block must update the same element - describe('SmardexEventPool ethereum', function () { - Object.keys(blockNumbers).forEach((event: string) => { - blockNumbers[event].forEach((blockNumber: number) => { - it(`${event}:${blockNumber} - should return correct state`, async function () { - const dexHelper = new DummyDexHelper(network); - - const logger = dexHelper.getLogger(dexKey); - - const SmardexPool = new SmardexEventPool( - new Interface(SmardexPoolLayerOneABI), - dexHelper, - poolAddress, - token0, - token1, - logger, - undefined, - undefined, - ); + const logger = dexHelper.getLogger(dexKey); + const smardex = new Smardex(network, dexKey, dexHelper); + const multicall = smardex.getFeesMultiCallData(poolAddress); + const SmardexPool = new SmardexEventPool( + new Interface( + smardex.isLayer1() + ? SmardexPoolLayerOneABI + : SmardexPoolLayerTwoABI, + ), + dexHelper, + poolAddress, + token0, + token1, + logger, + multicall?.callEntry, + multicall?.callDecoder, + smardex.isLayer1(), + ); - // It is done in generateState. But here have to make it manually - SmardexPool.poolAddress = poolAddress.toLowerCase(); - SmardexPool.addressesSubscribed[0] = poolAddress.toLowerCase(); + // It is done in generateState. But here have to make it manually + SmardexPool.poolAddress = poolAddress.toLowerCase(); + SmardexPool.addressesSubscribed[0] = poolAddress.toLowerCase(); - await testEventSubscriber( - SmardexPool, - SmardexPool.addressesSubscribed, - (_blockNumber: number) => - fetchPoolStateFromContractAtBlock( + await testEventSubscriber( SmardexPool, - _blockNumber, - poolAddress, - logger, - ), - blockNumber, - `${dexKey}_${poolAddress}`, - dexHelper.provider, - ); + SmardexPool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolStateFromContractAtBlock( + SmardexPool, + _blockNumber, + poolAddress, + logger, + ), + blockNumber, + `${dexKey}_${poolAddress}`, + dexHelper.provider, + ); + }); + }); }); }); }); From b58ef07717cafc91a5106acc1bef7895a47edbe4 Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 12 Sep 2023 14:44:15 +0200 Subject: [PATCH 267/833] fix: fees dynamic --- src/dex/smardex/smardex.ts | 70 +++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 6a4828286..003791cf1 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -76,7 +76,11 @@ export class SmardexEventPool extends StatefulEventSubscriber target: string; callData: string; }, - protected smardexFeesMulticallDecoder?: (values: any[]) => number[], + protected smardexFeesMulticallDecoder?: (values: any[]) => { + feesLp: number; + feesPool: number; + }, + private isLayerOne = true, ) { super( 'Smardex', @@ -94,14 +98,13 @@ export class SmardexEventPool extends StatefulEventSubscriber feesPool: number; priceAverageLastTimestamp: number; }> { - const dynamicFees = !!this.smardexFeesMultiCallEntry; let calldata = [ { target: this.poolAddress, callData: this.poolInterface.encodeFunctionData('getPriceAverage', []), }, ]; - if (dynamicFees) { + if (!this.isLayerOne) { calldata.push(this.smardexFeesMultiCallEntry!); } @@ -116,12 +119,12 @@ export class SmardexEventPool extends StatefulEventSubscriber )[2]; return { - feesLp: dynamicFees - ? this.smardexFeesMulticallDecoder!(data.returnData[1])[0] - : 500, - feesPool: dynamicFees - ? this.smardexFeesMulticallDecoder!(data.returnData[1])[1] - : 200, + feesLp: this.isLayerOne + ? 500 + : this.smardexFeesMulticallDecoder!(data.returnData[1]).feesLp, + feesPool: this.isLayerOne + ? 200 + : this.smardexFeesMulticallDecoder!(data.returnData[1]).feesPool, priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), }; } @@ -134,7 +137,9 @@ export class SmardexEventPool extends StatefulEventSubscriber log: Readonly, ): Promise | null> { if (!Object.values(TOPICS).includes(log.topics[0] as TOPICS)) return null; - const event = smardexPoolL1.parseLog(log); + const event = this.isLayerOne + ? smardexPoolL1.parseLog(log) + : smardexPoolL2.parseLog(log); switch (event.name) { case 'Sync': const fetchedSync = await this.fetchPairFeesAndLastTimestamp( @@ -160,7 +165,7 @@ export class SmardexEventPool extends StatefulEventSubscriber priceAverage0: state.priceAverage0, priceAverage1: state.priceAverage1, priceAverageLastTimestamp: state.priceAverageLastTimestamp, - feesLp: event.args.feesLp.toNumber(), + feesLp: event.args.feesLP.toNumber(), feesPool: event.args.feesPool.toNumber(), }; // case 'Swap': @@ -184,7 +189,6 @@ export class SmardexEventPool extends StatefulEventSubscriber blockNumber: number | 'latest' = 'latest', ): Promise> { const coder = new AbiCoder(); - const dynamicFees = !!this.smardexFeesMultiCallEntry; let calldata = [ { target: this.poolAddress, @@ -202,7 +206,7 @@ export class SmardexEventPool extends StatefulEventSubscriber callData: this.poolInterface.encodeFunctionData('getPriceAverage', []), }, ]; - if (dynamicFees) { + if (!this.isLayerOne) { calldata.push(this.smardexFeesMultiCallEntry!); } @@ -232,12 +236,12 @@ export class SmardexEventPool extends StatefulEventSubscriber priceAverage0: priceAverage0.toString(), priceAverage1: priceAverage1.toString(), priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), - feesLp: dynamicFees - ? this.smardexFeesMulticallDecoder!(data.returnData[3])[0] - : 500, - feesPool: dynamicFees - ? this.smardexFeesMulticallDecoder!(data.returnData[3])[1] - : 200, + feesLp: this.isLayerOne + ? 500 + : this.smardexFeesMulticallDecoder!(data.returnData[3]).feesLp, + feesPool: this.isLayerOne + ? 200 + : this.smardexFeesMulticallDecoder!(data.returnData[3]).feesPool, }; } } @@ -611,17 +615,26 @@ export class Smardex } // On Smardex the fees are upgradable on layer 2. - protected getFeesMultiCallData(pair: SmardexPair) { + public getFeesMultiCallData(pairAddress: string) { if (this.isLayer1()) { return null; } const callEntry = { - target: pair.exchange!, + target: pairAddress, callData: smardexPoolL2.encodeFunctionData('getPairFees'), }; - const callDecoder = (values: any[]): number[] => - smardexPoolL2.decodeFunctionResult('getPairFees', values) as number[]; - + const callDecoder = ( + values: any[], + ): { feesLp: number; feesPool: number } => { + const feesData = smardexPoolL2.decodeFunctionResult( + 'getPairFees', + values, + ); + return { + feesLp: feesData[0].toNumber(), + feesPool: feesData[1].toNumber(), + }; + }; return { callEntry, callDecoder, @@ -641,7 +654,7 @@ export class Smardex blockNumber: number, priceAverageLastTimestamp: number, ) { - const multiCallFeeData = this.getFeesMultiCallData(pair); + const multiCallFeeData = this.getFeesMultiCallData(pair.exchange!); pair.pool = new SmardexEventPool( this.isLayer1() ? smardexPoolL1 : smardexPoolL2, this.dexHelper, @@ -652,6 +665,7 @@ export class Smardex // For layer 2 we need to fetch the fees multiCallFeeData?.callEntry, multiCallFeeData?.callDecoder, + this.isLayer1(), ); pair.pool.addressesSubscribed.push(pair.exchange!); @@ -676,7 +690,7 @@ export class Smardex ): Promise { try { const multiCallFeeData = pairs.map(pair => - this.getFeesMultiCallData(pair), + this.getFeesMultiCallData(pair.exchange!), ); const calldata = pairs .map((pair, i) => { @@ -730,10 +744,10 @@ export class Smardex .toString(), feesLp: this.isLayer1() ? 500 - : multiCallFeeData[i]!.callDecoder(returnData[i][3])[0], + : multiCallFeeData[i]!.callDecoder(returnData[i][3]).feesLp, feesPool: this.isLayer1() ? 200 - : multiCallFeeData[i]!.callDecoder(returnData[i][3])[1], + : multiCallFeeData[i]!.callDecoder(returnData[i][3]).feesPool, })); } catch (e) { this.logger.error( From caa724f1124c48da02d03d076ae55bc5a8d881d9 Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 12 Sep 2023 16:05:31 +0200 Subject: [PATCH 268/833] tests(events): add bsc and arbitrum --- src/dex/smardex/smardex-events.test.ts | 108 ++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/src/dex/smardex/smardex-events.test.ts b/src/dex/smardex/smardex-events.test.ts index 33c6ca603..5be7eea21 100644 --- a/src/dex/smardex/smardex-events.test.ts +++ b/src/dex/smardex/smardex-events.test.ts @@ -55,11 +55,37 @@ const NETWORK_CONFIGS: NetworkConfig[] = [ 18064060, 18064194, 18065266, - 18066464, // the last one contains multiple Snyc events + 18066464, // the last one contains multiple Sync events ], ['Transfer']: [18064025, 18064045, 18065266], }, }, + + { + address: '0xf3a4B8eFe3e3049F6BC71B47ccB7Ce6665420179', + symbol0: 'SDEX', + symbol1: 'ETH', + events: { + ['Swap']: [ + 18120396, + 18120367, // multiple Swap events + 18119305, + 18118991, + 18120209, + ], + ['Burn']: [18114357, 18089610, 18026115], + ['Mint']: [18115825, 18109975, 18093408], + // ['FeesChanged']: [], // none on L1 + ['Sync']: [ + 18120396, + 18120367, // multiple Sync events + 18119305, + 18118991, + 18120209, + ], + ['Transfer']: [18108643, 18105778, 18105793], + }, + }, ], }, { @@ -77,6 +103,86 @@ const NETWORK_CONFIGS: NetworkConfig[] = [ ['Mint']: [47417315, 47414686, 47288517], ['FeesChanged']: [45861051], ['Sync']: [47436997, 47437089, 47437096, 47445056, 47445066], + ['Transfer']: [47423778, 47403369, 47343062], + }, + }, + { + address: '0x7130d1Ab6d9C657240331A4DE3e88b5497Be9cEB', + symbol0: 'WMATIC', + symbol1: 'USDC', + events: { + ['Swap']: [47448993, 47449888, 47449861, 47448993, 47449214], + ['Burn']: [47434291, 47433030, 47426957], + ['Mint']: [47354112, 47268128, 47252146], + ['FeesChanged']: [], // Fees didn't change on this pool + ['Sync']: [47448993, 47449888, 47449861, 47448993, 47449214], + ['Transfer']: [47338250, 47338178, 47333469], + }, + }, + ], + }, + { + name: 'arbitrum', + network: Network.ARBITRUM, + tokens: Tokens[Network.ARBITRUM], + pools: [ + { + address: '0xacCDd9EE1DCd393E346e5d6350230439b4DA09ab', + symbol0: 'SDEX', + symbol1: 'USDC', + events: { + ['Swap']: [130424308, 130422563, 130418994, 130415253, 130382808], + ['Burn']: [129969327, 129138853, 126200497], + ['Mint']: [130028302, 129940404, 129728771], + ['FeesChanged']: [], // Fees didn't change on this pool + ['Sync']: [130424308, 130422563, 130418994, 130415253, 130382808], + ['Transfer']: [130028373, 129918802, 129668897], + }, + }, + { + address: '0xD87899d10Eaa10F3adE05038A38251F758E5C0eb', + symbol0: 'ARB', + symbol1: 'USDC', + events: { + ['Swap']: [130429535, 130419879, 130417306, 130414469, 130416990], + ['Burn']: [130200966, 127933595, 125698828], + ['Mint']: [130263032, 130331095, 128594710], + ['FeesChanged']: [], // Fees didn't change on this pool + ['Sync']: [130429535, 130419879, 130417306, 130414469, 130416990], + ['Transfer']: [130423567, 130423514, 130331095], + }, + }, + ], + }, + { + name: 'bsc', + network: Network.BSC, + tokens: Tokens[Network.BSC], + pools: [ + { + address: '0xe7b89CbD4E833510F393CCfbE7D433EDbb137aB2', + symbol0: 'USDT', + symbol1: 'SDEX', + events: { + ['Swap']: [31678152, 31678000, 31674992, 31670581, 31675013], + ['Burn']: [31660547, 31655719, 31539131], + ['Mint']: [31652485, 31595468, 31571640], + ['FeesChanged']: [30531399], + ['Sync']: [31678152, 31678000, 31674992, 31670581, 31675013], + ['Transfer']: [31660547, 31655777, 31655736], + }, + }, + { + address: '0xf315833053a1187fd5e9813E38BD59937492857a', + symbol0: 'USDT', + symbol1: 'BNB', + events: { + ['Swap']: [31678534, 31675409, 31678534, 31675014, 31674391], + ['Burn']: [31666734, 31586726, 31462652], + ['Mint']: [31662048, 31554796, 31524123], + ['FeesChanged']: [], // Fees didn't change on this pool + ['Sync']: [31678534, 31675409, 31678534, 31675014, 31674391], + ['Transfer']: [31666734, 31632200, 31586970], }, }, ], From c6a6bae8965e09c5f8975449a39c8fdd8da1406a Mon Sep 17 00:00:00 2001 From: julien Date: Tue, 12 Sep 2023 16:28:24 +0200 Subject: [PATCH 269/833] rm: unused --- src/dex/smardex/smardex.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 02dc2ba0a..7e573502d 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -1,5 +1,4 @@ import { AbiCoder, Interface } from '@ethersproject/abi'; -import { BigNumber, utils } from 'ethers'; import _ from 'lodash'; import { DeepReadonly } from 'ts-essentials'; import { Contract } from 'web3-eth-contract'; @@ -36,7 +35,6 @@ import { getBigIntPow, getDexKeysWithNetwork, isETHAddress, - prependWithOx, } from '../../utils'; import SmardexFactoryLayerOneABI from '../../abi/smardex/layer-1/smardex-factory.json'; import SmardexFactoryLayerTwoABI from '../../abi/smardex/layer-2/smardex-factory.json'; From dbdf970eda689911ded6b795dd4598587f7befbc Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 12 Sep 2023 16:44:42 +0200 Subject: [PATCH 270/833] chore: smardex fees clean up --- src/dex/smardex/smardex.ts | 84 ++++++++++++++++++-------------------- src/dex/smardex/types.ts | 12 +++--- 2 files changed, 46 insertions(+), 50 deletions(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 003791cf1..95fcb8e8a 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -27,17 +27,13 @@ import { } from '../../types'; import { IDexHelper } from '../../dex-helper/index'; import { + SmardexFees, SmardexPair, SmardexPool, SmardexPoolOrderedParams, SmardexPoolState, } from './types'; -import { - getBigIntPow, - getDexKeysWithNetwork, - isETHAddress, - prependWithOx, -} from '../../utils'; +import { getBigIntPow, getDexKeysWithNetwork, isETHAddress } from '../../utils'; import SmardexFactoryLayerOneABI from '../../abi/smardex/layer-1/smardex-factory.json'; import SmardexFactoryLayerTwoABI from '../../abi/smardex/layer-2/smardex-factory.json'; import SmardexPoolLayerOneABI from '../../abi/smardex/layer-1/smardex-pool.json'; @@ -62,6 +58,12 @@ import { computeAmountIn, computeAmountOut } from './sdk/core'; const smardexPoolL1 = new Interface(SmardexPoolLayerOneABI); const smardexPoolL2 = new Interface(SmardexPoolLayerTwoABI); +// On layer 1, the fees are not upgradable +const feesLayerOne: SmardexFees = { + feesLP: 500n, + feesPool: 200n, +}; + const coder = new AbiCoder(); export class SmardexEventPool extends StatefulEventSubscriber { @@ -76,10 +78,7 @@ export class SmardexEventPool extends StatefulEventSubscriber target: string; callData: string; }, - protected smardexFeesMulticallDecoder?: (values: any[]) => { - feesLp: number; - feesPool: number; - }, + protected smardexFeesMulticallDecoder?: (values: any[]) => SmardexFees, private isLayerOne = true, ) { super( @@ -94,8 +93,8 @@ export class SmardexEventPool extends StatefulEventSubscriber } async fetchPairFeesAndLastTimestamp(blockNumber: number): Promise<{ - feesLp: number; - feesPool: number; + feesLP: bigint; + feesPool: bigint; priceAverageLastTimestamp: number; }> { let calldata = [ @@ -118,13 +117,12 @@ export class SmardexEventPool extends StatefulEventSubscriber data.returnData[0], )[2]; + const fees = this.isLayerOne + ? feesLayerOne + : this.smardexFeesMulticallDecoder!(data.returnData[1]); return { - feesLp: this.isLayerOne - ? 500 - : this.smardexFeesMulticallDecoder!(data.returnData[1]).feesLp, - feesPool: this.isLayerOne - ? 200 - : this.smardexFeesMulticallDecoder!(data.returnData[1]).feesPool, + feesLP: fees.feesLP, + feesPool: fees.feesPool, priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), }; } @@ -153,7 +151,7 @@ export class SmardexEventPool extends StatefulEventSubscriber priceAverage0: event.args.priceAverage0.toString(), priceAverage1: event.args.priceAverage1.toString(), priceAverageLastTimestamp: fetchedSync.priceAverageLastTimestamp, - feesLp: fetchedSync.feesLp, + feesLP: fetchedSync.feesLP, feesPool: fetchedSync.feesPool, }; case 'FeesChanged': // only triggerd on L2 @@ -165,8 +163,8 @@ export class SmardexEventPool extends StatefulEventSubscriber priceAverage0: state.priceAverage0, priceAverage1: state.priceAverage1, priceAverageLastTimestamp: state.priceAverageLastTimestamp, - feesLp: event.args.feesLP.toNumber(), - feesPool: event.args.feesPool.toNumber(), + feesLP: BigInt(event.args.feesLP), + feesPool: BigInt(event.args.feesPool), }; // case 'Swap': // const fetchedSwap = await this.fetchPairFeesAndLastTimestamp(log.blockNumber); @@ -178,7 +176,7 @@ export class SmardexEventPool extends StatefulEventSubscriber // priceAverage0: state.priceAverage0, // priceAverage1: state.priceAverage1, // priceAverageLastTimestamp: fetchedSwap.priceAverageLastTimestamp, - // feesLp: fetchedSwap.feesLp, + // feesLP: fetchedSwap.feesLP, // feesPool: fetchedSwap.feesPool, // }; } @@ -228,6 +226,10 @@ export class SmardexEventPool extends StatefulEventSubscriber const [priceAverage0, priceAverage1, priceAverageLastTimestamp] = coder.decode(['uint256', 'uint256', 'uint256'], data.returnData[2]); + const fees = this.isLayerOne + ? feesLayerOne + : this.smardexFeesMulticallDecoder!(data.returnData[3]); + return { reserves0: reserves0.toString(), reserves1: reserves1.toString(), @@ -236,12 +238,8 @@ export class SmardexEventPool extends StatefulEventSubscriber priceAverage0: priceAverage0.toString(), priceAverage1: priceAverage1.toString(), priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), - feesLp: this.isLayerOne - ? 500 - : this.smardexFeesMulticallDecoder!(data.returnData[3]).feesLp, - feesPool: this.isLayerOne - ? 200 - : this.smardexFeesMulticallDecoder!(data.returnData[3]).feesPool, + feesLP: fees.feesLP, + feesPool: fees.feesPool, }; } } @@ -493,7 +491,7 @@ export class Smardex +priceParams.priceAverageLastTimestamp, priceParams.priceAverage0, priceParams.priceAverage1, - priceParams.feesLp, + priceParams.feesLP, priceParams.feesPool, ).amount; @@ -520,7 +518,7 @@ export class Smardex +priceParams.priceAverageLastTimestamp, priceParams.priceAverage0, priceParams.priceAverage1, - priceParams.feesLp, + priceParams.feesLP, priceParams.feesPool, ).amount; @@ -605,7 +603,7 @@ export class Smardex pairState.fictiveReserves1, pairState.priceAverage0, pairState.priceAverage1, - pairState.feesLp, + pairState.feesLP, pairState.feesPool, blockNumber, pairState.priceAverageLastTimestamp, @@ -623,16 +621,14 @@ export class Smardex target: pairAddress, callData: smardexPoolL2.encodeFunctionData('getPairFees'), }; - const callDecoder = ( - values: any[], - ): { feesLp: number; feesPool: number } => { + const callDecoder = (values: any[]): SmardexFees => { const feesData = smardexPoolL2.decodeFunctionResult( 'getPairFees', values, ); return { - feesLp: feesData[0].toNumber(), - feesPool: feesData[1].toNumber(), + feesLP: feesData.feesLP_.toBigInt(), + feesPool: feesData.feesPool_.toBigInt(), }; }; return { @@ -649,8 +645,8 @@ export class Smardex fictiveReserves1: string, priceAverage0: string, priceAverage1: string, - feesLp: number, - feesPool: number, + feesLp: bigint, + feesPool: bigint, blockNumber: number, priceAverageLastTimestamp: number, ) { @@ -677,7 +673,7 @@ export class Smardex fictiveReserves1, priceAverage0, priceAverage1, - feesLp, + feesLP: feesLp, feesPool, priceAverageLastTimestamp, }, @@ -742,11 +738,11 @@ export class Smardex priceAverageLastTimestamp: coder .decode(['uint256', 'uint256', 'uint256'], returnData[i][2])[2] .toString(), - feesLp: this.isLayer1() - ? 500 - : multiCallFeeData[i]!.callDecoder(returnData[i][3]).feesLp, + feesLP: this.isLayer1() + ? feesLayerOne.feesLP + : multiCallFeeData[i]!.callDecoder(returnData[i][3]).feesLP, feesPool: this.isLayer1() - ? 200 + ? feesLayerOne.feesPool : multiCallFeeData[i]!.callDecoder(returnData[i][3]).feesPool, })); } catch (e) { @@ -863,7 +859,7 @@ export class Smardex priceAverage1: BigInt(pairState.priceAverage1), priceAverageLastTimestamp: pairState.priceAverageLastTimestamp, exchange: pair.exchange, - feesLp: BigInt(pairState.feesLp), + feesLP: BigInt(pairState.feesLP), feesPool: BigInt(pairState.feesPool), }; } diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index c1a11b750..fe80b80d2 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -7,7 +7,7 @@ import { import { UniswapV2Pair } from '../uniswap-v2/uniswap-v2'; import { type SmardexEventPool } from './smardex'; -export interface SmardexPoolState { +export interface SmardexPoolState extends SmardexFees { reserves0: string; reserves1: string; fictiveReserves0: string; @@ -15,8 +15,6 @@ export interface SmardexPoolState { priceAverage0: string; priceAverage1: string; priceAverageLastTimestamp: number; - feesLp: number; - feesPool: number; } // export interface SmardexData extends UniswapV2Data { @@ -45,7 +43,11 @@ export type SmardexParam = SellOnSmardexParam | BuyOnSmardexParam; export type DexParams = Omit; -export interface SmardexPoolOrderedParams { +export type SmardexFees = { + feesLP: bigint; + feesPool: bigint; +}; +export interface SmardexPoolOrderedParams extends SmardexFees { fromToken: string; toToken: string; token0: string; @@ -58,8 +60,6 @@ export interface SmardexPoolOrderedParams { priceAverage1: bigint; priceAverageLastTimestamp: number; exchange: string; - feesLp: bigint; - feesPool: bigint; } export interface SmardexPair extends Omit { From e335eafa6dab9bccd18173d63e5d3231c53b3c7c Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 12 Sep 2023 18:36:00 +0100 Subject: [PATCH 271/833] 2.35.3-quick-perps-proxy.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 55739ce6e..717db1967 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.2", + "version": "2.35.3-quick-perps-proxy.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 68bb5369c8a0401b5ed4acf582953f01d9a4d42e Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Tue, 12 Sep 2023 22:08:24 -0400 Subject: [PATCH 272/833] start --- src/dex/solidly-v3/config.ts | 15 ++ src/dex/solidly-v3/solidly-v3-e2e.test.ts | 162 +++++++++++ src/dex/solidly-v3/solidly-v3-events.test.ts | 106 ++++++++ .../solidly-v3/solidly-v3-integration.test.ts | 251 ++++++++++++++++++ src/dex/solidly-v3/solidly-v3-pool.ts | 91 +++++++ src/dex/solidly-v3/solidly-v3.ts | 178 +++++++++++++ src/dex/solidly-v3/types.ts | 22 ++ 7 files changed, 825 insertions(+) create mode 100644 src/dex/solidly-v3/config.ts create mode 100644 src/dex/solidly-v3/solidly-v3-e2e.test.ts create mode 100644 src/dex/solidly-v3/solidly-v3-events.test.ts create mode 100644 src/dex/solidly-v3/solidly-v3-integration.test.ts create mode 100644 src/dex/solidly-v3/solidly-v3-pool.ts create mode 100644 src/dex/solidly-v3/solidly-v3.ts create mode 100644 src/dex/solidly-v3/types.ts diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts new file mode 100644 index 000000000..9516279e5 --- /dev/null +++ b/src/dex/solidly-v3/config.ts @@ -0,0 +1,15 @@ +import { DexParams } from './types'; +import { DexConfigMap, AdapterMappings } from '../../types'; +import { Network, SwapSide } from '../../constants'; + +export const SolidlyV3Config: DexConfigMap = { + SolidlyV3: { + // TODO: complete me! + }, +}; + +export const Adapters: Record = { + // TODO: add adapters for each chain + // This is an example to copy + [Network.MAINNET]: { [SwapSide.SELL]: [{ name: '', index: 0 }] }, +}; diff --git a/src/dex/solidly-v3/solidly-v3-e2e.test.ts b/src/dex/solidly-v3/solidly-v3-e2e.test.ts new file mode 100644 index 000000000..7069dd5ca --- /dev/null +++ b/src/dex/solidly-v3/solidly-v3-e2e.test.ts @@ -0,0 +1,162 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { testE2E } from '../../../tests/utils-e2e'; +import { + Tokens, + Holders, + NativeTokenSymbols, +} from '../../../tests/constants-e2e'; +import { Network, ContractMethod, SwapSide } from '../../constants'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; + +/* + README + ====== + + This test script should add e2e tests for SolidlyV3. The tests + should cover as many cases as possible. Most of the DEXes follow + the following test structure: + - DexName + - ForkName + Network + - ContractMethod + - ETH -> Token swap + - Token -> ETH swap + - Token -> Token swap + + The template already enumerates the basic structure which involves + testing simpleSwap, multiSwap, megaSwap contract methods for + ETH <> TOKEN and TOKEN <> TOKEN swaps. You should replace tokenA and + tokenB with any two highly liquid tokens on SolidlyV3 for the tests + to work. If the tokens that you would like to use are not defined in + Tokens or Holders map, you can update the './tests/constants-e2e' + + Other than the standard cases that are already added by the template + it is highly recommended to add test cases which could be specific + to testing SolidlyV3 (Eg. Tests based on poolType, special tokens, + etc). + + You can run this individual test script by running: + `npx jest src/dex//-e2e.test.ts` + + e2e tests use the Tenderly fork api. Please add the following to your + .env file: + TENDERLY_TOKEN=Find this under Account>Settings>Authorization. + TENDERLY_ACCOUNT_ID=Your Tenderly account name. + TENDERLY_PROJECT=Name of a Tenderly project you have created in your + dashboard. + + (This comment should be removed from the final implementation) +*/ + +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + // TODO: Add any direct swap contractMethod name if it exists + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + // TODO: If buy is not supported remove the buy contract methods + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }), + ); + }); +} + +describe('SolidlyV3 E2E', () => { + const dexKey = 'SolidlyV3'; + + describe('Mainnet', () => { + const network = Network.MAINNET; + + // TODO: Modify the tokenASymbol, tokenBSymbol, tokenAAmount; + const tokenASymbol: string = 'tokenASymbol'; + const tokenBSymbol: string = 'tokenBSymbol'; + + const tokenAAmount: string = 'tokenAAmount'; + const tokenBAmount: string = 'tokenBAmount'; + const nativeTokenAmount = '1000000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + + // TODO: Add any additional test cases required to test SolidlyV3 + }); +}); diff --git a/src/dex/solidly-v3/solidly-v3-events.test.ts b/src/dex/solidly-v3/solidly-v3-events.test.ts new file mode 100644 index 000000000..223cdfec6 --- /dev/null +++ b/src/dex/solidly-v3/solidly-v3-events.test.ts @@ -0,0 +1,106 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { SolidlyV3EventPool } from './solidly-v3-pool'; +import { Network } from '../../constants'; +import { Address } from '../../types'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { testEventSubscriber } from '../../../tests/utils-events'; +import { PoolState } from './types'; + +/* + README + ====== + + This test script adds unit tests for SolidlyV3 event based + system. This is done by fetching the state on-chain before the + event block, manually pushing the block logs to the event-subscriber, + comparing the local state with on-chain state. + + Most of the logic for testing is abstracted by `testEventSubscriber`. + You need to do two things to make the tests work: + + 1. Fetch the block numbers where certain events were released. You + can modify the `./scripts/fetch-event-blocknumber.ts` to get the + block numbers for different events. Make sure to get sufficient + number of blockNumbers to cover all possible cases for the event + mutations. + + 2. Complete the implementation for fetchPoolState function. The + function should fetch the on-chain state of the event subscriber + using just the blocknumber. + + The template tests only include the test for a single event + subscriber. There can be cases where multiple event subscribers + exist for a single DEX. In such cases additional tests should be + added. + + You can run this individual test script by running: + `npx jest src/dex//-events.test.ts` + + (This comment should be removed from the final implementation) +*/ + +jest.setTimeout(50 * 1000); + +async function fetchPoolState( + solidlyV3Pools: SolidlyV3EventPool, + blockNumber: number, + poolAddress: string, +): Promise { + // TODO: complete me! + return {}; +} + +// eventName -> blockNumbers +type EventMappings = Record; + +describe('SolidlyV3 EventPool Mainnet', function () { + const dexKey = 'SolidlyV3'; + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + const logger = dexHelper.getLogger(dexKey); + let solidlyV3Pool: SolidlyV3EventPool; + + // poolAddress -> EventMappings + const eventsToTest: Record = { + // TODO: complete me! + }; + + beforeEach(async () => { + solidlyV3Pool = new SolidlyV3EventPool( + dexKey, + network, + dexHelper, + logger, + /* TODO: Put here additional constructor arguments if needed */ + ); + }); + + Object.entries(eventsToTest).forEach( + ([poolAddress, events]: [string, EventMappings]) => { + describe(`Events for ${poolAddress}`, () => { + Object.entries(events).forEach( + ([eventName, blockNumbers]: [string, number[]]) => { + describe(`${eventName}`, () => { + blockNumbers.forEach((blockNumber: number) => { + it(`State after ${blockNumber}`, async function () { + await testEventSubscriber( + solidlyV3Pool, + solidlyV3Pool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolState(solidlyV3Pool, _blockNumber, poolAddress), + blockNumber, + `${dexKey}_${poolAddress}`, + dexHelper.provider, + ); + }); + }); + }); + }, + ); + }); + }, + ); +}); diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts new file mode 100644 index 000000000..8ffe7758d --- /dev/null +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -0,0 +1,251 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { Interface, Result } from '@ethersproject/abi'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { Network, SwapSide } from '../../constants'; +import { BI_POWS } from '../../bigint-constants'; +import { SolidlyV3 } from './solidly-v3'; +import { + checkPoolPrices, + checkPoolsLiquidity, + checkConstantPoolPrices, +} from '../../../tests/utils'; +import { Tokens } from '../../../tests/constants-e2e'; + +/* + README + ====== + + This test script adds tests for SolidlyV3 general integration + with the DEX interface. The test cases below are example tests. + It is recommended to add tests which cover SolidlyV3 specific + logic. + + You can run this individual test script by running: + `npx jest src/dex//-integration.test.ts` + + (This comment should be removed from the final implementation) +*/ + +function getReaderCalldata( + exchangeAddress: string, + readerIface: Interface, + amounts: bigint[], + funcName: string, + // TODO: Put here additional arguments you need +) { + return amounts.map(amount => ({ + target: exchangeAddress, + callData: readerIface.encodeFunctionData(funcName, [ + // TODO: Put here additional arguments to encode them + amount, + ]), + })); +} + +function decodeReaderResult( + results: Result, + readerIface: Interface, + funcName: string, +) { + // TODO: Adapt this function for your needs + return results.map(result => { + const parsed = readerIface.decodeFunctionResult(funcName, result); + return BigInt(parsed[0]._hex); + }); +} + +async function checkOnChainPricing( + solidlyV3: SolidlyV3, + funcName: string, + blockNumber: number, + prices: bigint[], + amounts: bigint[], +) { + const exchangeAddress = ''; // TODO: Put here the real exchange address + + // TODO: Replace dummy interface with the real one + // Normally you can get it from solidlyV3.Iface or from eventPool. + // It depends on your implementation + const readerIface = new Interface(''); + + const readerCallData = getReaderCalldata( + exchangeAddress, + readerIface, + amounts.slice(1), + funcName, + ); + const readerResult = ( + await solidlyV3.dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blockNumber) + ).returnData; + + const expectedPrices = [0n].concat( + decodeReaderResult(readerResult, readerIface, funcName), + ); + + expect(prices).toEqual(expectedPrices); +} + +async function testPricingOnNetwork( + solidlyV3: SolidlyV3, + network: Network, + dexKey: string, + blockNumber: number, + srcTokenSymbol: string, + destTokenSymbol: string, + side: SwapSide, + amounts: bigint[], + funcNameToCheck: string, +) { + const networkTokens = Tokens[network]; + + const pools = await solidlyV3.getPoolIdentifiers( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + side, + blockNumber, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await solidlyV3.getPricesVolume( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + amounts, + side, + blockNumber, + pools, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + if (solidlyV3.hasConstantPriceLargeAmounts) { + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + } else { + checkPoolPrices(poolPrices!, amounts, side, dexKey); + } + + // Check if onchain pricing equals to calculated ones + await checkOnChainPricing( + solidlyV3, + funcNameToCheck, + blockNumber, + poolPrices![0].prices, + amounts, + ); +} + +describe('SolidlyV3', function () { + const dexKey = 'SolidlyV3'; + let blockNumber: number; + let solidlyV3: SolidlyV3; + + describe('Mainnet', () => { + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + + // TODO: Put here token Symbol to check against + // Don't forget to update relevant tokens in constant-e2e.ts + const srcTokenSymbol = 'srcTokenSymbol'; + const destTokenSymbol = 'destTokenSymbol'; + + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals], + 2n * BI_POWS[tokens[destTokenSymbol].decimals], + 3n * BI_POWS[tokens[destTokenSymbol].decimals], + 4n * BI_POWS[tokens[destTokenSymbol].decimals], + 5n * BI_POWS[tokens[destTokenSymbol].decimals], + 6n * BI_POWS[tokens[destTokenSymbol].decimals], + 7n * BI_POWS[tokens[destTokenSymbol].decimals], + 8n * BI_POWS[tokens[destTokenSymbol].decimals], + 9n * BI_POWS[tokens[destTokenSymbol].decimals], + 10n * BI_POWS[tokens[destTokenSymbol].decimals], + ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + solidlyV3 = new SolidlyV3(network, dexKey, dexHelper); + if (solidlyV3.initializePricing) { + await solidlyV3.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + solidlyV3, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + '', // TODO: Put here proper function name to check pricing + ); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + solidlyV3, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + '', // TODO: Put here proper function name to check pricing + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newSolidlyV3 = new SolidlyV3(network, dexKey, dexHelper); + if (newSolidlyV3.updatePoolState) { + await newSolidlyV3.updatePoolState(); + } + const poolLiquidity = await newSolidlyV3.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newSolidlyV3.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); + }); +}); diff --git a/src/dex/solidly-v3/solidly-v3-pool.ts b/src/dex/solidly-v3/solidly-v3-pool.ts new file mode 100644 index 000000000..827b6bde1 --- /dev/null +++ b/src/dex/solidly-v3/solidly-v3-pool.ts @@ -0,0 +1,91 @@ +import { Interface } from '@ethersproject/abi'; +import { DeepReadonly } from 'ts-essentials'; +import { Log, Logger } from '../../types'; +import { catchParseLogError } from '../../utils'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { PoolState } from './types'; + +export class SolidlyV3EventPool extends StatefulEventSubscriber { + handlers: { + [event: string]: ( + event: any, + state: DeepReadonly, + log: Readonly, + ) => DeepReadonly | null; + } = {}; + + logDecoder: (log: Log) => any; + + addressesSubscribed: string[]; + + constructor( + readonly parentName: string, + protected network: number, + protected dexHelper: IDexHelper, + logger: Logger, + protected solidlyV3Iface = new Interface( + '' /* TODO: Import and put here SolidlyV3 ABI */, + ), // TODO: add any additional params required for event subscriber + ) { + // TODO: Add pool name + super(parentName, 'POOL_NAME', dexHelper, logger); + + // TODO: make logDecoder decode logs that + this.logDecoder = (log: Log) => this.solidlyV3Iface.parseLog(log); + this.addressesSubscribed = [ + /* subscribed addresses */ + ]; + + // Add handlers + this.handlers['myEvent'] = this.handleMyEvent.bind(this); + } + + /** + * The function is called every time any of the subscribed + * addresses release log. The function accepts the current + * state, updates the state according to the log, and returns + * the updated state. + * @param state - Current state of event subscriber + * @param log - Log released by one of the subscribed addresses + * @returns Updates state of the event subscriber after the log + */ + protected processLog( + state: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + try { + const event = this.logDecoder(log); + if (event.name in this.handlers) { + return this.handlers[event.name](event, state, log); + } + } catch (e) { + catchParseLogError(e, this.logger); + } + + return null; + } + + /** + * The function generates state using on-chain calls. This + * function is called to regenerate state if the event based + * system fails to fetch events and the local state is no + * more correct. + * @param blockNumber - Blocknumber for which the state should + * should be generated + * @returns state of the event subscriber at blocknumber + */ + async generateState(blockNumber: number): Promise> { + // TODO: complete me! + return {}; + } + + // Its just a dummy example + handleMyEvent( + event: any, + state: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + return null; + } +} diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts new file mode 100644 index 000000000..d632bdded --- /dev/null +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -0,0 +1,178 @@ +import { AsyncOrSync } from 'ts-essentials'; +import { + Token, + Address, + ExchangePrices, + PoolPrices, + AdapterExchangeParam, + SimpleExchangeParam, + PoolLiquidity, + Logger, +} from '../../types'; +import { SwapSide, Network } from '../../constants'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { getDexKeysWithNetwork } from '../../utils'; +import { IDex } from '../../dex/idex'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { SolidlyV3Data } from './types'; +import { SimpleExchange } from '../simple-exchange'; +import { SolidlyV3Config, Adapters } from './config'; +import { SolidlyV3EventPool } from './solidly-v3-pool'; + +export class SolidlyV3 extends SimpleExchange implements IDex { + protected eventPools: SolidlyV3EventPool; + + readonly hasConstantPriceLargeAmounts = false; + // TODO: set true here if protocols works only with wrapped asset + readonly needWrapNative = true; + + readonly isFeeOnTransferSupported = false; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(SolidlyV3Config); + + logger: Logger; + + constructor( + readonly network: Network, + readonly dexKey: string, + readonly dexHelper: IDexHelper, + protected adapters = Adapters[network] || {}, // TODO: add any additional optional params to support other fork DEXes + ) { + super(dexHelper, dexKey); + this.logger = dexHelper.getLogger(dexKey); + this.eventPools = new SolidlyV3EventPool( + dexKey, + network, + dexHelper, + this.logger, + ); + } + + // Initialize pricing is called once in the start of + // pricing service. It is intended to setup the integration + // for pricing requests. It is optional for a DEX to + // implement this function + async initializePricing(blockNumber: number) { + // TODO: complete me! + } + + // Returns the list of contract adapters (name and index) + // for a buy/sell. Return null if there are no adapters. + getAdapters(side: SwapSide): { name: string; index: number }[] | null { + return this.adapters[side] ? this.adapters[side] : null; + } + + // Returns list of pool identifiers that can be used + // for a given swap. poolIdentifiers must be unique + // across DEXes. It is recommended to use + // ${dexKey}_${poolAddress} as a poolIdentifier + async getPoolIdentifiers( + srcToken: Token, + destToken: Token, + side: SwapSide, + blockNumber: number, + ): Promise { + // TODO: complete me! + return []; + } + + // Returns pool prices for amounts. + // If limitPools is defined only pools in limitPools + // should be used. If limitPools is undefined then + // any pools can be used. + async getPricesVolume( + srcToken: Token, + destToken: Token, + amounts: bigint[], + side: SwapSide, + blockNumber: number, + limitPools?: string[], + ): Promise> { + // TODO: complete me! + return null; + } + + // Returns estimated gas cost of calldata for this DEX in multiSwap + getCalldataGasCost(poolPrices: PoolPrices): number | number[] { + // TODO: update if there is any payload in getAdapterParam + return CALLDATA_GAS_COST.DEX_NO_PAYLOAD; + } + + // Encode params required by the exchange adapter + // Used for multiSwap, buy & megaSwap + // Hint: abiCoder.encodeParameter() could be useful + getAdapterParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: SolidlyV3Data, + side: SwapSide, + ): AdapterExchangeParam { + // TODO: complete me! + const { exchange } = data; + + // Encode here the payload for adapter + const payload = ''; + + return { + targetExchange: exchange, + payload, + networkFee: '0', + }; + } + + // Encode call data used by simpleSwap like routers + // Used for simpleSwap & simpleBuy + // Hint: this.buildSimpleParamWithoutWETHConversion + // could be useful + async getSimpleParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: SolidlyV3Data, + side: SwapSide, + ): Promise { + // TODO: complete me! + const { exchange } = data; + + // Encode here the transaction arguments + const swapData = ''; + + return this.buildSimpleParamWithoutWETHConversion( + srcToken, + srcAmount, + destToken, + destAmount, + swapData, + exchange, + ); + } + + // This is called once before getTopPoolsForToken is + // called for multiple tokens. This can be helpful to + // update common state required for calculating + // getTopPoolsForToken. It is optional for a DEX + // to implement this + async updatePoolState(): Promise { + // TODO: complete me! + } + + // Returns list of top pools based on liquidity. Max + // limit number pools should be returned. + async getTopPoolsForToken( + tokenAddress: Address, + limit: number, + ): Promise { + //TODO: complete me! + return []; + } + + // This is optional function in case if your implementation has acquired any resources + // you need to release for graceful shutdown. For example, it may be any interval timer + releaseResources(): AsyncOrSync { + // TODO: complete me! + } +} diff --git a/src/dex/solidly-v3/types.ts b/src/dex/solidly-v3/types.ts new file mode 100644 index 000000000..306817ec7 --- /dev/null +++ b/src/dex/solidly-v3/types.ts @@ -0,0 +1,22 @@ +import { Address } from '../../types'; + +export type PoolState = { + // TODO: poolState is the state of event + // subscriber. This should be the minimum + // set of parameters required to compute + // pool prices. Complete me! +}; + +export type SolidlyV3Data = { + // TODO: SolidlyV3Data is the dex data that is + // returned by the API that can be used for + // tx building. The data structure should be minimal. + // Complete me! + exchange: Address; +}; + +export type DexParams = { + // TODO: DexParams is set of parameters the can + // be used to initiate a DEX fork. + // Complete me! +}; From 02e847e2115d733dbdf65760cbade2bbab851655 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Tue, 12 Sep 2023 23:04:38 -0400 Subject: [PATCH 273/833] start config --- src/dex/solidly-v3/config.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index 9516279e5..627cd7abd 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -4,7 +4,11 @@ import { Network, SwapSide } from '../../constants'; export const SolidlyV3Config: DexConfigMap = { SolidlyV3: { - // TODO: complete me! + [Network.MAINNET]: { + factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', + subgraphURL: + 'https://thegraph.com/hosted-service/subgraph/fromif/solidly-v3', + }, }, }; From d22b1d2a54ffe7e2e44b23cffba56d487fbbf345 Mon Sep 17 00:00:00 2001 From: julien Date: Wed, 13 Sep 2023 08:15:31 +0200 Subject: [PATCH 274/833] fix: e2e test + added SDEX holder L2 --- src/dex/smardex/smardex-e2e.test.ts | 324 ++++++++++++++-------------- tests/constants-e2e.ts | 5 +- 2 files changed, 166 insertions(+), 163 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index 634e47257..70301dc95 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -78,171 +78,171 @@ describe('Smardex E2E', () => { ], ]) .flat(2), - // [Network.ARBITRUM]: [ - // [ - // { - // name: 'WETH', - // sellAmount: '1500000000000000000', // 1.5 WETH - // buyAmount: '250000000000000000000000', // 250K SDEX - // }, - // { - // name: 'SDEX', - // sellAmount: '250000000000000000000000', // 250K SDEX - // buyAmount: '1500000000000000000', // 1.5 WETH - // }, - // ], - // [ - // { - // name: 'USDT', - // sellAmount: '1200000000', // 1200 USDT - // buyAmount: '300000000000000000000000', // 300K SDEX - // }, - // { - // name: 'SDEX', - // sellAmount: '300000000000000000000000', // 300K SDEX - // buyAmount: '1200000000', // 1200 USDT - // }, - // ], - // [ - // { - // name: 'WBTC', - // sellAmount: '30000000', // 0.3 WBTC - // buyAmount: '2500000000000000000', // 2.5 WETH - // }, - // { - // name: 'WETH', - // sellAmount: '2500000000000000000', // 2.5 WETH - // buyAmount: '30000000', // 0.3 WBTC - // }, - // ], - // ] - // .map((pair, i, arr) => [ - // [pair], - // [ - // arr[i].map(token => ({ - // ...token, - // sellAmount: token.sellAmount + '0', - // buyAmount: token.buyAmount + '0', - // })), - // ], - // ]) - // .flat(2), - // [Network.BSC]: [ - // [ - // { - // name: 'USDT', - // sellAmount: '1200000000', // 1200 USDT - // buyAmount: '300000000000000000000000', // 300K SDEX - // }, - // { - // name: 'SDEX', - // sellAmount: '300000000000000000000000', // 300K SDEX - // buyAmount: '1200000000', // 1200 USDT - // }, - // ], - // [ - // { - // name: 'SDEX', - // sellAmount: '5000000', // 005 WBTC - // buyAmount: '300000000000000000000000', // 300K SDEX - // }, - // { - // name: 'bBTC', - // sellAmount: '300000000000000000000000', // 300K SDEX - // buyAmount: '5000000', // 0.05 WBTC - // }, - // ], - // [ - // { - // name: 'USDT', - // sellAmount: '1500000000', // 1500 USDT - // buyAmount: '20000000000000000000', // 20 BNB - // }, - // { - // name: 'BNB', - // sellAmount: '20000000000000000000', // 20 BNB - // buyAmount: '1500000000', // 1500 USDT - // }, - // ], - // ] - // .map((pair, i, arr) => [ - // [pair], - // [ - // arr[i].map(token => ({ - // ...token, - // sellAmount: token.sellAmount + '0', - // buyAmount: token.buyAmount + '0', - // })), - // ], - // ]) - // .flat(2), - // [Network.POLYGON]: [ - // [ - // { - // name: 'WETH', - // sellAmount: '1500000000000000000', // 1.5 WETH - // buyAmount: '250000000000000000000000', // 250K SDEX - // }, - // { - // name: 'SDEX', - // sellAmount: '250000000000000000000000', // 250K SDEX - // buyAmount: '1500000000000000000', // 1.5 WETH - // }, - // ], - // [ - // { - // name: 'USDC', - // sellAmount: '2500000000', // 2500 USDC - // buyAmount: '300000000000000000000000', // 300K SDEX - // }, - // { - // name: 'SDEX', - // sellAmount: '300000000000000000000000', // 300K SDEX - // buyAmount: '2500000000', // 2500 USDC - // }, - // ], - // [ - // { - // name: 'USDC', - // sellAmount: '2500000000', // 2500 USDC - // buyAmount: '8000000000000000000000', // 8000 MATIC - // }, - // { - // name: 'MATIC', - // sellAmount: '8000000000000000000000', // 8000 MATIC - // buyAmount: '2500000000', // 2500 USDC - // }, - // ], - // [ - // { - // name: 'SDEX', - // sellAmount: '9000000', // 0.09 WBTC - // buyAmount: '190000000000000000000000', // 190K SDEX - // }, - // { - // name: 'WBTC', - // sellAmount: '190000000000000000000000', // 190K SDEX - // buyAmount: '9000000', // 0.09 WBTC - // }, - // ], - // ] - // .map((pair, i, arr) => [ - // [pair], - // [ - // arr[i].map(token => ({ - // ...token, - // sellAmount: token.sellAmount + '0', - // buyAmount: token.buyAmount + '0', - // })), - // ], - // ]) - // .flat(2), + [Network.ARBITRUM]: [ + [ + { + name: 'WETH', + sellAmount: '1500000000000000000', // 1.5 WETH + buyAmount: '250000000000000000000000', // 250K SDEX + }, + { + name: 'SDEX', + sellAmount: '250000000000000000000000', // 250K SDEX + buyAmount: '1500000000000000000', // 1.5 WETH + }, + ], + [ + { + name: 'USDC', + sellAmount: '1200000000', // 1200 USDC + buyAmount: '300000000000000000000000', // 300K SDEX + }, + { + name: 'SDEX', + sellAmount: '300000000000000000000000', // 300K SDEX + buyAmount: '1200000000', // 1200 USDC + }, + ], + [ + { + name: 'WBTC', + sellAmount: '30000000', // 0.3 WBTC + buyAmount: '110000000000000000000', // 110 SDEX + }, + { + name: 'SDEX', + sellAmount: '110000000000000000000', // 110 SDEX + buyAmount: '30000000', // 0.3 WBTC + }, + ], + ] + .map((pair, i, arr) => [ + [pair], + [ + arr[i].map(token => ({ + ...token, + sellAmount: token.sellAmount + '0', + buyAmount: token.buyAmount + '0', + })), + ], + ]) + .flat(2), + [Network.BSC]: [ + [ + { + name: 'USDT', + sellAmount: '1200000000', // 1200 USDT + buyAmount: '300000000000000000000000', // 300K SDEX + }, + { + name: 'SDEX', + sellAmount: '300000000000000000000000', // 300K SDEX + buyAmount: '1200000000', // 1200 USDT + }, + ], + [ + { + name: 'SDEX', + sellAmount: '5000000', // 005 WBTC + buyAmount: '300000000000000000000000', // 300K SDEX + }, + { + name: 'bBTC', + sellAmount: '300000000000000000000000', // 300K SDEX + buyAmount: '5000000', // 0.05 WBTC + }, + ], + [ + { + name: 'USDT', + sellAmount: '1500000000', // 1500 USDT + buyAmount: '20000000000000000000', // 20 BNB + }, + { + name: 'BNB', + sellAmount: '20000000000000000000', // 20 BNB + buyAmount: '1500000000', // 1500 USDT + }, + ], + ] + .map((pair, i, arr) => [ + [pair], + [ + arr[i].map(token => ({ + ...token, + sellAmount: token.sellAmount + '0', + buyAmount: token.buyAmount + '0', + })), + ], + ]) + .flat(2), + [Network.POLYGON]: [ + [ + { + name: 'WETH', + sellAmount: '1500000000000000000', // 1.5 WETH + buyAmount: '250000000000000000000000', // 250K SDEX + }, + { + name: 'SDEX', + sellAmount: '250000000000000000000000', // 250K SDEX + buyAmount: '1500000000000000000', // 1.5 WETH + }, + ], + [ + { + name: 'USDC', + sellAmount: '2500000000', // 2500 USDC + buyAmount: '300000000000000000000000', // 300K SDEX + }, + { + name: 'SDEX', + sellAmount: '300000000000000000000000', // 300K SDEX + buyAmount: '2500000000', // 2500 USDC + }, + ], + [ + { + name: 'USDC', + sellAmount: '2500000000', // 2500 USDC + buyAmount: '8000000000000000000000', // 8000 MATIC + }, + { + name: 'MATIC', + sellAmount: '8000000000000000000000', // 8000 MATIC + buyAmount: '2500000000', // 2500 USDC + }, + ], + [ + { + name: 'SDEX', + sellAmount: '9000000', // 0.09 WBTC + buyAmount: '190000000000000000000000', // 190K SDEX + }, + { + name: 'WBTC', + sellAmount: '190000000000000000000000', // 190K SDEX + buyAmount: '9000000', // 0.09 WBTC + }, + ], + ] + .map((pair, i, arr) => [ + [pair], + [ + arr[i].map(token => ({ + ...token, + sellAmount: token.sellAmount + '0', + buyAmount: token.buyAmount + '0', + })), + ], + ]) + .flat(2), }; // TODO add Base network when available - Object.keys(allPairs).forEach( - netKey => { - const network = Number(netKey); + const networkKeys = [Network.MAINNET, Network.ARBITRUM, Network.BSC, Network.POLYGON]; + networkKeys.forEach( + network => { const tokens = Tokens[network]; const holders = Holders[network]; const provider = new StaticJsonRpcProvider( diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 23453baae..0c821f6c7 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -880,7 +880,6 @@ export const Holders: { } = { [Network.MAINNET]: { ETH: '0x176F3DAb24a159341c0509bB36B833E7fdd0a132', - SDEX: '0xE03c726340ccB2FbBAF6ca91533Ab64e64Fb9d4A', USDC: '0x79E2Ba942B0e8fDB6ff3d406e930289d10B49ADe', WBTC: '0x1cb17a66dc606a52785f69f08f4256526abd4943', sBTC: '0xA2e3475D13776C6E42ff37B47286827d959B2195', @@ -940,6 +939,7 @@ export const Holders: { crvUSD: '0xA920De414eA4Ab66b97dA1bFE9e6EcA7d4219635', GHO: '0x844Dc85EdD8492A56228D293cfEbb823EF3E10EC', wibBTC: '0xFbdCA68601f835b27790D98bbb8eC7f05FDEaA9B', + SDEX: '0xE03c726340ccB2FbBAF6ca91533Ab64e64Fb9d4A', }, [Network.ROPSTEN]: { ETH: '0x43262A12d8610AA70C15DbaeAC321d51613c9071', @@ -975,6 +975,7 @@ export const Holders: { amUSDT: '0x832b11846a27b3ba25d68ae80c39fab155d18c49', amUSDC: '0x6e7f19cd23049c7118e14470e2bf85d2e26ee0ae', MAI: '0x9a8cf02f3e56c664ce75e395d0e4f3dc3dafe138', + SDEX: '0xB0470cF15B22a6A32c49a7C20E3821B944A76058', }, [Network.FANTOM]: { DAI: '0x370f4b2dcf75c94d8d4450b493661a9c6170d0b5', @@ -1011,6 +1012,7 @@ export const Holders: { anyBTC: '0x4ffef8e8a75c20ab0ddf96c50d2457277d27923c', nUSD: '0x28ec0b36f0819ecb5005cab836f4ed5a2eca4d13', axlUSD: '0xc03fbeda9069b22a120ae6a09349a0b5eea5570a', + SDEX: '0xB0470cF15B22a6A32c49a7C20E3821B944A76058', }, [Network.AVALANCHE]: { AVAX: '0xD6216fC19DB775Df9774a6E33526131dA7D19a2c', @@ -1067,6 +1069,7 @@ export const Holders: { ZYB: '0x3ec0eddcd1e25025077327886a78133589082fb2', WBTC: '0xd9d611c6943585bc0e18e51034af8fa28778f7da', RDNT: '0x62383739d68dd0f844103db8dfb05a7eded5bbe6', + SDEX: '0xb0470cf15b22a6a32c49a7c20e3821b944a76058', }, [Network.OPTIMISM]: { ETH: '0x9ef21bE1C270AA1c3c3d750F458442397fBFFCB6', From 8c096a2172d764aee2f1fd0a6afd5237d7395e70 Mon Sep 17 00:00:00 2001 From: julien Date: Wed, 13 Sep 2023 11:03:28 +0200 Subject: [PATCH 275/833] fix: e2e values --- src/dex/smardex/smardex-e2e.test.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index 4af89693a..f398aaa5e 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -106,13 +106,13 @@ describe('Smardex E2E', () => { [ { name: 'WBTC', - sellAmount: '30000000', // 0.3 WBTC - buyAmount: '110000000000000000000', // 110 SDEX + sellAmount: '5000000', // 0.05 WBTC + buyAmount: '31000000000000000000000', // 31K SDEX }, { name: 'SDEX', - sellAmount: '110000000000000000000', // 110 SDEX - buyAmount: '30000000', // 0.3 WBTC + sellAmount: '31000000000000000000000', // 31K SDEX + buyAmount: '5000000', // 0.05 WBTC }, ], ] @@ -143,13 +143,13 @@ describe('Smardex E2E', () => { [ { name: 'SDEX', - sellAmount: '5000000', // 005 WBTC - buyAmount: '300000000000000000000000', // 300K SDEX + sellAmount: '300000000000000000000000', // 300K SDEX + buyAmount: '50000000000000000', // 0.05 bBTC }, { name: 'bBTC', - sellAmount: '300000000000000000000000', // 300K SDEX - buyAmount: '5000000', // 0.05 WBTC + sellAmount: '50000000000000000', // 0.05 bBTC + buyAmount: '300000000000000000000000', // 300K SDEX }, ], [ @@ -216,13 +216,13 @@ describe('Smardex E2E', () => { [ { name: 'SDEX', - sellAmount: '9000000', // 0.09 WBTC - buyAmount: '190000000000000000000000', // 190K SDEX + sellAmount: '190000000000000000000000', // 190K SDEX + buyAmount: '8000000', // 0.08 WBTC }, { name: 'WBTC', - sellAmount: '190000000000000000000000', // 190K SDEX - buyAmount: '9000000', // 0.09 WBTC + sellAmount: '8000000', // 0.08 WBTC + buyAmount: '190000000000000000000000', // 190K SDEX }, ], ] From 0ff3c79675c19678491ff025b93a571333fe69f8 Mon Sep 17 00:00:00 2001 From: julien Date: Wed, 13 Sep 2023 11:03:48 +0200 Subject: [PATCH 276/833] fix: lint --- src/dex/smardex/smardex-e2e.test.ts | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index f398aaa5e..793700ff6 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -240,17 +240,21 @@ describe('Smardex E2E', () => { }; // TODO add Base network when available - const networkKeys = [Network.MAINNET, Network.ARBITRUM, Network.BSC, Network.POLYGON]; - networkKeys.forEach( - network => { - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - describe(`Smardex Swap on Chain ${network}`, () => { - const dexKey = 'Smardex'; + const networkKeys = [ + Network.MAINNET, + Network.ARBITRUM, + Network.BSC, + Network.POLYGON, + ]; + networkKeys.forEach(network => { + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + describe(`Smardex Swap on Chain ${network}`, () => { + const dexKey = 'Smardex'; const sideToContractMethods = new Map([ [ From d2f93ea9f3bd975a32e0f2178e55ff182fb71a06 Mon Sep 17 00:00:00 2001 From: julien Date: Wed, 13 Sep 2023 11:29:13 +0200 Subject: [PATCH 277/833] fix: USDT on BSC --- src/dex/smardex/smardex-e2e.test.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index 793700ff6..a00cea52a 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -131,13 +131,13 @@ describe('Smardex E2E', () => { [ { name: 'USDT', - sellAmount: '1200000000', // 1200 USDT + sellAmount: '1200000000000000000000', // 1200 USDT buyAmount: '300000000000000000000000', // 300K SDEX }, { name: 'SDEX', sellAmount: '300000000000000000000000', // 300K SDEX - buyAmount: '1200000000', // 1200 USDT + buyAmount: '120000000000000000000', // 1200 USDT }, ], [ @@ -155,13 +155,13 @@ describe('Smardex E2E', () => { [ { name: 'USDT', - sellAmount: '1500000000', // 1500 USDT + sellAmount: '1500000000000000000000', // 1500 USDT buyAmount: '20000000000000000000', // 20 BNB }, { name: 'BNB', sellAmount: '20000000000000000000', // 20 BNB - buyAmount: '1500000000', // 1500 USDT + buyAmount: '1500000000000000000000', // 1500 USDT }, ], ] @@ -311,3 +311,5 @@ describe('Smardex E2E', () => { }); }); }); +/* +# What's changed From 1f2269c571a60c936ae3a8e7bbb9e2d9e4affae3 Mon Sep 17 00:00:00 2001 From: julien Date: Wed, 13 Sep 2023 11:42:29 +0200 Subject: [PATCH 278/833] fix: comment --- src/dex/smardex/smardex.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index dfb8e43e6..11b491b42 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -379,7 +379,7 @@ export class Smardex const unitAmount = getBigIntPow(isSell ? from.decimals : to.decimals); - // TODO SMARDEX does not support Fees on Transfer Tokens + // SmarDex does not support Fees on Transfer Tokens const [unitVolumeWithFee, ...amountsWithFee] = applyTransferFee( [unitAmount, ...amounts], side, From e0d83af23ea7df9cead426bfc954ae0476a60057 Mon Sep 17 00:00:00 2001 From: julien Date: Wed, 13 Sep 2023 11:59:18 +0200 Subject: [PATCH 279/833] rm: comment --- src/dex/smardex/smardex-e2e.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index a00cea52a..af3ae5613 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -311,5 +311,3 @@ describe('Smardex E2E', () => { }); }); }); -/* -# What's changed From f81f135c7e5de645fb80799557964f8ca9f3b711 Mon Sep 17 00:00:00 2001 From: Esteban Date: Wed, 13 Sep 2023 12:05:55 +0200 Subject: [PATCH 280/833] chore(api-key): rename the smardex key env var --- src/dex/smardex/smardex.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 11b491b42..4c511119a 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -990,7 +990,7 @@ export class Smardex variables: { token: tokenAddress.toLowerCase(), limit }, }, SUBGRAPH_TIMEOUT, - { 'x-api-key': process.env.SDEX_SUBGRAPH_APIKEY! }, + { 'x-api-key': process.env.API_KEY_SMARDEX_SUBGRAPH! }, ); if (!(data && data.pools0 && data.pools1)) From d854cfda4a4ca5cbbcc5527b0de786be0a6187f3 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 13 Sep 2023 15:17:47 +0100 Subject: [PATCH 281/833] fix: add more logs to QuickPerps --- src/dex/quick-perps/pool.ts | 1 + src/dex/quick-perps/quick-perps.ts | 80 +++++++++++++++++------------- 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/src/dex/quick-perps/pool.ts b/src/dex/quick-perps/pool.ts index 022686655..26fe455ba 100644 --- a/src/dex/quick-perps/pool.ts +++ b/src/dex/quick-perps/pool.ts @@ -104,6 +104,7 @@ export class QuickPerpsEventPool extends ComposedEventSubscriber { const evenState = this.getState(blockNumber); if (evenState) return evenState; const onChainState = await this.generateState(blockNumber); + this.logger.warn(`State is generated in RPC fallback call`); this.setState(onChainState, blockNumber); return onChainState; } diff --git a/src/dex/quick-perps/quick-perps.ts b/src/dex/quick-perps/quick-perps.ts index ac0e4e0c3..0cbefeea7 100644 --- a/src/dex/quick-perps/quick-perps.ts +++ b/src/dex/quick-perps/quick-perps.ts @@ -117,45 +117,55 @@ export class QuickPerps extends SimpleExchange implements IDex { limitPools?: string[], ): Promise> { if (side === SwapSide.BUY || !this.pool) return null; - const srcAddress = this.dexHelper.config - .wrapETH(srcToken) - .address.toLowerCase(); - const destAddress = this.dexHelper.config - .wrapETH(destToken) - .address.toLowerCase(); - if ( - srcAddress === destAddress || - !( - this.supportedTokensMap[srcAddress] && - this.supportedTokensMap[destAddress] + try { + const srcAddress = this.dexHelper.config + .wrapETH(srcToken) + .address.toLowerCase(); + const destAddress = this.dexHelper.config + .wrapETH(destToken) + .address.toLowerCase(); + if ( + srcAddress === destAddress || + !( + this.supportedTokensMap[srcAddress] && + this.supportedTokensMap[destAddress] + ) ) - ) - return null; - const srcPoolIdentifier = `${this.dexKey}_${srcAddress}`; - const destPoolIdentifier = `${this.dexKey}_${destAddress}`; - const pools = [srcPoolIdentifier, destPoolIdentifier]; - if (limitPools && pools.some(p => !limitPools.includes(p))) return null; + return null; + const srcPoolIdentifier = `${this.dexKey}_${srcAddress}`; + const destPoolIdentifier = `${this.dexKey}_${destAddress}`; + const pools = [srcPoolIdentifier, destPoolIdentifier]; + if (limitPools && pools.some(p => !limitPools.includes(p))) return null; - const unitVolume = getBigIntPow(srcToken.decimals); - const prices = await this.pool.getAmountOut( - srcAddress, - destAddress, - [unitVolume, ...amounts], - blockNumber, - ); + const unitVolume = getBigIntPow(srcToken.decimals); + const prices = await this.pool.getAmountOut( + srcAddress, + destAddress, + [unitVolume, ...amounts], + blockNumber, + ); - if (!prices) return null; + if (!prices) return null; - return [ - { - prices: prices.slice(1), - unit: prices[0], - gasCost: QuickPerpsGasCost, - exchange: this.dexKey, - data: {}, - poolAddresses: [this.params.vault], - }, - ]; + return [ + { + prices: prices.slice(1), + unit: prices[0], + gasCost: QuickPerpsGasCost, + exchange: this.dexKey, + data: {}, + poolAddresses: [this.params.vault], + }, + ]; + } catch (e) { + this.logger.error( + `Error_getPrices ${srcToken.symbol || srcToken.address}, ${ + destToken.symbol || destToken.address + }, ${side}: `, + e, + ); + return null; + } } // Returns estimated gas cost of calldata for this DEX in multiSwap From 4704f8c3a50306a208886f50739dcc659b85068b Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 13 Sep 2023 15:18:28 +0100 Subject: [PATCH 282/833] 2.35.3-quick-perps-proxy.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 717db1967..9981907ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.3-quick-perps-proxy.0", + "version": "2.35.3-quick-perps-proxy.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1b2ed239db654e414410c2f3e1a0a3397f21f1e1 Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Wed, 13 Sep 2023 20:43:36 +0300 Subject: [PATCH 283/833] fix(BACK-1264): adapt config for prod contracts --- src/config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index ef6b679cd..9c3d7369b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -354,9 +354,9 @@ const baseConfigs: { [network: number]: BaseConfig } = { nativeTokenSymbol: 'ETH', wrappedNativeTokenAddress: '0x4200000000000000000000000000000000000006', hasEIP1559: false, - augustusAddress: '0x793a0Bb089c6787e84277f08179DAC594eDb9443', + augustusAddress: '0x59C7C832e96D2568bea6db468C1aAdcbbDa08A52', augustusRFQAddress: '0xa003dFBA51C9e1e56C67ae445b852bdEd7aC5EEd', - tokenTransferProxyAddress: '0xCADa28FC80ceB3baF3BEa4C2d7a819e69435907E', + tokenTransferProxyAddress: '0x93aAAe79a53759cD164340E4C8766E4Db5331cD7', multicallV2Address: '0xeDF6D2a16e8081F777eB623EeB4411466556aF3d', privateHttpProvider: process.env.HTTP_PROVIDER_8453, hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', From d187d03b24977325675b3f061da759c84c7f6dc9 Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Wed, 13 Sep 2023 20:45:44 +0300 Subject: [PATCH 284/833] fix(BACK-1264): increment dex-lib version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 311c8f8e4..f715ae85f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.3-base-support.0", + "version": "2.35.3-base-support.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 2b1d3383a2e709b087035678b2cb3236b5c5e1b2 Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Thu, 14 Sep 2023 15:34:47 +0300 Subject: [PATCH 285/833] feat(BACK-1264): Change subgraph url for base --- package.json | 2 +- src/dex/uniswap-v3/config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f715ae85f..c103ce8db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.3-base-support.1", + "version": "2.35.3-base-support.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index 4a503e9f4..116c7c7e7 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -117,7 +117,7 @@ export const UniswapV3Config: DexConfigMap = { initRetryFrequency: 10, initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, subgraphURL: - 'https://api.thegraph.com/subgraphs/name/lynnshaoyu/uniswap-v3-base', + 'https://api.studio.thegraph.com/query/48211/uniswap-v3-base/version/latest', }, }, SushiSwapV3: { From 6714ef8a0eb94caceda2a3279f7379de755bdb28 Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 14 Sep 2023 14:25:50 +0100 Subject: [PATCH 286/833] feat: add locking to state generate --- src/stateful-event-subscriber.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/stateful-event-subscriber.ts b/src/stateful-event-subscriber.ts index e76e47ffc..5a05b70c7 100644 --- a/src/stateful-event-subscriber.ts +++ b/src/stateful-event-subscriber.ts @@ -51,6 +51,8 @@ export abstract class StatefulEventSubscriber private _lastPublishedTimeMs: number = 0; + private isForcedGenerateStateIsRunning = false; + constructor( public readonly parentName: string, _name: string, @@ -95,8 +97,16 @@ export abstract class StatefulEventSubscriber this.logger.debug( `${this.parentName}: ${this.name}: forced to regenerate state`, ); - const state = await this.generateState(blockNumber); - this.setState(state, blockNumber); + if (this.isForcedGenerateStateIsRunning) { + return; + } + this.isForcedGenerateStateIsRunning = true; + try { + const state = await this.generateState(blockNumber); + this.setState(state, blockNumber); + } finally { + this.isForcedGenerateStateIsRunning = false; + } } else { if (this.dexHelper.config.isSlave && this.masterPoolNeeded) { let stateAsString = await this.dexHelper.cache.hget( From c0eb94ef261833e8a0da64e9bd1bf194462a4f22 Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 14 Sep 2023 14:26:34 +0100 Subject: [PATCH 287/833] 2.35.3-quick-perps-proxy.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9981907ac..a4be68104 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.3-quick-perps-proxy.1", + "version": "2.35.3-quick-perps-proxy.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 4a3d014c9ed8a1f1ab466f8dac26c4ad75767dc2 Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 14 Sep 2023 15:43:32 +0100 Subject: [PATCH 288/833] feat: remove lock for initialize --- src/stateful-event-subscriber.ts | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/stateful-event-subscriber.ts b/src/stateful-event-subscriber.ts index 5a05b70c7..e76e47ffc 100644 --- a/src/stateful-event-subscriber.ts +++ b/src/stateful-event-subscriber.ts @@ -51,8 +51,6 @@ export abstract class StatefulEventSubscriber private _lastPublishedTimeMs: number = 0; - private isForcedGenerateStateIsRunning = false; - constructor( public readonly parentName: string, _name: string, @@ -97,16 +95,8 @@ export abstract class StatefulEventSubscriber this.logger.debug( `${this.parentName}: ${this.name}: forced to regenerate state`, ); - if (this.isForcedGenerateStateIsRunning) { - return; - } - this.isForcedGenerateStateIsRunning = true; - try { - const state = await this.generateState(blockNumber); - this.setState(state, blockNumber); - } finally { - this.isForcedGenerateStateIsRunning = false; - } + const state = await this.generateState(blockNumber); + this.setState(state, blockNumber); } else { if (this.dexHelper.config.isSlave && this.masterPoolNeeded) { let stateAsString = await this.dexHelper.cache.hget( From 11ab515b6bbb97a45de8f1907db723da63c74fc6 Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 14 Sep 2023 15:49:04 +0100 Subject: [PATCH 289/833] 2.35.3-quick-perps-proxy.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a4be68104..a9f9539aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.3-quick-perps-proxy.2", + "version": "2.35.3-quick-perps-proxy.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 880ff7b33916bfb46f26ebb4109bf3a4080562fb Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 14 Sep 2023 15:24:27 -0400 Subject: [PATCH 290/833] remove subgraph, suspect it won't be used --- src/dex/solidly-v3/config.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index 627cd7abd..f94c9b94f 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -6,8 +6,6 @@ export const SolidlyV3Config: DexConfigMap = { SolidlyV3: { [Network.MAINNET]: { factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', - subgraphURL: - 'https://thegraph.com/hosted-service/subgraph/fromif/solidly-v3', }, }, }; From bfec1edb1310a0ce0069fae245085e644bdb8239 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 14 Sep 2023 18:51:29 -0400 Subject: [PATCH 291/833] continue --- src/dex/solidly-v3/solidly-v3-integration.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 8ffe7758d..4be071b69 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -159,8 +159,8 @@ describe('SolidlyV3', function () { // TODO: Put here token Symbol to check against // Don't forget to update relevant tokens in constant-e2e.ts - const srcTokenSymbol = 'srcTokenSymbol'; - const destTokenSymbol = 'destTokenSymbol'; + const srcTokenSymbol = 'WETH'; + const destTokenSymbol = 'USDT'; const amountsForSell = [ 0n, From 69414df9471d3d6a14b9fedfe30819e9c62e9545 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 15 Sep 2023 16:00:20 +0100 Subject: [PATCH 292/833] 2.35.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c103ce8db..45b9c357b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.3-base-support.2", + "version": "2.35.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1b456b45a6460e659535b253bcbcdc44b686a08b Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Fri, 15 Sep 2023 13:04:01 -0400 Subject: [PATCH 293/833] add SolidlyV3Pool abi --- src/abi/solidly-v3/SolidlyV3Pool.abi.json | 738 ++++++++++++++++++++++ src/dex/solidly-v3/solidly-v3-pool.ts | 1 + 2 files changed, 739 insertions(+) create mode 100644 src/abi/solidly-v3/SolidlyV3Pool.abi.json diff --git a/src/abi/solidly-v3/SolidlyV3Pool.abi.json b/src/abi/solidly-v3/SolidlyV3Pool.abi.json new file mode 100644 index 000000000..cf00c0559 --- /dev/null +++ b/src/abi/solidly-v3/SolidlyV3Pool.abi.json @@ -0,0 +1,738 @@ +[ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { + "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": "sender", + "type": "address" + }, + { + "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": "CollectProtocol", + "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": "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": "uint24", + "name": "feeOld", + "type": "uint24" + }, + { + "indexed": false, + "internalType": "uint24", + "name": "feeNew", + "type": "uint24" + } + ], + "name": "SetFee", + "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": "uint256", "name": "amount0Min", "type": "uint256" }, + { "internalType": "uint256", "name": "amount1Min", "type": "uint256" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "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": "amountToBurn", "type": "uint128" }, + { + "internalType": "uint128", + "name": "amount0ToCollect", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1ToCollect", + "type": "uint128" + } + ], + "name": "burnAndCollect", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0FromBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1FromBurn", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount0Collected", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Collected", + "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": "amountToBurn", "type": "uint128" }, + { + "internalType": "uint256", + "name": "amount0FromBurnMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1FromBurnMin", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount0ToCollect", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1ToCollect", + "type": "uint128" + }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "burnAndCollect", + "outputs": [ + { + "internalType": "uint256", + "name": "amount0FromBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount1FromBurn", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount0Collected", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Collected", + "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": [ + { "internalType": "address", "name": "recipient", "type": "address" }, + { + "internalType": "uint128", + "name": "amount0Requested", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Requested", + "type": "uint128" + } + ], + "name": "collectProtocol", + "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": [ + { "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": [ + { "internalType": "uint160", "name": "sqrtPriceX96", "type": "uint160" } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "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": "uint256", "name": "amount0Min", "type": "uint256" }, + { "internalType": "uint256", "name": "amount1Min", "type": "uint256" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "mint", + "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": "amount", "type": "uint128" } + ], + "name": "mint", + "outputs": [ + { "internalType": "uint256", "name": "amount0", "type": "uint256" }, + { "internalType": "uint256", "name": "amount1", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "poolFees", + "outputs": [ + { "internalType": "uint128", "name": "token0", "type": "uint128" }, + { "internalType": "uint128", "name": "token1", "type": "uint128" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "name": "positions", + "outputs": [ + { "internalType": "uint128", "name": "liquidity", "type": "uint128" }, + { "internalType": "uint128", "name": "tokensOwed0", "type": "uint128" }, + { "internalType": "uint128", "name": "tokensOwed1", "type": "uint128" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bool", "name": "zeroForOne", "type": "bool" }, + { "internalType": "int256", "name": "amountSpecified", "type": "int256" }, + { + "internalType": "uint160", + "name": "sqrtPriceLimitX96", + "type": "uint160" + } + ], + "name": "quoteSwap", + "outputs": [ + { "internalType": "int256", "name": "amount0", "type": "int256" }, + { "internalType": "int256", "name": "amount1", "type": "int256" }, + { + "internalType": "uint160", + "name": "sqrtPriceX96After", + "type": "uint160" + }, + { "internalType": "int24", "name": "tickAfter", "type": "int24" }, + { "internalType": "uint128", "name": "liquidityAfter", "type": "uint128" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint24", "name": "fee", "type": "uint24" }], + "name": "setFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "slot0", + "outputs": [ + { "internalType": "uint160", "name": "sqrtPriceX96", "type": "uint160" }, + { "internalType": "int24", "name": "tick", "type": "int24" }, + { "internalType": "uint24", "name": "fee", "type": "uint24" }, + { "internalType": "bool", "name": "unlocked", "type": "bool" } + ], + "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": "uint256", "name": "amountLimit", "type": "uint256" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "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": "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": "address", "name": "recipient", "type": "address" }, + { "internalType": "bool", "name": "zeroForOne", "type": "bool" }, + { "internalType": "int256", "name": "amountSpecified", "type": "int256" }, + { + "internalType": "uint160", + "name": "sqrtPriceLimitX96", + "type": "uint160" + }, + { "internalType": "uint256", "name": "amountLimit", "type": "uint256" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" } + ], + "name": "swap", + "outputs": [ + { "internalType": "int256", "name": "amount0", "type": "int256" }, + { "internalType": "int256", "name": "amount1", "type": "int256" } + ], + "stateMutability": "nonpayable", + "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" + } + ], + "name": "swap", + "outputs": [ + { "internalType": "int256", "name": "amount0", "type": "int256" }, + { "internalType": "int256", "name": "amount1", "type": "int256" } + ], + "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": "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" + } +] diff --git a/src/dex/solidly-v3/solidly-v3-pool.ts b/src/dex/solidly-v3/solidly-v3-pool.ts index 827b6bde1..81a48be2e 100644 --- a/src/dex/solidly-v3/solidly-v3-pool.ts +++ b/src/dex/solidly-v3/solidly-v3-pool.ts @@ -5,6 +5,7 @@ import { catchParseLogError } from '../../utils'; import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; import { IDexHelper } from '../../dex-helper/idex-helper'; import { PoolState } from './types'; +import SolidlyV3PoolABI from '../../abi/uniswap-v3/UniswapV3Pool.abi.json'; export class SolidlyV3EventPool extends StatefulEventSubscriber { handlers: { From c8a39cab48fcd451ba9eea3f6a42548c79171585 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sat, 16 Sep 2023 17:03:09 -0400 Subject: [PATCH 294/833] start copying --- src/dex/solidly-v3/config.ts | 255 +++- src/dex/solidly-v3/constants.ts | 41 + src/dex/solidly-v3/contract-math/BitMath.ts | 90 ++ .../solidly-v3/contract-math/FixedPoint128.ts | 3 + .../solidly-v3/contract-math/FixedPoint96.ts | 4 + src/dex/solidly-v3/contract-math/FullMath.ts | 30 + .../solidly-v3/contract-math/LiquidityMath.ts | 17 + src/dex/solidly-v3/contract-math/Oracle.ts | 226 ++++ .../solidly-v3/contract-math/SqrtPriceMath.ts | 226 ++++ src/dex/solidly-v3/contract-math/SwapMath.ts | 139 ++ src/dex/solidly-v3/contract-math/Tick.ts | 82 ++ .../solidly-v3/contract-math/TickBitMap.ts | 123 ++ src/dex/solidly-v3/contract-math/TickMath.ts | 211 +++ .../solidly-v3/contract-math/UnsafeMath.ts | 5 + .../contract-math/uniswap-v3-math.ts | 666 ++++++++++ src/dex/solidly-v3/contract-math/utils.ts | 55 + src/dex/solidly-v3/solidly-v3-pool.ts | 539 +++++++- src/dex/solidly-v3/solidly-v3.ts | 1176 +++++++++++++++-- src/dex/solidly-v3/types.ts | 188 ++- src/dex/solidly-v3/utils.ts | 83 ++ 20 files changed, 4006 insertions(+), 153 deletions(-) create mode 100644 src/dex/solidly-v3/constants.ts create mode 100644 src/dex/solidly-v3/contract-math/BitMath.ts create mode 100644 src/dex/solidly-v3/contract-math/FixedPoint128.ts create mode 100644 src/dex/solidly-v3/contract-math/FixedPoint96.ts create mode 100644 src/dex/solidly-v3/contract-math/FullMath.ts create mode 100644 src/dex/solidly-v3/contract-math/LiquidityMath.ts create mode 100644 src/dex/solidly-v3/contract-math/Oracle.ts create mode 100644 src/dex/solidly-v3/contract-math/SqrtPriceMath.ts create mode 100644 src/dex/solidly-v3/contract-math/SwapMath.ts create mode 100644 src/dex/solidly-v3/contract-math/Tick.ts create mode 100644 src/dex/solidly-v3/contract-math/TickBitMap.ts create mode 100644 src/dex/solidly-v3/contract-math/TickMath.ts create mode 100644 src/dex/solidly-v3/contract-math/UnsafeMath.ts create mode 100644 src/dex/solidly-v3/contract-math/uniswap-v3-math.ts create mode 100644 src/dex/solidly-v3/contract-math/utils.ts create mode 100644 src/dex/solidly-v3/utils.ts diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index f94c9b94f..2fca2c601 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -1,17 +1,264 @@ import { DexParams } from './types'; import { DexConfigMap, AdapterMappings } from '../../types'; import { Network, SwapSide } from '../../constants'; +import { Address } from '../../types'; + +const SUPPORTED_FEES = [10000n, 3000n, 500n, 100n]; + +// Pools that will be initialized on app startup +// They are added for testing +export const PoolsToPreload: DexConfigMap< + { token0: Address; token1: Address }[] +> = { + UniswapV3: { + [Network.POLYGON]: [ + { + token0: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270'.toLowerCase(), + token1: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174'.toLowerCase(), + }, + { + token0: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619'.toLowerCase(), + token1: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174'.toLowerCase(), + }, + ], + }, +}; export const SolidlyV3Config: DexConfigMap = { - SolidlyV3: { + UniswapV3: { [Network.MAINNET]: { factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', + quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', + router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3', + }, + [Network.BSC]: { + factory: '0xdB1d10011AD0Ff90774D0C6Bb92e5C5c8b4461F7', + quoter: '0x78D78E420Da98ad378D7799bE8f4AF69033EB077', + router: '0x83c346ba3d4bf36b308705e24fad80999401854b', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x593F39A4Ba26A9c8ed2128ac95D109E8e403C485', + uniswapMulticall: '0x963Df249eD09c358A4819E39d9Cd5736c3087184', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-bsc', + }, + [Network.POLYGON]: { + factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', + quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', + router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-polygon', + }, + [Network.ARBITRUM]: { + factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', + quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', + router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/ianlapham/arbitrum-minimal', + }, + [Network.OPTIMISM]: { + factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', + quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', + router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x4FF0dEC5f9a763Aa1E5C2a962aa6f4eDFeE4f9eA', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/ianlapham/optimism-post-regenesis', + }, + [Network.AVALANCHE]: { + factory: '0x740b1c1de25031C31FF4fC9A62f554A55cdC1baD', + quoter: '0xbe0F5544EC67e9B3b2D979aaA43f18Fd87E6257F', + router: '0x33895c09a0ec0718ce66ab35dfd0b656d77cd053', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', + uniswapMulticall: '0x0139141Cd4Ee88dF3Cdb65881D411bAE271Ef0C2', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/lynnshaoyu/uniswap-v3-avax', + }, + }, + SushiSwapV3: { + [Network.MAINNET]: { + factory: '0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F', + quoter: '0x64e8802FE490fa7cc61d3463958199161Bb608A7', + router: '0x00F23572b16c5e9e58e7b965DEF51Ff8Ff546E34', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-ethereum', + }, + [Network.POLYGON]: { + factory: '0x917933899c6a5f8e37f31e19f92cdbff7e8ff0e2', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x34D41cE301257a4615D4F5AD260FA91D03925243', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-polygon', + }, + [Network.BSC]: { + factory: '0x126555dd55a39328F69400d6aE4F782Bd4C34ABb', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0xDCf4EE5B700e2a5Fec458e06B763A4a3E3004494', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x593F39A4Ba26A9c8ed2128ac95D109E8e403C485', + uniswapMulticall: '0x963Df249eD09c358A4819E39d9Cd5736c3087184', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-bsc', + }, + [Network.AVALANCHE]: { + factory: '0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0x24c90C7d8fb463722e304A71255341610Fa7589b', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', + uniswapMulticall: '0x8C0F842791F03C095b6c633759224FcC9ACe68ea', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-avalanche', + }, + [Network.FANTOM]: { + factory: '0x7770978eED668a3ba661d51a773d3a992Fc9DDCB', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0xDCf4EE5B700e2a5Fec458e06B763A4a3E3004494', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', + uniswapMulticall: '0xB1395e098c0a847CC719Bcf1Fc8114421a9F8232', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-fantom', + }, + [Network.ARBITRUM]: { + factory: '0x1af415a1eba07a4986a52b6f2e7de7003d82231e', + quoter: '0x0524E833cCD057e4d7A296e3aaAb9f7675964Ce1', + router: '0xbDa4176fD98b47018aF673805d069b9dbd49373D', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-arbitrum', + }, + [Network.OPTIMISM]: { + factory: '0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0xa05d8C3F278fC7b20b39Ea7A3035E3aD8D808c78', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x4FF0dEC5f9a763Aa1E5C2a962aa6f4eDFeE4f9eA', + uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-optimism', + }, + }, + ChronosV3: { + [Network.ARBITRUM]: { + factory: '0x4Db9D624F67E00dbF8ef7AE0e0e8eE54aF1dee49', + quoter: '0x6E7f0Ca45171a4440c0CDdF3A46A8dC5D4c2d4A0', + router: '0xE0aBdFD837D451640CF43cB1Ec4eE87976eFbb41', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x46b44eb4Cc3bEbB9f04C419f691aB85Ff885A4D6', + uniswapMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', + chunksCount: 10, + initRetryFrequency: 10, + initHash: + '0x09c178be473df44d1de6970978a4fdedce1ce52a23b2b979754547f6b43a19a5', + subgraphURL: + 'https://subgraph.chronos.exchange/subgraphs/name/chronos-v3', + }, + }, + 'QuickSwapV3.1': { + [Network.ZKEVM]: { + factory: '0xD9a2AD9E927Bd7014116CC5c7328f028D4318178', + quoter: '0xc2f30976cebf6b7400fe1300540a342411340d29', + router: '0x1e7e4c855520b2106320952a570a3e5e3e618101', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x983ab0171159b7e17835cc6aec70c72b8aadb133', + uniswapMulticall: '0x61530d6E1c7A47BBB3e48e8b8EdF7569DcFeE121', + chunksCount: 5, + initRetryFrequency: 30, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.studio.thegraph.com/query/44554/uniswap-v3/version/latest', }, }, }; export const Adapters: Record = { - // TODO: add adapters for each chain - // This is an example to copy - [Network.MAINNET]: { [SwapSide.SELL]: [{ name: '', index: 0 }] }, + [Network.MAINNET]: { + [SwapSide.SELL]: [{ name: 'Adapter01', index: 6 }], + [SwapSide.BUY]: [{ name: 'BuyAdapter', index: 2 }], + }, + [Network.BSC]: { + [SwapSide.SELL]: [{ name: 'BscAdapter02', index: 4 }], + [SwapSide.BUY]: [{ name: 'BscBuyAdapter', index: 5 }], + }, + [Network.POLYGON]: { + [SwapSide.SELL]: [{ name: 'PolygonAdapter01', index: 13 }], + [SwapSide.BUY]: [{ name: 'PolygonBuyAdapter', index: 2 }], + }, + [Network.ARBITRUM]: { + [SwapSide.SELL]: [{ name: 'ArbitrumAdapter01', index: 3 }], + [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 2 }], + }, + [Network.OPTIMISM]: { + [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 3 }], + [SwapSide.BUY]: [{ name: 'OptimismBuyAdapter', index: 2 }], + }, + [Network.FANTOM]: { + [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 11 }], + [SwapSide.BUY]: [{ name: 'FantomBuyAdapter', index: 3 }], + }, + [Network.ZKEVM]: { + [SwapSide.SELL]: [{ name: 'PolygonZkEvmAdapter01', index: 1 }], + [SwapSide.BUY]: [{ name: 'PolygonZkEvmBuyAdapter', index: 1 }], + }, + [Network.AVALANCHE]: { + [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 5 }], + [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 6 }], + }, }; diff --git a/src/dex/solidly-v3/constants.ts b/src/dex/solidly-v3/constants.ts new file mode 100644 index 000000000..e625c3882 --- /dev/null +++ b/src/dex/solidly-v3/constants.ts @@ -0,0 +1,41 @@ +export const UNISWAPV3_TICK_GAS_COST = 24_000; // Ceiled +export const UNISWAPV3_TICK_BASE_OVERHEAD = 75_000; +export const UNISWAPV3_POOL_SEARCH_OVERHEAD = 10_000; + +// This is used for price calculation. If out of scope, return 0n +export const TICK_BITMAP_TO_USE = 4n; + +// This is used to check if the state is still valid. +export const TICK_BITMAP_BUFFER = 8n; + +export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 128; + +export const UNISWAPV3_SUBGRAPH_URL = + 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3'; + +export const UNISWAPV3_EFFICIENCY_FACTOR = 3; + +export const ZERO_TICK_INFO = { + liquidityGross: 0n, + liquidityNet: 0n, + tickCumulativeOutside: 0n, + secondsPerLiquidityOutsideX128: 0n, + secondsOutside: 0n, + initialized: false, +}; + +export const ZERO_ORACLE_OBSERVATION = { + blockTimestamp: 0n, + tickCumulative: 0n, + secondsPerLiquidityCumulativeX128: 0n, + initialized: false, +}; + +export const OUT_OF_RANGE_ERROR_POSTFIX = `INVALID_TICK_BIT_MAP_RANGES`; + +export const DEFAULT_POOL_INIT_CODE_HASH = `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`; + +export enum DirectMethods { + directSell = 'directUniV3Swap', + directBuy = 'directUniV3Buy', +} diff --git a/src/dex/solidly-v3/contract-math/BitMath.ts b/src/dex/solidly-v3/contract-math/BitMath.ts new file mode 100644 index 000000000..d7a2e6d9a --- /dev/null +++ b/src/dex/solidly-v3/contract-math/BitMath.ts @@ -0,0 +1,90 @@ +import { + BI_MAX_UINT128, + BI_MAX_UINT16, + BI_MAX_UINT32, + BI_MAX_UINT64, + BI_MAX_UINT8, +} from '../../../bigint-constants'; +import { _require } from '../../../utils'; + +export class BitMath { + static mostSignificantBit(x: bigint): bigint { + _require(x > 0, '', { x }, 'x > 0'); + let r = 0n; + + if (x >= 0x100000000000000000000000000000000n) { + x >>= 128n; + r += 128n; + } + if (x >= 0x10000000000000000n) { + x >>= 64n; + r += 64n; + } + if (x >= 0x100000000n) { + x >>= 32n; + r += 32n; + } + if (x >= 0x10000n) { + x >>= 16n; + r += 16n; + } + if (x >= 0x100n) { + x >>= 8n; + r += 8n; + } + if (x >= 0x10n) { + x >>= 4n; + r += 4n; + } + if (x >= 0x4n) { + x >>= 2n; + r += 2n; + } + if (x >= 0x2n) r += 1n; + + return r; + } + + static leastSignificantBit(x: bigint): bigint { + _require(x > 0, '', { x }, 'x > 0'); + + let r = 255n; + if ((x & BI_MAX_UINT128) > 0n) { + r -= 128n; + } else { + x >>= 128n; + } + if ((x & BI_MAX_UINT64) > 0n) { + r -= 64n; + } else { + x >>= 64n; + } + if ((x & BI_MAX_UINT32) > 0n) { + r -= 32n; + } else { + x >>= 32n; + } + if ((x & BI_MAX_UINT16) > 0n) { + r -= 16n; + } else { + x >>= 16n; + } + if ((x & BI_MAX_UINT8) > 0n) { + r -= 8n; + } else { + x >>= 8n; + } + if ((x & 0xfn) > 0n) { + r -= 4n; + } else { + x >>= 4n; + } + if ((x & 0x3n) > 0n) { + r -= 2n; + } else { + x >>= 2n; + } + if ((x & 0x1n) > 0n) r -= 1n; + return r; + } +} diff --git a/src/dex/solidly-v3/contract-math/FixedPoint128.ts b/src/dex/solidly-v3/contract-math/FixedPoint128.ts new file mode 100644 index 000000000..2058307bd --- /dev/null +++ b/src/dex/solidly-v3/contract-math/FixedPoint128.ts @@ -0,0 +1,3 @@ +export class FixedPoint128 { + static readonly Q128 = 0x100000000000000000000000000000000n; +} diff --git a/src/dex/solidly-v3/contract-math/FixedPoint96.ts b/src/dex/solidly-v3/contract-math/FixedPoint96.ts new file mode 100644 index 000000000..1a551dcb9 --- /dev/null +++ b/src/dex/solidly-v3/contract-math/FixedPoint96.ts @@ -0,0 +1,4 @@ +export class FixedPoint96 { + static readonly RESOLUTION = 96n; + static readonly Q96 = 0x1000000000000000000000000n; +} diff --git a/src/dex/solidly-v3/contract-math/FullMath.ts b/src/dex/solidly-v3/contract-math/FullMath.ts new file mode 100644 index 000000000..7c6a3bdc3 --- /dev/null +++ b/src/dex/solidly-v3/contract-math/FullMath.ts @@ -0,0 +1,30 @@ +import { BI_MAX_UINT256 } from '../../../bigint-constants'; +import { _require } from '../../../utils'; + +export class FullMath { + static mulDiv(a: bigint, b: bigint, denominator: bigint) { + const result = (a * b) / denominator; + + _require( + result <= BI_MAX_UINT256, + '', + { result, BI_MAX_UINT: BI_MAX_UINT256 }, + 'result <= BI_MAX_UINT', + ); + + return result; + } + + static mulDivRoundingUp(a: bigint, b: bigint, denominator: bigint) { + const result = (a * b + denominator - 1n) / denominator; + + _require( + result <= BI_MAX_UINT256, + '', + { result, BI_MAX_UINT: BI_MAX_UINT256 }, + 'result <= BI_MAX_UINT', + ); + + return result; + } +} diff --git a/src/dex/solidly-v3/contract-math/LiquidityMath.ts b/src/dex/solidly-v3/contract-math/LiquidityMath.ts new file mode 100644 index 000000000..a495e55cc --- /dev/null +++ b/src/dex/solidly-v3/contract-math/LiquidityMath.ts @@ -0,0 +1,17 @@ +import { _require } from '../../../utils'; + +export class LiquidityMath { + static addDelta(x: bigint, y: bigint): bigint { + let z; + if (y < 0) { + const _y = BigInt.asUintN(128, -y); + z = x - _y; + _require(z < x, 'LS', { z, x, y, _y }, 'z < x'); + } else { + const _y = BigInt.asUintN(128, y); + z = x + _y; + _require(z >= x, 'LA', { z, x, y, _y }, 'z >= x'); + } + return z; + } +} diff --git a/src/dex/solidly-v3/contract-math/Oracle.ts b/src/dex/solidly-v3/contract-math/Oracle.ts new file mode 100644 index 000000000..19b1918d1 --- /dev/null +++ b/src/dex/solidly-v3/contract-math/Oracle.ts @@ -0,0 +1,226 @@ +import { + OracleObservation, + OracleObservationCandidates, + PoolState, +} from '../types'; +import { _require } from '../../../utils'; +import { DeepReadonly } from 'ts-essentials'; +import { ZERO_ORACLE_OBSERVATION } from '../constants'; + +function replaceUndefinedObservationWithZero(state: PoolState, index: number) { + if (state.observations[index] === undefined) { + state.observations[index] = { ...ZERO_ORACLE_OBSERVATION }; + } +} + +export class Oracle { + static transform( + state: DeepReadonly, + last: OracleObservation, + blockTimestamp: bigint, + tick: bigint, + liquidity: bigint, + ): OracleObservation { + const delta = blockTimestamp - last.blockTimestamp; + return { + blockTimestamp: state.blockTimestamp, + tickCumulative: last.tickCumulative + BigInt.asIntN(56, tick) * delta, + secondsPerLiquidityCumulativeX128: + last.secondsPerLiquidityCumulativeX128 + + (BigInt.asUintN(160, delta) << 128n) / + (liquidity > 0n ? liquidity : 1n), + initialized: true, + }; + } + + static write( + state: PoolState, + index: number, + blockTimestamp: bigint, + tick: bigint, + liquidity: bigint, + cardinality: number, + cardinalityNext: number, + ): [number, number] { + const last = state.observations[index]; + + if (last.blockTimestamp == state.blockTimestamp) + return [index, cardinality]; + + let indexUpdated = 0; + let cardinalityUpdated = 0; + + if (cardinalityNext > cardinality && index == cardinality - 1) { + cardinalityUpdated = cardinalityNext; + } else { + cardinalityUpdated = cardinality; + } + + indexUpdated = (index + 1) % cardinalityUpdated; + + state.observations[indexUpdated] = Oracle.transform( + state, + last, + blockTimestamp, + tick, + liquidity, + ); + if (indexUpdated !== index) { + delete state.observations[index]; + } + return [indexUpdated, cardinalityUpdated]; + } + + static lte(time: bigint, a: bigint, b: bigint): boolean { + if (a <= time && b <= time) return a <= b; + + const aAdjusted = a > time ? a : a + 2n ** 32n; + const bAdjusted = b > time ? b : b + 2n ** 32n; + return aAdjusted <= bAdjusted; + } + + static binarySearch( + state: DeepReadonly, + time: bigint, + target: bigint, + index: number, + cardinality: number, + ): OracleObservationCandidates { + let l = (index + 1) % cardinality; + let r = l + cardinality - 1; + let i; + + let beforeOrAt; + let atOrAfter; + while (true) { + i = (l + r) / 2; + + beforeOrAt = state.observations[i % cardinality]; + + // we've landed on an uninitialized tick, keep searching higher (more recently) + if (!beforeOrAt.initialized) { + l = i + 1; + continue; + } + + atOrAfter = state.observations[(i + 1) % cardinality]; + + const targetAtOrAfter = Oracle.lte( + time, + beforeOrAt.blockTimestamp, + target, + ); + + // check if we've found the answer! + if (targetAtOrAfter && Oracle.lte(time, target, atOrAfter.blockTimestamp)) + break; + + if (!targetAtOrAfter) r = i - 1; + else l = i + 1; + } + return { beforeOrAt, atOrAfter }; + } + + static getSurroundingObservations( + state: DeepReadonly, + time: bigint, + target: bigint, + tick: bigint, + index: number, + liquidity: bigint, + cardinality: number, + ): OracleObservationCandidates { + let beforeOrAt = state.observations[index]; + + if (Oracle.lte(time, beforeOrAt.blockTimestamp, target)) { + if (beforeOrAt.blockTimestamp === target) { + return { beforeOrAt, atOrAfter: beforeOrAt }; + } else { + return { + beforeOrAt, + atOrAfter: Oracle.transform( + state, + beforeOrAt, + target, + tick, + liquidity, + ), + }; + } + } + + beforeOrAt = state.observations[(index + 1) % cardinality]; + if (!beforeOrAt.initialized) beforeOrAt = state.observations[0]; + + _require( + Oracle.lte(time, beforeOrAt.blockTimestamp, target), + 'OLD', + { time, beforeOrAtBlockTimestamp: beforeOrAt.blockTimestamp, target }, + 'Oracle.lte(time, beforeOrAt.blockTimestamp, target)', + ); + + return Oracle.binarySearch(state, time, target, index, cardinality); + } + + static observeSingle( + state: DeepReadonly, + time: bigint, + secondsAgo: bigint, + tick: bigint, + index: number, + liquidity: bigint, + cardinality: number, + ): [bigint, bigint] { + if (secondsAgo == 0n) { + let last = state.observations[index]; + if (last.blockTimestamp != time) + last = Oracle.transform(state, last, time, tick, liquidity); + return [last.tickCumulative, last.secondsPerLiquidityCumulativeX128]; + } + + const target = time - secondsAgo; + + const { beforeOrAt, atOrAfter } = Oracle.getSurroundingObservations( + state, + time, + target, + tick, + index, + liquidity, + cardinality, + ); + + if (target === beforeOrAt.blockTimestamp) { + return [ + beforeOrAt.tickCumulative, + beforeOrAt.secondsPerLiquidityCumulativeX128, + ]; + } else if (target === atOrAfter.blockTimestamp) { + return [ + atOrAfter.tickCumulative, + atOrAfter.secondsPerLiquidityCumulativeX128, + ]; + } else { + const observationTimeDelta = + atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp; + const targetDelta = target - beforeOrAt.blockTimestamp; + return [ + beforeOrAt.tickCumulative + + ((atOrAfter.tickCumulative - beforeOrAt.tickCumulative) / + observationTimeDelta) * + targetDelta, + beforeOrAt.secondsPerLiquidityCumulativeX128 + + BigInt.asUintN( + 160, + (BigInt.asUintN( + 256, + atOrAfter.secondsPerLiquidityCumulativeX128 - + beforeOrAt.secondsPerLiquidityCumulativeX128, + ) * + targetDelta) / + observationTimeDelta, + ), + ]; + } + } +} diff --git a/src/dex/solidly-v3/contract-math/SqrtPriceMath.ts b/src/dex/solidly-v3/contract-math/SqrtPriceMath.ts new file mode 100644 index 000000000..31b801d73 --- /dev/null +++ b/src/dex/solidly-v3/contract-math/SqrtPriceMath.ts @@ -0,0 +1,226 @@ +import { BI_MAX_UINT160 } from '../../../bigint-constants'; +import { FixedPoint96 } from './FixedPoint96'; +import { FullMath } from './FullMath'; +import { UnsafeMath } from './UnsafeMath'; +import { _require } from '../../../utils'; + +export class SqrtPriceMath { + static getNextSqrtPriceFromAmount0RoundingUp( + sqrtPX96: bigint, + liquidity: bigint, + amount: bigint, + add: boolean, + ): bigint { + if (amount === 0n) return sqrtPX96; + const numerator1 = + BigInt.asUintN(256, liquidity) << FixedPoint96.RESOLUTION; + + const product = amount * sqrtPX96; + if (add) { + if (product / amount === sqrtPX96) { + const denominator = numerator1 + product; + if (denominator >= numerator1) { + return BigInt.asUintN( + 160, + FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator), + ); + } + } + return BigInt.asUintN( + 160, + UnsafeMath.divRoundingUp(numerator1, numerator1 / sqrtPX96 + amount), + ); + } else { + _require( + product / amount === sqrtPX96 && numerator1 > product, + '', + { product, amount, sqrtPX96, numerator1 }, + 'product / amount === sqrtPX96 && numerator1 > product', + ); + const denominator = numerator1 - product; + return BigInt.asUintN( + 160, + FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator), + ); + } + } + + static getNextSqrtPriceFromAmount1RoundingDown( + sqrtPX96: bigint, + liquidity: bigint, + amount: bigint, + add: boolean, + ): bigint { + if (add) { + const quotient = + amount <= BI_MAX_UINT160 + ? (amount << FixedPoint96.RESOLUTION) / liquidity + : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity); + return BigInt.asUintN(160, BigInt.asUintN(256, sqrtPX96) + quotient); + } else { + const quotient = + amount <= BI_MAX_UINT160 + ? UnsafeMath.divRoundingUp( + amount << FixedPoint96.RESOLUTION, + liquidity, + ) + : FullMath.mulDivRoundingUp(amount, FixedPoint96.Q96, liquidity); + + _require( + sqrtPX96 > quotient, + '', + { sqrtPX96, quotient }, + 'sqrtPX96 > quotient', + ); + return BigInt.asUintN(160, sqrtPX96 - quotient); + } + } + + static getNextSqrtPriceFromInput( + sqrtPX96: bigint, + liquidity: bigint, + amountIn: bigint, + zeroForOne: boolean, + ): bigint { + _require(sqrtPX96 > 0n, '', { sqrtPX96 }, 'sqrtPX96 > 0n'); + _require(liquidity > 0n, '', { liquidity }, 'liquidity > 0n'); + + return zeroForOne + ? SqrtPriceMath.getNextSqrtPriceFromAmount0RoundingUp( + sqrtPX96, + liquidity, + amountIn, + true, + ) + : SqrtPriceMath.getNextSqrtPriceFromAmount1RoundingDown( + sqrtPX96, + liquidity, + amountIn, + true, + ); + } + + static getNextSqrtPriceFromOutput( + sqrtPX96: bigint, + liquidity: bigint, + amountOut: bigint, + zeroForOne: boolean, + ): bigint { + _require(sqrtPX96 > 0n, '', { sqrtPX96 }, 'sqrtPX96 > 0n'); + _require(liquidity > 0n, '', { liquidity }, 'liquidity > 0n'); + + return zeroForOne + ? SqrtPriceMath.getNextSqrtPriceFromAmount1RoundingDown( + sqrtPX96, + liquidity, + amountOut, + false, + ) + : SqrtPriceMath.getNextSqrtPriceFromAmount0RoundingUp( + sqrtPX96, + liquidity, + amountOut, + false, + ); + } + + static getAmount0Delta( + sqrtRatioAX96: bigint, + sqrtRatioBX96: bigint, + liquidity: bigint, + roundUp: boolean, + ) { + if (sqrtRatioAX96 > sqrtRatioBX96) { + [sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]; + } + + const numerator1 = + BigInt.asUintN(256, liquidity) << FixedPoint96.RESOLUTION; + const numerator2 = sqrtRatioBX96 - sqrtRatioAX96; + + _require(sqrtRatioAX96 > 0, '', { sqrtRatioAX96 }, 'sqrtRatioAX96 > 0'); + + return roundUp + ? UnsafeMath.divRoundingUp( + FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96), + sqrtRatioAX96, + ) + : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96; + } + + static getAmount1Delta( + sqrtRatioAX96: bigint, + sqrtRatioBX96: bigint, + liquidity: bigint, + roundUp: boolean, + ) { + if (sqrtRatioAX96 > sqrtRatioBX96) + [sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]; + + return roundUp + ? FullMath.mulDivRoundingUp( + liquidity, + sqrtRatioBX96 - sqrtRatioAX96, + FixedPoint96.Q96, + ) + : FullMath.mulDiv( + liquidity, + sqrtRatioBX96 - sqrtRatioAX96, + FixedPoint96.Q96, + ); + } + + // Overloaded with different argument numbers + static _getAmount0DeltaO( + sqrtRatioAX96: bigint, + sqrtRatioBX96: bigint, + liquidity: bigint, + ) { + return liquidity < 0 + ? -BigInt.asIntN( + 256, + SqrtPriceMath.getAmount0Delta( + sqrtRatioAX96, + sqrtRatioBX96, + BigInt.asUintN(128, -liquidity), + false, + ), + ) + : BigInt.asIntN( + 256, + SqrtPriceMath.getAmount0Delta( + sqrtRatioAX96, + sqrtRatioBX96, + BigInt.asUintN(128, liquidity), + true, + ), + ); + } + + // Overloaded with different argument numbers + static _getAmount1DeltaO( + sqrtRatioAX96: bigint, + sqrtRatioBX96: bigint, + liquidity: bigint, + ) { + return liquidity < 0 + ? -BigInt.asIntN( + 256, + SqrtPriceMath.getAmount1Delta( + sqrtRatioAX96, + sqrtRatioBX96, + BigInt.asUintN(128, -liquidity), + false, + ), + ) + : BigInt.asIntN( + 256, + SqrtPriceMath.getAmount1Delta( + sqrtRatioAX96, + sqrtRatioBX96, + BigInt.asUintN(128, liquidity), + true, + ), + ); + } +} diff --git a/src/dex/solidly-v3/contract-math/SwapMath.ts b/src/dex/solidly-v3/contract-math/SwapMath.ts new file mode 100644 index 000000000..3f19cf8cb --- /dev/null +++ b/src/dex/solidly-v3/contract-math/SwapMath.ts @@ -0,0 +1,139 @@ +import { BI_POWS } from '../../../bigint-constants'; +import { FullMath } from './FullMath'; +import { SqrtPriceMath } from './SqrtPriceMath'; + +export class SwapMath { + static computeSwapStep( + sqrtRatioCurrentX96: bigint, + sqrtRatioTargetX96: bigint, + liquidity: bigint, + amountRemaining: bigint, + feePips: bigint, + ): { + sqrtRatioNextX96: bigint; + amountIn: bigint; + amountOut: bigint; + feeAmount: bigint; + } { + const zeroForOne = sqrtRatioCurrentX96 >= sqrtRatioTargetX96; + const exactIn = amountRemaining >= 0n; + + let sqrtRatioNextX96 = 0n; + let amountIn = 0n; + let amountOut = 0n; + let feeAmount = 0n; + + if (exactIn) { + const amountRemainingLessFee = FullMath.mulDiv( + BigInt.asUintN(256, amountRemaining), + BI_POWS[6] - feePips, + BI_POWS[6], + ); + amountIn = zeroForOne + ? SqrtPriceMath.getAmount0Delta( + sqrtRatioTargetX96, + sqrtRatioCurrentX96, + liquidity, + true, + ) + : SqrtPriceMath.getAmount1Delta( + sqrtRatioCurrentX96, + sqrtRatioTargetX96, + liquidity, + true, + ); + if (amountRemainingLessFee >= amountIn) + sqrtRatioNextX96 = sqrtRatioTargetX96; + else + sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromInput( + sqrtRatioCurrentX96, + liquidity, + amountRemainingLessFee, + zeroForOne, + ); + } else { + amountOut = zeroForOne + ? SqrtPriceMath.getAmount1Delta( + sqrtRatioTargetX96, + sqrtRatioCurrentX96, + liquidity, + false, + ) + : SqrtPriceMath.getAmount0Delta( + sqrtRatioCurrentX96, + sqrtRatioTargetX96, + liquidity, + false, + ); + if (BigInt.asUintN(256, -amountRemaining) >= amountOut) + sqrtRatioNextX96 = sqrtRatioTargetX96; + else + sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromOutput( + sqrtRatioCurrentX96, + liquidity, + BigInt.asUintN(256, -amountRemaining), + zeroForOne, + ); + } + + const max = sqrtRatioTargetX96 == sqrtRatioNextX96; + + if (zeroForOne) { + amountIn = + max && exactIn + ? amountIn + : SqrtPriceMath.getAmount0Delta( + sqrtRatioNextX96, + sqrtRatioCurrentX96, + liquidity, + true, + ); + amountOut = + max && !exactIn + ? amountOut + : SqrtPriceMath.getAmount1Delta( + sqrtRatioNextX96, + sqrtRatioCurrentX96, + liquidity, + false, + ); + } else { + amountIn = + max && exactIn + ? amountIn + : SqrtPriceMath.getAmount1Delta( + sqrtRatioCurrentX96, + sqrtRatioNextX96, + liquidity, + true, + ); + amountOut = + max && !exactIn + ? amountOut + : SqrtPriceMath.getAmount0Delta( + sqrtRatioCurrentX96, + sqrtRatioNextX96, + liquidity, + false, + ); + } + + // cap the output amount to not exceed the remaining output amount + if (!exactIn && amountOut > BigInt.asUintN(256, -amountRemaining)) { + amountOut = BigInt.asUintN(256, -amountRemaining); + } + + if (exactIn && sqrtRatioNextX96 != sqrtRatioTargetX96) { + // we didn't reach the target, so take the remainder of the maximum input as fee + feeAmount = BigInt.asUintN(256, amountRemaining) - amountIn; + } else { + feeAmount = FullMath.mulDivRoundingUp( + amountIn, + feePips, + BI_POWS[6] - feePips, + ); + } + + return { sqrtRatioNextX96, amountIn, amountOut, feeAmount }; + } +} diff --git a/src/dex/solidly-v3/contract-math/Tick.ts b/src/dex/solidly-v3/contract-math/Tick.ts new file mode 100644 index 000000000..ab2e3c48b --- /dev/null +++ b/src/dex/solidly-v3/contract-math/Tick.ts @@ -0,0 +1,82 @@ +import { PoolState, TickInfo } from '../types'; +import { LiquidityMath } from './LiquidityMath'; +import { _require } from '../../../utils'; +import { NumberAsString } from '@paraswap/core'; +import { ZERO_TICK_INFO } from '../constants'; + +export class Tick { + static update( + state: Pick, + tick: bigint, + tickCurrent: bigint, + liquidityDelta: bigint, + secondsPerLiquidityCumulativeX128: bigint, + tickCumulative: bigint, + time: bigint, + upper: boolean, + maxLiquidity: bigint, + ): boolean { + let info = state.ticks[Number(tick)]; + + if (info === undefined) { + info = { ...ZERO_TICK_INFO }; + state.ticks[Number(tick)] = info; + } + + const liquidityGrossBefore = info.liquidityGross; + const liquidityGrossAfter = LiquidityMath.addDelta( + liquidityGrossBefore, + liquidityDelta, + ); + + _require( + liquidityGrossAfter <= maxLiquidity, + 'LO', + { liquidityGrossAfter, maxLiquidity }, + 'liquidityGrossAfter <= maxLiquidity', + ); + + const flipped = (liquidityGrossAfter == 0n) != (liquidityGrossBefore == 0n); + + if (liquidityGrossBefore == 0n) { + if (tick <= tickCurrent) { + info.secondsPerLiquidityOutsideX128 = secondsPerLiquidityCumulativeX128; + info.tickCumulativeOutside = tickCumulative; + info.secondsOutside = time; + } + info.initialized = true; + } + + info.liquidityGross = liquidityGrossAfter; + + info.liquidityNet = upper + ? BigInt.asIntN( + 128, + BigInt.asIntN(256, info.liquidityNet) - liquidityDelta, + ) + : BigInt.asIntN( + 128, + BigInt.asIntN(256, info.liquidityNet) + liquidityDelta, + ); + return flipped; + } + + static clear(state: Pick, tick: bigint) { + delete state.ticks[Number(tick)]; + } + + static cross( + ticks: Record, + tick: bigint, + secondsPerLiquidityCumulativeX128: bigint, + tickCumulative: bigint, + time: bigint, + ): bigint { + const info = ticks[Number(tick)]; + info.secondsPerLiquidityOutsideX128 = + secondsPerLiquidityCumulativeX128 - info.secondsPerLiquidityOutsideX128; + info.tickCumulativeOutside = tickCumulative - info.tickCumulativeOutside; + info.secondsOutside = time - info.secondsOutside; + return info.liquidityNet; + } +} diff --git a/src/dex/solidly-v3/contract-math/TickBitMap.ts b/src/dex/solidly-v3/contract-math/TickBitMap.ts new file mode 100644 index 000000000..405cfa70e --- /dev/null +++ b/src/dex/solidly-v3/contract-math/TickBitMap.ts @@ -0,0 +1,123 @@ +import { BI_MAX_UINT8 } from '../../../bigint-constants'; +import { PoolState } from '../types'; +import { BitMath } from './BitMath'; +import { _require } from '../../../utils'; +import { DeepReadonly } from 'ts-essentials'; +import { + OUT_OF_RANGE_ERROR_POSTFIX, + TICK_BITMAP_BUFFER, + TICK_BITMAP_TO_USE, +} from '../constants'; + +function isWordPosOut( + wordPos: bigint, + startTickBitmap: bigint, + // For pricing we use wider range to check price impact. If function called from event + // it must always be within buffer + isPriceQuery: boolean, +) { + let lowerTickBitmapLimit; + let upperTickBitmapLimit; + + if (isPriceQuery) { + lowerTickBitmapLimit = + startTickBitmap - (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE); + upperTickBitmapLimit = + startTickBitmap + (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE); + } else { + lowerTickBitmapLimit = startTickBitmap - TICK_BITMAP_BUFFER; + upperTickBitmapLimit = startTickBitmap + TICK_BITMAP_BUFFER; + } + + _require( + wordPos >= lowerTickBitmapLimit && wordPos <= upperTickBitmapLimit, + `wordPos is out of safe state tickBitmap request range: ${OUT_OF_RANGE_ERROR_POSTFIX}`, + { wordPos }, + `wordPos >= LOWER_TICK_REQUEST_LIMIT && wordPos <= UPPER_TICK_REQUEST_LIMIT`, + ); +} + +export class TickBitMap { + static position(tick: bigint): [bigint, bigint] { + return [BigInt.asIntN(16, tick >> 8n), BigInt.asUintN(8, tick % 256n)]; + } + + static flipTick( + state: Pick, + tick: bigint, + tickSpacing: bigint, + ) { + _require( + tick % tickSpacing === 0n, + '', + { tick, tickSpacing }, + 'tick % tickSpacing == 0n,', + ); + const [wordPos, bitPos] = TickBitMap.position(tick / tickSpacing); + const mask = 1n << bitPos; + + // flipTick is used only in _updatePosition which is always state changing event + // Therefore it is never used in price query + isWordPosOut(wordPos, state.startTickBitmap, false); + + const stringWordPos = wordPos.toString(); + if (state.tickBitmap[stringWordPos] === undefined) { + state.tickBitmap[stringWordPos] = 0n; + } + + state.tickBitmap[stringWordPos] ^= mask; + } + + static nextInitializedTickWithinOneWord( + state: DeepReadonly>, + tick: bigint, + tickSpacing: bigint, + lte: boolean, + isPriceQuery: boolean, + ): [bigint, boolean] { + let compressed = tick / tickSpacing; + if (tick < 0n && tick % tickSpacing != 0n) compressed--; + + let next = 0n; + let initialized = false; + + if (lte) { + const [wordPos, bitPos] = TickBitMap.position(compressed); + const mask = (1n << bitPos) - 1n + (1n << bitPos); + + isWordPosOut(wordPos, state.startTickBitmap, isPriceQuery); + let tickBitmapValue = state.tickBitmap[wordPos.toString()]; + tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; + + const masked = tickBitmapValue & mask; + + initialized = masked != 0n; + next = initialized + ? (compressed - + BigInt.asIntN(24, bitPos - BitMath.mostSignificantBit(masked))) * + tickSpacing + : (compressed - BigInt.asIntN(24, bitPos)) * tickSpacing; + } else { + // start from the word of the next tick, since the current tick state doesn't matter + const [wordPos, bitPos] = TickBitMap.position(compressed + 1n); + const mask = ~((1n << bitPos) - 1n); + + isWordPosOut(wordPos, state.startTickBitmap, isPriceQuery); + let tickBitmapValue = state.tickBitmap[wordPos.toString()]; + tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; + + const masked = tickBitmapValue & mask; + + initialized = masked != 0n; + next = initialized + ? (compressed + + 1n + + BigInt.asIntN(24, BitMath.leastSignificantBit(masked) - bitPos)) * + tickSpacing + : (compressed + 1n + BigInt.asIntN(24, BI_MAX_UINT8 - bitPos)) * + tickSpacing; + } + + return [next, initialized]; + } +} diff --git a/src/dex/solidly-v3/contract-math/TickMath.ts b/src/dex/solidly-v3/contract-math/TickMath.ts new file mode 100644 index 000000000..5515ce15c --- /dev/null +++ b/src/dex/solidly-v3/contract-math/TickMath.ts @@ -0,0 +1,211 @@ +import { gt } from 'lodash'; +import { BI_MAX_UINT256 } from '../../../bigint-constants'; +import { _gt } from './utils'; +import { _require } from '../../../utils'; + +export class TickMath { + static readonly MIN_TICK = -887272n; + static readonly MAX_TICK = -TickMath.MIN_TICK; + static readonly MIN_SQRT_RATIO = 4295128739n; + static readonly MAX_SQRT_RATIO = + 1461446703485210103287273052203988822378723970342n; + + static getSqrtRatioAtTick(tick: bigint): bigint { + const absTick = + tick < 0n + ? BigInt.asUintN(256, -BigInt.asIntN(256, tick)) + : BigInt.asUintN(256, BigInt.asIntN(256, tick)); + _require( + absTick <= BigInt.asUintN(256, TickMath.MAX_TICK), + 'T', + { absTick }, + 'absTick <= BigInt.asUintN(256, TickMath.MAX_TICK)', + ); + + let ratio = + (absTick & 0x1n) !== 0n + ? 0xfffcb933bd6fad37aa2d162d1a594001n + : 0x100000000000000000000000000000000n; + if ((absTick & 0x2n) !== 0n) + ratio = (ratio * 0xfff97272373d413259a46990580e213an) >> 128n; + if ((absTick & 0x4n) !== 0n) + ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdccn) >> 128n; + if ((absTick & 0x8n) !== 0n) + ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0n) >> 128n; + if ((absTick & 0x10n) !== 0n) + ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644n) >> 128n; + if ((absTick & 0x20n) !== 0n) + ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0n) >> 128n; + if ((absTick & 0x40n) !== 0n) + ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861n) >> 128n; + if ((absTick & 0x80n) !== 0n) + ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053n) >> 128n; + if ((absTick & 0x100n) !== 0n) + ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4n) >> 128n; + if ((absTick & 0x200n) !== 0n) + ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54n) >> 128n; + if ((absTick & 0x400n) !== 0n) + ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3n) >> 128n; + if ((absTick & 0x800n) !== 0n) + ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9n) >> 128n; + if ((absTick & 0x1000n) !== 0n) + ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825n) >> 128n; + if ((absTick & 0x2000n) !== 0n) + ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5n) >> 128n; + if ((absTick & 0x4000n) !== 0n) + ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7n) >> 128n; + if ((absTick & 0x8000n) !== 0n) + ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6n) >> 128n; + if ((absTick & 0x10000n) !== 0n) + ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9n) >> 128n; + if ((absTick & 0x20000n) !== 0n) + ratio = (ratio * 0x5d6af8dedb81196699c329225ee604n) >> 128n; + if ((absTick & 0x40000n) !== 0n) + ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98n) >> 128n; + if ((absTick & 0x80000n) !== 0n) + ratio = (ratio * 0x48a170391f7dc42444e8fa2n) >> 128n; + + if (tick > 0) ratio = BI_MAX_UINT256 / ratio; + return BigInt.asUintN( + 160, + (ratio >> 32n) + (ratio % (1n << 32n) == 0n ? 0n : 1n), + ); + } + + static getTickAtSqrtRatio(sqrtPriceX96: bigint): bigint { + _require( + sqrtPriceX96 >= TickMath.MIN_SQRT_RATIO && + sqrtPriceX96 < TickMath.MAX_SQRT_RATIO, + 'R', + { sqrtPriceX96 }, + 'sqrtPriceX96 >= TickMath.MIN_SQRT_RATIO && sqrtPriceX96 < TickMath.MAX_SQRT_RATIO', + ); + + let ratio = BigInt.asUintN(256, sqrtPriceX96) << 32n; + + let r = ratio; + let msb = 0n; + + let f = _gt(r, 0xffffffffffffffffffffffffffffffffn) << 7n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xffffffffffffffffn) << 6n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xffffffffn) << 5n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xffffn) << 4n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xffn) << 3n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xfn) << 2n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0x3n) << 1n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0x1n); + msb = msb | f; + + if (msb >= 128n) r = ratio >> (msb - 127n); + else r = ratio << (127n - msb); + + let log_2 = (BigInt.asIntN(256, msb) - 128n) << 64n; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 63n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 62n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 61n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 60n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 59n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 58n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 57n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 56n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 55n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 54n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 53n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 52n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 51n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 50n); + + const log_sqrt10001 = log_2 * 255738958999603826347141n; // 128.128 number + + const tickLow = BigInt.asIntN( + 24, + (log_sqrt10001 - 3402992956809132418596140100660247210n) >> 128n, + ); + const tickHi = BigInt.asIntN( + 24, + (log_sqrt10001 + 291339464771989622907027621153398088495n) >> 128n, + ); + + return tickLow === tickHi + ? tickLow + : TickMath.getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 + ? tickHi + : tickLow; + } +} diff --git a/src/dex/solidly-v3/contract-math/UnsafeMath.ts b/src/dex/solidly-v3/contract-math/UnsafeMath.ts new file mode 100644 index 000000000..aebd7c579 --- /dev/null +++ b/src/dex/solidly-v3/contract-math/UnsafeMath.ts @@ -0,0 +1,5 @@ +export class UnsafeMath { + static divRoundingUp(x: bigint, y: bigint) { + return (x + y - 1n) / y; + } +} diff --git a/src/dex/solidly-v3/contract-math/uniswap-v3-math.ts b/src/dex/solidly-v3/contract-math/uniswap-v3-math.ts new file mode 100644 index 000000000..d18881006 --- /dev/null +++ b/src/dex/solidly-v3/contract-math/uniswap-v3-math.ts @@ -0,0 +1,666 @@ +import _ from 'lodash'; +import { OutputResult, PoolState, Slot0, TickInfo } from '../types'; +import { LiquidityMath } from './LiquidityMath'; +import { Oracle } from './Oracle'; +import { SqrtPriceMath } from './SqrtPriceMath'; +import { SwapMath } from './SwapMath'; +import { Tick } from './Tick'; +import { TickBitMap } from './TickBitMap'; +import { TickMath } from './TickMath'; +import { _require } from '../../../utils'; +import { DeepReadonly } from 'ts-essentials'; +import { NumberAsString, SwapSide } from '@paraswap/core'; +import { BI_MAX_INT } from '../../../bigint-constants'; +import { + MAX_PRICING_COMPUTATION_STEPS_ALLOWED, + OUT_OF_RANGE_ERROR_POSTFIX, +} from '../constants'; + +type ModifyPositionParams = { + tickLower: bigint; + tickUpper: bigint; + liquidityDelta: bigint; +}; + +export type PriceComputationState = { + amountSpecifiedRemaining: bigint; + amountCalculated: bigint; + sqrtPriceX96: bigint; + tick: bigint; + protocolFee: bigint; + liquidity: bigint; + isFirstCycleState: boolean; +}; + +export type PriceComputationCache = { + liquidityStart: bigint; + blockTimestamp: bigint; + feeProtocol: bigint; + secondsPerLiquidityCumulativeX128: bigint; + tickCumulative: bigint; + computedLatestObservation: boolean; + tickCount: number; +}; + +export function _updatePriceComputationObjects< + T extends PriceComputationState | PriceComputationCache, +>(toUpdate: T, updateBy: T) { + for (const k of Object.keys(updateBy) as (keyof T)[]) { + toUpdate[k] = updateBy[k]; + } +} + +function _priceComputationCycles( + poolState: DeepReadonly, + ticksCopy: Record, + slot0Start: Slot0, + state: PriceComputationState, + cache: PriceComputationCache, + sqrtPriceLimitX96: bigint, + zeroForOne: boolean, + exactInput: boolean, +): [ + // result + PriceComputationState, + // Latest calculated full cycle state we can use for bigger amounts + { + latestFullCycleState: PriceComputationState; + latestFullCycleCache: PriceComputationCache; + }, +] { + const latestFullCycleState: PriceComputationState = { ...state }; + + if (cache.tickCount == 0) { + cache.tickCount = 1; + } + const latestFullCycleCache: PriceComputationCache = { ...cache }; + + // We save tick before any change. Later we use this to restore + // state before last step + let lastTicksCopy: { index: number; tick: TickInfo } | undefined; + + let i = 0; + for ( + ; + state.amountSpecifiedRemaining !== 0n && + state.sqrtPriceX96 !== sqrtPriceLimitX96; + ++i + ) { + if ( + latestFullCycleCache.tickCount + i > + MAX_PRICING_COMPUTATION_STEPS_ALLOWED + ) { + state.amountSpecifiedRemaining = 0n; + state.amountCalculated = 0n; + break; + } + + const step = { + sqrtPriceStartX96: 0n, + tickNext: 0n, + initialized: false, + sqrtPriceNextX96: 0n, + amountIn: 0n, + amountOut: 0n, + feeAmount: 0n, + }; + + step.sqrtPriceStartX96 = state.sqrtPriceX96; + + try { + [step.tickNext, step.initialized] = + TickBitMap.nextInitializedTickWithinOneWord( + poolState, + state.tick, + poolState.tickSpacing, + zeroForOne, + true, + ); + } catch (e) { + if ( + e instanceof Error && + e.message.endsWith(OUT_OF_RANGE_ERROR_POSTFIX) + ) { + state.amountSpecifiedRemaining = 0n; + state.amountCalculated = 0n; + break; + } + throw e; + } + + if (step.tickNext < TickMath.MIN_TICK) { + step.tickNext = TickMath.MIN_TICK; + } else if (step.tickNext > TickMath.MAX_TICK) { + step.tickNext = TickMath.MAX_TICK; + } + + step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext); + + const swapStepResult = SwapMath.computeSwapStep( + state.sqrtPriceX96, + ( + zeroForOne + ? step.sqrtPriceNextX96 < sqrtPriceLimitX96 + : step.sqrtPriceNextX96 > sqrtPriceLimitX96 + ) + ? sqrtPriceLimitX96 + : step.sqrtPriceNextX96, + state.liquidity, + state.amountSpecifiedRemaining, + poolState.fee, + ); + + state.sqrtPriceX96 = swapStepResult.sqrtRatioNextX96; + step.amountIn = swapStepResult.amountIn; + step.amountOut = swapStepResult.amountOut; + step.feeAmount = swapStepResult.feeAmount; + + if (exactInput) { + state.amountSpecifiedRemaining -= step.amountIn + step.feeAmount; + state.amountCalculated = state.amountCalculated - step.amountOut; + } else { + state.amountSpecifiedRemaining += step.amountOut; + state.amountCalculated = + state.amountCalculated + step.amountIn + step.feeAmount; + } + + if (cache.feeProtocol > 0n) { + const delta = step.feeAmount / cache.feeProtocol; + step.feeAmount -= delta; + state.protocolFee += delta; + } + + if (state.sqrtPriceX96 === step.sqrtPriceNextX96) { + if (step.initialized) { + if (!cache.computedLatestObservation) { + [cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128] = + Oracle.observeSingle( + poolState, + cache.blockTimestamp, + 0n, + slot0Start.tick, + slot0Start.observationIndex, + cache.liquidityStart, + slot0Start.observationCardinality, + ); + cache.computedLatestObservation = true; + } + + if (state.amountSpecifiedRemaining === 0n) { + const castTickNext = Number(step.tickNext); + lastTicksCopy = { + index: castTickNext, + tick: { ...ticksCopy[castTickNext] }, + }; + } + + let liquidityNet = Tick.cross( + ticksCopy, + step.tickNext, + cache.secondsPerLiquidityCumulativeX128, + cache.tickCumulative, + cache.blockTimestamp, + ); + if (zeroForOne) liquidityNet = -liquidityNet; + + state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet); + } + + state.tick = zeroForOne ? step.tickNext - 1n : step.tickNext; + } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) { + state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96); + } + + if (state.amountSpecifiedRemaining !== 0n) { + _updatePriceComputationObjects(latestFullCycleState, state); + _updatePriceComputationObjects(latestFullCycleCache, cache); + // If it last cycle, check if ticks were changed and then restore previous state + // for next calculations + } else if (lastTicksCopy !== undefined) { + ticksCopy[lastTicksCopy.index] = lastTicksCopy.tick; + } + } + + if (i > 1) { + latestFullCycleCache.tickCount += i - 1; + } + + if (state.amountSpecifiedRemaining !== 0n) { + state.amountSpecifiedRemaining = 0n; + state.amountCalculated = 0n; + } + + return [state, { latestFullCycleState, latestFullCycleCache }]; +} + +class UniswapV3Math { + queryOutputs( + poolState: DeepReadonly, + // Amounts must increase + amounts: bigint[], + zeroForOne: boolean, + side: SwapSide, + ): OutputResult { + const slot0Start = poolState.slot0; + + const isSell = side === SwapSide.SELL; + + // While calculating, ticks are changing, so to not change the actual state, + // we use copy + const ticksCopy = _.cloneDeep(poolState.ticks); + + const sqrtPriceLimitX96 = zeroForOne + ? TickMath.MIN_SQRT_RATIO + 1n + : TickMath.MAX_SQRT_RATIO - 1n; + + const cache: PriceComputationCache = { + liquidityStart: poolState.liquidity, + blockTimestamp: this._blockTimestamp(poolState), + feeProtocol: zeroForOne + ? slot0Start.feeProtocol % 16n + : slot0Start.feeProtocol >> 4n, + secondsPerLiquidityCumulativeX128: 0n, + tickCumulative: 0n, + computedLatestObservation: false, + tickCount: 0, + }; + + const state: PriceComputationState = { + // Will be overwritten later + amountSpecifiedRemaining: 0n, + amountCalculated: 0n, + sqrtPriceX96: slot0Start.sqrtPriceX96, + tick: slot0Start.tick, + protocolFee: 0n, + liquidity: cache.liquidityStart, + isFirstCycleState: true, + }; + + let isOutOfRange = false; + let previousAmount = 0n; + + const outputs = new Array(amounts.length); + const tickCounts = new Array(amounts.length); + for (const [i, amount] of amounts.entries()) { + if (amount === 0n) { + outputs[i] = 0n; + tickCounts[i] = 0; + continue; + } + + const amountSpecified = isSell + ? BigInt.asIntN(256, amount) + : -BigInt.asIntN(256, amount); + + if (state.isFirstCycleState) { + // Set first non zero amount + state.amountSpecifiedRemaining = amountSpecified; + state.isFirstCycleState = false; + } else { + state.amountSpecifiedRemaining = + amountSpecified - (previousAmount - state.amountSpecifiedRemaining); + } + + const exactInput = amountSpecified > 0n; + + _require( + zeroForOne + ? sqrtPriceLimitX96 < slot0Start.sqrtPriceX96 && + sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO + : sqrtPriceLimitX96 > slot0Start.sqrtPriceX96 && + sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO, + 'SPL', + { zeroForOne, sqrtPriceLimitX96, slot0Start }, + 'zeroForOne ? sqrtPriceLimitX96 < slot0Start.sqrtPriceX96 && sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO : sqrtPriceLimitX96 > slot0Start.sqrtPriceX96 && sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO', + ); + + if (!isOutOfRange) { + const [finalState, { latestFullCycleState, latestFullCycleCache }] = + _priceComputationCycles( + poolState, + ticksCopy, + slot0Start, + state, + cache, + sqrtPriceLimitX96, + zeroForOne, + exactInput, + ); + if ( + finalState.amountSpecifiedRemaining === 0n && + finalState.amountCalculated === 0n + ) { + isOutOfRange = true; + outputs[i] = 0n; + tickCounts[i] = 0; + continue; + } + + // We use it on next step to correct state.amountSpecifiedRemaining + previousAmount = amountSpecified; + + // First extract calculated values + const [amount0, amount1] = + zeroForOne === exactInput + ? [ + amountSpecified - finalState.amountSpecifiedRemaining, + finalState.amountCalculated, + ] + : [ + finalState.amountCalculated, + amountSpecified - finalState.amountSpecifiedRemaining, + ]; + + // Update for next amount + _updatePriceComputationObjects(state, latestFullCycleState); + _updatePriceComputationObjects(cache, latestFullCycleCache); + + if (isSell) { + outputs[i] = BigInt.asUintN(256, -(zeroForOne ? amount1 : amount0)); + tickCounts[i] = latestFullCycleCache.tickCount; + continue; + } else { + outputs[i] = zeroForOne + ? BigInt.asUintN(256, amount0) + : BigInt.asUintN(256, amount1); + tickCounts[i] = latestFullCycleCache.tickCount; + continue; + } + } else { + outputs[i] = 0n; + tickCounts[i] = 0; + } + } + + return { + outputs, + tickCounts, + }; + } + + swapFromEvent( + poolState: PoolState, + newSqrtPriceX96: bigint, + newTick: bigint, + newLiquidity: bigint, + zeroForOne: boolean, + ): void { + const slot0Start = poolState.slot0; + + const cache = { + liquidityStart: poolState.liquidity, + blockTimestamp: this._blockTimestamp(poolState), + feeProtocol: 0n, + secondsPerLiquidityCumulativeX128: 0n, + tickCumulative: 0n, + computedLatestObservation: false, + }; + + const state = { + // Because I don't have the exact amount user used, set this number to MAX_NUMBER to proceed + // with calculations. I think it is not a problem since in loop I don't rely on this value + amountSpecifiedRemaining: BI_MAX_INT, + amountCalculated: 0n, + sqrtPriceX96: slot0Start.sqrtPriceX96, + tick: slot0Start.tick, + protocolFee: 0n, + liquidity: cache.liquidityStart, + }; + + // Because I didn't have all variables, adapted loop stop with state.tick !== newTick + // condition. This cycle need only to calculate Tick.cross() function values + // It means that we are interested in cycling only if state.tick !== newTick + // When they become equivalent, we proceed with state updating part as normal + // And if assumptions regarding this cycle are correct, we don't need to process + // the last cycle when state.tick === newTick + while (state.tick !== newTick && state.sqrtPriceX96 !== newSqrtPriceX96) { + const step = { + sqrtPriceStartX96: 0n, + tickNext: 0n, + initialized: false, + sqrtPriceNextX96: 0n, + amountIn: 0n, + amountOut: 0n, + feeAmount: 0n, + }; + + step.sqrtPriceStartX96 = state.sqrtPriceX96; + + [step.tickNext, step.initialized] = + TickBitMap.nextInitializedTickWithinOneWord( + poolState, + state.tick, + poolState.tickSpacing, + zeroForOne, + false, + ); + + if (step.tickNext < TickMath.MIN_TICK) { + step.tickNext = TickMath.MIN_TICK; + } else if (step.tickNext > TickMath.MAX_TICK) { + step.tickNext = TickMath.MAX_TICK; + } + + step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext); + + const swapStepResult = SwapMath.computeSwapStep( + state.sqrtPriceX96, + ( + zeroForOne + ? step.sqrtPriceNextX96 < newSqrtPriceX96 + : step.sqrtPriceNextX96 > newSqrtPriceX96 + ) + ? newSqrtPriceX96 + : step.sqrtPriceNextX96, + state.liquidity, + state.amountSpecifiedRemaining, + poolState.fee, + ); + + state.sqrtPriceX96 = swapStepResult.sqrtRatioNextX96; + + if (state.sqrtPriceX96 == step.sqrtPriceNextX96) { + if (step.initialized) { + if (!cache.computedLatestObservation) { + [cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128] = + Oracle.observeSingle( + poolState, + cache.blockTimestamp, + 0n, + slot0Start.tick, + slot0Start.observationIndex, + cache.liquidityStart, + slot0Start.observationCardinality, + ); + cache.computedLatestObservation = true; + } + + let liquidityNet = Tick.cross( + poolState.ticks, + step.tickNext, + cache.secondsPerLiquidityCumulativeX128, + cache.tickCumulative, + cache.blockTimestamp, + ); + + if (zeroForOne) liquidityNet = -liquidityNet; + + state.liquidity = LiquidityMath.addDelta( + state.liquidity, + liquidityNet, + ); + } + + state.tick = zeroForOne ? step.tickNext - 1n : step.tickNext; + } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) { + state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96); + } + } + + if (slot0Start.tick !== newTick) { + const [observationIndex, observationCardinality] = Oracle.write( + poolState, + slot0Start.observationIndex, + this._blockTimestamp(poolState), + slot0Start.tick, + poolState.liquidity, + slot0Start.observationCardinality, + slot0Start.observationCardinalityNext, + ); + + [ + poolState.slot0.sqrtPriceX96, + poolState.slot0.tick, + poolState.slot0.observationIndex, + poolState.slot0.observationCardinality, + ] = [newSqrtPriceX96, newTick, observationIndex, observationCardinality]; + } else { + poolState.slot0.sqrtPriceX96 = newSqrtPriceX96; + } + + if (poolState.liquidity !== newLiquidity) + poolState.liquidity = newLiquidity; + } + + _modifyPosition( + state: PoolState, + params: ModifyPositionParams, + ): [bigint, bigint] { + const _slot0 = state.slot0; + + this._updatePosition( + state, + params.tickLower, + params.tickUpper, + params.liquidityDelta, + _slot0.tick, + ); + + let amount0 = 0n; + let amount1 = 0n; + if (params.liquidityDelta !== 0n) { + if (_slot0.tick < params.tickLower) { + amount0 = SqrtPriceMath._getAmount0DeltaO( + TickMath.getSqrtRatioAtTick(params.tickLower), + TickMath.getSqrtRatioAtTick(params.tickUpper), + params.liquidityDelta, + ); + } else if (_slot0.tick < params.tickUpper) { + const liquidityBefore = state.liquidity; + + [state.slot0.observationIndex, state.slot0.observationCardinality] = + Oracle.write( + state, + _slot0.observationIndex, + this._blockTimestamp(state), + _slot0.tick, + liquidityBefore, + _slot0.observationCardinality, + _slot0.observationCardinalityNext, + ); + + amount0 = SqrtPriceMath._getAmount0DeltaO( + _slot0.sqrtPriceX96, + TickMath.getSqrtRatioAtTick(params.tickUpper), + params.liquidityDelta, + ); + amount1 = SqrtPriceMath._getAmount1DeltaO( + TickMath.getSqrtRatioAtTick(params.tickLower), + _slot0.sqrtPriceX96, + params.liquidityDelta, + ); + + state.liquidity = LiquidityMath.addDelta( + liquidityBefore, + params.liquidityDelta, + ); + } else { + amount1 = SqrtPriceMath._getAmount1DeltaO( + TickMath.getSqrtRatioAtTick(params.tickLower), + TickMath.getSqrtRatioAtTick(params.tickUpper), + params.liquidityDelta, + ); + } + } + return [amount0, amount1]; + } + + private _isTickToProcess(state: PoolState, tick: bigint): boolean { + return tick >= state.lowestKnownTick && tick <= state.highestKnownTick; + } + + private _updatePosition( + state: PoolState, + tickLower: bigint, + tickUpper: bigint, + liquidityDelta: bigint, + tick: bigint, + ): void { + // if we need to update the ticks, do it + let flippedLower = false; + let flippedUpper = false; + if (liquidityDelta !== 0n) { + const time = this._blockTimestamp(state); + const [tickCumulative, secondsPerLiquidityCumulativeX128] = + Oracle.observeSingle( + state, + time, + 0n, + state.slot0.tick, + state.slot0.observationIndex, + state.liquidity, + state.slot0.observationCardinality, + ); + + if (this._isTickToProcess(state, tickLower)) { + flippedLower = Tick.update( + state, + tickLower, + tick, + liquidityDelta, + secondsPerLiquidityCumulativeX128, + tickCumulative, + time, + false, + state.maxLiquidityPerTick, + ); + } + if (this._isTickToProcess(state, tickUpper)) { + flippedUpper = Tick.update( + state, + tickUpper, + tick, + liquidityDelta, + secondsPerLiquidityCumulativeX128, + tickCumulative, + time, + true, + state.maxLiquidityPerTick, + ); + } + + if (flippedLower) { + TickBitMap.flipTick(state, tickLower, state.tickSpacing); + } + if (flippedUpper) { + TickBitMap.flipTick(state, tickUpper, state.tickSpacing); + } + } + + // clear any tick data that is no longer needed + if (liquidityDelta < 0n) { + if (flippedLower) { + Tick.clear(state, tickLower); + } + if (flippedUpper) { + Tick.clear(state, tickUpper); + } + } + } + + private _blockTimestamp(state: DeepReadonly) { + return BigInt.asUintN(32, state.blockTimestamp); + } +} + +export const uniswapV3Math = new UniswapV3Math(); diff --git a/src/dex/solidly-v3/contract-math/utils.ts b/src/dex/solidly-v3/contract-math/utils.ts new file mode 100644 index 000000000..65d97736d --- /dev/null +++ b/src/dex/solidly-v3/contract-math/utils.ts @@ -0,0 +1,55 @@ +import { NumberAsString } from '@paraswap/core'; +import { + TickBitMapMappingsWithBigNumber, + TickInfo, + TickInfoMappingsWithBigNumber, +} from '../types'; +import { bigIntify } from '../../../utils'; + +export function _mulmod(x: bigint, y: bigint, m: bigint): bigint { + return m === 0n ? 0n : (x * y) % m; +} + +export function _lt(x: bigint, y: bigint) { + return x < y ? 1n : 0n; +} + +export function _gt(x: bigint, y: bigint) { + return x > y ? 1n : 0n; +} + +export function _reduceTickBitmap( + tickBitmap: Record, + tickBitmapToReduce: TickBitMapMappingsWithBigNumber[], +) { + return tickBitmapToReduce.reduce>( + (acc, curr) => { + const { index, value } = curr; + acc[index] = bigIntify(value); + return acc; + }, + tickBitmap, + ); +} + +export function _reduceTicks( + ticks: Record, + ticksToReduce: TickInfoMappingsWithBigNumber[], +) { + return ticksToReduce.reduce>((acc, curr) => { + const { index, value } = curr; + if (value.initialized) { + acc[index] = { + liquidityGross: bigIntify(value.liquidityGross), + liquidityNet: bigIntify(value.liquidityNet), + tickCumulativeOutside: bigIntify(value.tickCumulativeOutside), + secondsPerLiquidityOutsideX128: bigIntify( + value.secondsPerLiquidityOutsideX128, + ), + secondsOutside: bigIntify(value.secondsOutside), + initialized: value.initialized, + }; + } + return acc; + }, ticks); +} diff --git a/src/dex/solidly-v3/solidly-v3-pool.ts b/src/dex/solidly-v3/solidly-v3-pool.ts index 81a48be2e..4bbf1903d 100644 --- a/src/dex/solidly-v3/solidly-v3-pool.ts +++ b/src/dex/solidly-v3/solidly-v3-pool.ts @@ -1,92 +1,519 @@ +import _ from 'lodash'; +import { Contract } from 'web3-eth-contract'; import { Interface } from '@ethersproject/abi'; -import { DeepReadonly } from 'ts-essentials'; -import { Log, Logger } from '../../types'; -import { catchParseLogError } from '../../utils'; -import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { ethers } from 'ethers'; +import { assert, DeepReadonly } from 'ts-essentials'; +import { Log, Logger, BlockHeader, Address } from '../../types'; +import { + InitializeStateOptions, + StatefulEventSubscriber, +} from '../../stateful-event-subscriber'; import { IDexHelper } from '../../dex-helper/idex-helper'; -import { PoolState } from './types'; -import SolidlyV3PoolABI from '../../abi/uniswap-v3/UniswapV3Pool.abi.json'; +import { + PoolState, + DecodedStateMultiCallResultWithRelativeBitmaps, + DecodeStateMultiCallFunc, +} from './types'; +import UniswapV3PoolABI from '../../abi/uniswap-v3/UniswapV3Pool.abi.json'; +import { bigIntify, catchParseLogError, isSampled } from '../../utils'; +import { uniswapV3Math } from './contract-math/uniswap-v3-math'; +import { MultiCallParams } from '../../lib/multi-wrapper'; +import { + OUT_OF_RANGE_ERROR_POSTFIX, + TICK_BITMAP_BUFFER, + TICK_BITMAP_TO_USE, +} from './constants'; +import { TickBitMap } from './contract-math/TickBitMap'; +import { uint256ToBigInt } from '../../lib/decoders'; +import { decodeStateMultiCallResultWithRelativeBitmaps } from './utils'; +import { _reduceTickBitmap, _reduceTicks } from './contract-math/utils'; export class SolidlyV3EventPool extends StatefulEventSubscriber { handlers: { [event: string]: ( event: any, - state: DeepReadonly, - log: Readonly, - ) => DeepReadonly | null; + pool: PoolState, + log: Log, + blockHeader: Readonly, + ) => PoolState; } = {}; logDecoder: (log: Log) => any; - addressesSubscribed: string[]; + readonly token0: Address; + + readonly token1: Address; + + private _poolAddress?: Address; + + private _stateRequestCallData?: MultiCallParams< + bigint | DecodedStateMultiCallResultWithRelativeBitmaps + >[]; + + public readonly poolIface = new Interface(UniswapV3PoolABI); + + public initFailed = false; + public initRetryAttemptCount = 0; + + public readonly feeCodeAsString; constructor( - readonly parentName: string, - protected network: number, - protected dexHelper: IDexHelper, + readonly dexHelper: IDexHelper, + parentName: string, + readonly stateMultiContract: Contract, + readonly decodeStateMultiCallResultWithRelativeBitmaps: + | DecodeStateMultiCallFunc + | undefined, + readonly erc20Interface: Interface, + protected readonly factoryAddress: Address, + public readonly feeCode: bigint, + token0: Address, + token1: Address, logger: Logger, - protected solidlyV3Iface = new Interface( - '' /* TODO: Import and put here SolidlyV3 ABI */, - ), // TODO: add any additional params required for event subscriber + mapKey: string = '', + readonly poolInitCodeHash: string, ) { - // TODO: Add pool name - super(parentName, 'POOL_NAME', dexHelper, logger); - - // TODO: make logDecoder decode logs that - this.logDecoder = (log: Log) => this.solidlyV3Iface.parseLog(log); - this.addressesSubscribed = [ - /* subscribed addresses */ - ]; + super( + parentName, + `${token0}_${token1}_${feeCode}`, + dexHelper, + logger, + true, + mapKey, + ); + this.feeCodeAsString = feeCode.toString(); + this.token0 = token0.toLowerCase(); + this.token1 = token1.toLowerCase(); + this.logDecoder = (log: Log) => this.poolIface.parseLog(log); + this.addressesSubscribed = new Array
(1); // Add handlers - this.handlers['myEvent'] = this.handleMyEvent.bind(this); - } - - /** - * The function is called every time any of the subscribed - * addresses release log. The function accepts the current - * state, updates the state according to the log, and returns - * the updated state. - * @param state - Current state of event subscriber - * @param log - Log released by one of the subscribed addresses - * @returns Updates state of the event subscriber after the log - */ + this.handlers['Swap'] = this.handleSwapEvent.bind(this); + this.handlers['Burn'] = this.handleBurnEvent.bind(this); + this.handlers['Mint'] = this.handleMintEvent.bind(this); + this.handlers['SetFeeProtocol'] = this.handleSetFeeProtocolEvent.bind(this); + this.handlers['IncreaseObservationCardinalityNext'] = + this.handleIncreaseObservationCardinalityNextEvent.bind(this); + + // Wen need them to keep balance of the pool up to date + this.handlers['Collect'] = this.handleCollectEvent.bind(this); + // Almost the same as Collect, but for pool owners + this.handlers['CollectProtocol'] = this.handleCollectEvent.bind(this); + this.handlers['Flash'] = this.handleFlashEvent.bind(this); + } + + get poolAddress() { + if (this._poolAddress === undefined) { + this._poolAddress = this._computePoolAddress( + this.token0, + this.token1, + this.feeCode, + ); + } + return this._poolAddress; + } + + set poolAddress(address: Address) { + this._poolAddress = address.toLowerCase(); + } + + async initialize( + blockNumber: number, + options?: InitializeStateOptions, + ) { + await super.initialize(blockNumber, options); + } + + protected async processBlockLogs( + state: DeepReadonly, + logs: Readonly[], + blockHeader: Readonly, + ): Promise | null> { + const newState = await super.processBlockLogs(state, logs, blockHeader); + if (newState && !newState.isValid) { + return await this.generateState(blockHeader.number); + } + return newState; + } + protected processLog( state: DeepReadonly, log: Readonly, + blockHeader: Readonly, ): DeepReadonly | null { try { const event = this.logDecoder(log); + + const uniswapV3EventLoggingSampleRate = + this.dexHelper.config.data.uniswapV3EventLoggingSampleRate; + if ( + !this.dexHelper.config.isSlave && + uniswapV3EventLoggingSampleRate && + isSampled(uniswapV3EventLoggingSampleRate) + ) { + this.logger.info( + `event=${event.name} - block=${ + blockHeader.number + }. Log sampled at rate ${uniswapV3EventLoggingSampleRate * 100}%`, + ); + } + if (event.name in this.handlers) { - return this.handlers[event.name](event, state, log); + // Because we have observations in array which is mutable by nature, there is a + // ts compile error: https://stackoverflow.com/questions/53412934/disable-allowing-assigning-readonly-types-to-non-readonly-types + // And there is no good workaround, so turn off the type checker for this line + const _state = _.cloneDeep(state) as PoolState; + try { + return this.handlers[event.name](event, _state, log, blockHeader); + } catch (e) { + if ( + e instanceof Error && + e.message.endsWith(OUT_OF_RANGE_ERROR_POSTFIX) + ) { + this.logger.warn( + `${this.parentName}: Pool ${this.poolAddress} on ${ + this.dexHelper.config.data.network + } is out of TickBitmap requested range. Re-query the state. ${JSON.stringify( + event, + )}`, + e, + ); + } else { + this.logger.error( + `${this.parentName}: Pool ${this.poolAddress}, ` + + `network=${this.dexHelper.config.data.network}: Unexpected ` + + `error while handling event on blockNumber=${blockHeader.number}, ` + + `blockHash=${blockHeader.hash} and parentHash=${ + blockHeader.parentHash + } for UniswapV3, ${JSON.stringify(event)}`, + e, + ); + } + _state.isValid = false; + return _state; + } } } catch (e) { catchParseLogError(e, this.logger); } + return null; // ignore unrecognized event + } + + private _getStateRequestCallData() { + if (!this._stateRequestCallData) { + const callData: MultiCallParams< + bigint | DecodedStateMultiCallResultWithRelativeBitmaps + >[] = [ + { + target: this.token0, + callData: this.erc20Interface.encodeFunctionData('balanceOf', [ + this.poolAddress, + ]), + decodeFunction: uint256ToBigInt, + }, + { + target: this.token1, + callData: this.erc20Interface.encodeFunctionData('balanceOf', [ + this.poolAddress, + ]), + decodeFunction: uint256ToBigInt, + }, + { + target: this.stateMultiContract.options.address, + callData: this.stateMultiContract.methods + .getFullStateWithRelativeBitmaps( + this.factoryAddress, + this.token0, + this.token1, + this.feeCode, + this.getBitmapRangeToRequest(), + this.getBitmapRangeToRequest(), + ) + .encodeABI(), + decodeFunction: + this.decodeStateMultiCallResultWithRelativeBitmaps !== undefined + ? this.decodeStateMultiCallResultWithRelativeBitmaps + : decodeStateMultiCallResultWithRelativeBitmaps, + }, + ]; - return null; + this._stateRequestCallData = callData; + } + return this._stateRequestCallData; } - /** - * The function generates state using on-chain calls. This - * function is called to regenerate state if the event based - * system fails to fetch events and the local state is no - * more correct. - * @param blockNumber - Blocknumber for which the state should - * should be generated - * @returns state of the event subscriber at blocknumber - */ - async generateState(blockNumber: number): Promise> { - // TODO: complete me! - return {}; + getBitmapRangeToRequest() { + return TICK_BITMAP_TO_USE + TICK_BITMAP_BUFFER; } - // Its just a dummy example - handleMyEvent( + async generateState(blockNumber: number): Promise> { + const callData = this._getStateRequestCallData(); + + const [resBalance0, resBalance1, resState] = + await this.dexHelper.multiWrapper.tryAggregate< + bigint | DecodedStateMultiCallResultWithRelativeBitmaps + >( + false, + callData, + blockNumber, + this.dexHelper.multiWrapper.defaultBatchSize, + false, + ); + + // Quite ugly solution, but this is the one that fits to current flow. + // I think UniswapV3 callbacks subscriptions are complexified for no reason. + // Need to be revisited later + assert(resState.success, 'Pool does not exist'); + + const [balance0, balance1, _state] = [ + resBalance0.returnData, + resBalance1.returnData, + resState.returnData, + ] as [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmaps]; + + const tickBitmap = {}; + const ticks = {}; + + _reduceTickBitmap(tickBitmap, _state.tickBitmap); + _reduceTicks(ticks, _state.ticks); + + const observations = { + [_state.slot0.observationIndex]: { + blockTimestamp: bigIntify(_state.observation.blockTimestamp), + tickCumulative: bigIntify(_state.observation.tickCumulative), + secondsPerLiquidityCumulativeX128: bigIntify( + _state.observation.secondsPerLiquidityCumulativeX128, + ), + initialized: _state.observation.initialized, + }, + }; + + const currentTick = bigIntify(_state.slot0.tick); + const tickSpacing = bigIntify(_state.tickSpacing); + + const startTickBitmap = TickBitMap.position(currentTick / tickSpacing)[0]; + const requestedRange = this.getBitmapRangeToRequest(); + + return { + pool: _state.pool, + blockTimestamp: bigIntify(_state.blockTimestamp), + slot0: { + sqrtPriceX96: bigIntify(_state.slot0.sqrtPriceX96), + tick: currentTick, + observationIndex: +_state.slot0.observationIndex, + observationCardinality: +_state.slot0.observationCardinality, + observationCardinalityNext: +_state.slot0.observationCardinalityNext, + feeProtocol: bigIntify(_state.slot0.feeProtocol), + }, + liquidity: bigIntify(_state.liquidity), + fee: this.feeCode, + tickSpacing, + maxLiquidityPerTick: bigIntify(_state.maxLiquidityPerTick), + tickBitmap, + ticks, + observations, + isValid: true, + startTickBitmap, + lowestKnownTick: + (BigInt.asIntN(24, startTickBitmap - requestedRange) << 8n) * + tickSpacing, + highestKnownTick: + ((BigInt.asIntN(24, startTickBitmap + requestedRange) << 8n) + + BigInt.asIntN(24, 255n)) * + tickSpacing, + balance0, + balance1, + }; + } + + handleSwapEvent( event: any, - state: DeepReadonly, - log: Readonly, - ): DeepReadonly | null { - return null; + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const newSqrtPriceX96 = bigIntify(event.args.sqrtPriceX96); + const amount0 = bigIntify(event.args.amount0); + const amount1 = bigIntify(event.args.amount1); + const newTick = bigIntify(event.args.tick); + const newLiquidity = bigIntify(event.args.liquidity); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + if (amount0 <= 0n && amount1 <= 0n) { + this.logger.error( + `${this.parentName}: amount0 <= 0n && amount1 <= 0n for ` + + `${this.poolAddress} and ${blockHeader.number}. Check why it happened`, + ); + pool.isValid = false; + return pool; + } else { + const zeroForOne = amount0 > 0n; + + uniswapV3Math.swapFromEvent( + pool, + newSqrtPriceX96, + newTick, + newLiquidity, + zeroForOne, + ); + + if (zeroForOne) { + if (amount1 < 0n) { + pool.balance1 -= BigInt.asUintN(256, -amount1); + } else { + this.logger.error( + `In swapEvent for pool ${pool.pool} received incorrect values ${zeroForOne} and ${amount1}`, + ); + pool.isValid = false; + } + // This is not correct fully, because pool may get more tokens then it needs, but + // it is not accounted in internal state, it should be good enough + pool.balance0 += BigInt.asUintN(256, amount0); + } else { + if (amount0 < 0n) { + pool.balance0 -= BigInt.asUintN(256, -amount0); + } else { + this.logger.error( + `In swapEvent for pool ${pool.pool} received incorrect values ${zeroForOne} and ${amount0}`, + ); + pool.isValid = false; + } + pool.balance1 += BigInt.asUintN(256, amount1); + } + + return pool; + } + } + + handleBurnEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const amount = bigIntify(event.args.amount); + const tickLower = bigIntify(event.args.tickLower); + const tickUpper = bigIntify(event.args.tickUpper); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + uniswapV3Math._modifyPosition(pool, { + tickLower, + tickUpper, + liquidityDelta: -BigInt.asIntN(128, BigInt.asIntN(256, amount)), + }); + + // From this transaction I conclude that there is no balance change from + // Burn event: https://dashboard.tenderly.co/tx/mainnet/0xfccf5341147ac3ad0e66452273d12dfc3219e81f8fb369a6cdecfb24b9b9d078/logs + // And it aligns with UniswapV3 doc: + // https://github.com/Uniswap/v3-core/blob/05c10bf6d547d6121622ac51c457f93775e1df09/contracts/interfaces/pool/IUniswapV3PoolActions.sol#L59 + // It just updates positions and tokensOwed which may be requested calling collect + // So, we don't need to update pool.balances0 and pool.balances1 here + + return pool; + } + + handleMintEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const amount = bigIntify(event.args.amount); + const tickLower = bigIntify(event.args.tickLower); + const tickUpper = bigIntify(event.args.tickUpper); + const amount0 = bigIntify(event.args.amount0); + const amount1 = bigIntify(event.args.amount1); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + uniswapV3Math._modifyPosition(pool, { + tickLower, + tickUpper, + liquidityDelta: amount, + }); + + pool.balance0 += amount0; + pool.balance1 += amount1; + + return pool; + } + + handleSetFeeProtocolEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const feeProtocol0 = bigIntify(event.args.feeProtocol0New); + const feeProtocol1 = bigIntify(event.args.feeProtocol1New); + pool.slot0.feeProtocol = feeProtocol0 + (feeProtocol1 << 4n); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + return pool; + } + + handleCollectEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const amount0 = bigIntify(event.args.amount0); + const amount1 = bigIntify(event.args.amount1); + pool.balance0 -= amount0; + pool.balance1 -= amount1; + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + return pool; + } + + handleFlashEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const paid0 = bigIntify(event.args.paid0); + const paid1 = bigIntify(event.args.paid1); + pool.balance0 += paid0; + pool.balance1 += paid1; + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + return pool; + } + + handleIncreaseObservationCardinalityNextEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + pool.slot0.observationCardinalityNext = parseInt( + event.args.observationCardinalityNextNew, + 10, + ); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + return pool; + } + + private _computePoolAddress( + token0: Address, + token1: Address, + fee: bigint, + ): Address { + // https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/PoolAddress.sol + if (token0 > token1) [token0, token1] = [token1, token0]; + + const encodedKey = ethers.utils.keccak256( + ethers.utils.defaultAbiCoder.encode( + ['address', 'address', 'uint24'], + [token0, token1, BigInt.asUintN(24, fee)], + ), + ); + + return ethers.utils.getCreate2Address( + this.factoryAddress, + encodedKey, + this.poolInitCodeHash, + ); } } diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index d632bdded..0ebf14f33 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -1,86 +1,514 @@ -import { AsyncOrSync } from 'ts-essentials'; +import { defaultAbiCoder, Interface } from '@ethersproject/abi'; +import _ from 'lodash'; +import { pack } from '@ethersproject/solidity'; import { Token, Address, ExchangePrices, - PoolPrices, AdapterExchangeParam, SimpleExchangeParam, PoolLiquidity, Logger, + NumberAsString, + PoolPrices, + TxInfo, + PreprocessTransactionOptions, + ExchangeTxInfo, } from '../../types'; -import { SwapSide, Network } from '../../constants'; +import { SwapSide, Network, CACHE_PREFIX } from '../../constants'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { getDexKeysWithNetwork } from '../../utils'; +import { + getBigIntPow, + getDexKeysWithNetwork, + interpolate, + isTruthy, + uuidToBytes16, +} from '../../utils'; import { IDex } from '../../dex/idex'; import { IDexHelper } from '../../dex-helper/idex-helper'; -import { SolidlyV3Data } from './types'; -import { SimpleExchange } from '../simple-exchange'; -import { SolidlyV3Config, Adapters } from './config'; +import { + DexParams, + OutputResult, + PoolState, + SolidlyV3Data, + UniswapV3Functions, + UniswapV3Param, + UniswapV3SimpleSwapParams, +} from './types'; +import { + getLocalDeadlineAsFriendlyPlaceholder, + SimpleExchange, +} from '../simple-exchange'; +import { SolidlyV3Config, Adapters, PoolsToPreload } from './config'; import { SolidlyV3EventPool } from './solidly-v3-pool'; +import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; +import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; +import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; +import DirectSwapABI from '../../abi/DirectSwap.json'; +import UniswapV3StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; +import { + DirectMethods, + UNISWAPV3_EFFICIENCY_FACTOR, + UNISWAPV3_POOL_SEARCH_OVERHEAD, + UNISWAPV3_TICK_BASE_OVERHEAD, + UNISWAPV3_TICK_GAS_COST, +} from './constants'; +import { assert, DeepReadonly } from 'ts-essentials'; +import { uniswapV3Math } from './contract-math/uniswap-v3-math'; +import { Contract } from 'web3-eth-contract'; +import { AbiItem } from 'web3-utils'; +import { BalanceRequest, getBalances } from '../../lib/tokens/balancer-fetcher'; +import { + AssetType, + DEFAULT_ID_ERC20, + DEFAULT_ID_ERC20_AS_STRING, +} from '../../lib/tokens/types'; +import { OptimalSwapExchange } from '@paraswap/core'; + +type PoolPairsInfo = { + token0: Address; + token1: Address; + fee: string; +}; + +const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 60 * 60 * 24 * 1000; // 24 hours +const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 30 * 60 * 1000; // Once in 30 minutes +const UNISWAPV3_QUOTE_GASLIMIT = 200_000; -export class SolidlyV3 extends SimpleExchange implements IDex { - protected eventPools: SolidlyV3EventPool; +export class SolidlyV3 + extends SimpleExchange + implements IDex +{ + readonly isFeeOnTransferSupported: boolean = false; + readonly eventPools: Record = {}; readonly hasConstantPriceLargeAmounts = false; - // TODO: set true here if protocols works only with wrapped asset readonly needWrapNative = true; - readonly isFeeOnTransferSupported = false; + readonly directSwapIface = new Interface(DirectSwapABI); + + intervalTask?: NodeJS.Timeout; public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(SolidlyV3Config); + getDexKeysWithNetwork( + _.pick(SolidlyV3Config, [ + 'UniswapV3', + 'SushiSwapV3', + 'QuickSwapV3.1', + 'RamsesV2', + 'ChronosV3', + ]), + ); logger: Logger; + private uniswapMulti: Contract; + private stateMultiContract: Contract; + + private notExistingPoolSetKey: string; + constructor( - readonly network: Network, - readonly dexKey: string, - readonly dexHelper: IDexHelper, - protected adapters = Adapters[network] || {}, // TODO: add any additional optional params to support other fork DEXes + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + protected adapters = Adapters[network] || {}, + readonly routerIface = new Interface(UniswapV3RouterABI), + readonly quoterIface = new Interface(UniswapV3QuoterV2ABI), + protected config = SolidlyV3Config[dexKey][network], + protected poolsToPreload = PoolsToPreload[dexKey]?.[network] || [], ) { super(dexHelper, dexKey); - this.logger = dexHelper.getLogger(dexKey); - this.eventPools = new SolidlyV3EventPool( - dexKey, - network, - dexHelper, - this.logger, + this.logger = dexHelper.getLogger(dexKey + '-' + network); + this.uniswapMulti = new this.dexHelper.web3Provider.eth.Contract( + UniswapV3MultiABI as AbiItem[], + this.config.uniswapMulticall, + ); + this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( + this.config.stateMultiCallAbi !== undefined + ? this.config.stateMultiCallAbi + : (UniswapV3StateMulticallABI as AbiItem[]), + this.config.stateMulticall, ); + + // To receive revert reasons + this.dexHelper.web3Provider.eth.handleRevert = false; + + // Normalize once all config addresses and use across all scenarios + this.config = this._toLowerForAllConfigAddresses(); + + this.notExistingPoolSetKey = + `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); } - // Initialize pricing is called once in the start of - // pricing service. It is intended to setup the integration - // for pricing requests. It is optional for a DEX to - // implement this function - async initializePricing(blockNumber: number) { - // TODO: complete me! + get supportedFees() { + return this.config.supportedFees; } - // Returns the list of contract adapters (name and index) - // for a buy/sell. Return null if there are no adapters. getAdapters(side: SwapSide): { name: string; index: number }[] | null { return this.adapters[side] ? this.adapters[side] : null; } - // Returns list of pool identifiers that can be used - // for a given swap. poolIdentifiers must be unique - // across DEXes. It is recommended to use - // ${dexKey}_${poolAddress} as a poolIdentifier + getPoolIdentifier(srcAddress: Address, destAddress: Address, fee: bigint) { + const tokenAddresses = this._sortTokens(srcAddress, destAddress).join('_'); + return `${this.dexKey}_${tokenAddresses}_${fee}`; + } + + async initializePricing(blockNumber: number) { + // This is only for testing, because cold pool fetching is goes out of + // FETCH_POOL_INDENTIFIER_TIMEOUT range + await Promise.all( + this.poolsToPreload.map(async pool => + Promise.all( + this.config.supportedFees.map(async fee => + this.getPool(pool.token0, pool.token1, fee, blockNumber), + ), + ), + ), + ); + + if (!this.dexHelper.config.isSlave) { + const cleanExpiredNotExistingPoolsKeys = async () => { + const maxTimestamp = + Date.now() - UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS; + await this.dexHelper.cache.zremrangebyscore( + this.notExistingPoolSetKey, + 0, + maxTimestamp, + ); + }; + + this.intervalTask = setInterval( + cleanExpiredNotExistingPoolsKeys.bind(this), + UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS, + ); + } + } + + async getPool( + srcAddress: Address, + destAddress: Address, + fee: bigint, + blockNumber: number, + ): Promise { + let pool = this.eventPools[ + this.getPoolIdentifier(srcAddress, destAddress, fee) + ] as SolidlyV3EventPool | null | undefined; + + if (pool === null) return null; + + if (pool) { + if (!pool.initFailed) { + return pool; + } else { + // if init failed then prefer to early return pool with empty state to fallback to rpc call + if ( + ++pool.initRetryAttemptCount % this.config.initRetryFrequency !== + 0 + ) { + return pool; + } + // else pursue with re-try initialization + } + } + + const [token0, token1] = this._sortTokens(srcAddress, destAddress); + + const key = `${token0}_${token1}_${fee}`.toLowerCase(); + + if (!pool) { + const notExistingPoolScore = await this.dexHelper.cache.zscore( + this.notExistingPoolSetKey, + key, + ); + + const poolDoesNotExist = notExistingPoolScore !== null; + + if (poolDoesNotExist) { + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = + null; + return null; + } + + await this.dexHelper.cache.hset( + this.dexmapKey, + key, + JSON.stringify({ + token0, + token1, + fee: fee.toString(), + }), + ); + } + + this.logger.trace(`starting to listen to new pool: ${key}`); + pool = + pool || + new SolidlyV3EventPool( + this.dexHelper, + this.dexKey, + this.stateMultiContract, + this.config.decodeStateMultiCallResultWithRelativeBitmaps, + this.erc20Interface, + this.config.factory, + fee, + token0, + token1, + this.logger, + this.cacheStateKey, + this.config.initHash, + ); + + try { + await pool.initialize(blockNumber, { + initCallback: (state: DeepReadonly) => { + //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber + pool!.addressesSubscribed[0] = state.pool; + pool!.poolAddress = state.pool; + pool!.initFailed = false; + pool!.initRetryAttemptCount = 0; + }, + }); + } catch (e) { + if (e instanceof Error && e.message.endsWith('Pool does not exist')) { + // no need to await we want the set to have the pool key but it's not blocking + this.dexHelper.cache.zadd( + this.notExistingPoolSetKey, + [Date.now(), key], + 'NX', + ); + + // Pool does not exist for this feeCode, so we can set it to null + // to prevent more requests for this pool + pool = null; + this.logger.trace( + `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, + e, + ); + } else { + // on unknown error mark as failed and increase retryCount for retry init strategy + // note: state would be null by default which allows to fallback + this.logger.warn( + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, + e, + ); + pool.initFailed = true; + } + } + + if (pool !== null) { + const allEventPools = Object.values(this.eventPools); + this.logger.info( + `starting to listen to new non-null pool: ${key}. Already following ${allEventPools + // Not that I like this reduce, but since it is done only on initialization, expect this to be ok + .reduce( + (acc, curr) => (curr !== null ? ++acc : acc), + 0, + )} non-null pools or ${allEventPools.length} total pools`, + ); + } + + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = + pool; + return pool; + } + + async addMasterPool(poolKey: string, blockNumber: number): Promise { + const _pairs = await this.dexHelper.cache.hget(this.dexmapKey, poolKey); + if (!_pairs) { + this.logger.warn( + `did not find poolConfig in for key ${this.dexmapKey} ${poolKey}`, + ); + return false; + } + + const poolInfo: PoolPairsInfo = JSON.parse(_pairs); + + const pool = await this.getPool( + poolInfo.token0, + poolInfo.token1, + BigInt(poolInfo.fee), + blockNumber, + ); + + if (!pool) { + return false; + } + + return true; + } + async getPoolIdentifiers( srcToken: Token, destToken: Token, side: SwapSide, blockNumber: number, ): Promise { - // TODO: complete me! - return []; + const _srcToken = this.dexHelper.config.wrapETH(srcToken); + const _destToken = this.dexHelper.config.wrapETH(destToken); + + const [_srcAddress, _destAddress] = this._getLoweredAddresses( + _srcToken, + _destToken, + ); + + if (_srcAddress === _destAddress) return []; + + const pools = ( + await Promise.all( + this.supportedFees.map(async fee => + this.getPool(_srcAddress, _destAddress, fee, blockNumber), + ), + ) + ).filter(pool => pool); + + if (pools.length === 0) return []; + + return pools.map(pool => + this.getPoolIdentifier(_srcAddress, _destAddress, pool!.feeCode), + ); + } + + async getPricingFromRpc( + from: Token, + to: Token, + amounts: bigint[], + side: SwapSide, + pools: SolidlyV3EventPool[], + ): Promise | null> { + if (pools.length === 0) { + return null; + } + this.logger.warn(`fallback to rpc for ${pools.length} pool(s)`); + + const requests = pools.map( + pool => ({ + owner: pool.poolAddress, + asset: side == SwapSide.SELL ? from.address : to.address, + assetType: AssetType.ERC20, + ids: [ + { + id: DEFAULT_ID_ERC20, + spenders: [], + }, + ], + }), + [], + ); + + const balances = await getBalances(this.dexHelper.multiWrapper, requests); + + pools = pools.filter((pool, index) => { + const balance = balances[index].amounts[DEFAULT_ID_ERC20_AS_STRING]; + if (balance >= amounts[amounts.length - 1]) { + return true; + } + this.logger.warn( + `[${this.network}][${pool.parentName}] have no balance ${pool.poolAddress} ${from.address} ${to.address}. (Balance: ${balance})`, + ); + return false; + }); + + pools.forEach(pool => { + this.logger.warn( + `[${this.network}][${pool.parentName}] fallback to rpc for ${pool.name}`, + ); + }); + + const unitVolume = getBigIntPow( + (side === SwapSide.SELL ? from : to).decimals, + ); + + const chunks = amounts.length - 1; + + const _width = Math.floor(chunks / this.config.chunksCount); + + const _amounts = [unitVolume].concat( + Array.from(Array(this.config.chunksCount).keys()).map( + i => amounts[(i + 1) * _width], + ), + ); + + const calldata = pools.map(pool => + _amounts.map(_amount => ({ + target: this.config.quoter, + gasLimit: UNISWAPV3_QUOTE_GASLIMIT, + callData: + side === SwapSide.SELL + ? this.quoterIface.encodeFunctionData('quoteExactInputSingle', [ + [ + from.address, + to.address, + _amount.toString(), + pool.feeCodeAsString, + 0, //sqrtPriceLimitX96 + ], + ]) + : this.quoterIface.encodeFunctionData('quoteExactOutputSingle', [ + [ + from.address, + to.address, + _amount.toString(), + pool.feeCodeAsString, + 0, //sqrtPriceLimitX96 + ], + ]), + })), + ); + + const data = await this.uniswapMulti.methods + .multicall(calldata.flat()) + .call(); + + const decode = (j: number): bigint => { + if (!data.returnData[j].success) { + return 0n; + } + const decoded = defaultAbiCoder.decode( + ['uint256'], + data.returnData[j].returnData, + ); + return BigInt(decoded[0].toString()); + }; + + let i = 0; + const result = pools.map(pool => { + const _rates = _amounts.map(() => decode(i++)); + const unit: bigint = _rates[0]; + + const prices = interpolate( + _amounts.slice(1), + _rates.slice(1), + amounts, + side, + ); + + return { + prices, + unit, + data: { + path: [ + { + tokenIn: from.address, + tokenOut: to.address, + fee: pool.feeCodeAsString, + }, + ], + exchange: pool.poolAddress, + }, + poolIdentifier: this.getPoolIdentifier( + pool.token0, + pool.token1, + pool.feeCode, + ), + exchange: this.dexKey, + gasCost: prices.map(p => (p === 0n ? 0 : UNISWAPV3_QUOTE_GASLIMIT)), + poolAddresses: [pool.poolAddress], + }; + }); + + return result; } - // Returns pool prices for amounts. - // If limitPools is defined only pools in limitPools - // should be used. If limitPools is undefined then - // any pools can be used. async getPricesVolume( srcToken: Token, destToken: Token, @@ -89,19 +517,214 @@ export class SolidlyV3 extends SimpleExchange implements IDex { blockNumber: number, limitPools?: string[], ): Promise> { - // TODO: complete me! - return null; - } + try { + const _srcToken = this.dexHelper.config.wrapETH(srcToken); + const _destToken = this.dexHelper.config.wrapETH(destToken); - // Returns estimated gas cost of calldata for this DEX in multiSwap - getCalldataGasCost(poolPrices: PoolPrices): number | number[] { - // TODO: update if there is any payload in getAdapterParam - return CALLDATA_GAS_COST.DEX_NO_PAYLOAD; + const [_srcAddress, _destAddress] = this._getLoweredAddresses( + _srcToken, + _destToken, + ); + + if (_srcAddress === _destAddress) return null; + + let selectedPools: SolidlyV3EventPool[] = []; + + if (!limitPools) { + selectedPools = ( + await Promise.all( + this.supportedFees.map(async fee => { + const locallyFoundPool = + this.eventPools[ + this.getPoolIdentifier(_srcAddress, _destAddress, fee) + ]; + if (locallyFoundPool) return locallyFoundPool; + + const newlyFetchedPool = await this.getPool( + _srcAddress, + _destAddress, + fee, + blockNumber, + ); + return newlyFetchedPool; + }), + ) + ).filter(isTruthy); + } else { + const pairIdentifierWithoutFee = this.getPoolIdentifier( + _srcAddress, + _destAddress, + 0n, + // Trim from 0 fee postfix, so it become comparable + ).slice(0, -1); + + const poolIdentifiers = limitPools.filter(identifier => + identifier.startsWith(pairIdentifierWithoutFee), + ); + + selectedPools = ( + await Promise.all( + poolIdentifiers.map(async identifier => { + let locallyFoundPool = this.eventPools[identifier]; + if (locallyFoundPool) return locallyFoundPool; + + const [, srcAddress, destAddress, fee] = identifier.split('_'); + const newlyFetchedPool = await this.getPool( + srcAddress, + destAddress, + BigInt(fee), + blockNumber, + ); + return newlyFetchedPool; + }), + ) + ).filter(isTruthy); + } + + if (selectedPools.length === 0) return null; + + const poolsToUse = selectedPools.reduce( + (acc, pool) => { + let state = pool.getState(blockNumber); + if (state === null) { + this.logger.trace( + `${this.dexKey}: State === null. Fallback to rpc ${pool.name}`, + ); + acc.poolWithoutState.push(pool); + } else { + acc.poolWithState.push(pool); + } + return acc; + }, + { + poolWithState: [] as SolidlyV3EventPool[], + poolWithoutState: [] as SolidlyV3EventPool[], + }, + ); + + const rpcResultsPromise = this.getPricingFromRpc( + _srcToken, + _destToken, + amounts, + side, + this.network === Network.ZKEVM ? [] : poolsToUse.poolWithoutState, + ); + + const states = poolsToUse.poolWithState.map( + p => p.getState(blockNumber)!, + ); + + const unitAmount = getBigIntPow( + side == SwapSide.SELL ? _srcToken.decimals : _destToken.decimals, + ); + + const _amounts = [...amounts.slice(1)]; + + const [token0] = this._sortTokens(_srcAddress, _destAddress); + + const zeroForOne = token0 === _srcAddress ? true : false; + + const result = await Promise.all( + poolsToUse.poolWithState.map(async (pool, i) => { + const state = states[i]; + + if (state.liquidity <= 0n) { + if (state.liquidity < 0) { + this.logger.error( + `${this.dexKey}-${this.network}: ${pool.poolAddress} pool has negative liquidity: ${state.liquidity}. Find with key: ${pool.mapKey}`, + ); + } + this.logger.trace(`pool have 0 liquidity`); + return null; + } + + const balanceDestToken = + _destAddress === pool.token0 ? state.balance0 : state.balance1; + + const unitResult = this._getOutputs( + state, + [unitAmount], + zeroForOne, + side, + balanceDestToken, + ); + const pricesResult = this._getOutputs( + state, + _amounts, + zeroForOne, + side, + balanceDestToken, + ); + + if (!unitResult || !pricesResult) { + this.logger.debug('Prices or unit is not calculated'); + return null; + } + + const prices = [0n, ...pricesResult.outputs]; + const gasCost = [ + 0, + ...pricesResult.outputs.map((p, index) => { + if (p == 0n) { + return 0; + } else { + return ( + UNISWAPV3_POOL_SEARCH_OVERHEAD + + UNISWAPV3_TICK_BASE_OVERHEAD + + pricesResult.tickCounts[index] * UNISWAPV3_TICK_GAS_COST + ); + } + }), + ]; + return { + unit: unitResult.outputs[0], + prices, + data: { + path: [ + { + tokenIn: _srcAddress, + tokenOut: _destAddress, + fee: pool.feeCode.toString(), + }, + ], + }, + poolIdentifier: this.getPoolIdentifier( + pool.token0, + pool.token1, + pool.feeCode, + ), + exchange: this.dexKey, + gasCost: gasCost, + poolAddresses: [pool.poolAddress], + }; + }), + ); + const rpcResults = await rpcResultsPromise; + + const notNullResult = result.filter( + res => res !== null, + ) as ExchangePrices; + + if (rpcResults) { + rpcResults.forEach(r => { + if (r) { + notNullResult.push(r); + } + }); + } + + return notNullResult; + } catch (e) { + this.logger.error( + `Error_getPricesVolume ${srcToken.symbol || srcToken.address}, ${ + destToken.symbol || destToken.address + }, ${side}:`, + e, + ); + return null; + } } - // Encode params required by the exchange adapter - // Used for multiSwap, buy & megaSwap - // Hint: abiCoder.encodeParameter() could be useful getAdapterParam( srcToken: string, destToken: string, @@ -110,23 +733,178 @@ export class SolidlyV3 extends SimpleExchange implements IDex { data: SolidlyV3Data, side: SwapSide, ): AdapterExchangeParam { - // TODO: complete me! - const { exchange } = data; + const { path: rawPath } = data; + const path = this._encodePath(rawPath, side); - // Encode here the payload for adapter - const payload = ''; + const payload = this.abiCoder.encodeParameter( + { + ParentStruct: { + path: 'bytes', + deadline: 'uint256', + }, + }, + { + path, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), // FIXME: more gas efficient to pass block.timestamp in adapter + }, + ); return { - targetExchange: exchange, + targetExchange: this.config.router, payload, networkFee: '0', }; } - // Encode call data used by simpleSwap like routers - // Used for simpleSwap & simpleBuy - // Hint: this.buildSimpleParamWithoutWETHConversion - // could be useful + getCalldataGasCost(poolPrices: PoolPrices): number | number[] { + const gasCost = + CALLDATA_GAS_COST.DEX_OVERHEAD + + CALLDATA_GAS_COST.LENGTH_SMALL + + // ParentStruct header + CALLDATA_GAS_COST.OFFSET_SMALL + + // ParentStruct -> path header + CALLDATA_GAS_COST.OFFSET_SMALL + + // ParentStruct -> deadline + CALLDATA_GAS_COST.TIMESTAMP + + // ParentStruct -> path (20+3+20 = 43 = 32+11 bytes) + CALLDATA_GAS_COST.LENGTH_SMALL + + CALLDATA_GAS_COST.FULL_WORD + + CALLDATA_GAS_COST.wordNonZeroBytes(11); + const arr = new Array(poolPrices.prices.length); + poolPrices.prices.forEach((p, index) => { + if (p == 0n) { + arr[index] = 0; + } else { + arr[index] = gasCost; + } + }); + return arr; + } + + getTokenFromAddress(address: Address): Token { + // In this Dex decimals are not used + return { address, decimals: 0 }; + } + + async preProcessTransaction( + optimalSwapExchange: OptimalSwapExchange, + srcToken: Token, + _0: Token, + _1: SwapSide, + options: PreprocessTransactionOptions, + ): Promise<[OptimalSwapExchange, ExchangeTxInfo]> { + if (!options.isDirectMethod) { + return [ + optimalSwapExchange, + { + deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), + }, + ]; + } + + assert( + optimalSwapExchange.data !== undefined, + `preProcessTransaction: data field is missing`, + ); + + let isApproved: boolean | undefined; + + try { + this.erc20Contract.options.address = + this.dexHelper.config.wrapETH(srcToken).address; + const allowance = await this.erc20Contract.methods + .allowance(this.augustusAddress, this.config.router) + .call(undefined, 'latest'); + isApproved = + BigInt(allowance.toString()) >= BigInt(optimalSwapExchange.srcAmount); + } catch (e) { + this.logger.error( + `preProcessTransaction failed to retrieve allowance info: `, + e, + ); + } + + return [ + { + ...optimalSwapExchange, + data: { + ...optimalSwapExchange.data, + isApproved, + }, + }, + { + deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), + }, + ]; + } + + getDirectParam( + srcToken: Address, + destToken: Address, + srcAmount: NumberAsString, + destAmount: NumberAsString, + expectedAmount: NumberAsString, + data: SolidlyV3Data, + side: SwapSide, + permit: string, + uuid: string, + feePercent: NumberAsString, + deadline: NumberAsString, + partner: string, + beneficiary: string, + contractMethod?: string, + ): TxInfo { + if ( + contractMethod !== DirectMethods.directSell && + contractMethod !== DirectMethods.directBuy + ) { + throw new Error(`Invalid contract method ${contractMethod}`); + } + + let isApproved: boolean = !!data.isApproved; + if (data.isApproved === undefined) { + this.logger.warn(`isApproved is undefined, defaulting to false`); + } + + const path = this._encodePath(data.path, side); + + const swapParams: UniswapV3Param = [ + srcToken, + destToken, + this.config.router, + srcAmount, + destAmount, + expectedAmount, + feePercent, + deadline, + partner, + isApproved, + beneficiary, + path, + permit, + uuidToBytes16(uuid), + ]; + + const encoder = (...params: UniswapV3Param) => { + return this.directSwapIface.encodeFunctionData( + side === SwapSide.SELL + ? DirectMethods.directSell + : DirectMethods.directBuy, + [params], + ); + }; + + return { + params: swapParams, + encoder, + networkFee: '0', + }; + } + + static getDirectFunctionName(): string[] { + return [DirectMethods.directSell, DirectMethods.directBuy]; + } + async getSimpleParam( srcToken: string, destToken: string, @@ -135,11 +913,31 @@ export class SolidlyV3 extends SimpleExchange implements IDex { data: SolidlyV3Data, side: SwapSide, ): Promise { - // TODO: complete me! - const { exchange } = data; + const swapFunction = + side === SwapSide.SELL + ? UniswapV3Functions.exactInput + : UniswapV3Functions.exactOutput; - // Encode here the transaction arguments - const swapData = ''; + const path = this._encodePath(data.path, side); + const swapFunctionParams: UniswapV3SimpleSwapParams = + side === SwapSide.SELL + ? { + recipient: this.augustusAddress, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), + amountIn: srcAmount, + amountOutMinimum: destAmount, + path, + } + : { + recipient: this.augustusAddress, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), + amountOut: destAmount, + amountInMaximum: srcAmount, + path, + }; + const swapData = this.routerIface.encodeFunctionData(swapFunction, [ + swapFunctionParams, + ]); return this.buildSimpleParamWithoutWETHConversion( srcToken, @@ -147,32 +945,248 @@ export class SolidlyV3 extends SimpleExchange implements IDex { destToken, destAmount, swapData, - exchange, + this.config.router, ); } - // This is called once before getTopPoolsForToken is - // called for multiple tokens. This can be helpful to - // update common state required for calculating - // getTopPoolsForToken. It is optional for a DEX - // to implement this - async updatePoolState(): Promise { - // TODO: complete me! - } - - // Returns list of top pools based on liquidity. Max - // limit number pools should be returned. async getTopPoolsForToken( tokenAddress: Address, limit: number, ): Promise { - //TODO: complete me! - return []; + const _tokenAddress = tokenAddress.toLowerCase(); + + const res = await this._querySubgraph( + `query ($token: Bytes!, $count: Int) { + pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + }`, + { + token: _tokenAddress, + count: limit, + }, + ); + + if (!(res && res.pools0 && res.pools1)) { + this.logger.error( + `Error_${this.dexKey}_Subgraph: couldn't fetch the pools from the subgraph`, + ); + return []; + } + + const pools0 = _.map(res.pools0, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token1.id.toLowerCase(), + decimals: parseInt(pool.token1.decimals), + }, + ], + liquidityUSD: + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + })); + + const pools1 = _.map(res.pools1, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token0.id.toLowerCase(), + decimals: parseInt(pool.token0.decimals), + }, + ], + liquidityUSD: + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + })); + + const pools = _.slice( + _.sortBy(_.concat(pools0, pools1), [pool => -1 * pool.liquidityUSD]), + 0, + limit, + ); + return pools; + } + + private async _getPoolsFromIdentifiers( + poolIdentifiers: string[], + blockNumber: number, + ): Promise { + const pools = await Promise.all( + poolIdentifiers.map(async identifier => { + const [, srcAddress, destAddress, fee] = identifier.split('_'); + return this.getPool(srcAddress, destAddress, BigInt(fee), blockNumber); + }), + ); + return pools.filter(pool => pool) as SolidlyV3EventPool[]; + } + + private _getLoweredAddresses(srcToken: Token, destToken: Token) { + return [srcToken.address.toLowerCase(), destToken.address.toLowerCase()]; + } + + private _sortTokens(srcAddress: Address, destAddress: Address) { + return [srcAddress, destAddress].sort((a, b) => (a < b ? -1 : 1)); + } + + private _toLowerForAllConfigAddresses() { + // If new config property will be added, the TS will throw compile error + const newConfig: DexParams = { + router: this.config.router.toLowerCase(), + quoter: this.config.quoter.toLowerCase(), + factory: this.config.factory.toLowerCase(), + supportedFees: this.config.supportedFees, + stateMulticall: this.config.stateMulticall.toLowerCase(), + chunksCount: this.config.chunksCount, + initRetryFrequency: this.config.initRetryFrequency, + uniswapMulticall: this.config.uniswapMulticall, + deployer: this.config.deployer?.toLowerCase(), + initHash: this.config.initHash, + subgraphURL: this.config.subgraphURL, + stateMultiCallAbi: this.config.stateMultiCallAbi, + decodeStateMultiCallResultWithRelativeBitmaps: + this.config.decodeStateMultiCallResultWithRelativeBitmaps, + }; + return newConfig; + } + + private _getOutputs( + state: DeepReadonly, + amounts: bigint[], + zeroForOne: boolean, + side: SwapSide, + destTokenBalance: bigint, + ): OutputResult | null { + try { + const outputsResult = uniswapV3Math.queryOutputs( + state, + amounts, + zeroForOne, + side, + ); + + if (side === SwapSide.SELL) { + if (outputsResult.outputs[0] > destTokenBalance) { + return null; + } + + for (let i = 0; i < outputsResult.outputs.length; i++) { + if (outputsResult.outputs[i] > destTokenBalance) { + outputsResult.outputs[i] = 0n; + outputsResult.tickCounts[i] = 0; + } + } + } else { + if (amounts[0] > destTokenBalance) { + return null; + } + + // This may be improved by first checking outputs and requesting outputs + // only for amounts that makes more sense, but I don't think this is really + // important now + for (let i = 0; i < amounts.length; i++) { + if (amounts[i] > destTokenBalance) { + outputsResult.outputs[i] = 0n; + outputsResult.tickCounts[i] = 0; + } + } + } + + return outputsResult; + } catch (e) { + this.logger.debug( + `${this.dexKey}: received error in _getOutputs while calculating outputs`, + e, + ); + return null; + } + } + + private async _querySubgraph( + query: string, + variables: Object, + timeout = 30000, + ) { + try { + const res = await this.dexHelper.httpRequest.post( + this.config.subgraphURL, + { query, variables }, + undefined, + { timeout: timeout }, + ); + return res.data; + } catch (e) { + this.logger.error(`${this.dexKey}: can not query subgraph: `, e); + return {}; + } + } + + private _encodePath( + path: { + tokenIn: Address; + tokenOut: Address; + fee: NumberAsString; + }[], + side: SwapSide, + ): string { + if (path.length === 0) { + this.logger.error( + `${this.dexKey}: Received invalid path=${path} for side=${side} to encode`, + ); + return '0x'; + } + + const { _path, types } = path.reduce( + ( + { _path, types }: { _path: string[]; types: string[] }, + curr, + index, + ): { _path: string[]; types: string[] } => { + if (index === 0) { + return { + types: ['address', 'uint24', 'address'], + _path: [curr.tokenIn, curr.fee, curr.tokenOut], + }; + } else { + return { + types: [...types, 'uint24', 'address'], + _path: [..._path, curr.fee, curr.tokenOut], + }; + } + }, + { _path: [], types: [] }, + ); + + return side === SwapSide.BUY + ? pack(types.reverse(), _path.reverse()) + : pack(types, _path); } - // This is optional function in case if your implementation has acquired any resources - // you need to release for graceful shutdown. For example, it may be any interval timer - releaseResources(): AsyncOrSync { - // TODO: complete me! + releaseResources() { + if (this.intervalTask !== undefined) { + clearInterval(this.intervalTask); + this.intervalTask = undefined; + } } } diff --git a/src/dex/solidly-v3/types.ts b/src/dex/solidly-v3/types.ts index 306817ec7..8c1bcee1a 100644 --- a/src/dex/solidly-v3/types.ts +++ b/src/dex/solidly-v3/types.ts @@ -1,22 +1,186 @@ +import { BigNumber, BytesLike } from 'ethers'; +import { NumberAsString } from '../../types'; import { Address } from '../../types'; +import { AbiItem } from 'web3-utils'; +import { MultiResult } from '../../lib/multi-wrapper'; + +export type OracleObservation = { + blockTimestamp: bigint; + tickCumulative: bigint; + secondsPerLiquidityCumulativeX128: bigint; + initialized: boolean; +}; + +export type OracleObservationCandidates = { + beforeOrAt: OracleObservation; + atOrAfter: OracleObservation; +}; + +export type TickInfo = { + liquidityGross: bigint; + liquidityNet: bigint; + tickCumulativeOutside: bigint; + secondsPerLiquidityOutsideX128: bigint; + secondsOutside: bigint; + initialized: boolean; +}; + +export type Slot0 = { + sqrtPriceX96: bigint; + tick: bigint; + observationIndex: number; + observationCardinality: number; + observationCardinalityNext: number; + feeProtocol: bigint; +}; export type PoolState = { - // TODO: poolState is the state of event - // subscriber. This should be the minimum - // set of parameters required to compute - // pool prices. Complete me! + pool: string; + blockTimestamp: bigint; + tickSpacing: bigint; + fee: bigint; + slot0: Slot0; + liquidity: bigint; + maxLiquidityPerTick: bigint; + tickBitmap: Record; + ticks: Record; + observations: Record; + isValid: boolean; + startTickBitmap: bigint; + lowestKnownTick: bigint; + highestKnownTick: bigint; + balance0: bigint; + balance1: bigint; }; export type SolidlyV3Data = { - // TODO: SolidlyV3Data is the dex data that is - // returned by the API that can be used for - // tx building. The data structure should be minimal. - // Complete me! - exchange: Address; + path: { + tokenIn: Address; + tokenOut: Address; + fee: NumberAsString; + }[]; + isApproved?: boolean; }; +export type DecodeStateMultiCallFunc = ( + result: MultiResult | BytesLike, +) => DecodedStateMultiCallResultWithRelativeBitmaps; + export type DexParams = { - // TODO: DexParams is set of parameters the can - // be used to initiate a DEX fork. - // Complete me! + router: Address; + quoter: Address; + factory: Address; + stateMulticall: Address; + uniswapMulticall: Address; + supportedFees: bigint[]; + chunksCount: number; + initRetryFrequency: number; + deployer?: Address; + subgraphURL: string; + initHash: string; + stateMultiCallAbi?: AbiItem[]; + decodeStateMultiCallResultWithRelativeBitmaps?: DecodeStateMultiCallFunc; +}; + +export type UniswapV3SimpleSwapSellParam = { + path: string; + recipient: Address; + deadline: string; + amountIn: NumberAsString; + amountOutMinimum: NumberAsString; +}; + +export type UniswapV3SimpleSwapBuyParam = { + path: string; + recipient: Address; + deadline: string; + amountOut: NumberAsString; + amountInMaximum: NumberAsString; +}; + +export type UniswapV3SimpleSwapParams = + | UniswapV3SimpleSwapSellParam + | UniswapV3SimpleSwapBuyParam; + +export type UniswapV3Param = [ + fromToken: Address, + toToken: Address, + exchange: Address, + fromAmount: NumberAsString, + toAmount: NumberAsString, + expectedAmount: NumberAsString, + feePercent: NumberAsString, + deadline: NumberAsString, + partner: Address, + isApproved: boolean, + beneficiary: Address, + path: string, + permit: string, + uuid: string, +]; + +export enum UniswapV3Functions { + exactInput = 'exactInput', + exactOutput = 'exactOutput', +} + +export type TickInfoMappings = { + index: number; + value: TickInfo; +}; + +export type TickBitMapMappings = { + index: number; + value: bigint; +}; + +export type OutputResult = { + outputs: bigint[]; + tickCounts: number[]; +}; + +// Just rewrote every type with BigNumber basically + +export type TickBitMapMappingsWithBigNumber = { + index: number; + value: BigNumber; +}; + +export type TickInfoWithBigNumber = { + initialized: boolean; + liquidityGross: BigNumber; + liquidityNet: BigNumber; + secondsOutside: number; + secondsPerLiquidityOutsideX128: BigNumber; + tickCumulativeOutside: BigNumber; +}; + +export type TickInfoMappingsWithBigNumber = { + index: number; + value: TickInfoWithBigNumber; +}; + +export type DecodedStateMultiCallResultWithRelativeBitmaps = { + pool: Address; + blockTimestamp: BigNumber; + slot0: { + feeProtocol: number; + observationCardinality: number; + observationCardinalityNext: number; + observationIndex: number; + sqrtPriceX96: BigNumber; + tick: number; + unlocked: boolean; + }; + liquidity: BigNumber; + tickSpacing: number; + maxLiquidityPerTick: BigNumber; + observation: { + blockTimestamp: number; + initialized: boolean; + secondsPerLiquidityCumulativeX128: BigNumber; + tickCumulative: BigNumber; + }; + tickBitmap: TickBitMapMappingsWithBigNumber[]; + ticks: TickInfoMappingsWithBigNumber[]; }; diff --git a/src/dex/solidly-v3/utils.ts b/src/dex/solidly-v3/utils.ts new file mode 100644 index 000000000..afd953e07 --- /dev/null +++ b/src/dex/solidly-v3/utils.ts @@ -0,0 +1,83 @@ +import { BytesLike, ethers } from 'ethers'; +import { assert } from 'ts-essentials'; +import { extractSuccessAndValue } from '../../lib/decoders'; +import { MultiResult } from '../../lib/multi-wrapper'; +import { DexConfigMap } from '../../types'; +import { + DexParams, + DecodedStateMultiCallResultWithRelativeBitmaps, +} from './types'; + +export function getUniswapV3DexKey(UniswapV3Config: DexConfigMap) { + const UniswapV3Keys = Object.keys(UniswapV3Config); + if (UniswapV3Keys.length !== 1) { + throw new Error( + `UniswapV3 key in UniswapV3Config is not unique. Update relevant places (optimizer) or fix config issue. Received: ${JSON.stringify( + UniswapV3Config, + (_0, value) => (typeof value === 'bigint' ? value.toString() : value), + )}`, + ); + } + + return UniswapV3Keys[0].toLowerCase(); +} + +export function decodeStateMultiCallResultWithRelativeBitmaps( + result: MultiResult | BytesLike, +): DecodedStateMultiCallResultWithRelativeBitmaps { + const [isSuccess, toDecode] = extractSuccessAndValue(result); + + assert( + isSuccess && toDecode !== '0x', + `decodeStateMultiCallResultWithRelativeBitmaps failed to get decodable result: ${result}`, + ); + + const decoded = ethers.utils.defaultAbiCoder.decode( + [ + // I don't want to pass here any interface, so I just use it in ethers format + ` + tuple( + address pool, + uint256 blockTimestamp, + tuple( + uint160 sqrtPriceX96, + int24 tick, + uint16 observationIndex, + uint16 observationCardinality, + uint16 observationCardinalityNext, + uint8 feeProtocol, + bool unlocked, + ) slot0, + uint128 liquidity, + int24 tickSpacing, + uint128 maxLiquidityPerTick, + tuple( + uint32 blockTimestamp, + int56 tickCumulative, + uint160 secondsPerLiquidityCumulativeX128, + bool initialized, + ) observation, + tuple( + int16 index, + uint256 value, + )[] tickBitmap, + tuple( + int24 index, + tuple( + uint128 liquidityGross, + int128 liquidityNet, + int56 tickCumulativeOutside, + uint160 secondsPerLiquidityOutsideX128, + uint32 secondsOutside, + bool initialized, + ) value, + )[] ticks + ) + `, + ], + toDecode, + )[0]; + // This conversion is not precise, because when we decode, we have more values + // But I typed only the ones that are used later + return decoded as DecodedStateMultiCallResultWithRelativeBitmaps; +} From e95021243e61ac8b2f2329a8408ce92d16d12733 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sat, 16 Sep 2023 17:10:40 -0400 Subject: [PATCH 295/833] remove stuff from config --- src/dex/solidly-v3/config.ts | 217 +---------------------------------- 1 file changed, 1 insertion(+), 216 deletions(-) diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index 2fca2c601..98592ba9d 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -25,7 +25,7 @@ export const PoolsToPreload: DexConfigMap< }; export const SolidlyV3Config: DexConfigMap = { - UniswapV3: { + SolidlyV3: { [Network.MAINNET]: { factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', @@ -38,193 +38,6 @@ export const SolidlyV3Config: DexConfigMap = { initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, subgraphURL: 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3', }, - [Network.BSC]: { - factory: '0xdB1d10011AD0Ff90774D0C6Bb92e5C5c8b4461F7', - quoter: '0x78D78E420Da98ad378D7799bE8f4AF69033EB077', - router: '0x83c346ba3d4bf36b308705e24fad80999401854b', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x593F39A4Ba26A9c8ed2128ac95D109E8e403C485', - uniswapMulticall: '0x963Df249eD09c358A4819E39d9Cd5736c3087184', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-bsc', - }, - [Network.POLYGON]: { - factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', - quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', - router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-polygon', - }, - [Network.ARBITRUM]: { - factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', - quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', - router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/ianlapham/arbitrum-minimal', - }, - [Network.OPTIMISM]: { - factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', - quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', - router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x4FF0dEC5f9a763Aa1E5C2a962aa6f4eDFeE4f9eA', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/ianlapham/optimism-post-regenesis', - }, - [Network.AVALANCHE]: { - factory: '0x740b1c1de25031C31FF4fC9A62f554A55cdC1baD', - quoter: '0xbe0F5544EC67e9B3b2D979aaA43f18Fd87E6257F', - router: '0x33895c09a0ec0718ce66ab35dfd0b656d77cd053', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', - uniswapMulticall: '0x0139141Cd4Ee88dF3Cdb65881D411bAE271Ef0C2', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/lynnshaoyu/uniswap-v3-avax', - }, - }, - SushiSwapV3: { - [Network.MAINNET]: { - factory: '0xbACEB8eC6b9355Dfc0269C18bac9d6E2Bdc29C4F', - quoter: '0x64e8802FE490fa7cc61d3463958199161Bb608A7', - router: '0x00F23572b16c5e9e58e7b965DEF51Ff8Ff546E34', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-ethereum', - }, - [Network.POLYGON]: { - factory: '0x917933899c6a5f8e37f31e19f92cdbff7e8ff0e2', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x34D41cE301257a4615D4F5AD260FA91D03925243', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x6Dc993Fe1e945A640576B4Dca81281d8e998DF71', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-polygon', - }, - [Network.BSC]: { - factory: '0x126555dd55a39328F69400d6aE4F782Bd4C34ABb', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0xDCf4EE5B700e2a5Fec458e06B763A4a3E3004494', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x593F39A4Ba26A9c8ed2128ac95D109E8e403C485', - uniswapMulticall: '0x963Df249eD09c358A4819E39d9Cd5736c3087184', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-bsc', - }, - [Network.AVALANCHE]: { - factory: '0x3e603C14aF37EBdaD31709C4f848Fc6aD5BEc715', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0x24c90C7d8fb463722e304A71255341610Fa7589b', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', - uniswapMulticall: '0x8C0F842791F03C095b6c633759224FcC9ACe68ea', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-avalanche', - }, - [Network.FANTOM]: { - factory: '0x7770978eED668a3ba661d51a773d3a992Fc9DDCB', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0xDCf4EE5B700e2a5Fec458e06B763A4a3E3004494', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', - uniswapMulticall: '0xB1395e098c0a847CC719Bcf1Fc8114421a9F8232', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-fantom', - }, - [Network.ARBITRUM]: { - factory: '0x1af415a1eba07a4986a52b6f2e7de7003d82231e', - quoter: '0x0524E833cCD057e4d7A296e3aaAb9f7675964Ce1', - router: '0xbDa4176fD98b47018aF673805d069b9dbd49373D', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-arbitrum', - }, - [Network.OPTIMISM]: { - factory: '0x9c6522117e2ed1fE5bdb72bb0eD5E3f2bdE7DBe0', - quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', - router: '0xa05d8C3F278fC7b20b39Ea7A3035E3aD8D808c78', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x4FF0dEC5f9a763Aa1E5C2a962aa6f4eDFeE4f9eA', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-optimism', - }, - }, - ChronosV3: { - [Network.ARBITRUM]: { - factory: '0x4Db9D624F67E00dbF8ef7AE0e0e8eE54aF1dee49', - quoter: '0x6E7f0Ca45171a4440c0CDdF3A46A8dC5D4c2d4A0', - router: '0xE0aBdFD837D451640CF43cB1Ec4eE87976eFbb41', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x46b44eb4Cc3bEbB9f04C419f691aB85Ff885A4D6', - uniswapMulticall: '0xaBB58098A7B5172A9b0B38a1925A522dbf0b4FC3', - chunksCount: 10, - initRetryFrequency: 10, - initHash: - '0x09c178be473df44d1de6970978a4fdedce1ce52a23b2b979754547f6b43a19a5', - subgraphURL: - 'https://subgraph.chronos.exchange/subgraphs/name/chronos-v3', - }, - }, - 'QuickSwapV3.1': { - [Network.ZKEVM]: { - factory: '0xD9a2AD9E927Bd7014116CC5c7328f028D4318178', - quoter: '0xc2f30976cebf6b7400fe1300540a342411340d29', - router: '0x1e7e4c855520b2106320952a570a3e5e3e618101', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x983ab0171159b7e17835cc6aec70c72b8aadb133', - uniswapMulticall: '0x61530d6E1c7A47BBB3e48e8b8EdF7569DcFeE121', - chunksCount: 5, - initRetryFrequency: 30, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: - 'https://api.studio.thegraph.com/query/44554/uniswap-v3/version/latest', - }, }, }; @@ -233,32 +46,4 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'Adapter01', index: 6 }], [SwapSide.BUY]: [{ name: 'BuyAdapter', index: 2 }], }, - [Network.BSC]: { - [SwapSide.SELL]: [{ name: 'BscAdapter02', index: 4 }], - [SwapSide.BUY]: [{ name: 'BscBuyAdapter', index: 5 }], - }, - [Network.POLYGON]: { - [SwapSide.SELL]: [{ name: 'PolygonAdapter01', index: 13 }], - [SwapSide.BUY]: [{ name: 'PolygonBuyAdapter', index: 2 }], - }, - [Network.ARBITRUM]: { - [SwapSide.SELL]: [{ name: 'ArbitrumAdapter01', index: 3 }], - [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 2 }], - }, - [Network.OPTIMISM]: { - [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 3 }], - [SwapSide.BUY]: [{ name: 'OptimismBuyAdapter', index: 2 }], - }, - [Network.FANTOM]: { - [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 11 }], - [SwapSide.BUY]: [{ name: 'FantomBuyAdapter', index: 3 }], - }, - [Network.ZKEVM]: { - [SwapSide.SELL]: [{ name: 'PolygonZkEvmAdapter01', index: 1 }], - [SwapSide.BUY]: [{ name: 'PolygonZkEvmBuyAdapter', index: 1 }], - }, - [Network.AVALANCHE]: { - [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 5 }], - [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 6 }], - }, }; From 8c8d015aa92fd8706c43f1fc529e6b658d808253 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sat, 16 Sep 2023 17:15:25 -0400 Subject: [PATCH 296/833] use SolidlyV3ABI --- src/dex/solidly-v3/solidly-v3-pool.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-pool.ts b/src/dex/solidly-v3/solidly-v3-pool.ts index 4bbf1903d..aa6256ec6 100644 --- a/src/dex/solidly-v3/solidly-v3-pool.ts +++ b/src/dex/solidly-v3/solidly-v3-pool.ts @@ -14,7 +14,7 @@ import { DecodedStateMultiCallResultWithRelativeBitmaps, DecodeStateMultiCallFunc, } from './types'; -import UniswapV3PoolABI from '../../abi/uniswap-v3/UniswapV3Pool.abi.json'; +import SolidlyV3PoolABI from '../../abi/solidly-v3/SolidlyV3Pool.abi.json'; import { bigIntify, catchParseLogError, isSampled } from '../../utils'; import { uniswapV3Math } from './contract-math/uniswap-v3-math'; import { MultiCallParams } from '../../lib/multi-wrapper'; @@ -50,7 +50,7 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { bigint | DecodedStateMultiCallResultWithRelativeBitmaps >[]; - public readonly poolIface = new Interface(UniswapV3PoolABI); + public readonly poolIface = new Interface(SolidlyV3PoolABI); public initFailed = false; public initRetryAttemptCount = 0; From a5b9b672d0bde0630c194764921bccb8ce76a197 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 16 Sep 2023 23:41:11 +0200 Subject: [PATCH 297/833] rfq: fix double spending issue which leads to taping into the same market maker token liquidity --- src/dex/generic-rfq/generic-rfq.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/dex/generic-rfq/generic-rfq.ts b/src/dex/generic-rfq/generic-rfq.ts index 2c682d8b1..e7b388a0e 100644 --- a/src/dex/generic-rfq/generic-rfq.ts +++ b/src/dex/generic-rfq/generic-rfq.ts @@ -67,11 +67,9 @@ export class GenericRFQ extends ParaSwapLimitOrders { side: SwapSide, blockNumber: number, ): Promise { - const _srcToken = this.dexHelper.config.wrapETH(srcToken); const _destToken = this.dexHelper.config.wrapETH(destToken); - return [ - `${this.dexKey}_${_srcToken.address}_${_destToken.address}`.toLowerCase(), - ]; + // Keep only destination token in order to prevent taping into the same market maker liquidity during same swap (double spending) + return [`${this.dexKey}_${_destToken.address}`.toLowerCase()]; } calcOutsFromAmounts( From c42149ea7489acacf40fac8f79a3182b414ff334 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 16 Sep 2023 23:43:35 +0200 Subject: [PATCH 298/833] 2.35.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 45b9c357b..0d103e6c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.3", + "version": "2.35.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 36d07cb77c9c3448509734e7e67e6993d1dbbfc3 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sat, 16 Sep 2023 17:50:16 -0400 Subject: [PATCH 299/833] start integration test --- .../solidly-v3/solidly-v3-integration.test.ts | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 4be071b69..8bccfe18e 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -77,11 +77,12 @@ async function checkOnChainPricing( amounts.slice(1), funcName, ); - const readerResult = ( - await solidlyV3.dexHelper.multiContract.methods - .aggregate(readerCallData) - .call({}, blockNumber) - ).returnData; + // const readerResult = ( + // await solidlyV3.dexHelper.multiContract.methods + // .aggregate(readerCallData) + // .call({}, blockNumber) + // ).returnData; + const readerResult: any[] = []; const expectedPrices = [0n].concat( decodeReaderResult(readerResult, readerIface, funcName), @@ -198,6 +199,10 @@ describe('SolidlyV3', function () { } }); + it('base case', async function () { + console.log('base case'); + }); + it('getPoolIdentifiers and getPricesVolume SELL', async function () { await testPricingOnNetwork( solidlyV3, @@ -230,9 +235,9 @@ describe('SolidlyV3', function () { // We have to check without calling initializePricing, because // pool-tracker is not calling that function const newSolidlyV3 = new SolidlyV3(network, dexKey, dexHelper); - if (newSolidlyV3.updatePoolState) { - await newSolidlyV3.updatePoolState(); - } + // if (newSolidlyV3.updatePoolState) { + // await newSolidlyV3.updatePoolState(); + // } const poolLiquidity = await newSolidlyV3.getTopPoolsForToken( tokens[srcTokenSymbol].address, 10, From 8104acdc187dc6da4bd88d8d15b4acac244d442b Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sun, 17 Sep 2023 14:23:29 -0400 Subject: [PATCH 300/833] add first integration test --- .../solidly-v3/solidly-v3-integration.test.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 8bccfe18e..1d69d3252 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -203,6 +203,26 @@ describe('SolidlyV3', function () { console.log('base case'); }); + it('WETH -> USDT getPoolIdentifiers and getPricesVolume SELL', async function () { + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + const blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const solidlyV3 = new SolidlyV3(network, dexKey, dexHelper); + + const WETH = Tokens[network]['WETH']; + const USDT = Tokens[network]['USDT']; + + const amounts = [0n, 1n * BI_POWS[18], 2n * BI_POWS[18]]; + + const pools = await solidlyV3.getPoolIdentifiers( + WETH, + USDT, + SwapSide.SELL, + blockNumber, + ); + console.log(`WBNB <> USDT Pool Identifiers: `, pools); + }); + it('getPoolIdentifiers and getPricesVolume SELL', async function () { await testPricingOnNetwork( solidlyV3, From 2859657b89ae28e15235941e1e4f3eab91c593b6 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sun, 17 Sep 2023 14:28:01 -0400 Subject: [PATCH 301/833] reduce num of supported fees --- src/dex/solidly-v3/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index 98592ba9d..3d788d80c 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -3,7 +3,7 @@ import { DexConfigMap, AdapterMappings } from '../../types'; import { Network, SwapSide } from '../../constants'; import { Address } from '../../types'; -const SUPPORTED_FEES = [10000n, 3000n, 500n, 100n]; +const SUPPORTED_FEES = [3000n]; // Pools that will be initialized on app startup // They are added for testing From 98f63f35e418f14fe484c2922cfec3501702e2c9 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sun, 17 Sep 2023 14:36:39 -0400 Subject: [PATCH 302/833] delete SetFeeProtocol and IncreaseObservationCardinalityNext events --- src/dex/solidly-v3/solidly-v3-pool.ts | 31 --------------------------- 1 file changed, 31 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-pool.ts b/src/dex/solidly-v3/solidly-v3-pool.ts index aa6256ec6..95ce3e773 100644 --- a/src/dex/solidly-v3/solidly-v3-pool.ts +++ b/src/dex/solidly-v3/solidly-v3-pool.ts @@ -91,9 +91,6 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { this.handlers['Swap'] = this.handleSwapEvent.bind(this); this.handlers['Burn'] = this.handleBurnEvent.bind(this); this.handlers['Mint'] = this.handleMintEvent.bind(this); - this.handlers['SetFeeProtocol'] = this.handleSetFeeProtocolEvent.bind(this); - this.handlers['IncreaseObservationCardinalityNext'] = - this.handleIncreaseObservationCardinalityNextEvent.bind(this); // Wen need them to keep balance of the pool up to date this.handlers['Collect'] = this.handleCollectEvent.bind(this); @@ -437,20 +434,6 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { return pool; } - handleSetFeeProtocolEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - const feeProtocol0 = bigIntify(event.args.feeProtocol0New); - const feeProtocol1 = bigIntify(event.args.feeProtocol1New); - pool.slot0.feeProtocol = feeProtocol0 + (feeProtocol1 << 4n); - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - - return pool; - } - handleCollectEvent( event: any, pool: PoolState, @@ -481,20 +464,6 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { return pool; } - handleIncreaseObservationCardinalityNextEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - pool.slot0.observationCardinalityNext = parseInt( - event.args.observationCardinalityNextNew, - 10, - ); - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - return pool; - } - private _computePoolAddress( token0: Address, token1: Address, From e87e969027e39fe6e5ae8419b30364281eb1b53d Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sun, 17 Sep 2023 15:36:45 -0400 Subject: [PATCH 303/833] add getPricesVolume() --- src/dex/solidly-v3/solidly-v3-integration.test.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 1d69d3252..ac42cbd94 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -220,7 +220,19 @@ describe('SolidlyV3', function () { SwapSide.SELL, blockNumber, ); - console.log(`WBNB <> USDT Pool Identifiers: `, pools); + console.log(`WETH <> USDT Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await solidlyV3.getPricesVolume( + WETH, + USDT, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log(`WETH <> USDT Pool Prices: `, poolPrices); }); it('getPoolIdentifiers and getPricesVolume SELL', async function () { From c808e62a5f8cfc416d0284a9f91b678fbac6fb9f Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sun, 17 Sep 2023 15:52:57 -0400 Subject: [PATCH 304/833] add some comments --- src/dex/solidly-v3/config.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index 3d788d80c..2eb0545c7 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -4,6 +4,7 @@ import { Network, SwapSide } from '../../constants'; import { Address } from '../../types'; const SUPPORTED_FEES = [3000n]; +// const SUPPORTED_FEES = [500n]; // Pools that will be initialized on app startup // They are added for testing @@ -28,6 +29,7 @@ export const SolidlyV3Config: DexConfigMap = { SolidlyV3: { [Network.MAINNET]: { factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', + // factory: '0x735bb16affe83a3dc4dc418abccf179617cf9ff2', quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', supportedFees: SUPPORTED_FEES, From 54b9f9f42db4228c05ca1a30ab63b50a8f540efc Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sun, 17 Sep 2023 17:08:27 -0400 Subject: [PATCH 305/833] the commented out stuff is all solidly variables --- src/dex/solidly-v3/config.ts | 1 + src/dex/solidly-v3/solidly-v3-pool.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index 2eb0545c7..f798f1319 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -38,6 +38,7 @@ export const SolidlyV3Config: DexConfigMap = { chunksCount: 10, initRetryFrequency: 10, initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + // initHash: `0x2d6541efe1e24667ba5408a35ae420462924d43db1251d7580804ac81545109b`, subgraphURL: 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3', }, }, diff --git a/src/dex/solidly-v3/solidly-v3-pool.ts b/src/dex/solidly-v3/solidly-v3-pool.ts index 95ce3e773..9e49c1443 100644 --- a/src/dex/solidly-v3/solidly-v3-pool.ts +++ b/src/dex/solidly-v3/solidly-v3-pool.ts @@ -476,6 +476,7 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { ethers.utils.defaultAbiCoder.encode( ['address', 'address', 'uint24'], [token0, token1, BigInt.asUintN(24, fee)], + // [token0, token1, BigInt.asUintN(24, 10n)], ), ); From 27c74fcef93c25095b770d7dabd75320f3689580 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sun, 17 Sep 2023 17:43:07 -0400 Subject: [PATCH 306/833] change some variables --- src/dex/solidly-v3/config.ts | 12 ++++++------ src/dex/solidly-v3/solidly-v3-pool.ts | 8 ++++++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index f798f1319..d7ceb7402 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -3,8 +3,8 @@ import { DexConfigMap, AdapterMappings } from '../../types'; import { Network, SwapSide } from '../../constants'; import { Address } from '../../types'; -const SUPPORTED_FEES = [3000n]; -// const SUPPORTED_FEES = [500n]; +// const SUPPORTED_FEES = [3000n]; +const SUPPORTED_FEES = [500n]; // Pools that will be initialized on app startup // They are added for testing @@ -28,8 +28,8 @@ export const PoolsToPreload: DexConfigMap< export const SolidlyV3Config: DexConfigMap = { SolidlyV3: { [Network.MAINNET]: { - factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', - // factory: '0x735bb16affe83a3dc4dc418abccf179617cf9ff2', + // factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', + factory: '0x735bb16affe83a3dc4dc418abccf179617cf9ff2', quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', supportedFees: SUPPORTED_FEES, @@ -37,8 +37,8 @@ export const SolidlyV3Config: DexConfigMap = { uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', chunksCount: 10, initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - // initHash: `0x2d6541efe1e24667ba5408a35ae420462924d43db1251d7580804ac81545109b`, + // initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + initHash: `0x2d6541efe1e24667ba5408a35ae420462924d43db1251d7580804ac81545109b`, subgraphURL: 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3', }, }, diff --git a/src/dex/solidly-v3/solidly-v3-pool.ts b/src/dex/solidly-v3/solidly-v3-pool.ts index 9e49c1443..f5f03d871 100644 --- a/src/dex/solidly-v3/solidly-v3-pool.ts +++ b/src/dex/solidly-v3/solidly-v3-pool.ts @@ -28,6 +28,10 @@ import { uint256ToBigInt } from '../../lib/decoders'; import { decodeStateMultiCallResultWithRelativeBitmaps } from './utils'; import { _reduceTickBitmap, _reduceTicks } from './contract-math/utils'; +const FEES_TO_TICK_SPACING: Record = { + 500: 10n, +}; + export class SolidlyV3EventPool extends StatefulEventSubscriber { handlers: { [event: string]: ( @@ -475,8 +479,8 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { const encodedKey = ethers.utils.keccak256( ethers.utils.defaultAbiCoder.encode( ['address', 'address', 'uint24'], - [token0, token1, BigInt.asUintN(24, fee)], - // [token0, token1, BigInt.asUintN(24, 10n)], + // [token0, token1, BigInt.asUintN(24, fee)], + [token0, token1, BigInt.asUintN(24, FEES_TO_TICK_SPACING[Number(fee)])], ), ); From 6b952f9b24e24684e1c9c06349891ab10b2a4a2b Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sun, 17 Sep 2023 19:44:59 -0400 Subject: [PATCH 307/833] isolate the uniswap E2E test so it is a single token -> token --- src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 1668 ++++++++++----------- 1 file changed, 834 insertions(+), 834 deletions(-) diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index 4d097abc7..8c88088a3 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -116,56 +116,56 @@ describe('UniswapV3 E2E', () => { describe('UniswapV3', () => { const dexKey = 'UniswapV3'; - describe('UniswapV3 MAINNET', () => { - const network = Network.MAINNET; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - it('BUY DAI -> USDC', async () => { - await testE2E( - tokens['DAI'], - tokens['USDC'], - holders['DAI'], - '100000000000', - SwapSide.BUY, - dexKey, - ContractMethod.simpleBuy, - network, - provider, - ); - }); - it('SELL WETH -> SHIBA', async () => { - await testE2E( - tokens['WETH'], - tokens['SHIBA'], - holders['WETH'], - '1000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('directSwap SELL WETH -> USDC', async () => { - await testE2E( - tokens['WETH'], - tokens['USDC'], - holders['WETH'], - '1000000000000000000', - SwapSide.SELL, - dexKey, - ContractMethod.directUniV3Swap, - network, - provider, - ); - }); - }); + // describe('UniswapV3 MAINNET', () => { + // const network = Network.MAINNET; + // const tokens = Tokens[network]; + // const holders = Holders[network]; + // const provider = new StaticJsonRpcProvider( + // generateConfig(network).privateHttpProvider, + // network, + // ); + // + // it('BUY DAI -> USDC', async () => { + // await testE2E( + // tokens['DAI'], + // tokens['USDC'], + // holders['DAI'], + // '100000000000', + // SwapSide.BUY, + // dexKey, + // ContractMethod.simpleBuy, + // network, + // provider, + // ); + // }); + // it('SELL WETH -> SHIBA', async () => { + // await testE2E( + // tokens['WETH'], + // tokens['SHIBA'], + // holders['WETH'], + // '1000000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.simpleSwap, + // network, + // provider, + // ); + // }); + // + // it('directSwap SELL WETH -> USDC', async () => { + // await testE2E( + // tokens['WETH'], + // tokens['USDC'], + // holders['WETH'], + // '1000000000000000000', + // SwapSide.SELL, + // dexKey, + // ContractMethod.directUniV3Swap, + // network, + // provider, + // ); + // }); + // }); describe('UniswapV3 POLYGON', () => { const network = Network.POLYGON; @@ -189,202 +189,50 @@ describe('UniswapV3 E2E', () => { SwapSide.SELL, [ ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ContractMethod.directUniV3Swap, - ], - ], - [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - ContractMethod.buy, - ContractMethod.directUniV3Buy, - ], - ], - ]); - - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }), - ); - }); - - describe('UniswapV3 BSC', () => { - const network = Network.BSC; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const tokenASymbol: string = 'BUSD'; - const tokenBSymbol: string = 'WBNB'; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const tokenAAmount: string = '100000000000000000000'; - const tokenBAmount: string = '1000000000000000000'; - const nativeTokenAmount = '1000000000000000000'; - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ], - ], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - ]); - - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }), - ); - }); - - describe('UniswapV3 Optimism', () => { - const network = Network.OPTIMISM; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const tokenASymbol: string = 'OP'; - const tokenBSymbol: string = 'ETH'; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const tokenAAmount: string = '1000000000000000000'; - const tokenBAmount: string = '1000000000000000000'; - const nativeTokenAmount = '1000000000000000000'; - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + // ContractMethod.directUniV3Swap, ], ], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + // [ + // SwapSide.BUY, + // [ + // ContractMethod.simpleBuy, + // ContractMethod.buy, + // ContractMethod.directUniV3Buy, + // ], + // ], ]); sideToContractMethods.forEach((contractMethods, side) => contractMethods.forEach((contractMethod: ContractMethod) => { describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); + // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + // await testE2E( + // tokens[nativeTokenSymbol], + // tokens[tokenASymbol], + // holders[nativeTokenSymbol], + // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + // await testE2E( + // tokens[tokenASymbol], + // tokens[nativeTokenSymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { await testE2E( tokens[tokenASymbol], @@ -403,601 +251,753 @@ describe('UniswapV3 E2E', () => { ); }); - describe('UniswapV3 Avalanche', () => { - const network = Network.AVALANCHE; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ], - ], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - ]); - - const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = - [ - [ - { - name: 'AVAX', - sellAmount: '1000000000000000000', - buyAmount: '500000', - }, - { - name: 'USDT', - sellAmount: '1000000', - buyAmount: '10000000000000000000', - }, - ], - [ - { - name: 'AVAX', - sellAmount: '1000000000000000000', - buyAmount: '500000', - }, - { - name: 'USDC', - sellAmount: '1000000', - buyAmount: '1000000000000000000', - }, - ], - [ - { - name: 'WAVAX', - sellAmount: '1000000000000000000', - buyAmount: '500000', - }, - { - name: 'USDC', - sellAmount: '1000000', - buyAmount: '20000000000000000', - }, - ], - [ - { - name: 'WAVAX', - sellAmount: '1000000000000000000', - buyAmount: '10000000', - }, - { name: 'USDT', sellAmount: '1000000', buyAmount: '2000000000000' }, - ], - [ - { name: 'USDC', sellAmount: '1000000', buyAmount: '100000000' }, - { name: 'USDT', sellAmount: '100000000', buyAmount: '100000000' }, - ], - ]; - - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - contractMethods.forEach((contractMethod: ContractMethod) => { - pairs.forEach(pair => { - describe(`${contractMethod}`, () => { - it(`${pair[0].name} -> ${pair[1].name}`, async () => { - await testE2E( - tokens[pair[0].name], - tokens[pair[1].name], - holders[pair[0].name], - side === SwapSide.SELL - ? pair[0].sellAmount - : pair[0].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${pair[1].name} -> ${pair[0].name}`, async () => { - await testE2E( - tokens[pair[1].name], - tokens[pair[0].name], - holders[pair[1].name], - side === SwapSide.SELL - ? pair[1].sellAmount - : pair[1].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }); - }); - }), - ); - }); + // describe('UniswapV3 BSC', () => { + // const network = Network.BSC; + // const tokens = Tokens[network]; + // const holders = Holders[network]; + // const provider = new StaticJsonRpcProvider( + // generateConfig(network).privateHttpProvider, + // network, + // ); + // + // const tokenASymbol: string = 'BUSD'; + // const tokenBSymbol: string = 'WBNB'; + // const nativeTokenSymbol = NativeTokenSymbols[network]; + // + // const tokenAAmount: string = '100000000000000000000'; + // const tokenBAmount: string = '1000000000000000000'; + // const nativeTokenAmount = '1000000000000000000'; + // + // const sideToContractMethods = new Map([ + // [ + // SwapSide.SELL, + // [ + // ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + // ], + // ], + // [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + // ]); + // + // sideToContractMethods.forEach((contractMethods, side) => + // contractMethods.forEach((contractMethod: ContractMethod) => { + // describe(`${contractMethod}`, () => { + // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + // await testE2E( + // tokens[nativeTokenSymbol], + // tokens[tokenASymbol], + // holders[nativeTokenSymbol], + // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + // await testE2E( + // tokens[tokenASymbol], + // tokens[nativeTokenSymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + // await testE2E( + // tokens[tokenASymbol], + // tokens[tokenBSymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // }); + // }), + // ); + // }); + // + // describe('UniswapV3 Optimism', () => { + // const network = Network.OPTIMISM; + // const tokens = Tokens[network]; + // const holders = Holders[network]; + // const provider = new StaticJsonRpcProvider( + // generateConfig(network).privateHttpProvider, + // network, + // ); + // + // const tokenASymbol: string = 'OP'; + // const tokenBSymbol: string = 'ETH'; + // const nativeTokenSymbol = NativeTokenSymbols[network]; + // + // const tokenAAmount: string = '1000000000000000000'; + // const tokenBAmount: string = '1000000000000000000'; + // const nativeTokenAmount = '1000000000000000000'; + // + // const sideToContractMethods = new Map([ + // [ + // SwapSide.SELL, + // [ + // ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + // ], + // ], + // [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + // ]); + // + // sideToContractMethods.forEach((contractMethods, side) => + // contractMethods.forEach((contractMethod: ContractMethod) => { + // describe(`${contractMethod}`, () => { + // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + // await testE2E( + // tokens[nativeTokenSymbol], + // tokens[tokenASymbol], + // holders[nativeTokenSymbol], + // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + // await testE2E( + // tokens[tokenASymbol], + // tokens[nativeTokenSymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + // await testE2E( + // tokens[tokenASymbol], + // tokens[tokenBSymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // }); + // }), + // ); + // }); + // + // describe('UniswapV3 Avalanche', () => { + // const network = Network.AVALANCHE; + // const tokens = Tokens[network]; + // const holders = Holders[network]; + // const provider = new StaticJsonRpcProvider( + // generateConfig(network).privateHttpProvider, + // network, + // ); + // + // const sideToContractMethods = new Map([ + // [ + // SwapSide.SELL, + // [ + // ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + // ], + // ], + // [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + // ]); + // + // const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = + // [ + // [ + // { + // name: 'AVAX', + // sellAmount: '1000000000000000000', + // buyAmount: '500000', + // }, + // { + // name: 'USDT', + // sellAmount: '1000000', + // buyAmount: '10000000000000000000', + // }, + // ], + // [ + // { + // name: 'AVAX', + // sellAmount: '1000000000000000000', + // buyAmount: '500000', + // }, + // { + // name: 'USDC', + // sellAmount: '1000000', + // buyAmount: '1000000000000000000', + // }, + // ], + // [ + // { + // name: 'WAVAX', + // sellAmount: '1000000000000000000', + // buyAmount: '500000', + // }, + // { + // name: 'USDC', + // sellAmount: '1000000', + // buyAmount: '20000000000000000', + // }, + // ], + // [ + // { + // name: 'WAVAX', + // sellAmount: '1000000000000000000', + // buyAmount: '10000000', + // }, + // { name: 'USDT', sellAmount: '1000000', buyAmount: '2000000000000' }, + // ], + // [ + // { name: 'USDC', sellAmount: '1000000', buyAmount: '100000000' }, + // { name: 'USDT', sellAmount: '100000000', buyAmount: '100000000' }, + // ], + // ]; + // + // sideToContractMethods.forEach((contractMethods, side) => + // describe(`${side}`, () => { + // contractMethods.forEach((contractMethod: ContractMethod) => { + // pairs.forEach(pair => { + // describe(`${contractMethod}`, () => { + // it(`${pair[0].name} -> ${pair[1].name}`, async () => { + // await testE2E( + // tokens[pair[0].name], + // tokens[pair[1].name], + // holders[pair[0].name], + // side === SwapSide.SELL + // ? pair[0].sellAmount + // : pair[0].buyAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${pair[1].name} -> ${pair[0].name}`, async () => { + // await testE2E( + // tokens[pair[1].name], + // tokens[pair[0].name], + // holders[pair[1].name], + // side === SwapSide.SELL + // ? pair[1].sellAmount + // : pair[1].buyAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // }); + // }); + // }); + // }), + // ); + // }); }); - describe('RamsesV2', () => { - const dexKey = 'RamsesV2'; - - describe('Arbitrum', () => { - const network = Network.ARBITRUM; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const tokenASymbol: string = 'USDCe'; - const tokenBSymbol: string = 'USDT'; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const tokenAAmount: string = '1100000'; - const tokenBAmount: string = '1000000'; - const nativeTokenAmount = '1100000000000'; - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ContractMethod.directUniV3Swap, - ], - ], - [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - ContractMethod.buy, - ContractMethod.directUniV3Buy, - ], - ], - ]); - - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }), - ); - }); - }); - - describe('ChronosV3', () => { - const dexKey = 'ChronosV3'; - describe('Arbitrum', () => { - const network = Network.ARBITRUM; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const tokenASymbol: string = 'USDCe'; - const tokenBSymbol: string = 'USDT'; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const tokenAAmount: string = '2000000'; - const tokenBAmount: string = '2000000'; - const nativeTokenAmount = '100000000000000000'; - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ContractMethod.directUniV3Swap, - ], - ], - [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - ContractMethod.buy, - ContractMethod.directUniV3Buy, - ], - ], - ]); - - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }), - ); - }); - }); - - describe('SushiSwapV3 E2E', () => { - const dexKey = 'SushiSwapV3'; - - describe('MAINNET', () => { - const network = Network.MAINNET; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; - - const tokenAAmount: string = '111110000'; - const tokenBAmount: string = '1100000000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); - - describe('ARBITRUM', () => { - const network = Network.ARBITRUM; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDCe'; - - const tokenAAmount: string = '10000000'; - const tokenBAmount: string = '10000000'; - const nativeTokenAmount = '900000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); - - describe('POLYGON', () => { - const network = Network.POLYGON; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; - - const tokenAAmount: string = '21111000'; - const tokenBAmount: string = '200000000'; - const nativeTokenAmount = '110000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); - - describe('BSC', () => { - const network = Network.BSC; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ContractMethod.directUniV3Swap, - ], - ], - [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - ContractMethod.buy, - ContractMethod.directUniV3Buy, - ], - ], - ]); - - const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = - [ - [ - { - name: 'USDC', - sellAmount: '100000000000000000000', - buyAmount: '100000000000000000000', - }, - { - name: 'USDT', - sellAmount: '100000000000000000000', - buyAmount: '100000000000000000000', - }, - ], - [ - { - name: 'BNB', - sellAmount: '1000000000000000000', - buyAmount: '10000000000000000000', - }, - { - name: 'USDT', - sellAmount: '1000000000000000000000', - buyAmount: '20000000000000000', - }, - ], - ]; - - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - contractMethods.forEach((contractMethod: ContractMethod) => { - pairs.forEach(pair => { - describe(`${contractMethod}`, () => { - it(`${pair[0].name} -> ${pair[1].name}`, async () => { - await testE2E( - tokens[pair[0].name], - tokens[pair[1].name], - holders[pair[0].name], - side === SwapSide.SELL - ? pair[0].sellAmount - : pair[0].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${pair[1].name} -> ${pair[0].name}`, async () => { - await testE2E( - tokens[pair[1].name], - tokens[pair[0].name], - holders[pair[1].name], - side === SwapSide.SELL - ? pair[1].sellAmount - : pair[1].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }); - }); - }), - ); - }); - - describe('AVALANCHE', () => { - const network = Network.AVALANCHE; - - const tokenASymbol: string = 'USDT'; - const tokenBSymbol: string = 'USDC'; - - const tokenAAmount: string = '111110'; - const tokenBAmount: string = '100000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); - - describe('FANTOM', () => { - const network = Network.FANTOM; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ContractMethod.directUniV3Swap, - ], - ], - [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - ContractMethod.buy, - ContractMethod.directUniV3Buy, - ], - ], - ]); - - const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = - [ - [ - { - name: 'FTM', - sellAmount: '100000000000000000', - buyAmount: '100000000', - }, - { - name: 'USDC', - sellAmount: '100000000', - buyAmount: '100000000000000000', - }, - ], - [ - { - name: 'WFTM', - sellAmount: '100000000000000', - buyAmount: '1000000000000000', - }, - { - name: 'WETH', - sellAmount: '1000000000000000', - buyAmount: '100000000000000', - }, - ], - ]; - - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - contractMethods.forEach((contractMethod: ContractMethod) => { - pairs.forEach(pair => { - describe(`${contractMethod}`, () => { - it(`${pair[0].name} -> ${pair[1].name}`, async () => { - await testE2E( - tokens[pair[0].name], - tokens[pair[1].name], - holders[pair[0].name], - side === SwapSide.SELL - ? pair[0].sellAmount - : pair[0].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${pair[1].name} -> ${pair[0].name}`, async () => { - await testE2E( - tokens[pair[1].name], - tokens[pair[0].name], - holders[pair[1].name], - side === SwapSide.SELL - ? pair[1].sellAmount - : pair[1].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }); - }); - }), - ); - }); - - describe('OPTIMISM', () => { - const network = Network.OPTIMISM; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; - - const tokenAAmount: string = '111110000'; - const tokenBAmount: string = '10000000'; - const nativeTokenAmount = '11000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); - }); + // describe('RamsesV2', () => { + // const dexKey = 'RamsesV2'; + // + // describe('Arbitrum', () => { + // const network = Network.ARBITRUM; + // const tokens = Tokens[network]; + // const holders = Holders[network]; + // const provider = new StaticJsonRpcProvider( + // generateConfig(network).privateHttpProvider, + // network, + // ); + // + // const tokenASymbol: string = 'USDCe'; + // const tokenBSymbol: string = 'USDT'; + // const nativeTokenSymbol = NativeTokenSymbols[network]; + // + // const tokenAAmount: string = '1100000'; + // const tokenBAmount: string = '1000000'; + // const nativeTokenAmount = '1100000000000'; + // + // const sideToContractMethods = new Map([ + // [ + // SwapSide.SELL, + // [ + // ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + // ContractMethod.directUniV3Swap, + // ], + // ], + // [ + // SwapSide.BUY, + // [ + // ContractMethod.simpleBuy, + // ContractMethod.buy, + // ContractMethod.directUniV3Buy, + // ], + // ], + // ]); + // + // sideToContractMethods.forEach((contractMethods, side) => + // contractMethods.forEach((contractMethod: ContractMethod) => { + // describe(`${contractMethod}`, () => { + // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + // await testE2E( + // tokens[nativeTokenSymbol], + // tokens[tokenASymbol], + // holders[nativeTokenSymbol], + // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + // await testE2E( + // tokens[tokenASymbol], + // tokens[nativeTokenSymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + // await testE2E( + // tokens[tokenASymbol], + // tokens[tokenBSymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // }); + // }), + // ); + // }); + // }); + // + // describe('ChronosV3', () => { + // const dexKey = 'ChronosV3'; + // describe('Arbitrum', () => { + // const network = Network.ARBITRUM; + // const tokens = Tokens[network]; + // const holders = Holders[network]; + // const provider = new StaticJsonRpcProvider( + // generateConfig(network).privateHttpProvider, + // network, + // ); + // + // const tokenASymbol: string = 'USDCe'; + // const tokenBSymbol: string = 'USDT'; + // const nativeTokenSymbol = NativeTokenSymbols[network]; + // + // const tokenAAmount: string = '2000000'; + // const tokenBAmount: string = '2000000'; + // const nativeTokenAmount = '100000000000000000'; + // + // const sideToContractMethods = new Map([ + // [ + // SwapSide.SELL, + // [ + // ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + // ContractMethod.directUniV3Swap, + // ], + // ], + // [ + // SwapSide.BUY, + // [ + // ContractMethod.simpleBuy, + // ContractMethod.buy, + // ContractMethod.directUniV3Buy, + // ], + // ], + // ]); + // + // sideToContractMethods.forEach((contractMethods, side) => + // contractMethods.forEach((contractMethod: ContractMethod) => { + // describe(`${contractMethod}`, () => { + // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + // await testE2E( + // tokens[nativeTokenSymbol], + // tokens[tokenASymbol], + // holders[nativeTokenSymbol], + // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + // await testE2E( + // tokens[tokenASymbol], + // tokens[nativeTokenSymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + // await testE2E( + // tokens[tokenASymbol], + // tokens[tokenBSymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // }); + // }), + // ); + // }); + // }); + // + // describe('SushiSwapV3 E2E', () => { + // const dexKey = 'SushiSwapV3'; + // + // describe('MAINNET', () => { + // const network = Network.MAINNET; + // + // const tokenASymbol: string = 'USDC'; + // const tokenBSymbol: string = 'USDT'; + // + // const tokenAAmount: string = '111110000'; + // const tokenBAmount: string = '1100000000'; + // const nativeTokenAmount = '11000000000000000'; + // + // testForNetwork( + // network, + // dexKey, + // tokenASymbol, + // tokenBSymbol, + // tokenAAmount, + // tokenBAmount, + // nativeTokenAmount, + // ); + // }); + // + // describe('ARBITRUM', () => { + // const network = Network.ARBITRUM; + // + // const tokenASymbol: string = 'USDC'; + // const tokenBSymbol: string = 'USDCe'; + // + // const tokenAAmount: string = '10000000'; + // const tokenBAmount: string = '10000000'; + // const nativeTokenAmount = '900000000000000'; + // + // testForNetwork( + // network, + // dexKey, + // tokenASymbol, + // tokenBSymbol, + // tokenAAmount, + // tokenBAmount, + // nativeTokenAmount, + // ); + // }); + // + // describe('POLYGON', () => { + // const network = Network.POLYGON; + // + // const tokenASymbol: string = 'USDC'; + // const tokenBSymbol: string = 'USDT'; + // + // const tokenAAmount: string = '21111000'; + // const tokenBAmount: string = '200000000'; + // const nativeTokenAmount = '110000000000000000'; + // + // testForNetwork( + // network, + // dexKey, + // tokenASymbol, + // tokenBSymbol, + // tokenAAmount, + // tokenBAmount, + // nativeTokenAmount, + // ); + // }); + // + // describe('BSC', () => { + // const network = Network.BSC; + // const tokens = Tokens[network]; + // const holders = Holders[network]; + // const provider = new StaticJsonRpcProvider( + // generateConfig(network).privateHttpProvider, + // network, + // ); + // + // const sideToContractMethods = new Map([ + // [ + // SwapSide.SELL, + // [ + // ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + // ContractMethod.directUniV3Swap, + // ], + // ], + // [ + // SwapSide.BUY, + // [ + // ContractMethod.simpleBuy, + // ContractMethod.buy, + // ContractMethod.directUniV3Buy, + // ], + // ], + // ]); + // + // const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = + // [ + // [ + // { + // name: 'USDC', + // sellAmount: '100000000000000000000', + // buyAmount: '100000000000000000000', + // }, + // { + // name: 'USDT', + // sellAmount: '100000000000000000000', + // buyAmount: '100000000000000000000', + // }, + // ], + // [ + // { + // name: 'BNB', + // sellAmount: '1000000000000000000', + // buyAmount: '10000000000000000000', + // }, + // { + // name: 'USDT', + // sellAmount: '1000000000000000000000', + // buyAmount: '20000000000000000', + // }, + // ], + // ]; + // + // sideToContractMethods.forEach((contractMethods, side) => + // describe(`${side}`, () => { + // contractMethods.forEach((contractMethod: ContractMethod) => { + // pairs.forEach(pair => { + // describe(`${contractMethod}`, () => { + // it(`${pair[0].name} -> ${pair[1].name}`, async () => { + // await testE2E( + // tokens[pair[0].name], + // tokens[pair[1].name], + // holders[pair[0].name], + // side === SwapSide.SELL + // ? pair[0].sellAmount + // : pair[0].buyAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${pair[1].name} -> ${pair[0].name}`, async () => { + // await testE2E( + // tokens[pair[1].name], + // tokens[pair[0].name], + // holders[pair[1].name], + // side === SwapSide.SELL + // ? pair[1].sellAmount + // : pair[1].buyAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // }); + // }); + // }); + // }), + // ); + // }); + // + // describe('AVALANCHE', () => { + // const network = Network.AVALANCHE; + // + // const tokenASymbol: string = 'USDT'; + // const tokenBSymbol: string = 'USDC'; + // + // const tokenAAmount: string = '111110'; + // const tokenBAmount: string = '100000'; + // const nativeTokenAmount = '11000000000000000'; + // + // testForNetwork( + // network, + // dexKey, + // tokenASymbol, + // tokenBSymbol, + // tokenAAmount, + // tokenBAmount, + // nativeTokenAmount, + // ); + // }); + // + // describe('FANTOM', () => { + // const network = Network.FANTOM; + // const tokens = Tokens[network]; + // const holders = Holders[network]; + // const provider = new StaticJsonRpcProvider( + // generateConfig(network).privateHttpProvider, + // network, + // ); + // + // const sideToContractMethods = new Map([ + // [ + // SwapSide.SELL, + // [ + // ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + // ContractMethod.directUniV3Swap, + // ], + // ], + // [ + // SwapSide.BUY, + // [ + // ContractMethod.simpleBuy, + // ContractMethod.buy, + // ContractMethod.directUniV3Buy, + // ], + // ], + // ]); + // + // const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = + // [ + // [ + // { + // name: 'FTM', + // sellAmount: '100000000000000000', + // buyAmount: '100000000', + // }, + // { + // name: 'USDC', + // sellAmount: '100000000', + // buyAmount: '100000000000000000', + // }, + // ], + // [ + // { + // name: 'WFTM', + // sellAmount: '100000000000000', + // buyAmount: '1000000000000000', + // }, + // { + // name: 'WETH', + // sellAmount: '1000000000000000', + // buyAmount: '100000000000000', + // }, + // ], + // ]; + // + // sideToContractMethods.forEach((contractMethods, side) => + // describe(`${side}`, () => { + // contractMethods.forEach((contractMethod: ContractMethod) => { + // pairs.forEach(pair => { + // describe(`${contractMethod}`, () => { + // it(`${pair[0].name} -> ${pair[1].name}`, async () => { + // await testE2E( + // tokens[pair[0].name], + // tokens[pair[1].name], + // holders[pair[0].name], + // side === SwapSide.SELL + // ? pair[0].sellAmount + // : pair[0].buyAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${pair[1].name} -> ${pair[0].name}`, async () => { + // await testE2E( + // tokens[pair[1].name], + // tokens[pair[0].name], + // holders[pair[1].name], + // side === SwapSide.SELL + // ? pair[1].sellAmount + // : pair[1].buyAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // }); + // }); + // }); + // }), + // ); + // }); + // + // describe('OPTIMISM', () => { + // const network = Network.OPTIMISM; + // + // const tokenASymbol: string = 'USDC'; + // const tokenBSymbol: string = 'USDT'; + // + // const tokenAAmount: string = '111110000'; + // const tokenBAmount: string = '10000000'; + // const nativeTokenAmount = '11000000000000000'; + // + // testForNetwork( + // network, + // dexKey, + // tokenASymbol, + // tokenBSymbol, + // tokenAAmount, + // tokenBAmount, + // nativeTokenAmount, + // ); + // }); + // }); }); From ee9b0da5548d9a614dd22dec016713e307978c19 Mon Sep 17 00:00:00 2001 From: Verisana Date: Mon, 18 Sep 2023 16:55:08 +0100 Subject: [PATCH 308/833] fix: update pool identifier for generic rfq --- src/dex/generic-rfq/generic-rfq.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/dex/generic-rfq/generic-rfq.ts b/src/dex/generic-rfq/generic-rfq.ts index e7b388a0e..c6c1584b1 100644 --- a/src/dex/generic-rfq/generic-rfq.ts +++ b/src/dex/generic-rfq/generic-rfq.ts @@ -6,6 +6,7 @@ import { PreprocessTransactionOptions, Config, PoolLiquidity, + Address, } from '../../types'; import { Network, SwapSide } from '../../constants'; import { IDexHelper } from '../../dex-helper'; @@ -61,6 +62,11 @@ export class GenericRFQ extends ParaSwapLimitOrders { return; } + getIdentifier(srcToken: Address, destToken: Address) { + // Keep only destination token in order to prevent taping into the same market maker liquidity during same swap (double spending) + return `${this.dexKey}_${destToken}`.toLowerCase(); + } + async getPoolIdentifiers( srcToken: Token, destToken: Token, @@ -68,8 +74,7 @@ export class GenericRFQ extends ParaSwapLimitOrders { blockNumber: number, ): Promise { const _destToken = this.dexHelper.config.wrapETH(destToken); - // Keep only destination token in order to prevent taping into the same market maker liquidity during same swap (double spending) - return [`${this.dexKey}_${_destToken.address}`.toLowerCase()]; + return [this.getIdentifier(srcToken.address, _destToken.address)]; } calcOutsFromAmounts( From 585e63527e1db838a4c3df3e6384556f0e8a26e2 Mon Sep 17 00:00:00 2001 From: Verisana Date: Mon, 18 Sep 2023 16:55:49 +0100 Subject: [PATCH 309/833] 2.35.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0d103e6c1..2ac433ac0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.4", + "version": "2.35.5", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 460a9b0c16a32aa153325f069f0501cd3d3db417 Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 19 Sep 2023 14:13:43 +0100 Subject: [PATCH 310/833] test: make tests for hashflow work --- src/config.ts | 4 +-- src/dex-helper/dummy-dex-helper.ts | 5 +++- src/dex/hashflow/hashflow-e2e.test.ts | 39 ++++++++++++++++++++++++--- tests/tenderly-simulation.ts | 4 +-- tests/utils-e2e.ts | 3 ++- 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/config.ts b/src/config.ts index 9c3d7369b..9a35f8fd7 100644 --- a/src/config.ts +++ b/src/config.ts @@ -191,8 +191,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_137`]?.split(',') || [], adapterAddresses: { PolygonAdapter01: '0xE44769f42E1e9592f86B82f206407a8f7C84b4ed', - PolygonAdapter02: '0xa05d8C3F278fC7b20b39Ea7A3035E3aD8D808c78', - PolygonBuyAdapter: '0xB11bCA7B01b425afD0743A4D77B4f593883f94C0', + PolygonAdapter02: '0x654cD2Cf97D23059B3db4FaA38BB2b1F8351211d', + PolygonBuyAdapter: '0x4426a1F87Ee7e366542c58e29c02AFa2b5878b37', }, uniswapV2ExchangeRouterAddress: '0xf3938337F7294fEf84e9B2c6D548A93F956Cc281', diff --git a/src/dex-helper/dummy-dex-helper.ts b/src/dex-helper/dummy-dex-helper.ts index 69be935b8..b1db1cca0 100644 --- a/src/dex-helper/dummy-dex-helper.ts +++ b/src/dex-helper/dummy-dex-helper.ts @@ -41,6 +41,7 @@ class DummyCache implements ICache { } async rawget(key: string): Promise { + return this.storage[key] ? this.storage[key] : null; return null; } @@ -49,10 +50,12 @@ class DummyCache implements ICache { value: string, ttl: number, ): Promise { - return null; + this.storage[key] = value; + return 'OK'; } async rawdel(key: string): Promise { + delete this.storage[key]; return; } diff --git a/src/dex/hashflow/hashflow-e2e.test.ts b/src/dex/hashflow/hashflow-e2e.test.ts index 0ccd6797a..abd15126f 100644 --- a/src/dex/hashflow/hashflow-e2e.test.ts +++ b/src/dex/hashflow/hashflow-e2e.test.ts @@ -11,6 +11,9 @@ import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; +// Give time for rate fetcher to fill the cache +const sleepMs = 3000; + function testForNetwork( network: Network, dexKey: string, @@ -58,6 +61,11 @@ function testForNetwork( contractMethod, network, provider, + undefined, + undefined, + undefined, + undefined, + sleepMs, ); }); it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => { @@ -71,6 +79,11 @@ function testForNetwork( contractMethod, network, provider, + undefined, + undefined, + undefined, + undefined, + sleepMs, ); }); } else { @@ -85,6 +98,11 @@ function testForNetwork( contractMethod, network, provider, + undefined, + undefined, + undefined, + undefined, + sleepMs, ); }); it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { @@ -98,6 +116,11 @@ function testForNetwork( contractMethod, network, provider, + undefined, + undefined, + undefined, + undefined, + sleepMs, ); }); it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { @@ -111,6 +134,11 @@ function testForNetwork( contractMethod, network, provider, + undefined, + undefined, + undefined, + undefined, + sleepMs, ); }); it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => { @@ -124,6 +152,11 @@ function testForNetwork( contractMethod, network, provider, + undefined, + undefined, + undefined, + undefined, + sleepMs, ); }); } @@ -163,9 +196,9 @@ describe('Hashflow E2E', () => { const tokenASymbol: string = 'USDC'; const tokenBSymbol: string = 'DAI'; - const tokenAAmount: string = '100000000'; - const tokenBAmount: string = '100000000000000000000'; - const nativeTokenAmount = '1000000000000000000'; + const tokenAAmount: string = '1000000000'; + const tokenBAmount: string = '1000000000000000000000'; + const nativeTokenAmount = '100000000000000000000'; testForNetwork( network, diff --git a/tests/tenderly-simulation.ts b/tests/tenderly-simulation.ts index 1d845b5ac..ddc53c786 100644 --- a/tests/tenderly-simulation.ts +++ b/tests/tenderly-simulation.ts @@ -149,13 +149,13 @@ export class TenderlySimulation implements TransactionSimulator { return { success: true, gasUsed: data.transaction.gas_used, - tenderlyUrl: `https://dashboard.tenderly.co/${TENDERLY_ACCOUNT_ID}/${TENDERLY_PROJECT}/fork/${this.forkId}/simulation/${lastTx}`, + url: `https://dashboard.tenderly.co/${TENDERLY_ACCOUNT_ID}/${TENDERLY_PROJECT}/fork/${this.forkId}/simulation/${lastTx}`, transaction: data.transaction, }; } else { return { success: false, - tenderlyUrl: `https://dashboard.tenderly.co/${TENDERLY_ACCOUNT_ID}/${TENDERLY_PROJECT}/fork/${this.forkId}/simulation/${lastTx}`, + 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}`, }; } diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index ca5e068df..f1b96c7d2 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -298,6 +298,7 @@ export async function testE2E( ), ); expect(whitelistTx.success).toEqual(true); + console.log(`Successfully whitelisted ${deployedTestContractAddress}`); if (testContractType === 'router') { const setImplementationTx = await ts.simulate( @@ -622,7 +623,7 @@ export async function newTestE2E({ parseInt(priceRoute.gasCost) - parseInt(swapTx!.gasUsed) }`, ); - console.log(`Tenderly URL: ${swapTx!.tenderlyUrl}`); + console.log(`Tenderly URL: ${swapTx!.url}`); expect(swapTx!.success).toEqual(true); } } finally { From e706d9fcbecb0096b80d3e1187de349767bac6e8 Mon Sep 17 00:00:00 2001 From: julien Date: Tue, 19 Sep 2023 16:22:21 +0200 Subject: [PATCH 311/833] feat: use generic url route for subgraph --- src/dex/smardex/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/smardex/config.ts b/src/dex/smardex/config.ts index 35291c0da..59572790e 100644 --- a/src/dex/smardex/config.ts +++ b/src/dex/smardex/config.ts @@ -2,7 +2,7 @@ import { DexParams } from './types'; import { DexConfigMap, AdapterMappings } from '../../types'; import { Network } from '../../constants'; -const gatewaySubgraph = 'https://subgraph.smardex.io/paraswap'; +const gatewaySubgraph = 'https://subgraph.smardex.io'; const mainnetInitHash = '0xb477a06204165d50e6d795c7c216306290eff5d6015f8b65bb46002a8775b548'; const layer2InitHash = From b4c2b1645fc7202b0aa94cbd3e3a24cdc21d2cf4 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Tue, 19 Sep 2023 22:40:55 -0400 Subject: [PATCH 312/833] change stateMulticall address --- src/dex/solidly-v3/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index d7ceb7402..9ef25dd92 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -33,7 +33,7 @@ export const SolidlyV3Config: DexConfigMap = { quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', supportedFees: SUPPORTED_FEES, - stateMulticall: '0x9c764D2e92dA68E4CDfD784B902283A095ff8b63', + stateMulticall: '0xb229563028302AA693EEaD62F80CC331aEDE4e26', uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', chunksCount: 10, initRetryFrequency: 10, From fb406e58574d390e980704ad64086ea562441a5b Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Tue, 19 Sep 2023 23:16:24 -0400 Subject: [PATCH 313/833] big start of refactor, change feeCode -> tickSpacing --- .husky/pre-commit | 2 +- src/dex/solidly-v3/config.ts | 3 +- src/dex/solidly-v3/solidly-v3-pool.ts | 40 ++++++--------- src/dex/solidly-v3/solidly-v3.ts | 71 +++++++++++++++------------ src/dex/solidly-v3/types.ts | 22 ++------- 5 files changed, 59 insertions(+), 79 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index 9163e8448..7e07d664d 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" -yarn checks && yarn build +#yarn checks && yarn build diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index 9ef25dd92..2a49b4edc 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -5,6 +5,7 @@ import { Address } from '../../types'; // const SUPPORTED_FEES = [3000n]; const SUPPORTED_FEES = [500n]; +const SUPPORTED_TICK_SPACINGS = [10n]; // Pools that will be initialized on app startup // They are added for testing @@ -32,7 +33,7 @@ export const SolidlyV3Config: DexConfigMap = { factory: '0x735bb16affe83a3dc4dc418abccf179617cf9ff2', quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', - supportedFees: SUPPORTED_FEES, + supportedTickSpacings: SUPPORTED_TICK_SPACINGS, stateMulticall: '0xb229563028302AA693EEaD62F80CC331aEDE4e26', uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', chunksCount: 10, diff --git a/src/dex/solidly-v3/solidly-v3-pool.ts b/src/dex/solidly-v3/solidly-v3-pool.ts index f5f03d871..197ce90f1 100644 --- a/src/dex/solidly-v3/solidly-v3-pool.ts +++ b/src/dex/solidly-v3/solidly-v3-pool.ts @@ -59,7 +59,8 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { public initFailed = false; public initRetryAttemptCount = 0; - public readonly feeCodeAsString; + // public readonly feeCodeAsString; + public readonly tickSpacingAsString: string; constructor( readonly dexHelper: IDexHelper, @@ -70,7 +71,7 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { | undefined, readonly erc20Interface: Interface, protected readonly factoryAddress: Address, - public readonly feeCode: bigint, + public readonly tickSpacing: bigint, token0: Address, token1: Address, logger: Logger, @@ -79,13 +80,14 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { ) { super( parentName, - `${token0}_${token1}_${feeCode}`, + `${token0}_${token1}_${tickSpacing}`, dexHelper, logger, true, mapKey, ); - this.feeCodeAsString = feeCode.toString(); + // this.feeCodeAsString = feeCode.toString(); + this.tickSpacingAsString = tickSpacing.toString(); this.token0 = token0.toLowerCase(); this.token1 = token1.toLowerCase(); this.logDecoder = (log: Log) => this.poolIface.parseLog(log); @@ -108,7 +110,7 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { this._poolAddress = this._computePoolAddress( this.token0, this.token1, - this.feeCode, + this.tickSpacing, ); } return this._poolAddress; @@ -226,7 +228,7 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { this.factoryAddress, this.token0, this.token1, - this.feeCode, + this.tickSpacing, this.getBitmapRangeToRequest(), this.getBitmapRangeToRequest(), ) @@ -278,19 +280,9 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { _reduceTickBitmap(tickBitmap, _state.tickBitmap); _reduceTicks(ticks, _state.ticks); - const observations = { - [_state.slot0.observationIndex]: { - blockTimestamp: bigIntify(_state.observation.blockTimestamp), - tickCumulative: bigIntify(_state.observation.tickCumulative), - secondsPerLiquidityCumulativeX128: bigIntify( - _state.observation.secondsPerLiquidityCumulativeX128, - ), - initialized: _state.observation.initialized, - }, - }; - const currentTick = bigIntify(_state.slot0.tick); const tickSpacing = bigIntify(_state.tickSpacing); + const fee = bigIntify(_state.slot0.fee) const startTickBitmap = TickBitMap.position(currentTick / tickSpacing)[0]; const requestedRange = this.getBitmapRangeToRequest(); @@ -301,18 +293,14 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { slot0: { sqrtPriceX96: bigIntify(_state.slot0.sqrtPriceX96), tick: currentTick, - observationIndex: +_state.slot0.observationIndex, - observationCardinality: +_state.slot0.observationCardinality, - observationCardinalityNext: +_state.slot0.observationCardinalityNext, - feeProtocol: bigIntify(_state.slot0.feeProtocol), + fee: bigIntify(_state.slot0.fee), }, liquidity: bigIntify(_state.liquidity), - fee: this.feeCode, + fee: fee, tickSpacing, maxLiquidityPerTick: bigIntify(_state.maxLiquidityPerTick), tickBitmap, ticks, - observations, isValid: true, startTickBitmap, lowestKnownTick: @@ -471,16 +459,16 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { private _computePoolAddress( token0: Address, token1: Address, - fee: bigint, + tickSpacing: bigint, ): Address { // https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/PoolAddress.sol if (token0 > token1) [token0, token1] = [token1, token0]; const encodedKey = ethers.utils.keccak256( ethers.utils.defaultAbiCoder.encode( - ['address', 'address', 'uint24'], + ['address', 'address', 'int24'], // [token0, token1, BigInt.asUintN(24, fee)], - [token0, token1, BigInt.asUintN(24, FEES_TO_TICK_SPACING[Number(fee)])], + [token0, token1, BigInt.asUintN(24, tickSpacing)], ), ); diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index 0ebf14f33..5a28f7ecc 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -140,17 +140,21 @@ export class SolidlyV3 `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); } - get supportedFees() { - return this.config.supportedFees; + get supportedTickSpacings() { + return this.config.supportedTickSpacings; } getAdapters(side: SwapSide): { name: string; index: number }[] | null { return this.adapters[side] ? this.adapters[side] : null; } - getPoolIdentifier(srcAddress: Address, destAddress: Address, fee: bigint) { + getPoolIdentifier( + srcAddress: Address, + destAddress: Address, + tickSpacing: bigint, + ) { const tokenAddresses = this._sortTokens(srcAddress, destAddress).join('_'); - return `${this.dexKey}_${tokenAddresses}_${fee}`; + return `${this.dexKey}_${tokenAddresses}_${tickSpacing}`; } async initializePricing(blockNumber: number) { @@ -159,8 +163,8 @@ export class SolidlyV3 await Promise.all( this.poolsToPreload.map(async pool => Promise.all( - this.config.supportedFees.map(async fee => - this.getPool(pool.token0, pool.token1, fee, blockNumber), + this.config.supportedTickSpacings.map(async tickSpacing => + this.getPool(pool.token0, pool.token1, tickSpacing, blockNumber), ), ), ), @@ -187,11 +191,11 @@ export class SolidlyV3 async getPool( srcAddress: Address, destAddress: Address, - fee: bigint, + tickSpacing: bigint, blockNumber: number, ): Promise { let pool = this.eventPools[ - this.getPoolIdentifier(srcAddress, destAddress, fee) + this.getPoolIdentifier(srcAddress, destAddress, tickSpacing) ] as SolidlyV3EventPool | null | undefined; if (pool === null) return null; @@ -213,7 +217,7 @@ export class SolidlyV3 const [token0, token1] = this._sortTokens(srcAddress, destAddress); - const key = `${token0}_${token1}_${fee}`.toLowerCase(); + const key = `${token0}_${token1}_${tickSpacing}`.toLowerCase(); if (!pool) { const notExistingPoolScore = await this.dexHelper.cache.zscore( @@ -224,8 +228,9 @@ export class SolidlyV3 const poolDoesNotExist = notExistingPoolScore !== null; if (poolDoesNotExist) { - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - null; + this.eventPools[ + this.getPoolIdentifier(srcAddress, destAddress, tickSpacing) + ] = null; return null; } @@ -235,7 +240,7 @@ export class SolidlyV3 JSON.stringify({ token0, token1, - fee: fee.toString(), + fee: tickSpacing.toString(), }), ); } @@ -250,7 +255,7 @@ export class SolidlyV3 this.config.decodeStateMultiCallResultWithRelativeBitmaps, this.erc20Interface, this.config.factory, - fee, + tickSpacing, token0, token1, this.logger, @@ -281,14 +286,14 @@ export class SolidlyV3 // to prevent more requests for this pool pool = null; this.logger.trace( - `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, + `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${tickSpacing} not found`, e, ); } else { // on unknown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${tickSpacing} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, e, ); pool.initFailed = true; @@ -307,8 +312,9 @@ export class SolidlyV3 ); } - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - pool; + this.eventPools[ + this.getPoolIdentifier(srcAddress, destAddress, tickSpacing) + ] = pool; return pool; } @@ -355,8 +361,8 @@ export class SolidlyV3 const pools = ( await Promise.all( - this.supportedFees.map(async fee => - this.getPool(_srcAddress, _destAddress, fee, blockNumber), + this.supportedTickSpacings.map(async tickSpacing => + this.getPool(_srcAddress, _destAddress, tickSpacing, blockNumber), ), ) ).filter(pool => pool); @@ -364,7 +370,7 @@ export class SolidlyV3 if (pools.length === 0) return []; return pools.map(pool => - this.getPoolIdentifier(_srcAddress, _destAddress, pool!.feeCode), + this.getPoolIdentifier(_srcAddress, _destAddress, pool!.tickSpacing), ); } @@ -439,7 +445,7 @@ export class SolidlyV3 from.address, to.address, _amount.toString(), - pool.feeCodeAsString, + pool.tickSpacingAsString, 0, //sqrtPriceLimitX96 ], ]) @@ -448,7 +454,7 @@ export class SolidlyV3 from.address, to.address, _amount.toString(), - pool.feeCodeAsString, + pool.tickSpacingAsString, 0, //sqrtPriceLimitX96 ], ]), @@ -490,7 +496,7 @@ export class SolidlyV3 { tokenIn: from.address, tokenOut: to.address, - fee: pool.feeCodeAsString, + fee: pool.tickSpacingAsString, }, ], exchange: pool.poolAddress, @@ -498,7 +504,7 @@ export class SolidlyV3 poolIdentifier: this.getPoolIdentifier( pool.token0, pool.token1, - pool.feeCode, + pool.tickSpacing, ), exchange: this.dexKey, gasCost: prices.map(p => (p === 0n ? 0 : UNISWAPV3_QUOTE_GASLIMIT)), @@ -533,17 +539,17 @@ export class SolidlyV3 if (!limitPools) { selectedPools = ( await Promise.all( - this.supportedFees.map(async fee => { + this.supportedTickSpacings.map(async tickSpacing => { const locallyFoundPool = this.eventPools[ - this.getPoolIdentifier(_srcAddress, _destAddress, fee) + this.getPoolIdentifier(_srcAddress, _destAddress, tickSpacing) ]; if (locallyFoundPool) return locallyFoundPool; const newlyFetchedPool = await this.getPool( _srcAddress, _destAddress, - fee, + tickSpacing, blockNumber, ); return newlyFetchedPool; @@ -568,11 +574,12 @@ export class SolidlyV3 let locallyFoundPool = this.eventPools[identifier]; if (locallyFoundPool) return locallyFoundPool; - const [, srcAddress, destAddress, fee] = identifier.split('_'); + const [, srcAddress, destAddress, tickSpacing] = + identifier.split('_'); const newlyFetchedPool = await this.getPool( srcAddress, destAddress, - BigInt(fee), + BigInt(tickSpacing), blockNumber, ); return newlyFetchedPool; @@ -684,14 +691,14 @@ export class SolidlyV3 { tokenIn: _srcAddress, tokenOut: _destAddress, - fee: pool.feeCode.toString(), + fee: pool.tickSpacing.toString(), }, ], }, poolIdentifier: this.getPoolIdentifier( pool.token0, pool.token1, - pool.feeCode, + pool.tickSpacing, ), exchange: this.dexKey, gasCost: gasCost, @@ -1056,7 +1063,7 @@ export class SolidlyV3 router: this.config.router.toLowerCase(), quoter: this.config.quoter.toLowerCase(), factory: this.config.factory.toLowerCase(), - supportedFees: this.config.supportedFees, + supportedTickSpacings: this.config.supportedTickSpacings, stateMulticall: this.config.stateMulticall.toLowerCase(), chunksCount: this.config.chunksCount, initRetryFrequency: this.config.initRetryFrequency, diff --git a/src/dex/solidly-v3/types.ts b/src/dex/solidly-v3/types.ts index 8c1bcee1a..d90950c09 100644 --- a/src/dex/solidly-v3/types.ts +++ b/src/dex/solidly-v3/types.ts @@ -28,10 +28,7 @@ export type TickInfo = { export type Slot0 = { sqrtPriceX96: bigint; tick: bigint; - observationIndex: number; - observationCardinality: number; - observationCardinalityNext: number; - feeProtocol: bigint; + fee: bigint; }; export type PoolState = { @@ -44,7 +41,6 @@ export type PoolState = { maxLiquidityPerTick: bigint; tickBitmap: Record; ticks: Record; - observations: Record; isValid: boolean; startTickBitmap: bigint; lowestKnownTick: bigint; @@ -72,7 +68,7 @@ export type DexParams = { factory: Address; stateMulticall: Address; uniswapMulticall: Address; - supportedFees: bigint[]; + supportedTickSpacings: bigint[]; chunksCount: number; initRetryFrequency: number; deployer?: Address; @@ -150,9 +146,6 @@ export type TickInfoWithBigNumber = { initialized: boolean; liquidityGross: BigNumber; liquidityNet: BigNumber; - secondsOutside: number; - secondsPerLiquidityOutsideX128: BigNumber; - tickCumulativeOutside: BigNumber; }; export type TickInfoMappingsWithBigNumber = { @@ -164,23 +157,14 @@ export type DecodedStateMultiCallResultWithRelativeBitmaps = { pool: Address; blockTimestamp: BigNumber; slot0: { - feeProtocol: number; - observationCardinality: number; - observationCardinalityNext: number; - observationIndex: number; sqrtPriceX96: BigNumber; tick: number; + fee: number; unlocked: boolean; }; liquidity: BigNumber; tickSpacing: number; maxLiquidityPerTick: BigNumber; - observation: { - blockTimestamp: number; - initialized: boolean; - secondsPerLiquidityCumulativeX128: BigNumber; - tickCumulative: BigNumber; - }; tickBitmap: TickBitMapMappingsWithBigNumber[]; ticks: TickInfoMappingsWithBigNumber[]; }; From 7286cb86a549da831abf4544dc35461e0fe762cc Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Tue, 19 Sep 2023 23:42:10 -0400 Subject: [PATCH 314/833] remove oracle. update tick --- src/dex/solidly-v3/contract-math/Tick.ts | 16 -- src/dex/solidly-v3/types.ts | 16 -- src/dex/uniswap-v3/contract-math/Oracle.ts | 226 --------------------- 3 files changed, 258 deletions(-) delete mode 100644 src/dex/uniswap-v3/contract-math/Oracle.ts diff --git a/src/dex/solidly-v3/contract-math/Tick.ts b/src/dex/solidly-v3/contract-math/Tick.ts index ab2e3c48b..31345ee26 100644 --- a/src/dex/solidly-v3/contract-math/Tick.ts +++ b/src/dex/solidly-v3/contract-math/Tick.ts @@ -8,11 +8,7 @@ export class Tick { static update( state: Pick, tick: bigint, - tickCurrent: bigint, liquidityDelta: bigint, - secondsPerLiquidityCumulativeX128: bigint, - tickCumulative: bigint, - time: bigint, upper: boolean, maxLiquidity: bigint, ): boolean { @@ -39,11 +35,6 @@ export class Tick { const flipped = (liquidityGrossAfter == 0n) != (liquidityGrossBefore == 0n); if (liquidityGrossBefore == 0n) { - if (tick <= tickCurrent) { - info.secondsPerLiquidityOutsideX128 = secondsPerLiquidityCumulativeX128; - info.tickCumulativeOutside = tickCumulative; - info.secondsOutside = time; - } info.initialized = true; } @@ -68,15 +59,8 @@ export class Tick { static cross( ticks: Record, tick: bigint, - secondsPerLiquidityCumulativeX128: bigint, - tickCumulative: bigint, - time: bigint, ): bigint { const info = ticks[Number(tick)]; - info.secondsPerLiquidityOutsideX128 = - secondsPerLiquidityCumulativeX128 - info.secondsPerLiquidityOutsideX128; - info.tickCumulativeOutside = tickCumulative - info.tickCumulativeOutside; - info.secondsOutside = time - info.secondsOutside; return info.liquidityNet; } } diff --git a/src/dex/solidly-v3/types.ts b/src/dex/solidly-v3/types.ts index d90950c09..07c4cfc2c 100644 --- a/src/dex/solidly-v3/types.ts +++ b/src/dex/solidly-v3/types.ts @@ -4,24 +4,9 @@ import { Address } from '../../types'; import { AbiItem } from 'web3-utils'; import { MultiResult } from '../../lib/multi-wrapper'; -export type OracleObservation = { - blockTimestamp: bigint; - tickCumulative: bigint; - secondsPerLiquidityCumulativeX128: bigint; - initialized: boolean; -}; - -export type OracleObservationCandidates = { - beforeOrAt: OracleObservation; - atOrAfter: OracleObservation; -}; - export type TickInfo = { liquidityGross: bigint; liquidityNet: bigint; - tickCumulativeOutside: bigint; - secondsPerLiquidityOutsideX128: bigint; - secondsOutside: bigint; initialized: boolean; }; @@ -35,7 +20,6 @@ export type PoolState = { pool: string; blockTimestamp: bigint; tickSpacing: bigint; - fee: bigint; slot0: Slot0; liquidity: bigint; maxLiquidityPerTick: bigint; diff --git a/src/dex/uniswap-v3/contract-math/Oracle.ts b/src/dex/uniswap-v3/contract-math/Oracle.ts deleted file mode 100644 index 19b1918d1..000000000 --- a/src/dex/uniswap-v3/contract-math/Oracle.ts +++ /dev/null @@ -1,226 +0,0 @@ -import { - OracleObservation, - OracleObservationCandidates, - PoolState, -} from '../types'; -import { _require } from '../../../utils'; -import { DeepReadonly } from 'ts-essentials'; -import { ZERO_ORACLE_OBSERVATION } from '../constants'; - -function replaceUndefinedObservationWithZero(state: PoolState, index: number) { - if (state.observations[index] === undefined) { - state.observations[index] = { ...ZERO_ORACLE_OBSERVATION }; - } -} - -export class Oracle { - static transform( - state: DeepReadonly, - last: OracleObservation, - blockTimestamp: bigint, - tick: bigint, - liquidity: bigint, - ): OracleObservation { - const delta = blockTimestamp - last.blockTimestamp; - return { - blockTimestamp: state.blockTimestamp, - tickCumulative: last.tickCumulative + BigInt.asIntN(56, tick) * delta, - secondsPerLiquidityCumulativeX128: - last.secondsPerLiquidityCumulativeX128 + - (BigInt.asUintN(160, delta) << 128n) / - (liquidity > 0n ? liquidity : 1n), - initialized: true, - }; - } - - static write( - state: PoolState, - index: number, - blockTimestamp: bigint, - tick: bigint, - liquidity: bigint, - cardinality: number, - cardinalityNext: number, - ): [number, number] { - const last = state.observations[index]; - - if (last.blockTimestamp == state.blockTimestamp) - return [index, cardinality]; - - let indexUpdated = 0; - let cardinalityUpdated = 0; - - if (cardinalityNext > cardinality && index == cardinality - 1) { - cardinalityUpdated = cardinalityNext; - } else { - cardinalityUpdated = cardinality; - } - - indexUpdated = (index + 1) % cardinalityUpdated; - - state.observations[indexUpdated] = Oracle.transform( - state, - last, - blockTimestamp, - tick, - liquidity, - ); - if (indexUpdated !== index) { - delete state.observations[index]; - } - return [indexUpdated, cardinalityUpdated]; - } - - static lte(time: bigint, a: bigint, b: bigint): boolean { - if (a <= time && b <= time) return a <= b; - - const aAdjusted = a > time ? a : a + 2n ** 32n; - const bAdjusted = b > time ? b : b + 2n ** 32n; - return aAdjusted <= bAdjusted; - } - - static binarySearch( - state: DeepReadonly, - time: bigint, - target: bigint, - index: number, - cardinality: number, - ): OracleObservationCandidates { - let l = (index + 1) % cardinality; - let r = l + cardinality - 1; - let i; - - let beforeOrAt; - let atOrAfter; - while (true) { - i = (l + r) / 2; - - beforeOrAt = state.observations[i % cardinality]; - - // we've landed on an uninitialized tick, keep searching higher (more recently) - if (!beforeOrAt.initialized) { - l = i + 1; - continue; - } - - atOrAfter = state.observations[(i + 1) % cardinality]; - - const targetAtOrAfter = Oracle.lte( - time, - beforeOrAt.blockTimestamp, - target, - ); - - // check if we've found the answer! - if (targetAtOrAfter && Oracle.lte(time, target, atOrAfter.blockTimestamp)) - break; - - if (!targetAtOrAfter) r = i - 1; - else l = i + 1; - } - return { beforeOrAt, atOrAfter }; - } - - static getSurroundingObservations( - state: DeepReadonly, - time: bigint, - target: bigint, - tick: bigint, - index: number, - liquidity: bigint, - cardinality: number, - ): OracleObservationCandidates { - let beforeOrAt = state.observations[index]; - - if (Oracle.lte(time, beforeOrAt.blockTimestamp, target)) { - if (beforeOrAt.blockTimestamp === target) { - return { beforeOrAt, atOrAfter: beforeOrAt }; - } else { - return { - beforeOrAt, - atOrAfter: Oracle.transform( - state, - beforeOrAt, - target, - tick, - liquidity, - ), - }; - } - } - - beforeOrAt = state.observations[(index + 1) % cardinality]; - if (!beforeOrAt.initialized) beforeOrAt = state.observations[0]; - - _require( - Oracle.lte(time, beforeOrAt.blockTimestamp, target), - 'OLD', - { time, beforeOrAtBlockTimestamp: beforeOrAt.blockTimestamp, target }, - 'Oracle.lte(time, beforeOrAt.blockTimestamp, target)', - ); - - return Oracle.binarySearch(state, time, target, index, cardinality); - } - - static observeSingle( - state: DeepReadonly, - time: bigint, - secondsAgo: bigint, - tick: bigint, - index: number, - liquidity: bigint, - cardinality: number, - ): [bigint, bigint] { - if (secondsAgo == 0n) { - let last = state.observations[index]; - if (last.blockTimestamp != time) - last = Oracle.transform(state, last, time, tick, liquidity); - return [last.tickCumulative, last.secondsPerLiquidityCumulativeX128]; - } - - const target = time - secondsAgo; - - const { beforeOrAt, atOrAfter } = Oracle.getSurroundingObservations( - state, - time, - target, - tick, - index, - liquidity, - cardinality, - ); - - if (target === beforeOrAt.blockTimestamp) { - return [ - beforeOrAt.tickCumulative, - beforeOrAt.secondsPerLiquidityCumulativeX128, - ]; - } else if (target === atOrAfter.blockTimestamp) { - return [ - atOrAfter.tickCumulative, - atOrAfter.secondsPerLiquidityCumulativeX128, - ]; - } else { - const observationTimeDelta = - atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp; - const targetDelta = target - beforeOrAt.blockTimestamp; - return [ - beforeOrAt.tickCumulative + - ((atOrAfter.tickCumulative - beforeOrAt.tickCumulative) / - observationTimeDelta) * - targetDelta, - beforeOrAt.secondsPerLiquidityCumulativeX128 + - BigInt.asUintN( - 160, - (BigInt.asUintN( - 256, - atOrAfter.secondsPerLiquidityCumulativeX128 - - beforeOrAt.secondsPerLiquidityCumulativeX128, - ) * - targetDelta) / - observationTimeDelta, - ), - ]; - } - } -} From 411ac3206b39b4758ebcadd7a4d0997f89242268 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Tue, 19 Sep 2023 23:59:08 -0400 Subject: [PATCH 315/833] tenatively go over uniswap-v3-math.ts. delete Oracle.ts --- src/dex/solidly-v3/contract-math/Oracle.ts | 226 ------------------ .../contract-math/uniswap-v3-math.ts | 111 +-------- 2 files changed, 4 insertions(+), 333 deletions(-) delete mode 100644 src/dex/solidly-v3/contract-math/Oracle.ts diff --git a/src/dex/solidly-v3/contract-math/Oracle.ts b/src/dex/solidly-v3/contract-math/Oracle.ts deleted file mode 100644 index 19b1918d1..000000000 --- a/src/dex/solidly-v3/contract-math/Oracle.ts +++ /dev/null @@ -1,226 +0,0 @@ -import { - OracleObservation, - OracleObservationCandidates, - PoolState, -} from '../types'; -import { _require } from '../../../utils'; -import { DeepReadonly } from 'ts-essentials'; -import { ZERO_ORACLE_OBSERVATION } from '../constants'; - -function replaceUndefinedObservationWithZero(state: PoolState, index: number) { - if (state.observations[index] === undefined) { - state.observations[index] = { ...ZERO_ORACLE_OBSERVATION }; - } -} - -export class Oracle { - static transform( - state: DeepReadonly, - last: OracleObservation, - blockTimestamp: bigint, - tick: bigint, - liquidity: bigint, - ): OracleObservation { - const delta = blockTimestamp - last.blockTimestamp; - return { - blockTimestamp: state.blockTimestamp, - tickCumulative: last.tickCumulative + BigInt.asIntN(56, tick) * delta, - secondsPerLiquidityCumulativeX128: - last.secondsPerLiquidityCumulativeX128 + - (BigInt.asUintN(160, delta) << 128n) / - (liquidity > 0n ? liquidity : 1n), - initialized: true, - }; - } - - static write( - state: PoolState, - index: number, - blockTimestamp: bigint, - tick: bigint, - liquidity: bigint, - cardinality: number, - cardinalityNext: number, - ): [number, number] { - const last = state.observations[index]; - - if (last.blockTimestamp == state.blockTimestamp) - return [index, cardinality]; - - let indexUpdated = 0; - let cardinalityUpdated = 0; - - if (cardinalityNext > cardinality && index == cardinality - 1) { - cardinalityUpdated = cardinalityNext; - } else { - cardinalityUpdated = cardinality; - } - - indexUpdated = (index + 1) % cardinalityUpdated; - - state.observations[indexUpdated] = Oracle.transform( - state, - last, - blockTimestamp, - tick, - liquidity, - ); - if (indexUpdated !== index) { - delete state.observations[index]; - } - return [indexUpdated, cardinalityUpdated]; - } - - static lte(time: bigint, a: bigint, b: bigint): boolean { - if (a <= time && b <= time) return a <= b; - - const aAdjusted = a > time ? a : a + 2n ** 32n; - const bAdjusted = b > time ? b : b + 2n ** 32n; - return aAdjusted <= bAdjusted; - } - - static binarySearch( - state: DeepReadonly, - time: bigint, - target: bigint, - index: number, - cardinality: number, - ): OracleObservationCandidates { - let l = (index + 1) % cardinality; - let r = l + cardinality - 1; - let i; - - let beforeOrAt; - let atOrAfter; - while (true) { - i = (l + r) / 2; - - beforeOrAt = state.observations[i % cardinality]; - - // we've landed on an uninitialized tick, keep searching higher (more recently) - if (!beforeOrAt.initialized) { - l = i + 1; - continue; - } - - atOrAfter = state.observations[(i + 1) % cardinality]; - - const targetAtOrAfter = Oracle.lte( - time, - beforeOrAt.blockTimestamp, - target, - ); - - // check if we've found the answer! - if (targetAtOrAfter && Oracle.lte(time, target, atOrAfter.blockTimestamp)) - break; - - if (!targetAtOrAfter) r = i - 1; - else l = i + 1; - } - return { beforeOrAt, atOrAfter }; - } - - static getSurroundingObservations( - state: DeepReadonly, - time: bigint, - target: bigint, - tick: bigint, - index: number, - liquidity: bigint, - cardinality: number, - ): OracleObservationCandidates { - let beforeOrAt = state.observations[index]; - - if (Oracle.lte(time, beforeOrAt.blockTimestamp, target)) { - if (beforeOrAt.blockTimestamp === target) { - return { beforeOrAt, atOrAfter: beforeOrAt }; - } else { - return { - beforeOrAt, - atOrAfter: Oracle.transform( - state, - beforeOrAt, - target, - tick, - liquidity, - ), - }; - } - } - - beforeOrAt = state.observations[(index + 1) % cardinality]; - if (!beforeOrAt.initialized) beforeOrAt = state.observations[0]; - - _require( - Oracle.lte(time, beforeOrAt.blockTimestamp, target), - 'OLD', - { time, beforeOrAtBlockTimestamp: beforeOrAt.blockTimestamp, target }, - 'Oracle.lte(time, beforeOrAt.blockTimestamp, target)', - ); - - return Oracle.binarySearch(state, time, target, index, cardinality); - } - - static observeSingle( - state: DeepReadonly, - time: bigint, - secondsAgo: bigint, - tick: bigint, - index: number, - liquidity: bigint, - cardinality: number, - ): [bigint, bigint] { - if (secondsAgo == 0n) { - let last = state.observations[index]; - if (last.blockTimestamp != time) - last = Oracle.transform(state, last, time, tick, liquidity); - return [last.tickCumulative, last.secondsPerLiquidityCumulativeX128]; - } - - const target = time - secondsAgo; - - const { beforeOrAt, atOrAfter } = Oracle.getSurroundingObservations( - state, - time, - target, - tick, - index, - liquidity, - cardinality, - ); - - if (target === beforeOrAt.blockTimestamp) { - return [ - beforeOrAt.tickCumulative, - beforeOrAt.secondsPerLiquidityCumulativeX128, - ]; - } else if (target === atOrAfter.blockTimestamp) { - return [ - atOrAfter.tickCumulative, - atOrAfter.secondsPerLiquidityCumulativeX128, - ]; - } else { - const observationTimeDelta = - atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp; - const targetDelta = target - beforeOrAt.blockTimestamp; - return [ - beforeOrAt.tickCumulative + - ((atOrAfter.tickCumulative - beforeOrAt.tickCumulative) / - observationTimeDelta) * - targetDelta, - beforeOrAt.secondsPerLiquidityCumulativeX128 + - BigInt.asUintN( - 160, - (BigInt.asUintN( - 256, - atOrAfter.secondsPerLiquidityCumulativeX128 - - beforeOrAt.secondsPerLiquidityCumulativeX128, - ) * - targetDelta) / - observationTimeDelta, - ), - ]; - } - } -} diff --git a/src/dex/solidly-v3/contract-math/uniswap-v3-math.ts b/src/dex/solidly-v3/contract-math/uniswap-v3-math.ts index d18881006..f09ee2ed3 100644 --- a/src/dex/solidly-v3/contract-math/uniswap-v3-math.ts +++ b/src/dex/solidly-v3/contract-math/uniswap-v3-math.ts @@ -1,7 +1,6 @@ import _ from 'lodash'; import { OutputResult, PoolState, Slot0, TickInfo } from '../types'; import { LiquidityMath } from './LiquidityMath'; -import { Oracle } from './Oracle'; import { SqrtPriceMath } from './SqrtPriceMath'; import { SwapMath } from './SwapMath'; import { Tick } from './Tick'; @@ -33,12 +32,6 @@ export type PriceComputationState = { }; export type PriceComputationCache = { - liquidityStart: bigint; - blockTimestamp: bigint; - feeProtocol: bigint; - secondsPerLiquidityCumulativeX128: bigint; - tickCumulative: bigint; - computedLatestObservation: boolean; tickCount: number; }; @@ -147,7 +140,7 @@ function _priceComputationCycles( : step.sqrtPriceNextX96, state.liquidity, state.amountSpecifiedRemaining, - poolState.fee, + poolState.slot0.fee, ); state.sqrtPriceX96 = swapStepResult.sqrtRatioNextX96; @@ -164,27 +157,8 @@ function _priceComputationCycles( state.amountCalculated + step.amountIn + step.feeAmount; } - if (cache.feeProtocol > 0n) { - const delta = step.feeAmount / cache.feeProtocol; - step.feeAmount -= delta; - state.protocolFee += delta; - } - if (state.sqrtPriceX96 === step.sqrtPriceNextX96) { if (step.initialized) { - if (!cache.computedLatestObservation) { - [cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128] = - Oracle.observeSingle( - poolState, - cache.blockTimestamp, - 0n, - slot0Start.tick, - slot0Start.observationIndex, - cache.liquidityStart, - slot0Start.observationCardinality, - ); - cache.computedLatestObservation = true; - } if (state.amountSpecifiedRemaining === 0n) { const castTickNext = Number(step.tickNext); @@ -197,9 +171,6 @@ function _priceComputationCycles( let liquidityNet = Tick.cross( ticksCopy, step.tickNext, - cache.secondsPerLiquidityCumulativeX128, - cache.tickCumulative, - cache.blockTimestamp, ); if (zeroForOne) liquidityNet = -liquidityNet; @@ -254,14 +225,6 @@ class UniswapV3Math { : TickMath.MAX_SQRT_RATIO - 1n; const cache: PriceComputationCache = { - liquidityStart: poolState.liquidity, - blockTimestamp: this._blockTimestamp(poolState), - feeProtocol: zeroForOne - ? slot0Start.feeProtocol % 16n - : slot0Start.feeProtocol >> 4n, - secondsPerLiquidityCumulativeX128: 0n, - tickCumulative: 0n, - computedLatestObservation: false, tickCount: 0, }; @@ -272,7 +235,7 @@ class UniswapV3Math { sqrtPriceX96: slot0Start.sqrtPriceX96, tick: slot0Start.tick, protocolFee: 0n, - liquidity: cache.liquidityStart, + liquidity: poolState.liquidity, isFirstCycleState: true, }; @@ -454,33 +417,17 @@ class UniswapV3Math { : step.sqrtPriceNextX96, state.liquidity, state.amountSpecifiedRemaining, - poolState.fee, + poolState.slot0.fee, ); state.sqrtPriceX96 = swapStepResult.sqrtRatioNextX96; if (state.sqrtPriceX96 == step.sqrtPriceNextX96) { if (step.initialized) { - if (!cache.computedLatestObservation) { - [cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128] = - Oracle.observeSingle( - poolState, - cache.blockTimestamp, - 0n, - slot0Start.tick, - slot0Start.observationIndex, - cache.liquidityStart, - slot0Start.observationCardinality, - ); - cache.computedLatestObservation = true; - } let liquidityNet = Tick.cross( poolState.ticks, step.tickNext, - cache.secondsPerLiquidityCumulativeX128, - cache.tickCumulative, - cache.blockTimestamp, ); if (zeroForOne) liquidityNet = -liquidityNet; @@ -497,26 +444,7 @@ class UniswapV3Math { } } - if (slot0Start.tick !== newTick) { - const [observationIndex, observationCardinality] = Oracle.write( - poolState, - slot0Start.observationIndex, - this._blockTimestamp(poolState), - slot0Start.tick, - poolState.liquidity, - slot0Start.observationCardinality, - slot0Start.observationCardinalityNext, - ); - - [ - poolState.slot0.sqrtPriceX96, - poolState.slot0.tick, - poolState.slot0.observationIndex, - poolState.slot0.observationCardinality, - ] = [newSqrtPriceX96, newTick, observationIndex, observationCardinality]; - } else { - poolState.slot0.sqrtPriceX96 = newSqrtPriceX96; - } + poolState.slot0.sqrtPriceX96 = newSqrtPriceX96; if (poolState.liquidity !== newLiquidity) poolState.liquidity = newLiquidity; @@ -533,7 +461,6 @@ class UniswapV3Math { params.tickLower, params.tickUpper, params.liquidityDelta, - _slot0.tick, ); let amount0 = 0n; @@ -548,17 +475,6 @@ class UniswapV3Math { } else if (_slot0.tick < params.tickUpper) { const liquidityBefore = state.liquidity; - [state.slot0.observationIndex, state.slot0.observationCardinality] = - Oracle.write( - state, - _slot0.observationIndex, - this._blockTimestamp(state), - _slot0.tick, - liquidityBefore, - _slot0.observationCardinality, - _slot0.observationCardinalityNext, - ); - amount0 = SqrtPriceMath._getAmount0DeltaO( _slot0.sqrtPriceX96, TickMath.getSqrtRatioAtTick(params.tickUpper), @@ -594,33 +510,18 @@ class UniswapV3Math { tickLower: bigint, tickUpper: bigint, liquidityDelta: bigint, - tick: bigint, ): void { // if we need to update the ticks, do it let flippedLower = false; let flippedUpper = false; if (liquidityDelta !== 0n) { const time = this._blockTimestamp(state); - const [tickCumulative, secondsPerLiquidityCumulativeX128] = - Oracle.observeSingle( - state, - time, - 0n, - state.slot0.tick, - state.slot0.observationIndex, - state.liquidity, - state.slot0.observationCardinality, - ); if (this._isTickToProcess(state, tickLower)) { flippedLower = Tick.update( state, tickLower, - tick, liquidityDelta, - secondsPerLiquidityCumulativeX128, - tickCumulative, - time, false, state.maxLiquidityPerTick, ); @@ -629,11 +530,7 @@ class UniswapV3Math { flippedUpper = Tick.update( state, tickUpper, - tick, liquidityDelta, - secondsPerLiquidityCumulativeX128, - tickCumulative, - time, true, state.maxLiquidityPerTick, ); From 0b78917643cbf9f5f7a23081eacdb354a846f2ec Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Wed, 20 Sep 2023 00:02:19 -0400 Subject: [PATCH 316/833] readd uniswap's Oracle.ts --- src/dex/uniswap-v3/contract-math/Oracle.ts | 226 +++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 src/dex/uniswap-v3/contract-math/Oracle.ts diff --git a/src/dex/uniswap-v3/contract-math/Oracle.ts b/src/dex/uniswap-v3/contract-math/Oracle.ts new file mode 100644 index 000000000..ef17f079a --- /dev/null +++ b/src/dex/uniswap-v3/contract-math/Oracle.ts @@ -0,0 +1,226 @@ +import { + OracleObservation, + OracleObservationCandidates, + PoolState, +} from '../types'; +import { _require } from '../../../utils'; +import { DeepReadonly } from 'ts-essentials'; +import { ZERO_ORACLE_OBSERVATION } from '../constants'; + +function replaceUndefinedObservationWithZero(state: PoolState, index: number) { + if (state.observations[index] === undefined) { + state.observations[index] = { ...ZERO_ORACLE_OBSERVATION }; + } +} + +export class Oracle { + static transform( + state: DeepReadonly, + last: OracleObservation, + blockTimestamp: bigint, + tick: bigint, + liquidity: bigint, + ): OracleObservation { + const delta = blockTimestamp - last.blockTimestamp; + return { + blockTimestamp: state.blockTimestamp, + tickCumulative: last.tickCumulative + BigInt.asIntN(56, tick) * delta, + secondsPerLiquidityCumulativeX128: + last.secondsPerLiquidityCumulativeX128 + + (BigInt.asUintN(160, delta) << 128n) / + (liquidity > 0n ? liquidity : 1n), + initialized: true, + }; + } + + static write( + state: PoolState, + index: number, + blockTimestamp: bigint, + tick: bigint, + liquidity: bigint, + cardinality: number, + cardinalityNext: number, + ): [number, number] { + const last = state.observations[index]; + + if (last.blockTimestamp == state.blockTimestamp) + return [index, cardinality]; + + let indexUpdated = 0; + let cardinalityUpdated = 0; + + if (cardinalityNext > cardinality && index == cardinality - 1) { + cardinalityUpdated = cardinalityNext; + } else { + cardinalityUpdated = cardinality; + } + + indexUpdated = (index + 1) % cardinalityUpdated; + + state.observations[indexUpdated] = Oracle.transform( + state, + last, + blockTimestamp, + tick, + liquidity, + ); + if (indexUpdated !== index) { + delete state.observations[index]; + } + return [indexUpdated, cardinalityUpdated]; + } + + static lte(time: bigint, a: bigint, b: bigint): boolean { + if (a <= time && b <= time) return a <= b; + + const aAdjusted = a > time ? a : a + 2n ** 32n; + const bAdjusted = b > time ? b : b + 2n ** 32n; + return aAdjusted <= bAdjusted; + } + + static binarySearch( + state: DeepReadonly, + time: bigint, + target: bigint, + index: number, + cardinality: number, + ): OracleObservationCandidates { + let l = (index + 1) % cardinality; + let r = l + cardinality - 1; + let i; + + let beforeOrAt; + let atOrAfter; + while (true) { + i = (l + r) / 2; + + beforeOrAt = state.observations[i % cardinality]; + + // we've landed on an uninitialized tick, keep searching higher (more recently) + if (!beforeOrAt.initialized) { + l = i + 1; + continue; + } + + atOrAfter = state.observations[(i + 1) % cardinality]; + + const targetAtOrAfter = Oracle.lte( + time, + beforeOrAt.blockTimestamp, + target, + ); + + // check if we've found the answer! + if (targetAtOrAfter && Oracle.lte(time, target, atOrAfter.blockTimestamp)) + break; + + if (!targetAtOrAfter) r = i - 1; + else l = i + 1; + } + return { beforeOrAt, atOrAfter }; + } + + static getSurroundingObservations( + state: DeepReadonly, + time: bigint, + target: bigint, + tick: bigint, + index: number, + liquidity: bigint, + cardinality: number, + ): OracleObservationCandidates { + let beforeOrAt = state.observations[index]; + + if (Oracle.lte(time, beforeOrAt.blockTimestamp, target)) { + if (beforeOrAt.blockTimestamp === target) { + return { beforeOrAt, atOrAfter: beforeOrAt }; + } else { + return { + beforeOrAt, + atOrAfter: Oracle.transform( + state, + beforeOrAt, + target, + tick, + liquidity, + ), + }; + } + } + + beforeOrAt = state.observations[(index + 1) % cardinality]; + if (!beforeOrAt.initialized) beforeOrAt = state.observations[0]; + + _require( + Oracle.lte(time, beforeOrAt.blockTimestamp, target), + 'OLD', + { time, beforeOrAtBlockTimestamp: beforeOrAt.blockTimestamp, target }, + 'Oracle.lte(time, beforeOrAt.blockTimestamp, target)', + ); + + return Oracle.binarySearch(state, time, target, index, cardinality); + } + + static observeSingle( + state: DeepReadonly, + time: bigint, + secondsAgo: bigint, + tick: bigint, + index: number, + liquidity: bigint, + cardinality: number, + ): [bigint, bigint] { + if (secondsAgo == 0n) { + let last = state.observations[index]; + if (last.blockTimestamp != time) + last = Oracle.transform(state, last, time, tick, liquidity); + return [last.tickCumulative, last.secondsPerLiquidityCumulativeX128]; + } + + const target = time - secondsAgo; + + const { beforeOrAt, atOrAfter } = Oracle.getSurroundingObservations( + state, + time, + target, + tick, + index, + liquidity, + cardinality, + ); + + if (target === beforeOrAt.blockTimestamp) { + return [ + beforeOrAt.tickCumulative, + beforeOrAt.secondsPerLiquidityCumulativeX128, + ]; + } else if (target === atOrAfter.blockTimestamp) { + return [ + atOrAfter.tickCumulative, + atOrAfter.secondsPerLiquidityCumulativeX128, + ]; + } else { + const observationTimeDelta = + atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp; + const targetDelta = target - beforeOrAt.blockTimestamp; + return [ + beforeOrAt.tickCumulative + + ((atOrAfter.tickCumulative - beforeOrAt.tickCumulative) / + observationTimeDelta) * + targetDelta, + beforeOrAt.secondsPerLiquidityCumulativeX128 + + BigInt.asUintN( + 160, + (BigInt.asUintN( + 256, + atOrAfter.secondsPerLiquidityCumulativeX128 - + beforeOrAt.secondsPerLiquidityCumulativeX128, + ) * + targetDelta) / + observationTimeDelta, + ), + ]; + } + } +} From 102e571d1cb32837caed752f867004e940faa08c Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Wed, 20 Sep 2023 00:02:30 -0400 Subject: [PATCH 317/833] some typing --- src/dex/solidly-v3/contract-math/utils.ts | 5 ----- src/dex/solidly-v3/solidly-v3-pool.ts | 1 - 2 files changed, 6 deletions(-) diff --git a/src/dex/solidly-v3/contract-math/utils.ts b/src/dex/solidly-v3/contract-math/utils.ts index 65d97736d..6f0960ccd 100644 --- a/src/dex/solidly-v3/contract-math/utils.ts +++ b/src/dex/solidly-v3/contract-math/utils.ts @@ -42,11 +42,6 @@ export function _reduceTicks( acc[index] = { liquidityGross: bigIntify(value.liquidityGross), liquidityNet: bigIntify(value.liquidityNet), - tickCumulativeOutside: bigIntify(value.tickCumulativeOutside), - secondsPerLiquidityOutsideX128: bigIntify( - value.secondsPerLiquidityOutsideX128, - ), - secondsOutside: bigIntify(value.secondsOutside), initialized: value.initialized, }; } diff --git a/src/dex/solidly-v3/solidly-v3-pool.ts b/src/dex/solidly-v3/solidly-v3-pool.ts index 197ce90f1..96e285de8 100644 --- a/src/dex/solidly-v3/solidly-v3-pool.ts +++ b/src/dex/solidly-v3/solidly-v3-pool.ts @@ -296,7 +296,6 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { fee: bigIntify(_state.slot0.fee), }, liquidity: bigIntify(_state.liquidity), - fee: fee, tickSpacing, maxLiquidityPerTick: bigIntify(_state.maxLiquidityPerTick), tickBitmap, From 9bc6b09b4a5980337bcc8645c80af867dc444d0d Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Wed, 20 Sep 2023 00:19:25 -0400 Subject: [PATCH 318/833] use SolidlyV3StateMulticallABI --- src/abi/solidly-v3/SolidlyV3StateMulticall.abi.json | 1 + src/dex/solidly-v3/solidly-v3.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 src/abi/solidly-v3/SolidlyV3StateMulticall.abi.json diff --git a/src/abi/solidly-v3/SolidlyV3StateMulticall.abi.json b/src/abi/solidly-v3/SolidlyV3StateMulticall.abi.json new file mode 100644 index 000000000..5eb67b60c --- /dev/null +++ b/src/abi/solidly-v3/SolidlyV3StateMulticall.abi.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"contract IUniswapV3Factory","name":"factory","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"int16","name":"tickBitmapStart","type":"int16"},{"internalType":"int16","name":"tickBitmapEnd","type":"int16"}],"name":"getAdditionalBitmapWithTicks","outputs":[{"components":[{"internalType":"int16","name":"index","type":"int16"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IUniswapV3StateMulticall.TickBitMapMappings[]","name":"tickBitmap","type":"tuple[]"},{"components":[{"internalType":"int24","name":"index","type":"int24"},{"components":[{"internalType":"uint128","name":"liquidityGross","type":"uint128"},{"internalType":"int128","name":"liquidityNet","type":"int128"},{"internalType":"bool","name":"initialized","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.TickInfo","name":"value","type":"tuple"}],"internalType":"struct IUniswapV3StateMulticall.TickInfoMappings[]","name":"ticks","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IUniswapV3Factory","name":"factory","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"int16","name":"tickBitmapStart","type":"int16"},{"internalType":"int16","name":"tickBitmapEnd","type":"int16"}],"name":"getAdditionalBitmapWithoutTicks","outputs":[{"components":[{"internalType":"int16","name":"index","type":"int16"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IUniswapV3StateMulticall.TickBitMapMappings[]","name":"tickBitmap","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IUniswapV3Factory","name":"factory","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"int16","name":"tickBitmapStart","type":"int16"},{"internalType":"int16","name":"tickBitmapEnd","type":"int16"}],"name":"getFullState","outputs":[{"components":[{"internalType":"contract IUniswapV3Pool","name":"pool","type":"address"},{"internalType":"uint256","name":"blockTimestamp","type":"uint256"},{"components":[{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"bool","name":"unlocked","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.Slot0","name":"slot0","type":"tuple"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"uint128","name":"maxLiquidityPerTick","type":"uint128"},{"components":[{"internalType":"int16","name":"index","type":"int16"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IUniswapV3StateMulticall.TickBitMapMappings[]","name":"tickBitmap","type":"tuple[]"},{"components":[{"internalType":"int24","name":"index","type":"int24"},{"components":[{"internalType":"uint128","name":"liquidityGross","type":"uint128"},{"internalType":"int128","name":"liquidityNet","type":"int128"},{"internalType":"bool","name":"initialized","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.TickInfo","name":"value","type":"tuple"}],"internalType":"struct IUniswapV3StateMulticall.TickInfoMappings[]","name":"ticks","type":"tuple[]"}],"internalType":"struct IUniswapV3StateMulticall.StateResult","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IUniswapV3Factory","name":"factory","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"int16","name":"leftBitmapAmount","type":"int16"},{"internalType":"int16","name":"rightBitmapAmount","type":"int16"}],"name":"getFullStateWithRelativeBitmaps","outputs":[{"components":[{"internalType":"contract IUniswapV3Pool","name":"pool","type":"address"},{"internalType":"uint256","name":"blockTimestamp","type":"uint256"},{"components":[{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"bool","name":"unlocked","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.Slot0","name":"slot0","type":"tuple"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"uint128","name":"maxLiquidityPerTick","type":"uint128"},{"components":[{"internalType":"int16","name":"index","type":"int16"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IUniswapV3StateMulticall.TickBitMapMappings[]","name":"tickBitmap","type":"tuple[]"},{"components":[{"internalType":"int24","name":"index","type":"int24"},{"components":[{"internalType":"uint128","name":"liquidityGross","type":"uint128"},{"internalType":"int128","name":"liquidityNet","type":"int128"},{"internalType":"bool","name":"initialized","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.TickInfo","name":"value","type":"tuple"}],"internalType":"struct IUniswapV3StateMulticall.TickInfoMappings[]","name":"ticks","type":"tuple[]"}],"internalType":"struct IUniswapV3StateMulticall.StateResult","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IUniswapV3Factory","name":"factory","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"int16","name":"tickBitmapStart","type":"int16"},{"internalType":"int16","name":"tickBitmapEnd","type":"int16"}],"name":"getFullStateWithoutTicks","outputs":[{"components":[{"internalType":"contract IUniswapV3Pool","name":"pool","type":"address"},{"internalType":"uint256","name":"blockTimestamp","type":"uint256"},{"components":[{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"bool","name":"unlocked","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.Slot0","name":"slot0","type":"tuple"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"uint128","name":"maxLiquidityPerTick","type":"uint128"},{"components":[{"internalType":"int16","name":"index","type":"int16"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IUniswapV3StateMulticall.TickBitMapMappings[]","name":"tickBitmap","type":"tuple[]"},{"components":[{"internalType":"int24","name":"index","type":"int24"},{"components":[{"internalType":"uint128","name":"liquidityGross","type":"uint128"},{"internalType":"int128","name":"liquidityNet","type":"int128"},{"internalType":"bool","name":"initialized","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.TickInfo","name":"value","type":"tuple"}],"internalType":"struct IUniswapV3StateMulticall.TickInfoMappings[]","name":"ticks","type":"tuple[]"}],"internalType":"struct IUniswapV3StateMulticall.StateResult","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index 5a28f7ecc..cd83d453f 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -45,7 +45,7 @@ import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; import DirectSwapABI from '../../abi/DirectSwap.json'; -import UniswapV3StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; +import SolidlyV3StateMulticallABI from '../../abi/solidly-v3/SolidlyV3StateMulticall.abi.json'; import { DirectMethods, UNISWAPV3_EFFICIENCY_FACTOR, @@ -126,7 +126,7 @@ export class SolidlyV3 this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( this.config.stateMultiCallAbi !== undefined ? this.config.stateMultiCallAbi - : (UniswapV3StateMulticallABI as AbiItem[]), + : (SolidlyV3StateMulticallABI as AbiItem[]), this.config.stateMulticall, ); From f7043f5a352b98ecb144b50d2a9cf6ebe0229d0d Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Wed, 20 Sep 2023 00:45:06 -0400 Subject: [PATCH 319/833] use poolAddress instead of quoter --- src/dex/solidly-v3/solidly-v3-pool.ts | 2 +- src/dex/solidly-v3/solidly-v3.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-pool.ts b/src/dex/solidly-v3/solidly-v3-pool.ts index 96e285de8..eae03747b 100644 --- a/src/dex/solidly-v3/solidly-v3-pool.ts +++ b/src/dex/solidly-v3/solidly-v3-pool.ts @@ -48,7 +48,7 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { readonly token1: Address; - private _poolAddress?: Address; + public _poolAddress?: Address; private _stateRequestCallData?: MultiCallParams< bigint | DecodedStateMultiCallResultWithRelativeBitmaps diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index cd83d453f..3ab2d70be 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -436,7 +436,7 @@ export class SolidlyV3 const calldata = pools.map(pool => _amounts.map(_amount => ({ - target: this.config.quoter, + target: pool._poolAddress, gasLimit: UNISWAPV3_QUOTE_GASLIMIT, callData: side === SwapSide.SELL From 695f5b18abb6ad0c4b3272373f65ab70a0175162 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 20 Sep 2023 15:02:07 +0100 Subject: [PATCH 320/833] feat: update contract addresses --- src/config.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/config.ts b/src/config.ts index 9a35f8fd7..dc8edea4b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -50,9 +50,9 @@ const baseConfigs: { [network: number]: BaseConfig } = { adapterAddresses: { Adapter01: '0x9bE264469eF954c139Da4A45Cf76CbCC5e3A6A73', Adapter02: '0xFC2Ba6E830a04C25e207B8214b26d8C713F6881F', - Adapter03: '0x7c7f62e5ba00783f57b39df0530e32c195696a57', + Adapter03: '0xfb2a3de6c7B8c77b520E3da16021f3D8A4E93168', Adapter04: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', - BuyAdapter: '0xDCf4EE5B700e2a5Fec458e06B763A4a3E3004494', + BuyAdapter: '0x613876f3dE2Ec633f8054fE7a561324c1a01d9cB', }, uniswapV2ExchangeRouterAddress: '0xF9234CB08edb93c0d4a4d4c70cC3FfD070e78e07', @@ -163,8 +163,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_56`]?.split(',') || [], adapterAddresses: { BscAdapter01: '0xA31d9C571DF00e0F428B0bD24c34D103E8112222', - BscAdapter02: '0x1d2Fd92a1942A92a51198168eFCd626ed441CEC0', - BscBuyAdapter: '0x64C856fafE4C83a818514cBDfD661a3563a71B98', + BscAdapter02: '0x02f2c31ebDE63E871AD0E74c01E21c819292a59D', + BscBuyAdapter: '0x301c2813e3ceb43A448a12f21551EDBcdC37F157', }, rpcPollingMaxAllowedStateDelayInBlocks: 1, rpcPollingBlocksBackToTriggerUpdate: 1, @@ -221,8 +221,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_43114`]?.split(',') || [], adapterAddresses: { AvalancheAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9', - AvalancheAdapter02: '0xDCf4EE5B700e2a5Fec458e06B763A4a3E3004494', - AvalancheBuyAdapter: '0x7ebbDBB57d2ab59079423cf8337cf8805e225bB1', + AvalancheAdapter02: '0xFb8773AA4Fd02e54bbd352061D8Be1911FAa210a', + AvalancheBuyAdapter: '0x434C1Cca4842629230067674Dd54E21a14D9FD5D', }, uniswapV2ExchangeRouterAddress: '0x53e693c6C7FFC4446c53B205Cf513105Bf140D7b', @@ -276,9 +276,9 @@ const baseConfigs: { [network: number]: BaseConfig } = { hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], adapterAddresses: { - ArbitrumAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9', - ArbitrumAdapter02: '0x3ad7f275E27AC579cA88e0b4765828242A9E8C49', - ArbitrumBuyAdapter: '0x6c33C7f6CBB4a428fe9ee31ca500a787c9f1525b', + ArbitrumAdapter01: '0xD8134ACfc9c71Ab51452b5bA23A31354F4739032', + ArbitrumAdapter02: '0xD1F70c98a78d48A93F0B4dDa49057469dc5aC126', + ArbitrumBuyAdapter: '0x434C1Cca4842629230067674Dd54E21a14D9FD5D', }, uniswapV2ExchangeRouterAddress: '0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC', @@ -306,8 +306,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_10`]?.split(',') || [], adapterAddresses: { - OptimismAdapter01: '0x4669D27A649f5451e0D44C20a2b246431F1B0572', - OptimismBuyAdapter: '0xb2634B3CBc1E401AB3C2743DB44d459C5c9aA662', + OptimismAdapter01: '0x3ad7f275E27AC579cA88e0b4765828242A9E8C49', + OptimismBuyAdapter: '0xfdDD975FE4c1af20c24A3Ad2b33e8609a62DDC73', }, uniswapV2ExchangeRouterAddress: '0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC', From 7fdb68c22d30242b12aa8fee4f4813d10a07219b Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Wed, 20 Sep 2023 15:39:46 -0400 Subject: [PATCH 321/833] fix tuple decoding --- src/dex/solidly-v3/utils.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/dex/solidly-v3/utils.ts b/src/dex/solidly-v3/utils.ts index afd953e07..c5a39349a 100644 --- a/src/dex/solidly-v3/utils.ts +++ b/src/dex/solidly-v3/utils.ts @@ -42,21 +42,12 @@ export function decodeStateMultiCallResultWithRelativeBitmaps( tuple( uint160 sqrtPriceX96, int24 tick, - uint16 observationIndex, - uint16 observationCardinality, - uint16 observationCardinalityNext, - uint8 feeProtocol, + uint24 fee, bool unlocked, ) slot0, uint128 liquidity, int24 tickSpacing, uint128 maxLiquidityPerTick, - tuple( - uint32 blockTimestamp, - int56 tickCumulative, - uint160 secondsPerLiquidityCumulativeX128, - bool initialized, - ) observation, tuple( int16 index, uint256 value, @@ -66,9 +57,6 @@ export function decodeStateMultiCallResultWithRelativeBitmaps( tuple( uint128 liquidityGross, int128 liquidityNet, - int56 tickCumulativeOutside, - uint160 secondsPerLiquidityOutsideX128, - uint32 secondsOutside, bool initialized, ) value, )[] ticks From ecb72212d41b8a36cff24ea15ba1b5e6a58862a9 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Wed, 20 Sep 2023 21:26:23 -0400 Subject: [PATCH 322/833] add checkPoolPrices to integration test --- src/dex/solidly-v3/solidly-v3-integration.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index ac42cbd94..00566a1d7 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -233,6 +233,9 @@ describe('SolidlyV3', function () { pools, ); console.log(`WETH <> USDT Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); }); it('getPoolIdentifiers and getPricesVolume SELL', async function () { From 16038b911acb79d5d3446750d84ab3a5353f4e99 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 03:15:09 -0400 Subject: [PATCH 323/833] continue, broken equal assertion here --- src/dex/solidly-v3/constants.ts | 2 + .../solidly-v3/solidly-v3-integration.test.ts | 117 +++++++++++++----- 2 files changed, 87 insertions(+), 32 deletions(-) diff --git a/src/dex/solidly-v3/constants.ts b/src/dex/solidly-v3/constants.ts index e625c3882..96423f6d1 100644 --- a/src/dex/solidly-v3/constants.ts +++ b/src/dex/solidly-v3/constants.ts @@ -39,3 +39,5 @@ export enum DirectMethods { directSell = 'directUniV3Swap', directBuy = 'directUniV3Buy', } +export const MIN_SQRT_RATIO = BigInt(4295128739); +export const MAX_SQRT_RATIO = BigInt(1461446703485210103287273052203988822378723970342); \ No newline at end of file diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 00566a1d7..6afec6081 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -3,16 +3,19 @@ import dotenv from 'dotenv'; dotenv.config(); import { Interface, Result } from '@ethersproject/abi'; -import { DummyDexHelper } from '../../dex-helper/index'; +import {DummyDexHelper, IDexHelper} from '../../dex-helper/index'; import { Network, SwapSide } from '../../constants'; import { BI_POWS } from '../../bigint-constants'; import { SolidlyV3 } from './solidly-v3'; +import { MIN_SQRT_RATIO, MAX_SQRT_RATIO } from "./constants"; import { checkPoolPrices, checkPoolsLiquidity, checkConstantPoolPrices, } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; +import {Address} from "@paraswap/core"; +import SolidlyV3PoolABI from '../../abi/solidly-v3/SolidlyV3Pool.abi.json'; /* README @@ -34,14 +37,12 @@ function getReaderCalldata( readerIface: Interface, amounts: bigint[], funcName: string, - // TODO: Put here additional arguments you need + zeroForOne: boolean, + sqrtPriceLimitX96: bigint, ) { return amounts.map(amount => ({ target: exchangeAddress, - callData: readerIface.encodeFunctionData(funcName, [ - // TODO: Put here additional arguments to encode them - amount, - ]), + callData: readerIface.encodeFunctionData(funcName, [zeroForOne, amount.toString(), sqrtPriceLimitX96.toString()]), })); } @@ -58,37 +59,68 @@ function decodeReaderResult( } async function checkOnChainPricing( - solidlyV3: SolidlyV3, - funcName: string, + dexHelper: IDexHelper, blockNumber: number, + poolAddress: string, prices: bigint[], - amounts: bigint[], + tokenIn: Address, + tokenOut: Address, + tickSpacing: bigint, + _amounts: bigint[], ) { - const exchangeAddress = ''; // TODO: Put here the real exchange address + // Quoter address + // const exchangeAddress = '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'; + const readerIface = new Interface(SolidlyV3PoolABI); - // TODO: Replace dummy interface with the real one - // Normally you can get it from solidlyV3.Iface or from eventPool. - // It depends on your implementation - const readerIface = new Interface(''); + const sum = prices.reduce((acc, curr) => (acc += curr), 0n); + + if (sum === 0n) { + console.log( + `Prices were not calculated for tokenIn=${tokenIn}, tokenOut=${tokenOut}, tickSpacing=${tickSpacing.toString()}. Most likely price impact is too big for requested amount`, + ); + return false; + } const readerCallData = getReaderCalldata( - exchangeAddress, + poolAddress, readerIface, - amounts.slice(1), - funcName, + _amounts.slice(1), + 'quoteSwap', + true, + MIN_SQRT_RATIO + BigInt(1), ); - // const readerResult = ( - // await solidlyV3.dexHelper.multiContract.methods - // .aggregate(readerCallData) - // .call({}, blockNumber) - // ).returnData; - const readerResult: any[] = []; + + let readerResult; + try { + readerResult = ( + await dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blockNumber) + ).returnData; + } catch (e) { + console.log( + `Can not fetch on-chain pricing for tickSpacing ${tickSpacing}. It happens for low liquidity pools`, + e, + ); + return false; + } const expectedPrices = [0n].concat( - decodeReaderResult(readerResult, readerIface, funcName), + decodeReaderResult(readerResult, readerIface, 'quoteSwap'), ); - expect(prices).toEqual(expectedPrices); + console.log('EXPECTED PRICES: ', expectedPrices); + + let firstZeroIndex = prices.slice(1).indexOf(0n); + + // we skipped first, so add +1 on result + firstZeroIndex = firstZeroIndex === -1 ? prices.length : firstZeroIndex; + + // Compare only the ones for which we were able to calculate prices + expect(prices.slice(0, firstZeroIndex)).toEqual( + expectedPrices.slice(0, firstZeroIndex), + ); + return true; } async function testPricingOnNetwork( @@ -138,13 +170,13 @@ async function testPricingOnNetwork( } // Check if onchain pricing equals to calculated ones - await checkOnChainPricing( - solidlyV3, - funcNameToCheck, - blockNumber, - poolPrices![0].prices, - amounts, - ); + // await checkOnChainPricing( + // solidlyV3, + // funcNameToCheck, + // blockNumber, + // poolPrices![0].prices, + // amounts, + // ); } describe('SolidlyV3', function () { @@ -236,6 +268,27 @@ describe('SolidlyV3', function () { expect(poolPrices).not.toBeNull(); checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const tickSpacing = solidlyV3.eventPools[price.poolIdentifier!]!.tickSpacing; + const res = await checkOnChainPricing( + dexHelper, + blockNumber, + solidlyV3.eventPools[price.poolIdentifier!]!.poolAddress, + price.prices, + // TODO: don't hardcode tokens + '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', + '0xdac17f958d2ee523a2206206994597c13d831ec7', + tickSpacing, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); }); it('getPoolIdentifiers and getPricesVolume SELL', async function () { From b5769eef1e0eb844236ed49596e300842e416368 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 03:24:18 -0400 Subject: [PATCH 324/833] fix hex parsing for decoder --- src/dex/solidly-v3/solidly-v3-integration.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 6afec6081..ddf865b11 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -54,7 +54,7 @@ function decodeReaderResult( // TODO: Adapt this function for your needs return results.map(result => { const parsed = readerIface.decodeFunctionResult(funcName, result); - return BigInt(parsed[0]._hex); + return parsed[1]._hex[0] == '-' ? BigInt(parsed[1]._hex.slice(1)) : BigInt(parsed[1]._hex); }); } From d110722b4dc70de7b7c8d14fea05f4a581de779e Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 03:51:20 -0400 Subject: [PATCH 325/833] don't hardcode tokens --- src/dex/solidly-v3/solidly-v3-integration.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index ddf865b11..950d1282e 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -278,9 +278,8 @@ describe('SolidlyV3', function () { blockNumber, solidlyV3.eventPools[price.poolIdentifier!]!.poolAddress, price.prices, - // TODO: don't hardcode tokens - '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', - '0xdac17f958d2ee523a2206206994597c13d831ec7', + WETH.address, + USDT.address, tickSpacing, amounts, ); From 67f7f7d6bdc2e7492df7ab760d72c7508f192f2c Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 03:56:32 -0400 Subject: [PATCH 326/833] reorder some code --- .../solidly-v3/solidly-v3-integration.test.ts | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 950d1282e..4ef29192b 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -32,6 +32,14 @@ import SolidlyV3PoolABI from '../../abi/solidly-v3/SolidlyV3Pool.abi.json'; (This comment should be removed from the final implementation) */ +const network = Network.MAINNET; +const dexHelper = new DummyDexHelper(network); + +const WETH = Tokens[network]['WETH']; +const USDT = Tokens[network]['USDT']; + +const amounts = [0n, 1n * BI_POWS[18], 2n * BI_POWS[18]]; + function getReaderCalldata( exchangeAddress: string, readerIface: Interface, @@ -184,6 +192,11 @@ describe('SolidlyV3', function () { let blockNumber: number; let solidlyV3: SolidlyV3; + beforeEach(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const solidlyV3 = new SolidlyV3(network, dexKey, dexHelper); + }); + describe('Mainnet', () => { const network = Network.MAINNET; const dexHelper = new DummyDexHelper(network); @@ -236,15 +249,6 @@ describe('SolidlyV3', function () { }); it('WETH -> USDT getPoolIdentifiers and getPricesVolume SELL', async function () { - const network = Network.MAINNET; - const dexHelper = new DummyDexHelper(network); - const blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - const solidlyV3 = new SolidlyV3(network, dexKey, dexHelper); - - const WETH = Tokens[network]['WETH']; - const USDT = Tokens[network]['USDT']; - - const amounts = [0n, 1n * BI_POWS[18], 2n * BI_POWS[18]]; const pools = await solidlyV3.getPoolIdentifiers( WETH, From 30363e0f4f634cefe3067f64c7d4b7283919f8f7 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 03:57:57 -0400 Subject: [PATCH 327/833] delete some stuff --- .../solidly-v3/solidly-v3-integration.test.ts | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 4ef29192b..bbbf41d8b 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -244,11 +244,7 @@ describe('SolidlyV3', function () { } }); - it('base case', async function () { - console.log('base case'); - }); - - it('WETH -> USDT getPoolIdentifiers and getPricesVolume SELL', async function () { + it('getPoolIdentifiers and getPricesVolume SELL', async function () { const pools = await solidlyV3.getPoolIdentifiers( WETH, @@ -294,20 +290,6 @@ describe('SolidlyV3', function () { expect(falseChecksCounter).toBeLessThan(poolPrices!.length); }); - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - await testPricingOnNetwork( - solidlyV3, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.SELL, - amountsForSell, - '', // TODO: Put here proper function name to check pricing - ); - }); - it('getPoolIdentifiers and getPricesVolume BUY', async function () { await testPricingOnNetwork( solidlyV3, From a3037373581f5d6f7ba0479862dffafaa30a69f1 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 04:31:01 -0400 Subject: [PATCH 328/833] start getPoolIdentifiers and getPricesVolume BUY --- .../solidly-v3/solidly-v3-integration.test.ts | 49 ++++++++++++++++--- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index bbbf41d8b..5de00bac1 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -39,6 +39,8 @@ const WETH = Tokens[network]['WETH']; const USDT = Tokens[network]['USDT']; const amounts = [0n, 1n * BI_POWS[18], 2n * BI_POWS[18]]; +// Sell WETH to receive 1000 USDT, 2000 UDST, and 3000 USDT +const amountsBuy = [0n, 1000n * BI_POWS[6], 2000n * BI_POWS[6], 3000n * BI_POWS[6]]; function getReaderCalldata( exchangeAddress: string, @@ -291,17 +293,48 @@ describe('SolidlyV3', function () { }); it('getPoolIdentifiers and getPricesVolume BUY', async function () { - await testPricingOnNetwork( - solidlyV3, - network, - dexKey, + const pools = await solidlyV3.getPoolIdentifiers( + WETH, + USDT, + SwapSide.BUY, blockNumber, - srcTokenSymbol, - destTokenSymbol, + ); + console.log(`WETH <> USDT Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await solidlyV3.getPricesVolume( + WETH, + USDT, + amountsBuy, SwapSide.BUY, - amountsForBuy, - '', // TODO: Put here proper function name to check pricing + blockNumber, + pools, ); + console.log(`WETH <> USDT Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amountsBuy, SwapSide.BUY, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const tickSpacing = solidlyV3.eventPools[price.poolIdentifier!]!.tickSpacing; + const res = await checkOnChainPricing( + dexHelper, + blockNumber, + solidlyV3.eventPools[price.poolIdentifier!]!.poolAddress, + price.prices, + WETH.address, + USDT.address, + tickSpacing, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); }); it('getTopPoolsForToken', async function () { From 06afc92712be29d8d666b9122ff11d5d5f5614f3 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 21 Sep 2023 12:22:04 +0300 Subject: [PATCH 329/833] BACK-1288: fix RamsesV2 0.005% fee tier pools routing --- src/dex/uniswap-v3/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index 116c7c7e7..0cbc23907 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -233,7 +233,7 @@ export const UniswapV3Config: DexConfigMap = { deployer: '0xb3e423ab9cE6C03D98326A3A2a0D7D96b0829f22', quoter: '0xAA20EFF7ad2F523590dE6c04918DaAE0904E3b20', router: '0xAA23611badAFB62D37E7295A682D21960ac85A90', - supportedFees: SUPPORTED_FEES, + supportedFees: [...SUPPORTED_FEES, 50n], stateMulticall: '0x50EE4112Cab9c79812F23bE079aB3911395ACc8e', stateMultiCallAbi: RamsesV2StateMulticallABI as AbiItem[], uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', From c597d9990813fe12cffa7d5cf3ba0b38b29b7671 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 21 Sep 2023 12:25:00 +0300 Subject: [PATCH 330/833] 2.35.6-ramses-v2-50-fee-pools-bug --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ac433ac0..e9a8f7bae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.5", + "version": "2.35.6-ramses-v2-50-fee-pools-bug", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e7f5fb9cb4467897889587031ab26776c74e173c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 21 Sep 2023 16:00:43 +0300 Subject: [PATCH 331/833] BACK-1298: add Maverick on Base chain --- src/dex/maverick-v1/config.ts | 10 ++ src/dex/maverick-v1/maverick-v1-e2e.test.ts | 122 +++++++++++++++++++- tests/constants-e2e.ts | 15 +++ 3 files changed, 146 insertions(+), 1 deletion(-) diff --git a/src/dex/maverick-v1/config.ts b/src/dex/maverick-v1/config.ts index bd85811b8..90d1489f5 100644 --- a/src/dex/maverick-v1/config.ts +++ b/src/dex/maverick-v1/config.ts @@ -14,6 +14,12 @@ export const MaverickV1Config: DexConfigMap = { routerAddress: '0x4a585e0f7c18e2c414221d6402652d5e0990e5f8', poolInspectorAddress: '0xaA5BF61a664109e959D69C38734d4EA7dF74e456', }, + [Network.BASE]: { + subgraphURL: + 'https://api.studio.thegraph.com/query/42519/maverick-base/version/latest', + routerAddress: '0x32AED3Bce901DA12ca8489788F3A99fCe1056e14', + poolInspectorAddress: '0x550056A68cB155b6Cc3DeF4A7FA656260e7842e2', + }, }, }; @@ -22,4 +28,8 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'Adapter04', index: 2 }], [SwapSide.BUY]: [{ name: 'BuyAdapter', index: 8 }], }, + [Network.BASE]: { + [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 2 }], + [SwapSide.BUY]: [{ name: 'BaseBuyAdapter', index: 2 }], + }, }; diff --git a/src/dex/maverick-v1/maverick-v1-e2e.test.ts b/src/dex/maverick-v1/maverick-v1-e2e.test.ts index eebb6f57c..8f4c76a8e 100644 --- a/src/dex/maverick-v1/maverick-v1-e2e.test.ts +++ b/src/dex/maverick-v1/maverick-v1-e2e.test.ts @@ -11,10 +11,109 @@ import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, + slippage?: number | undefined, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ], + ], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + 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, + 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, + network, + provider, + undefined, + undefined, + undefined, + slippage, + ); + }); + }); + }); + }), + ); + }); +} + describe('MaverickV1 E2E', () => { const dexKey = 'MaverickV1'; - describe('MaverickV1 MAINNET', () => { + describe('MAINNET', () => { const network = Network.MAINNET; const tokens = Tokens[network]; const holders = Holders[network]; @@ -121,4 +220,25 @@ describe('MaverickV1 E2E', () => { ); }); }); + + describe('BASE', () => { + const network = Network.BASE; + + const tokenASymbol: string = 'USDbC'; + const tokenBSymbol: string = 'MAV'; + + const tokenAAmount: string = '1111100000'; + const tokenBAmount: string = '1100000000000000000'; + const nativeTokenAmount = '100000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); }); diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 069890872..e7d06f50a 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -892,6 +892,18 @@ export const Tokens: { address: '0x4200000000000000000000000000000000000006', decimals: 18, }, + MAV: { + address: '0x64b88c73A5DfA78D1713fE1b4c69a22d7E0faAa7', + decimals: 18, + }, + USDC: { + address: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913', + decimals: 6, + }, + USDbC: { + address: '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA', + decimals: 6, + }, ETH: { address: ETHER_ADDRESS, decimals: 18 }, }, }; @@ -1117,6 +1129,9 @@ export const Holders: { WETH: '0x4bb6b2efe7036020ba6f02a05602546c9f25bf28', PRIME: '0x956bcc6b56c99db382d9d97a30ba5f1402144b3e', ETH: '0xdd9176ea3e7559d6b68b537ef555d3e89403f742', + MAV: '0x7499785aa5d1bdf0a0ac862c1ef3698d3cba6568', + USDC: '0xaac391f166f33cdaefaa4afa6616a3bea66b694d', + USDbC: '0xc9d05a1c3c8e01dcb701d6185cdc21a5bb94becb', }, }; From 773a9fb69fd5eb2f172bbdf0993d70a0f6e3ed39 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 21 Sep 2023 16:01:43 +0300 Subject: [PATCH 332/833] 2.35.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e9a8f7bae..24dcb0c9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.6-ramses-v2-50-fee-pools-bug", + "version": "2.35.6", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 30d38287f67725cb3409887dc9a0a6631e8074e8 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 12:19:07 -0400 Subject: [PATCH 333/833] continue --- src/dex/solidly-v3/solidly-v3-integration.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 5de00bac1..8930b5b76 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -96,8 +96,8 @@ async function checkOnChainPricing( readerIface, _amounts.slice(1), 'quoteSwap', - true, - MIN_SQRT_RATIO + BigInt(1), + tokenIn < tokenOut, + tokenIn < tokenOut ? MIN_SQRT_RATIO + BigInt(1) : MAX_SQRT_RATIO - BigInt(1), ); let readerResult; @@ -328,7 +328,7 @@ describe('SolidlyV3', function () { WETH.address, USDT.address, tickSpacing, - amounts, + amountsBuy, ); if (res === false) falseChecksCounter++; }), From b90412ad70e5dee05531d103be6557ea3737a45a Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 12:32:05 -0400 Subject: [PATCH 334/833] add exactInput param to various places --- .../solidly-v3/solidly-v3-integration.test.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 8930b5b76..1caa7c1d8 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -49,10 +49,15 @@ function getReaderCalldata( funcName: string, zeroForOne: boolean, sqrtPriceLimitX96: bigint, + exactInput: boolean ) { return amounts.map(amount => ({ target: exchangeAddress, - callData: readerIface.encodeFunctionData(funcName, [zeroForOne, amount.toString(), sqrtPriceLimitX96.toString()]), + callData: readerIface.encodeFunctionData(funcName, [ + zeroForOne, + exactInput ? amount.toString() : `-${amount.toString()}`, + sqrtPriceLimitX96.toString() + ]), })); } @@ -60,11 +65,13 @@ function decodeReaderResult( results: Result, readerIface: Interface, funcName: string, + exactInput: boolean ) { - // TODO: Adapt this function for your needs return results.map(result => { const parsed = readerIface.decodeFunctionResult(funcName, result); - return parsed[1]._hex[0] == '-' ? BigInt(parsed[1]._hex.slice(1)) : BigInt(parsed[1]._hex); + // exactInput determines whether we want to get amount0 or amount1 + const index = exactInput ? 1 : 0; + return parsed[index]._hex[0] == '-' ? BigInt(parsed[index]._hex.slice(1)) : BigInt(parsed[index]._hex); }); } @@ -77,6 +84,7 @@ async function checkOnChainPricing( tokenOut: Address, tickSpacing: bigint, _amounts: bigint[], + exactInput: boolean ) { // Quoter address // const exchangeAddress = '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'; @@ -98,6 +106,7 @@ async function checkOnChainPricing( 'quoteSwap', tokenIn < tokenOut, tokenIn < tokenOut ? MIN_SQRT_RATIO + BigInt(1) : MAX_SQRT_RATIO - BigInt(1), + exactInput ); let readerResult; @@ -116,7 +125,7 @@ async function checkOnChainPricing( } const expectedPrices = [0n].concat( - decodeReaderResult(readerResult, readerIface, 'quoteSwap'), + decodeReaderResult(readerResult, readerIface, 'quoteSwap', exactInput), ); console.log('EXPECTED PRICES: ', expectedPrices); @@ -284,6 +293,7 @@ describe('SolidlyV3', function () { USDT.address, tickSpacing, amounts, + true ); if (res === false) falseChecksCounter++; }), @@ -329,6 +339,7 @@ describe('SolidlyV3', function () { USDT.address, tickSpacing, amountsBuy, + false ); if (res === false) falseChecksCounter++; }), From 05311d816e1c0e88ec0302627ca7085cb7521f8d Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 12:41:48 -0400 Subject: [PATCH 335/833] remove some comments / unused code --- .../solidly-v3/solidly-v3-integration.test.ts | 39 ------------------- 1 file changed, 39 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 1caa7c1d8..c82f86a67 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -86,8 +86,6 @@ async function checkOnChainPricing( _amounts: bigint[], exactInput: boolean ) { - // Quoter address - // const exchangeAddress = '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'; const readerIface = new Interface(SolidlyV3PoolABI); const sum = prices.reduce((acc, curr) => (acc += curr), 0n); @@ -187,15 +185,6 @@ async function testPricingOnNetwork( } else { checkPoolPrices(poolPrices!, amounts, side, dexKey); } - - // Check if onchain pricing equals to calculated ones - // await checkOnChainPricing( - // solidlyV3, - // funcNameToCheck, - // blockNumber, - // poolPrices![0].prices, - // amounts, - // ); } describe('SolidlyV3', function () { @@ -219,34 +208,6 @@ describe('SolidlyV3', function () { const srcTokenSymbol = 'WETH'; const destTokenSymbol = 'USDT'; - const amountsForSell = [ - 0n, - 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - 10n * BI_POWS[tokens[srcTokenSymbol].decimals], - ]; - - const amountsForBuy = [ - 0n, - 1n * BI_POWS[tokens[destTokenSymbol].decimals], - 2n * BI_POWS[tokens[destTokenSymbol].decimals], - 3n * BI_POWS[tokens[destTokenSymbol].decimals], - 4n * BI_POWS[tokens[destTokenSymbol].decimals], - 5n * BI_POWS[tokens[destTokenSymbol].decimals], - 6n * BI_POWS[tokens[destTokenSymbol].decimals], - 7n * BI_POWS[tokens[destTokenSymbol].decimals], - 8n * BI_POWS[tokens[destTokenSymbol].decimals], - 9n * BI_POWS[tokens[destTokenSymbol].decimals], - 10n * BI_POWS[tokens[destTokenSymbol].decimals], - ]; - beforeAll(async () => { blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); solidlyV3 = new SolidlyV3(network, dexKey, dexHelper); From 88e9b295d41b9a2d514872f511fed53db8952de2 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 12:51:16 -0400 Subject: [PATCH 336/833] uncomment --- src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 1668 ++++++++++----------- 1 file changed, 834 insertions(+), 834 deletions(-) diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index 8c88088a3..4d097abc7 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -116,56 +116,56 @@ describe('UniswapV3 E2E', () => { describe('UniswapV3', () => { const dexKey = 'UniswapV3'; - // describe('UniswapV3 MAINNET', () => { - // const network = Network.MAINNET; - // const tokens = Tokens[network]; - // const holders = Holders[network]; - // const provider = new StaticJsonRpcProvider( - // generateConfig(network).privateHttpProvider, - // network, - // ); - // - // it('BUY DAI -> USDC', async () => { - // await testE2E( - // tokens['DAI'], - // tokens['USDC'], - // holders['DAI'], - // '100000000000', - // SwapSide.BUY, - // dexKey, - // ContractMethod.simpleBuy, - // network, - // provider, - // ); - // }); - // it('SELL WETH -> SHIBA', async () => { - // await testE2E( - // tokens['WETH'], - // tokens['SHIBA'], - // holders['WETH'], - // '1000000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.simpleSwap, - // network, - // provider, - // ); - // }); - // - // it('directSwap SELL WETH -> USDC', async () => { - // await testE2E( - // tokens['WETH'], - // tokens['USDC'], - // holders['WETH'], - // '1000000000000000000', - // SwapSide.SELL, - // dexKey, - // ContractMethod.directUniV3Swap, - // network, - // provider, - // ); - // }); - // }); + describe('UniswapV3 MAINNET', () => { + const network = Network.MAINNET; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + it('BUY DAI -> USDC', async () => { + await testE2E( + tokens['DAI'], + tokens['USDC'], + holders['DAI'], + '100000000000', + SwapSide.BUY, + dexKey, + ContractMethod.simpleBuy, + network, + provider, + ); + }); + it('SELL WETH -> SHIBA', async () => { + await testE2E( + tokens['WETH'], + tokens['SHIBA'], + holders['WETH'], + '1000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); + + it('directSwap SELL WETH -> USDC', async () => { + await testE2E( + tokens['WETH'], + tokens['USDC'], + holders['WETH'], + '1000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.directUniV3Swap, + network, + provider, + ); + }); + }); describe('UniswapV3 POLYGON', () => { const network = Network.POLYGON; @@ -189,50 +189,202 @@ describe('UniswapV3 E2E', () => { SwapSide.SELL, [ ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - // ContractMethod.directUniV3Swap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, + ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); + + describe('UniswapV3 BSC', () => { + const network = Network.BSC; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'BUSD'; + const tokenBSymbol: string = 'WBNB'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '100000000000000000000'; + const tokenBAmount: string = '1000000000000000000'; + const nativeTokenAmount = '1000000000000000000'; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); + + describe('UniswapV3 Optimism', () => { + const network = Network.OPTIMISM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'OP'; + const tokenBSymbol: string = 'ETH'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '1000000000000000000'; + const tokenBAmount: string = '1000000000000000000'; + const nativeTokenAmount = '1000000000000000000'; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, ], ], - // [ - // SwapSide.BUY, - // [ - // ContractMethod.simpleBuy, - // ContractMethod.buy, - // ContractMethod.directUniV3Buy, - // ], - // ], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], ]); sideToContractMethods.forEach((contractMethods, side) => contractMethods.forEach((contractMethod: ContractMethod) => { describe(`${contractMethod}`, () => { - // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - // await testE2E( - // tokens[nativeTokenSymbol], - // tokens[tokenASymbol], - // holders[nativeTokenSymbol], - // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - // await testE2E( - // tokens[tokenASymbol], - // tokens[nativeTokenSymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { await testE2E( tokens[tokenASymbol], @@ -251,753 +403,601 @@ describe('UniswapV3 E2E', () => { ); }); - // describe('UniswapV3 BSC', () => { - // const network = Network.BSC; - // const tokens = Tokens[network]; - // const holders = Holders[network]; - // const provider = new StaticJsonRpcProvider( - // generateConfig(network).privateHttpProvider, - // network, - // ); - // - // const tokenASymbol: string = 'BUSD'; - // const tokenBSymbol: string = 'WBNB'; - // const nativeTokenSymbol = NativeTokenSymbols[network]; - // - // const tokenAAmount: string = '100000000000000000000'; - // const tokenBAmount: string = '1000000000000000000'; - // const nativeTokenAmount = '1000000000000000000'; - // - // const sideToContractMethods = new Map([ - // [ - // SwapSide.SELL, - // [ - // ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - // ], - // ], - // [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - // ]); - // - // sideToContractMethods.forEach((contractMethods, side) => - // contractMethods.forEach((contractMethod: ContractMethod) => { - // describe(`${contractMethod}`, () => { - // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - // await testE2E( - // tokens[nativeTokenSymbol], - // tokens[tokenASymbol], - // holders[nativeTokenSymbol], - // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - // await testE2E( - // tokens[tokenASymbol], - // tokens[nativeTokenSymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - // await testE2E( - // tokens[tokenASymbol], - // tokens[tokenBSymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // }); - // }), - // ); - // }); - // - // describe('UniswapV3 Optimism', () => { - // const network = Network.OPTIMISM; - // const tokens = Tokens[network]; - // const holders = Holders[network]; - // const provider = new StaticJsonRpcProvider( - // generateConfig(network).privateHttpProvider, - // network, - // ); - // - // const tokenASymbol: string = 'OP'; - // const tokenBSymbol: string = 'ETH'; - // const nativeTokenSymbol = NativeTokenSymbols[network]; - // - // const tokenAAmount: string = '1000000000000000000'; - // const tokenBAmount: string = '1000000000000000000'; - // const nativeTokenAmount = '1000000000000000000'; - // - // const sideToContractMethods = new Map([ - // [ - // SwapSide.SELL, - // [ - // ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - // ], - // ], - // [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - // ]); - // - // sideToContractMethods.forEach((contractMethods, side) => - // contractMethods.forEach((contractMethod: ContractMethod) => { - // describe(`${contractMethod}`, () => { - // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - // await testE2E( - // tokens[nativeTokenSymbol], - // tokens[tokenASymbol], - // holders[nativeTokenSymbol], - // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - // await testE2E( - // tokens[tokenASymbol], - // tokens[nativeTokenSymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - // await testE2E( - // tokens[tokenASymbol], - // tokens[tokenBSymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // }); - // }), - // ); - // }); - // - // describe('UniswapV3 Avalanche', () => { - // const network = Network.AVALANCHE; - // const tokens = Tokens[network]; - // const holders = Holders[network]; - // const provider = new StaticJsonRpcProvider( - // generateConfig(network).privateHttpProvider, - // network, - // ); - // - // const sideToContractMethods = new Map([ - // [ - // SwapSide.SELL, - // [ - // ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - // ], - // ], - // [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - // ]); - // - // const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = - // [ - // [ - // { - // name: 'AVAX', - // sellAmount: '1000000000000000000', - // buyAmount: '500000', - // }, - // { - // name: 'USDT', - // sellAmount: '1000000', - // buyAmount: '10000000000000000000', - // }, - // ], - // [ - // { - // name: 'AVAX', - // sellAmount: '1000000000000000000', - // buyAmount: '500000', - // }, - // { - // name: 'USDC', - // sellAmount: '1000000', - // buyAmount: '1000000000000000000', - // }, - // ], - // [ - // { - // name: 'WAVAX', - // sellAmount: '1000000000000000000', - // buyAmount: '500000', - // }, - // { - // name: 'USDC', - // sellAmount: '1000000', - // buyAmount: '20000000000000000', - // }, - // ], - // [ - // { - // name: 'WAVAX', - // sellAmount: '1000000000000000000', - // buyAmount: '10000000', - // }, - // { name: 'USDT', sellAmount: '1000000', buyAmount: '2000000000000' }, - // ], - // [ - // { name: 'USDC', sellAmount: '1000000', buyAmount: '100000000' }, - // { name: 'USDT', sellAmount: '100000000', buyAmount: '100000000' }, - // ], - // ]; - // - // sideToContractMethods.forEach((contractMethods, side) => - // describe(`${side}`, () => { - // contractMethods.forEach((contractMethod: ContractMethod) => { - // pairs.forEach(pair => { - // describe(`${contractMethod}`, () => { - // it(`${pair[0].name} -> ${pair[1].name}`, async () => { - // await testE2E( - // tokens[pair[0].name], - // tokens[pair[1].name], - // holders[pair[0].name], - // side === SwapSide.SELL - // ? pair[0].sellAmount - // : pair[0].buyAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${pair[1].name} -> ${pair[0].name}`, async () => { - // await testE2E( - // tokens[pair[1].name], - // tokens[pair[0].name], - // holders[pair[1].name], - // side === SwapSide.SELL - // ? pair[1].sellAmount - // : pair[1].buyAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // }); - // }); - // }); - // }), - // ); - // }); + describe('UniswapV3 Avalanche', () => { + const network = Network.AVALANCHE; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = + [ + [ + { + name: 'AVAX', + sellAmount: '1000000000000000000', + buyAmount: '500000', + }, + { + name: 'USDT', + sellAmount: '1000000', + buyAmount: '10000000000000000000', + }, + ], + [ + { + name: 'AVAX', + sellAmount: '1000000000000000000', + buyAmount: '500000', + }, + { + name: 'USDC', + sellAmount: '1000000', + buyAmount: '1000000000000000000', + }, + ], + [ + { + name: 'WAVAX', + sellAmount: '1000000000000000000', + buyAmount: '500000', + }, + { + name: 'USDC', + sellAmount: '1000000', + buyAmount: '20000000000000000', + }, + ], + [ + { + name: 'WAVAX', + sellAmount: '1000000000000000000', + buyAmount: '10000000', + }, + { name: 'USDT', sellAmount: '1000000', buyAmount: '2000000000000' }, + ], + [ + { name: 'USDC', sellAmount: '1000000', buyAmount: '100000000' }, + { name: 'USDT', sellAmount: '100000000', buyAmount: '100000000' }, + ], + ]; + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }); + }), + ); + }); }); - // describe('RamsesV2', () => { - // const dexKey = 'RamsesV2'; - // - // describe('Arbitrum', () => { - // const network = Network.ARBITRUM; - // const tokens = Tokens[network]; - // const holders = Holders[network]; - // const provider = new StaticJsonRpcProvider( - // generateConfig(network).privateHttpProvider, - // network, - // ); - // - // const tokenASymbol: string = 'USDCe'; - // const tokenBSymbol: string = 'USDT'; - // const nativeTokenSymbol = NativeTokenSymbols[network]; - // - // const tokenAAmount: string = '1100000'; - // const tokenBAmount: string = '1000000'; - // const nativeTokenAmount = '1100000000000'; - // - // const sideToContractMethods = new Map([ - // [ - // SwapSide.SELL, - // [ - // ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - // ContractMethod.directUniV3Swap, - // ], - // ], - // [ - // SwapSide.BUY, - // [ - // ContractMethod.simpleBuy, - // ContractMethod.buy, - // ContractMethod.directUniV3Buy, - // ], - // ], - // ]); - // - // sideToContractMethods.forEach((contractMethods, side) => - // contractMethods.forEach((contractMethod: ContractMethod) => { - // describe(`${contractMethod}`, () => { - // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - // await testE2E( - // tokens[nativeTokenSymbol], - // tokens[tokenASymbol], - // holders[nativeTokenSymbol], - // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - // await testE2E( - // tokens[tokenASymbol], - // tokens[nativeTokenSymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - // await testE2E( - // tokens[tokenASymbol], - // tokens[tokenBSymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // }); - // }), - // ); - // }); - // }); - // - // describe('ChronosV3', () => { - // const dexKey = 'ChronosV3'; - // describe('Arbitrum', () => { - // const network = Network.ARBITRUM; - // const tokens = Tokens[network]; - // const holders = Holders[network]; - // const provider = new StaticJsonRpcProvider( - // generateConfig(network).privateHttpProvider, - // network, - // ); - // - // const tokenASymbol: string = 'USDCe'; - // const tokenBSymbol: string = 'USDT'; - // const nativeTokenSymbol = NativeTokenSymbols[network]; - // - // const tokenAAmount: string = '2000000'; - // const tokenBAmount: string = '2000000'; - // const nativeTokenAmount = '100000000000000000'; - // - // const sideToContractMethods = new Map([ - // [ - // SwapSide.SELL, - // [ - // ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - // ContractMethod.directUniV3Swap, - // ], - // ], - // [ - // SwapSide.BUY, - // [ - // ContractMethod.simpleBuy, - // ContractMethod.buy, - // ContractMethod.directUniV3Buy, - // ], - // ], - // ]); - // - // sideToContractMethods.forEach((contractMethods, side) => - // contractMethods.forEach((contractMethod: ContractMethod) => { - // describe(`${contractMethod}`, () => { - // it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { - // await testE2E( - // tokens[nativeTokenSymbol], - // tokens[tokenASymbol], - // holders[nativeTokenSymbol], - // side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - // await testE2E( - // tokens[tokenASymbol], - // tokens[nativeTokenSymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - // await testE2E( - // tokens[tokenASymbol], - // tokens[tokenBSymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // }); - // }), - // ); - // }); - // }); - // - // describe('SushiSwapV3 E2E', () => { - // const dexKey = 'SushiSwapV3'; - // - // describe('MAINNET', () => { - // const network = Network.MAINNET; - // - // const tokenASymbol: string = 'USDC'; - // const tokenBSymbol: string = 'USDT'; - // - // const tokenAAmount: string = '111110000'; - // const tokenBAmount: string = '1100000000'; - // const nativeTokenAmount = '11000000000000000'; - // - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // nativeTokenAmount, - // ); - // }); - // - // describe('ARBITRUM', () => { - // const network = Network.ARBITRUM; - // - // const tokenASymbol: string = 'USDC'; - // const tokenBSymbol: string = 'USDCe'; - // - // const tokenAAmount: string = '10000000'; - // const tokenBAmount: string = '10000000'; - // const nativeTokenAmount = '900000000000000'; - // - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // nativeTokenAmount, - // ); - // }); - // - // describe('POLYGON', () => { - // const network = Network.POLYGON; - // - // const tokenASymbol: string = 'USDC'; - // const tokenBSymbol: string = 'USDT'; - // - // const tokenAAmount: string = '21111000'; - // const tokenBAmount: string = '200000000'; - // const nativeTokenAmount = '110000000000000000'; - // - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // nativeTokenAmount, - // ); - // }); - // - // describe('BSC', () => { - // const network = Network.BSC; - // const tokens = Tokens[network]; - // const holders = Holders[network]; - // const provider = new StaticJsonRpcProvider( - // generateConfig(network).privateHttpProvider, - // network, - // ); - // - // const sideToContractMethods = new Map([ - // [ - // SwapSide.SELL, - // [ - // ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - // ContractMethod.directUniV3Swap, - // ], - // ], - // [ - // SwapSide.BUY, - // [ - // ContractMethod.simpleBuy, - // ContractMethod.buy, - // ContractMethod.directUniV3Buy, - // ], - // ], - // ]); - // - // const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = - // [ - // [ - // { - // name: 'USDC', - // sellAmount: '100000000000000000000', - // buyAmount: '100000000000000000000', - // }, - // { - // name: 'USDT', - // sellAmount: '100000000000000000000', - // buyAmount: '100000000000000000000', - // }, - // ], - // [ - // { - // name: 'BNB', - // sellAmount: '1000000000000000000', - // buyAmount: '10000000000000000000', - // }, - // { - // name: 'USDT', - // sellAmount: '1000000000000000000000', - // buyAmount: '20000000000000000', - // }, - // ], - // ]; - // - // sideToContractMethods.forEach((contractMethods, side) => - // describe(`${side}`, () => { - // contractMethods.forEach((contractMethod: ContractMethod) => { - // pairs.forEach(pair => { - // describe(`${contractMethod}`, () => { - // it(`${pair[0].name} -> ${pair[1].name}`, async () => { - // await testE2E( - // tokens[pair[0].name], - // tokens[pair[1].name], - // holders[pair[0].name], - // side === SwapSide.SELL - // ? pair[0].sellAmount - // : pair[0].buyAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${pair[1].name} -> ${pair[0].name}`, async () => { - // await testE2E( - // tokens[pair[1].name], - // tokens[pair[0].name], - // holders[pair[1].name], - // side === SwapSide.SELL - // ? pair[1].sellAmount - // : pair[1].buyAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // }); - // }); - // }); - // }), - // ); - // }); - // - // describe('AVALANCHE', () => { - // const network = Network.AVALANCHE; - // - // const tokenASymbol: string = 'USDT'; - // const tokenBSymbol: string = 'USDC'; - // - // const tokenAAmount: string = '111110'; - // const tokenBAmount: string = '100000'; - // const nativeTokenAmount = '11000000000000000'; - // - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // nativeTokenAmount, - // ); - // }); - // - // describe('FANTOM', () => { - // const network = Network.FANTOM; - // const tokens = Tokens[network]; - // const holders = Holders[network]; - // const provider = new StaticJsonRpcProvider( - // generateConfig(network).privateHttpProvider, - // network, - // ); - // - // const sideToContractMethods = new Map([ - // [ - // SwapSide.SELL, - // [ - // ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - // ContractMethod.directUniV3Swap, - // ], - // ], - // [ - // SwapSide.BUY, - // [ - // ContractMethod.simpleBuy, - // ContractMethod.buy, - // ContractMethod.directUniV3Buy, - // ], - // ], - // ]); - // - // const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = - // [ - // [ - // { - // name: 'FTM', - // sellAmount: '100000000000000000', - // buyAmount: '100000000', - // }, - // { - // name: 'USDC', - // sellAmount: '100000000', - // buyAmount: '100000000000000000', - // }, - // ], - // [ - // { - // name: 'WFTM', - // sellAmount: '100000000000000', - // buyAmount: '1000000000000000', - // }, - // { - // name: 'WETH', - // sellAmount: '1000000000000000', - // buyAmount: '100000000000000', - // }, - // ], - // ]; - // - // sideToContractMethods.forEach((contractMethods, side) => - // describe(`${side}`, () => { - // contractMethods.forEach((contractMethod: ContractMethod) => { - // pairs.forEach(pair => { - // describe(`${contractMethod}`, () => { - // it(`${pair[0].name} -> ${pair[1].name}`, async () => { - // await testE2E( - // tokens[pair[0].name], - // tokens[pair[1].name], - // holders[pair[0].name], - // side === SwapSide.SELL - // ? pair[0].sellAmount - // : pair[0].buyAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${pair[1].name} -> ${pair[0].name}`, async () => { - // await testE2E( - // tokens[pair[1].name], - // tokens[pair[0].name], - // holders[pair[1].name], - // side === SwapSide.SELL - // ? pair[1].sellAmount - // : pair[1].buyAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // }); - // }); - // }); - // }), - // ); - // }); - // - // describe('OPTIMISM', () => { - // const network = Network.OPTIMISM; - // - // const tokenASymbol: string = 'USDC'; - // const tokenBSymbol: string = 'USDT'; - // - // const tokenAAmount: string = '111110000'; - // const tokenBAmount: string = '10000000'; - // const nativeTokenAmount = '11000000000000000'; - // - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // nativeTokenAmount, - // ); - // }); - // }); + describe('RamsesV2', () => { + const dexKey = 'RamsesV2'; + + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'USDCe'; + const tokenBSymbol: string = 'USDT'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '1100000'; + const tokenBAmount: string = '1000000'; + const nativeTokenAmount = '1100000000000'; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, + ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); + }); + + describe('ChronosV3', () => { + const dexKey = 'ChronosV3'; + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'USDCe'; + const tokenBSymbol: string = 'USDT'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '2000000'; + const tokenBAmount: string = '2000000'; + const nativeTokenAmount = '100000000000000000'; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, + ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); + }); + + describe('SushiSwapV3 E2E', () => { + const dexKey = 'SushiSwapV3'; + + describe('MAINNET', () => { + const network = Network.MAINNET; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '1100000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + + describe('ARBITRUM', () => { + const network = Network.ARBITRUM; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDCe'; + + const tokenAAmount: string = '10000000'; + const tokenBAmount: string = '10000000'; + const nativeTokenAmount = '900000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + + describe('POLYGON', () => { + const network = Network.POLYGON; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '21111000'; + const tokenBAmount: string = '200000000'; + const nativeTokenAmount = '110000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + + describe('BSC', () => { + const network = Network.BSC; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, + ], + ], + ]); + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = + [ + [ + { + name: 'USDC', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + { + name: 'USDT', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + ], + [ + { + name: 'BNB', + sellAmount: '1000000000000000000', + buyAmount: '10000000000000000000', + }, + { + name: 'USDT', + sellAmount: '1000000000000000000000', + buyAmount: '20000000000000000', + }, + ], + ]; + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }); + }), + ); + }); + + describe('AVALANCHE', () => { + const network = Network.AVALANCHE; + + const tokenASymbol: string = 'USDT'; + const tokenBSymbol: string = 'USDC'; + + const tokenAAmount: string = '111110'; + const tokenBAmount: string = '100000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + + describe('FANTOM', () => { + const network = Network.FANTOM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ContractMethod.directUniV3Buy, + ], + ], + ]); + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = + [ + [ + { + name: 'FTM', + sellAmount: '100000000000000000', + buyAmount: '100000000', + }, + { + name: 'USDC', + sellAmount: '100000000', + buyAmount: '100000000000000000', + }, + ], + [ + { + name: 'WFTM', + sellAmount: '100000000000000', + buyAmount: '1000000000000000', + }, + { + name: 'WETH', + sellAmount: '1000000000000000', + buyAmount: '100000000000000', + }, + ], + ]; + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }); + }), + ); + }); + + describe('OPTIMISM', () => { + const network = Network.OPTIMISM; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '10000000'; + const nativeTokenAmount = '11000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + }); }); From f8b362bd8dbe883030eba0e653cb7bd0fe5242df Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 13:05:37 -0400 Subject: [PATCH 337/833] Fix uniswap incorrect # of params --- src/dex/uniswap-v3/uniswap-v3-events.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dex/uniswap-v3/uniswap-v3-events.test.ts b/src/dex/uniswap-v3/uniswap-v3-events.test.ts index 1b769ecd2..306ebee60 100644 --- a/src/dex/uniswap-v3/uniswap-v3-events.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-events.test.ts @@ -13,6 +13,7 @@ import { Interface } from '@ethersproject/abi'; import ERC20ABI from '../../abi/erc20.json'; import StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; import { AbiItem } from 'web3-utils'; +import { decodeStateMultiCallResultWithRelativeBitmaps } from './utils'; jest.setTimeout(300 * 1000); const dexKey = 'UniswapV3'; @@ -100,6 +101,7 @@ describe('UniswapV3 Event', function () { StateMulticallABI as AbiItem[], config.stateMulticall, ), + decodeStateMultiCallResultWithRelativeBitmaps, new Interface(ERC20ABI), config.factory, poolFeeCode, @@ -155,6 +157,7 @@ describe('UniswapV3 Event', function () { StateMulticallABI as AbiItem[], config.stateMulticall, ), + decodeStateMultiCallResultWithRelativeBitmaps, new Interface(ERC20ABI), _config.factory, _feeCode, From 890ec3bc072f4a5bc5cd23673653363d63c8ac2e Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 17:15:21 -0400 Subject: [PATCH 338/833] update subgraph URL --- src/dex/solidly-v3/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index 2a49b4edc..ba81cea35 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -40,7 +40,7 @@ export const SolidlyV3Config: DexConfigMap = { initRetryFrequency: 10, // initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, initHash: `0x2d6541efe1e24667ba5408a35ae420462924d43db1251d7580804ac81545109b`, - subgraphURL: 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3', + subgraphURL: 'https://api.thegraph.com/subgraphs/name/solidlylabs/solidly-v3', }, }, }; From 8da3a3a1fd265a7967ea39f680176e6645d2f029 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 20:11:02 -0400 Subject: [PATCH 339/833] start events test --- src/dex/solidly-v3/solidly-v3-events.test.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-events.test.ts b/src/dex/solidly-v3/solidly-v3-events.test.ts index 223cdfec6..887de9af7 100644 --- a/src/dex/solidly-v3/solidly-v3-events.test.ts +++ b/src/dex/solidly-v3/solidly-v3-events.test.ts @@ -8,6 +8,7 @@ import { Address } from '../../types'; import { DummyDexHelper } from '../../dex-helper/index'; import { testEventSubscriber } from '../../../tests/utils-events'; import { PoolState } from './types'; +import {SolidlyV3Config} from "./config"; /* README @@ -43,14 +44,25 @@ import { PoolState } from './types'; */ jest.setTimeout(50 * 1000); +const dexKey = 'SolidlyV3'; +const network = Network.MAINNET; +const config = SolidlyV3Config[dexKey][network]; -async function fetchPoolState( - solidlyV3Pools: SolidlyV3EventPool, +async function fetchPoolStateFromContract( + solidlyV3Pool: SolidlyV3EventPool, blockNumber: number, poolAddress: string, ): Promise { - // TODO: complete me! - return {}; + const message = `SolidlyV3: ${poolAddress} blockNumber ${blockNumber}`; + console.log(`Fetching state ${message}`); + // Be careful to not request state prior to contract deployment + // Otherwise need to use manual state sourcing from multicall + // We had that mechanism, but removed it with this commit + // You can restore it, but better just to find block after state multicall + // deployment + const state = solidlyV3Pool.generateState(blockNumber); + console.log(`Done ${message}`); + return state; } // eventName -> blockNumbers From e3b2a15ed1867263ad2a33e5e50489ea7b18e058 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 21 Sep 2023 20:17:34 -0400 Subject: [PATCH 340/833] continue --- src/dex/solidly-v3/solidly-v3-events.test.ts | 118 +++++++++++-------- 1 file changed, 72 insertions(+), 46 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-events.test.ts b/src/dex/solidly-v3/solidly-v3-events.test.ts index 887de9af7..2928b4234 100644 --- a/src/dex/solidly-v3/solidly-v3-events.test.ts +++ b/src/dex/solidly-v3/solidly-v3-events.test.ts @@ -9,6 +9,11 @@ import { DummyDexHelper } from '../../dex-helper/index'; import { testEventSubscriber } from '../../../tests/utils-events'; import { PoolState } from './types'; import {SolidlyV3Config} from "./config"; +import {AbiItem} from "web3-utils"; +import {Interface} from "@ethersproject/abi"; +import StateMulticallABI from '../../abi/solidly-v3/SolidlyV3StateMulticall.abi.json'; +import { decodeStateMultiCallResultWithRelativeBitmaps } from './utils'; +import ERC20ABI from '../../abi/erc20.json'; /* README @@ -68,51 +73,72 @@ async function fetchPoolStateFromContract( // eventName -> blockNumbers type EventMappings = Record; -describe('SolidlyV3 EventPool Mainnet', function () { - const dexKey = 'SolidlyV3'; - const network = Network.MAINNET; - const dexHelper = new DummyDexHelper(network); - const logger = dexHelper.getLogger(dexKey); - let solidlyV3Pool: SolidlyV3EventPool; - - // poolAddress -> EventMappings - const eventsToTest: Record = { - // TODO: complete me! - }; - - beforeEach(async () => { - solidlyV3Pool = new SolidlyV3EventPool( - dexKey, - network, - dexHelper, - logger, - /* TODO: Put here additional constructor arguments if needed */ - ); - }); - - Object.entries(eventsToTest).forEach( - ([poolAddress, events]: [string, EventMappings]) => { - describe(`Events for ${poolAddress}`, () => { - Object.entries(events).forEach( - ([eventName, blockNumbers]: [string, number[]]) => { - describe(`${eventName}`, () => { - blockNumbers.forEach((blockNumber: number) => { - it(`State after ${blockNumber}`, async function () { - await testEventSubscriber( - solidlyV3Pool, - solidlyV3Pool.addressesSubscribed, - (_blockNumber: number) => - fetchPoolState(solidlyV3Pool, _blockNumber, poolAddress), - blockNumber, - `${dexKey}_${poolAddress}`, - dexHelper.provider, - ); - }); - }); - }); - }, - ); +describe('SolidlyV3 Event', function () { + const poolAddress = '0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640'; + const poolFeeCode = 500n; + const token0 = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'; + const token1 = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'; + + const blockNumbers: { [eventName: string]: number[] } = { + // topic0 - 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67 + ['Swap']: [ + 15846349, + // 15846351, 15846352, 15846353, 15846355, 15846357, 15846358, + // 15846360, 15846360, 15846361, 15846362, 15846364, 15846365, 15846366, + // 15846367, 15846368, 15846369, 15846370, 15846372, 15846373, 15846374, + // 15846375, 15846376, 15846381, 15846382, 15846383, 15846386, 15846387, + // 15846388, 15846390, 15846391, 15846392, 15846393, 15846398, 15846400, + // 15846403, 15846405, 15846407, 15846408, 15846411, 15846412, 15846413, + // 15846415, + ], + } + + describe('SolidlyV3EventPool', function () { + Object.keys(blockNumbers).forEach((event: string) => { + blockNumbers[event].forEach((blockNumber: number) => { + it(`${event}:${blockNumber} - should return correct state`, async function () { + const dexHelper = new DummyDexHelper(network); + // await dexHelper.init(); + + const logger = dexHelper.getLogger(dexKey); + + const solidlyV3Pool = new SolidlyV3EventPool( + dexHelper, + dexKey, + new dexHelper.web3Provider.eth.Contract( + StateMulticallABI as AbiItem[], + config.stateMulticall, + ), + decodeStateMultiCallResultWithRelativeBitmaps, + new Interface(ERC20ABI), + config.factory, + poolFeeCode, + token0, + token1, + logger, + undefined, + config.initHash, + ); + + // It is done in generateState. But here have to make it manually + solidlyV3Pool.poolAddress = poolAddress.toLowerCase(); + solidlyV3Pool.addressesSubscribed[0] = poolAddress; + + await testEventSubscriber( + solidlyV3Pool, + solidlyV3Pool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolStateFromContract( + solidlyV3Pool, + _blockNumber, + poolAddress, + ), + blockNumber, + `${dexKey}_${poolAddress}`, + dexHelper.provider, + ); + }); }); - }, - ); + }); + }); }); From 8b44be737a307228aac4aaf924ccff545cf05a68 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Fri, 22 Sep 2023 00:16:55 -0400 Subject: [PATCH 341/833] update some variables in events test --- src/dex/solidly-v3/solidly-v3-events.test.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-events.test.ts b/src/dex/solidly-v3/solidly-v3-events.test.ts index 2928b4234..79331a31f 100644 --- a/src/dex/solidly-v3/solidly-v3-events.test.ts +++ b/src/dex/solidly-v3/solidly-v3-events.test.ts @@ -74,15 +74,14 @@ async function fetchPoolStateFromContract( type EventMappings = Record; describe('SolidlyV3 Event', function () { - const poolAddress = '0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640'; - const poolFeeCode = 500n; - const token0 = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'; - const token1 = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'; + const poolAddress = '0x3198EAdB777b9b6C789bfc89491774644E95eD7e'; + const token0 = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'; + const token1 = '0xdac17f958d2ee523a2206206994597c13d831ec7'; const blockNumbers: { [eventName: string]: number[] } = { // topic0 - 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67 ['Swap']: [ - 15846349, + 18185415, // 15846351, 15846352, 15846353, 15846355, 15846357, 15846358, // 15846360, 15846360, 15846361, 15846362, 15846364, 15846365, 15846366, // 15846367, 15846368, 15846369, 15846370, 15846372, 15846373, 15846374, @@ -112,7 +111,7 @@ describe('SolidlyV3 Event', function () { decodeStateMultiCallResultWithRelativeBitmaps, new Interface(ERC20ABI), config.factory, - poolFeeCode, + 10n, token0, token1, logger, From 144feda1fb6faafd039c91068cd93fe953dad697 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Fri, 22 Sep 2023 00:28:01 -0400 Subject: [PATCH 342/833] fix a mistake in uniswapv3math --- src/dex/solidly-v3/contract-math/uniswap-v3-math.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/dex/solidly-v3/contract-math/uniswap-v3-math.ts b/src/dex/solidly-v3/contract-math/uniswap-v3-math.ts index f09ee2ed3..7c4336ceb 100644 --- a/src/dex/solidly-v3/contract-math/uniswap-v3-math.ts +++ b/src/dex/solidly-v3/contract-math/uniswap-v3-math.ts @@ -444,7 +444,14 @@ class UniswapV3Math { } } - poolState.slot0.sqrtPriceX96 = newSqrtPriceX96; + if (slot0Start.tick !== newTick) { + [ + poolState.slot0.sqrtPriceX96, + poolState.slot0.tick, + ] = [newSqrtPriceX96, newTick]; + } else { + poolState.slot0.sqrtPriceX96 = newSqrtPriceX96; + } if (poolState.liquidity !== newLiquidity) poolState.liquidity = newLiquidity; From 73781723863a1cdba9dd71d702395b3ff75e6af0 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Fri, 22 Sep 2023 00:44:23 -0400 Subject: [PATCH 343/833] add blocks for swap event --- src/dex/solidly-v3/solidly-v3-events.test.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-events.test.ts b/src/dex/solidly-v3/solidly-v3-events.test.ts index 79331a31f..af659d259 100644 --- a/src/dex/solidly-v3/solidly-v3-events.test.ts +++ b/src/dex/solidly-v3/solidly-v3-events.test.ts @@ -81,14 +81,8 @@ describe('SolidlyV3 Event', function () { const blockNumbers: { [eventName: string]: number[] } = { // topic0 - 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67 ['Swap']: [ - 18185415, - // 15846351, 15846352, 15846353, 15846355, 15846357, 15846358, - // 15846360, 15846360, 15846361, 15846362, 15846364, 15846365, 15846366, - // 15846367, 15846368, 15846369, 15846370, 15846372, 15846373, 15846374, - // 15846375, 15846376, 15846381, 15846382, 15846383, 15846386, 15846387, - // 15846388, 15846390, 15846391, 15846392, 15846393, 15846398, 15846400, - // 15846403, 15846405, 15846407, 15846408, 15846411, 15846412, 15846413, - // 15846415, + 18185415, 18185632, 18185654, 18186489, 18186623, 18186845, 18186959, 18187709, 18187816, + 18187818, 18187846, 18187849, 18187881 ], } From 5177f72095ce45cce82706f62ad1a345058dae9b Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Fri, 22 Sep 2023 01:36:31 -0400 Subject: [PATCH 344/833] add burn event --- src/dex/solidly-v3/solidly-v3-events.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dex/solidly-v3/solidly-v3-events.test.ts b/src/dex/solidly-v3/solidly-v3-events.test.ts index af659d259..5e516fa26 100644 --- a/src/dex/solidly-v3/solidly-v3-events.test.ts +++ b/src/dex/solidly-v3/solidly-v3-events.test.ts @@ -84,6 +84,7 @@ describe('SolidlyV3 Event', function () { 18185415, 18185632, 18185654, 18186489, 18186623, 18186845, 18186959, 18187709, 18187816, 18187818, 18187846, 18187849, 18187881 ], + ['Burn']: [18185393], } describe('SolidlyV3EventPool', function () { From 1eef7b19c176d0710b8b8435c82f914474bb67eb Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 22 Sep 2023 17:52:53 +0300 Subject: [PATCH 345/833] BACK-1298: integrate multiple DEXs on Base chain --- src/abi/aerodrome/aerodrome-pool-factory.json | 586 ++++++++++++++++++ src/config.ts | 4 +- src/dex/index.ts | 2 + src/dex/maverick-v1/maverick-v1-pool.ts | 3 + src/dex/maverick-v1/maverick-v1.ts | 3 + src/dex/pancakeswap-v3/config.ts | 19 + .../pancakeswap-v3/pancakeswap-v3-e2e.test.ts | 120 ++++ src/dex/solidly/config.ts | 14 + src/dex/solidly/forks-override/aerodrome.ts | 57 ++ src/dex/solidly/solidly-e2e.test.ts | 24 + src/dex/solidly/solidly.ts | 1 + src/dex/uniswap-v2/uniswap-v2.ts | 1 + src/dex/uniswap-v3/config.ts | 13 + src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 29 +- .../uniswap-v3/uniswap-v3-integration.test.ts | 142 +++++ tests/constants-e2e.ts | 5 + tests/utils-e2e.ts | 1 + 17 files changed, 1018 insertions(+), 6 deletions(-) create mode 100644 src/abi/aerodrome/aerodrome-pool-factory.json create mode 100644 src/dex/solidly/forks-override/aerodrome.ts diff --git a/src/abi/aerodrome/aerodrome-pool-factory.json b/src/abi/aerodrome/aerodrome-pool-factory.json new file mode 100644 index 000000000..56152f57d --- /dev/null +++ b/src/abi/aerodrome/aerodrome-pool-factory.json @@ -0,0 +1,586 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "FeeInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "FeeTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPool", + "type": "error" + }, + { + "inputs": [], + "name": "NotFeeManager", + "type": "error" + }, + { + "inputs": [], + "name": "NotPauser", + "type": "error" + }, + { + "inputs": [], + "name": "NotVoter", + "type": "error" + }, + { + "inputs": [], + "name": "PoolAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "SameAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroFee", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": true, + "internalType": "bool", + "name": "stable", + "type": "bool" + }, + { + "indexed": false, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "SetCustomFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "feeManager", + "type": "address" + } + ], + "name": "SetFeeManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "state", + "type": "bool" + } + ], + "name": "SetPauseState", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "pauser", + "type": "address" + } + ], + "name": "SetPauser", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "voter", + "type": "address" + } + ], + "name": "SetVoter", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_FEE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ZERO_FEE_INDICATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allPools", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allPoolsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "createPool", + "outputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + } + ], + "name": "createPool", + "outputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "customFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "bool", + "name": "_stable", + "type": "bool" + } + ], + "name": "getFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "uint24", + "name": "fee", + "type": "uint24" + } + ], + "name": "getPool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "internalType": "bool", + "name": "stable", + "type": "bool" + } + ], + "name": "getPool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "isPool", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "setCustomFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_stable", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "setFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_feeManager", + "type": "address" + } + ], + "name": "setFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_state", + "type": "bool" + } + ], + "name": "setPauseState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_pauser", + "type": "address" + } + ], + "name": "setPauser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_voter", + "type": "address" + } + ], + "name": "setVoter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stableFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "volatileFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/config.ts b/src/config.ts index dc8edea4b..b76504267 100644 --- a/src/config.ts +++ b/src/config.ts @@ -362,8 +362,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', hashFlowDisabledMMs: [], adapterAddresses: { - BaseAdapter01: '0x9F77bb28e97F093Aa6CbE37cE095C18605d98Af2', - BaseBuyAdapter: '0x8DE036910e34b0d8447Dd0D34C742636de1DDfEb', + BaseAdapter01: '0x77b1E160ABD2276D5741B4419A66ab34DbF0294d', + BaseBuyAdapter: '0x28c1F8948e9D18a6850832dDc966f36428fc5892', }, uniswapV2ExchangeRouterAddress: '0x75d199EfB540e47D27D52c62Da3E7daC2B9e834F', diff --git a/src/dex/index.ts b/src/dex/index.ts index 7484ca450..4595ad24f 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -47,6 +47,7 @@ import { Thena } from './solidly/forks-override/thena'; import { Chronos } from './solidly/forks-override/chronos'; import { Velodrome } from './solidly/forks-override/velodrome'; import { VelodromeV2 } from './solidly/forks-override/velodromeV2'; +import { Aerodrome } from './solidly/forks-override/aerodrome'; import { SpiritSwapV2 } from './solidly/forks-override/spiritSwapV2'; import { Synthetix } from './synthetix/synthetix'; import { Cone } from './solidly/forks-override/cone'; @@ -134,6 +135,7 @@ const Dexes = [ Chronos, Velodrome, VelodromeV2, + Aerodrome, Cone, SoliSnek, Equalizer, diff --git a/src/dex/maverick-v1/maverick-v1-pool.ts b/src/dex/maverick-v1/maverick-v1-pool.ts index 21537b441..5108a16f9 100644 --- a/src/dex/maverick-v1/maverick-v1-pool.ts +++ b/src/dex/maverick-v1/maverick-v1-pool.ts @@ -129,15 +129,18 @@ export class MaverickV1EventPool extends StatefulEventSubscriber { * @returns state of the event subscriber at blocknumber */ async generateState(blockNumber: number): Promise> { + console.log('BEFORE RAW BINS'); const rawBins = await this.poolInspectorContract.methods['getActiveBins']( this.address, 0, 0, ).call({}, blockNumber); + console.log('RAW BINS: ', rawBins); const rawState = await this.poolContract.methods['getState']().call( {}, blockNumber, ); + console.log('RAW STATE: ', rawState); let binPositions: { [tick: string]: { [kind: string]: bigint } } = {}; let bins: { [id: string]: Bin } = {}; let binMap: { [id: string]: bigint } = {}; diff --git a/src/dex/maverick-v1/maverick-v1.ts b/src/dex/maverick-v1/maverick-v1.ts index 1dd608b32..e7045ed98 100644 --- a/src/dex/maverick-v1/maverick-v1.ts +++ b/src/dex/maverick-v1/maverick-v1.ts @@ -78,6 +78,7 @@ export class MaverickV1 async setupEventPools(blockNumber: number) { const pools = await this.fetchAllSubgraphPools(); + await Promise.all( pools.map(async (pool: any) => { const eventPool = new MaverickV1EventPool( @@ -114,6 +115,8 @@ export class MaverickV1 this.pools[eventPool.address] = eventPool; }), ); + + console.log('THIS POOLS: ', this.pools); } // Initialize pricing is called once in the start of diff --git a/src/dex/pancakeswap-v3/config.ts b/src/dex/pancakeswap-v3/config.ts index 43636ee06..00ae8a2ac 100644 --- a/src/dex/pancakeswap-v3/config.ts +++ b/src/dex/pancakeswap-v3/config.ts @@ -53,6 +53,21 @@ export const PancakeswapV3Config: DexConfigMap = { subgraphURL: 'https://api.studio.thegraph.com/query/45376/exchange-v3-arbitrum/version/latest', }, + [Network.BASE]: { + factory: '0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865', + deployer: '0x41ff9AA7e16B8B1a8a8dc4f0eFacd93D02d071c9', + quoter: '0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997', + router: '0x1b81D678ffb9C0263b24A97847620C99d213eB14', + supportedFees: PANCAKE_SUPPORTED_FEES, + stateMulticall: '0xeBF40A40CA3D4310Bf53048F48e860656e1D7C81', + uniswapMulticall: '0x091e99cb1C49331a94dD62755D168E941AbD0693', + chunksCount: 10, + initRetryFrequency: 30, + initHash: + '0x6ce8eb472fa82df5469c6ab6d485f17c3ad13c8cd7af59b3d4a8026c5ce0f7e2', + subgraphURL: + 'https://api.studio.thegraph.com/query/45376/exchange-v3-base/version/latest', + }, }, }; @@ -69,4 +84,8 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'ArbitrumAdapter01', index: 3 }], [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 2 }], }, + [Network.BASE]: { + [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 1 }], + [SwapSide.BUY]: [{ name: 'BaseBuyAdapter', index: 1 }], + }, }; diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3-e2e.test.ts b/src/dex/pancakeswap-v3/pancakeswap-v3-e2e.test.ts index 9be62cd7e..f3c61fdd3 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3-e2e.test.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3-e2e.test.ts @@ -11,6 +11,105 @@ import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, + slippage?: number | undefined, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ], + ], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + 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, + 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, + network, + provider, + undefined, + undefined, + undefined, + slippage, + ); + }); + }); + }); + }), + ); + }); +} + describe('PancakeswapV3 E2E', () => { const dexKey = 'PancakeswapV3'; @@ -307,4 +406,25 @@ describe('PancakeswapV3 E2E', () => { }), ); }); + + describe('PancakeswapV3 Base', () => { + const network = Network.BASE; + + const tokenASymbol: string = 'USDbC'; + const tokenBSymbol: string = 'DAI'; + + const tokenAAmount: string = '11111000000'; + const tokenBAmount: string = '210000000000000000'; + const nativeTokenAmount = '110000000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); }); diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index b18dba6d7..b7143ffa7 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -83,6 +83,17 @@ export const SolidlyConfig: DexConfigMap = { feeCode: 0, }, }, + Aerodrome: { + [Network.BASE]: { + // There is no subgraph for Aerodrome + factoryAddress: '0x420DD381b31aEf6683db6B902084cB0FFECe40Da', + router: '0xDCf4EE5B700e2a5Fec458e06B763A4a3E3004494', + initCode: + '0x1a8f01f7eab324003d9388f229ea17991eee9c9d14586f429799f3656790eba0', + poolGasCost: 180 * 1000, + feeCode: 0, + }, + }, Cone: { [Network.BSC]: { subgraphURL: 'https://api.thegraph.com/subgraphs/name/cone-exchange/cone', @@ -182,4 +193,7 @@ export const Adapters: Record = { [Network.ARBITRUM]: { [SwapSide.SELL]: [{ name: 'ArbitrumAdapter02', index: 1 }], // chronos, ramses }, + [Network.BASE]: { + [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 3 }], // aerodrome + } }; diff --git a/src/dex/solidly/forks-override/aerodrome.ts b/src/dex/solidly/forks-override/aerodrome.ts new file mode 100644 index 000000000..dbc82685e --- /dev/null +++ b/src/dex/solidly/forks-override/aerodrome.ts @@ -0,0 +1,57 @@ +import { VelodromeV2 } from './velodromeV2'; +import { Network, NULL_ADDRESS } from '../../../constants'; +import { getDexKeysWithNetwork } from '../../../utils'; +import _ from 'lodash'; +import { SolidlyConfig } from '../config'; +import { Address, Token } from '../../../types'; +import { IDexHelper } from '../../../dex-helper'; +import AerodromeFactoryABI from '../../../abi/aerodrome/aerodrome-pool-factory.json'; + +export class Aerodrome extends VelodromeV2 { + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(_.pick(SolidlyConfig, ['Aerodrome'])); + + constructor( + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + ) { + super( + network, + dexKey, + dexHelper, + ); + + this.factory = new dexHelper.web3Provider.eth.Contract( + AerodromeFactoryABI as any, + SolidlyConfig[dexKey][network].factoryAddress, + ); + } + + async findSolidlyPair(from: Token, to: Token, stable: boolean) { + if (from.address.toLowerCase() === to.address.toLowerCase()) return null; + const [token0, token1] = + from.address.toLowerCase() < to.address.toLowerCase() + ? [from, to] + : [to, from]; + + const typePostfix = this.poolPostfix(stable); + const key = `${token0.address.toLowerCase()}-${token1.address.toLowerCase()}-${typePostfix}`; + let pair = this.pairs[key]; + if (pair) return pair; + + let exchange = await this.factory.methods + // Solidly has additional boolean parameter "StablePool" + // At first we look for uniswap-like volatile pool + .getPool(token0.address, token1.address, stable) + .call(); + + if (exchange === NULL_ADDRESS) { + pair = { token0, token1, stable }; + } else { + pair = { token0, token1, exchange, stable }; + } + this.pairs[key] = pair; + return pair; + } +} diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index 5395ad36b..d9e11541a 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -1404,4 +1404,28 @@ describe('Solidly E2E', () => { ); }); }); + + describe('Base', () => { + const network = Network.BASE; + + describe('Aerodrome', () => { + const dexKey = 'Aerodrome'; + const tokenASymbol: string = 'USDbC'; + const tokenBSymbol: string = 'DAI'; + + const tokenAAmount: string = '1111100000'; + const tokenBAmount: string = '100000000000000000'; + const nativeTokenAmount = '100000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }) + }); }); diff --git a/src/dex/solidly/solidly.ts b/src/dex/solidly/solidly.ts index 899acd50f..13b5a0c75 100644 --- a/src/dex/solidly/solidly.ts +++ b/src/dex/solidly/solidly.ts @@ -75,6 +75,7 @@ export class Solidly extends UniswapV2 { 'Chronos', 'Ramses', 'Equalizer', + 'Aerodrome', ]), ); diff --git a/src/dex/uniswap-v2/uniswap-v2.ts b/src/dex/uniswap-v2/uniswap-v2.ts index 134a3b40c..1eb6521a6 100644 --- a/src/dex/uniswap-v2/uniswap-v2.ts +++ b/src/dex/uniswap-v2/uniswap-v2.ts @@ -293,6 +293,7 @@ export class UniswapV2 priceParams: UniswapV2PoolOrderedParams, srcAmount: bigint, ): Promise { + console.log('GET SELL PRICE'); return Uniswapv2ConstantProductPool.getSellPrice( priceParams, srcAmount, diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index 0cbc23907..a967b754a 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -210,6 +210,19 @@ export const UniswapV3Config: DexConfigMap = { subgraphURL: 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-optimism', }, + [Network.BASE]: { + factory: '0xc35DADB65012eC5796536bD9864eD8773aBc74C4', + quoter: '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + router: '0xCc0e85901f33D375FcdD9a888B05Df9616F68277', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x7160f736c52e1e78e92FD4eE4D73e21A7Cf4F950', + uniswapMulticall: '0x091e99cb1C49331a94dD62755D168E941AbD0693', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-base', // incorrect url + }, }, ChronosV3: { [Network.ARBITRUM]: { diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index af9829d9f..0bae0339a 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -424,16 +424,16 @@ describe('UniswapV3 E2E', () => { [ SwapSide.SELL, [ - // ContractMethod.simpleSwap, + ContractMethod.simpleSwap, ContractMethod.multiSwap, - // ContractMethod.megaSwap, + ContractMethod.megaSwap, ], ], [ SwapSide.BUY, [ - // ContractMethod.simpleBuy, - // ContractMethod.buy + ContractMethod.simpleBuy, + ContractMethod.buy ], ], ]); @@ -1094,5 +1094,26 @@ describe('UniswapV3 E2E', () => { nativeTokenAmount, ); }); + + describe('BASE', () => { + const network = Network.BASE; + + const tokenASymbol: string = 'USDbC'; + const tokenBSymbol: string = 'DAI'; + + const tokenAAmount: string = '111110000'; + const tokenBAmount: string = '110000000000000000'; + const nativeTokenAmount = '1100000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); }); }); diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index bc286c582..47367cda3 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -959,4 +959,146 @@ describe('SushiSwapV3', () => { expect(falseChecksCounter).toBeLessThan(poolPrices!.length); }); }); + + describe('Base', () => { + let blockNumber: number; + let sushiSwapV3: UniswapV3; + let sushiSwapV3Mainnet: UniswapV3; + + const network = Network.BASE; + const dexHelper = new DummyDexHelper(network); + const TokenASymbol = 'USDbC'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'DAI'; + const TokenB = Tokens[network][TokenBSymbol]; + + beforeEach(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + sushiSwapV3 = new UniswapV3(network, dexKey, dexHelper); + sushiSwapV3Mainnet = new UniswapV3(Network.MAINNET, dexKey, dexHelper); + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + const amounts = [0n, BI_POWS[6], 2000000n]; + + const pools = await sushiSwapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await sushiSwapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = sushiSwapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + sushiSwapV3, + 'quoteExactInputSingle', + blockNumber, + '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + const amounts = [0n, BI_POWS[6], 2000000n]; + + const pools = await sushiSwapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await sushiSwapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = sushiSwapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + sushiSwapV3, + 'quoteExactOutputSingle', + blockNumber, + '0xb1E835Dc2785b52265711e17fCCb0fd018226a6e', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getTopPoolsForToken', async function () { + const poolLiquidity = await sushiSwapV3.getTopPoolsForToken( + TokenB.address, + 10, + ); + console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); + }); + }); + }); + diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index e7d06f50a..afcfce24f 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -904,6 +904,10 @@ export const Tokens: { address: '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA', decimals: 6, }, + DAI: { + address: '0x50c5725949a6f0c72e6c4a641f24049a917db0cb', + decimals: 18, + }, ETH: { address: ETHER_ADDRESS, decimals: 18 }, }, }; @@ -1132,6 +1136,7 @@ export const Holders: { MAV: '0x7499785aa5d1bdf0a0ac862c1ef3698d3cba6568', USDC: '0xaac391f166f33cdaefaa4afa6616a3bea66b694d', USDbC: '0xc9d05a1c3c8e01dcb701d6185cdc21a5bb94becb', + DAI: '0x20f03e26968b179025f65c1f4afadfd3959c8d03', }, }; diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index f1b96c7d2..ece7ac264 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -86,6 +86,7 @@ const MULTISIG: { [nid: number]: string } = { [Network.AVALANCHE]: '0x1e2ECA5e812D08D2A7F8664D69035163ff5BfEC2', [Network.OPTIMISM]: '0xf01121e808F782d7F34E857c27dA31AD1f151b39', [Network.ARBITRUM]: '0x90DfD8a6454CFE19be39EaB42ac93CD850c7f339', + [Network.BASE]: '0x6C674c8Df1aC663b822c4B6A56B4E5e889379AE0', }; class APIParaswapSDK implements IParaSwapSDK { From 3bd43ab0d0375e9d66ccf9fcd5248a65d981c0c1 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 22 Sep 2023 17:54:44 +0300 Subject: [PATCH 346/833] remove console.log --- src/dex/maverick-v1/maverick-v1-pool.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/dex/maverick-v1/maverick-v1-pool.ts b/src/dex/maverick-v1/maverick-v1-pool.ts index 5108a16f9..21537b441 100644 --- a/src/dex/maverick-v1/maverick-v1-pool.ts +++ b/src/dex/maverick-v1/maverick-v1-pool.ts @@ -129,18 +129,15 @@ export class MaverickV1EventPool extends StatefulEventSubscriber { * @returns state of the event subscriber at blocknumber */ async generateState(blockNumber: number): Promise> { - console.log('BEFORE RAW BINS'); const rawBins = await this.poolInspectorContract.methods['getActiveBins']( this.address, 0, 0, ).call({}, blockNumber); - console.log('RAW BINS: ', rawBins); const rawState = await this.poolContract.methods['getState']().call( {}, blockNumber, ); - console.log('RAW STATE: ', rawState); let binPositions: { [tick: string]: { [kind: string]: bigint } } = {}; let bins: { [id: string]: Bin } = {}; let binMap: { [id: string]: bigint } = {}; From 849a3a75c65092506587daa57488ecd37fbb7e1a Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 22 Sep 2023 17:55:28 +0300 Subject: [PATCH 347/833] remove console.log --- src/dex/maverick-v1/maverick-v1.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/dex/maverick-v1/maverick-v1.ts b/src/dex/maverick-v1/maverick-v1.ts index e7045ed98..9209f49dc 100644 --- a/src/dex/maverick-v1/maverick-v1.ts +++ b/src/dex/maverick-v1/maverick-v1.ts @@ -115,8 +115,6 @@ export class MaverickV1 this.pools[eventPool.address] = eventPool; }), ); - - console.log('THIS POOLS: ', this.pools); } // Initialize pricing is called once in the start of From 52884b59e0868ba7a51fff2b575e06d75d7b149e Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 22 Sep 2023 17:58:49 +0300 Subject: [PATCH 348/833] add base adapters for BalancerV2 and WoofiV2 --- src/dex/balancer-v2/config.ts | 4 ++++ src/dex/woo-fi-v2/config.ts | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/dex/balancer-v2/config.ts b/src/dex/balancer-v2/config.ts index cbb0b3a77..27897fadc 100644 --- a/src/dex/balancer-v2/config.ts +++ b/src/dex/balancer-v2/config.ts @@ -71,5 +71,9 @@ export const Adapters: Record = { [Network.AVALANCHE]: { [SwapSide.SELL]: [{ name: 'AvalancheAdapter01', index: 8 }], [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 7 }], + }, + [Network.BASE]: { + [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 4 }], + [SwapSide.BUY]: [{ name: 'BaseBuyAdapter', index: 3 }], } }; diff --git a/src/dex/woo-fi-v2/config.ts b/src/dex/woo-fi-v2/config.ts index 3e353615b..560c6c267 100644 --- a/src/dex/woo-fi-v2/config.ts +++ b/src/dex/woo-fi-v2/config.ts @@ -84,4 +84,7 @@ export const Adapters: Record = { [Network.AVALANCHE]: { [SwapSide.SELL]: [{ name: 'AvalancheAdapter01', index: 12 }], }, + [Network.BASE]: { + [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 5 }], + }, }; From 0af196819ab5d0d7106ffbdfbe082e35ab2590b6 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Fri, 22 Sep 2023 14:29:39 -0400 Subject: [PATCH 349/833] test mint event --- src/dex/solidly-v3/constants.ts | 3 --- src/dex/solidly-v3/solidly-v3-events.test.ts | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/dex/solidly-v3/constants.ts b/src/dex/solidly-v3/constants.ts index 96423f6d1..e9fdeeebb 100644 --- a/src/dex/solidly-v3/constants.ts +++ b/src/dex/solidly-v3/constants.ts @@ -18,9 +18,6 @@ export const UNISWAPV3_EFFICIENCY_FACTOR = 3; export const ZERO_TICK_INFO = { liquidityGross: 0n, liquidityNet: 0n, - tickCumulativeOutside: 0n, - secondsPerLiquidityOutsideX128: 0n, - secondsOutside: 0n, initialized: false, }; diff --git a/src/dex/solidly-v3/solidly-v3-events.test.ts b/src/dex/solidly-v3/solidly-v3-events.test.ts index 5e516fa26..f00348e7d 100644 --- a/src/dex/solidly-v3/solidly-v3-events.test.ts +++ b/src/dex/solidly-v3/solidly-v3-events.test.ts @@ -85,6 +85,7 @@ describe('SolidlyV3 Event', function () { 18187818, 18187846, 18187849, 18187881 ], ['Burn']: [18185393], + ['Mint']: [18189645, 18189685, 18190653], } describe('SolidlyV3EventPool', function () { From fc26821cf71aacedceaf2d5b1fbd27d2c6997975 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Fri, 22 Sep 2023 14:40:42 -0400 Subject: [PATCH 350/833] add test collect event --- src/dex/solidly-v3/solidly-v3-events.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dex/solidly-v3/solidly-v3-events.test.ts b/src/dex/solidly-v3/solidly-v3-events.test.ts index f00348e7d..df1817161 100644 --- a/src/dex/solidly-v3/solidly-v3-events.test.ts +++ b/src/dex/solidly-v3/solidly-v3-events.test.ts @@ -86,6 +86,7 @@ describe('SolidlyV3 Event', function () { ], ['Burn']: [18185393], ['Mint']: [18189645, 18189685, 18190653], + ['Collect']: [18185393], } describe('SolidlyV3EventPool', function () { From b17381e4183751ddbad9ac353859c96f165a72ec Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Fri, 22 Sep 2023 15:54:48 -0400 Subject: [PATCH 351/833] handleSetFeeEvent --- src/dex/solidly-v3/solidly-v3-events.test.ts | 2 ++ src/dex/solidly-v3/solidly-v3-pool.ts | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/dex/solidly-v3/solidly-v3-events.test.ts b/src/dex/solidly-v3/solidly-v3-events.test.ts index df1817161..864b1fe3f 100644 --- a/src/dex/solidly-v3/solidly-v3-events.test.ts +++ b/src/dex/solidly-v3/solidly-v3-events.test.ts @@ -87,6 +87,8 @@ describe('SolidlyV3 Event', function () { ['Burn']: [18185393], ['Mint']: [18189645, 18189685, 18190653], ['Collect']: [18185393], + //topic0 0x0eb63f4a36d6bdeee05aa00020a97d80c3e84f1b5b3ebf345fb67262e62b0f33 + ['SetFee']: [18180677, 18181047, 18182317, 18185660, 18186351, 18188882, 18193229] } describe('SolidlyV3EventPool', function () { diff --git a/src/dex/solidly-v3/solidly-v3-pool.ts b/src/dex/solidly-v3/solidly-v3-pool.ts index eae03747b..6f5a4f051 100644 --- a/src/dex/solidly-v3/solidly-v3-pool.ts +++ b/src/dex/solidly-v3/solidly-v3-pool.ts @@ -103,6 +103,7 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { // Almost the same as Collect, but for pool owners this.handlers['CollectProtocol'] = this.handleCollectEvent.bind(this); this.handlers['Flash'] = this.handleFlashEvent.bind(this); + this.handlers['SetFee'] = this.handleSetFeeEvent.bind(this); } get poolAddress() { @@ -455,6 +456,19 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { return pool; } + handleSetFeeEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader + ) { + const feeNew = bigIntify(event.args.feeNew); + pool.slot0.fee = feeNew; + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + return pool; + } + private _computePoolAddress( token0: Address, token1: Address, From 700c9163bc362c1e17e2bf8a02ff6593dda72922 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Fri, 22 Sep 2023 19:35:53 -0400 Subject: [PATCH 352/833] add SolidlyV3 as a DEX --- src/dex/index.ts | 2 ++ src/dex/solidly-v3/solidly-v3.ts | 6 +----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/dex/index.ts b/src/dex/index.ts index 7484ca450..00d326908 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -42,6 +42,7 @@ import { WooFiV2 } from './woo-fi-v2/woo-fi-v2'; import { ParaSwapLimitOrders } from './paraswap-limit-orders/paraswap-limit-orders'; import { AugustusRFQOrder } from './augustus-rfq'; import { Solidly } from './solidly/solidly'; +import { SolidlyV3} from "./solidly-v3/solidly-v3"; import { Ramses } from './solidly/forks-override/ramses'; import { Thena } from './solidly/forks-override/thena'; import { Chronos } from './solidly/forks-override/chronos'; @@ -147,6 +148,7 @@ const Dexes = [ SwaapV2, QuickPerps, NomiswapV2, + SolidlyV3, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index 3ab2d70be..ce3bac174 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -92,11 +92,7 @@ export class SolidlyV3 public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork( _.pick(SolidlyV3Config, [ - 'UniswapV3', - 'SushiSwapV3', - 'QuickSwapV3.1', - 'RamsesV2', - 'ChronosV3', + 'SolidlyV3', ]), ); From d617d39e48e05a19df65db60d719750536db08ee Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Fri, 22 Sep 2023 19:45:27 -0400 Subject: [PATCH 353/833] start e2e --- src/dex/solidly-v3/solidly-v3-e2e.test.ts | 148 ++++++++-------------- 1 file changed, 50 insertions(+), 98 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-e2e.test.ts b/src/dex/solidly-v3/solidly-v3-e2e.test.ts index 7069dd5ca..1fccaaeac 100644 --- a/src/dex/solidly-v3/solidly-v3-e2e.test.ts +++ b/src/dex/solidly-v3/solidly-v3-e2e.test.ts @@ -51,112 +51,64 @@ import { generateConfig } from '../../config'; (This comment should be removed from the final implementation) */ -function testForNetwork( - network: Network, - dexKey: string, - tokenASymbol: string, - tokenBSymbol: string, - tokenAAmount: string, - tokenBAmount: string, - nativeTokenAmount: string, -) { - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - const tokens = Tokens[network]; - const holders = Holders[network]; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - // TODO: Add any direct swap contractMethod name if it exists - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ], - ], - // TODO: If buy is not supported remove the buy contract methods - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - ]); - - describe(`${network}`, () => { - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - 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, - network, - provider, - ); - }); - it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }); - }), - ); - }); -} - describe('SolidlyV3 E2E', () => { const dexKey = 'SolidlyV3'; describe('Mainnet', () => { const network = Network.MAINNET; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); - // TODO: Modify the tokenASymbol, tokenBSymbol, tokenAAmount; - const tokenASymbol: string = 'tokenASymbol'; - const tokenBSymbol: string = 'tokenBSymbol'; + const tokenASymbol: string = 'WETH'; + const tokenBSymbol: string = 'USDT'; + const nativeTokenSymbol = NativeTokenSymbols[network]; - const tokenAAmount: string = 'tokenAAmount'; - const tokenBAmount: string = 'tokenBAmount'; - const nativeTokenAmount = '1000000000000000000'; + const tokenAAmount: string = '11000000000000000000'; + const tokenBAmount: string = '11000000'; + const nativeTokenAmount = '11000000000000000000'; - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + // ContractMethod.directUniV3Swap, + ], + ], + // [ + // SwapSide.BUY, + // [ + // ContractMethod.simpleBuy, + // ContractMethod.buy, + // ContractMethod.directUniV3Buy, + // ], + // ], + ]); - // TODO: Add any additional test cases required to test SolidlyV3 + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); }); }); From cfbabf9b71ebee40677cccc892d37666821f4d6f Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Fri, 22 Sep 2023 22:52:13 -0400 Subject: [PATCH 354/833] get simple swap to work --- src/dex/solidly-v3/solidly-v3.ts | 93 ++++++++++++++++---------------- src/dex/solidly-v3/types.ts | 16 ++++-- 2 files changed, 59 insertions(+), 50 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index ce3bac174..df5d7528c 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -30,7 +30,7 @@ import { DexParams, OutputResult, PoolState, - SolidlyV3Data, + SolidlyV3Data, SolidlyV3SimpleSwapParams, UniswapV3Functions, UniswapV3Param, UniswapV3SimpleSwapParams, @@ -46,6 +46,7 @@ import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.jso import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; import DirectSwapABI from '../../abi/DirectSwap.json'; import SolidlyV3StateMulticallABI from '../../abi/solidly-v3/SolidlyV3StateMulticall.abi.json'; +import SolidlyV3PoolABI from '../../abi/solidly-v3/SolidlyV3Pool.abi.json'; import { DirectMethods, UNISWAPV3_EFFICIENCY_FACTOR, @@ -64,6 +65,7 @@ import { DEFAULT_ID_ERC20_AS_STRING, } from '../../lib/tokens/types'; import { OptimalSwapExchange } from '@paraswap/core'; +import { TickMath } from "./contract-math/TickMath"; type PoolPairsInfo = { token0: Address; @@ -108,7 +110,7 @@ export class SolidlyV3 dexKey: string, protected dexHelper: IDexHelper, protected adapters = Adapters[network] || {}, - readonly routerIface = new Interface(UniswapV3RouterABI), + readonly poolIface = new Interface(SolidlyV3PoolABI), readonly quoterIface = new Interface(UniswapV3QuoterV2ABI), protected config = SolidlyV3Config[dexKey][network], protected poolsToPreload = PoolsToPreload[dexKey]?.[network] || [], @@ -488,14 +490,8 @@ export class SolidlyV3 prices, unit, data: { - path: [ - { - tokenIn: from.address, - tokenOut: to.address, - fee: pool.tickSpacingAsString, - }, - ], - exchange: pool.poolAddress, + zeroForOne: pool.token0.toLowerCase() == from.address.toLowerCase() ? true: false, + poolAddress: pool.poolAddress }, poolIdentifier: this.getPoolIdentifier( pool.token0, @@ -683,13 +679,8 @@ export class SolidlyV3 unit: unitResult.outputs[0], prices, data: { - path: [ - { - tokenIn: _srcAddress, - tokenOut: _destAddress, - fee: pool.tickSpacing.toString(), - }, - ], + zeroForOne, + poolAddress: pool.poolAddress }, poolIdentifier: this.getPoolIdentifier( pool.token0, @@ -736,8 +727,9 @@ export class SolidlyV3 data: SolidlyV3Data, side: SwapSide, ): AdapterExchangeParam { - const { path: rawPath } = data; - const path = this._encodePath(rawPath, side); + // const { path: rawPath } = data; + // const path = this._encodePath(rawPath, side); + const path = ''; const payload = this.abiCoder.encodeParameter( { @@ -869,7 +861,8 @@ export class SolidlyV3 this.logger.warn(`isApproved is undefined, defaulting to false`); } - const path = this._encodePath(data.path, side); + // const path = this._encodePath(data.path, side); + const path = ''; const swapParams: UniswapV3Param = [ srcToken, @@ -916,30 +909,40 @@ export class SolidlyV3 data: SolidlyV3Data, side: SwapSide, ): Promise { - const swapFunction = - side === SwapSide.SELL - ? UniswapV3Functions.exactInput - : UniswapV3Functions.exactOutput; - - const path = this._encodePath(data.path, side); - const swapFunctionParams: UniswapV3SimpleSwapParams = - side === SwapSide.SELL - ? { - recipient: this.augustusAddress, - deadline: getLocalDeadlineAsFriendlyPlaceholder(), - amountIn: srcAmount, - amountOutMinimum: destAmount, - path, - } - : { - recipient: this.augustusAddress, - deadline: getLocalDeadlineAsFriendlyPlaceholder(), - amountOut: destAmount, - amountInMaximum: srcAmount, - path, - }; - const swapData = this.routerIface.encodeFunctionData(swapFunction, [ - swapFunctionParams, + const swapFunction = this.poolIface.getFunction('swap(address,bool,int256,uint160,uint256,uint256)'); + + // const path = this._encodePath(data.path, side); + // const swapFunctionParams: UniswapV3SimpleSwapParams = + // side === SwapSide.SELL + // ? { + // recipient: this.augustusAddress, + // deadline: getLocalDeadlineAsFriendlyPlaceholder(), + // amountIn: srcAmount, + // amountOutMinimum: destAmount, + // path, + // } + // : { + // recipient: this.augustusAddress, + // deadline: getLocalDeadlineAsFriendlyPlaceholder(), + // amountOut: destAmount, + // amountInMaximum: srcAmount, + // path, + // }; + const swapFunctionParams: SolidlyV3SimpleSwapParams = { + recipient: this.augustusAddress, + zeroForOne: data.zeroForOne, + amountSpecified: side === SwapSide.SELL ? srcAmount.toString() : (-destAmount).toString(), + sqrtPriceLimitX96: data.zeroForOne ? (TickMath.MIN_SQRT_RATIO + BigInt(1)).toString() : (TickMath.MAX_SQRT_RATIO - BigInt(1)).toString(), + amountLimit: '1', + deadline: getLocalDeadlineAsFriendlyPlaceholder(), + } + const swapData = this.poolIface.encodeFunctionData(swapFunction, [ + swapFunctionParams.recipient, + swapFunctionParams.zeroForOne, + swapFunctionParams.amountSpecified, + swapFunctionParams.sqrtPriceLimitX96, + swapFunctionParams.amountLimit, + swapFunctionParams.deadline, ]); return this.buildSimpleParamWithoutWETHConversion( @@ -948,7 +951,7 @@ export class SolidlyV3 destToken, destAmount, swapData, - this.config.router, + data.poolAddress, ); } diff --git a/src/dex/solidly-v3/types.ts b/src/dex/solidly-v3/types.ts index 07c4cfc2c..99fa9aaa3 100644 --- a/src/dex/solidly-v3/types.ts +++ b/src/dex/solidly-v3/types.ts @@ -34,11 +34,8 @@ export type PoolState = { }; export type SolidlyV3Data = { - path: { - tokenIn: Address; - tokenOut: Address; - fee: NumberAsString; - }[]; + zeroForOne: boolean; + poolAddress: string; isApproved?: boolean; }; @@ -82,6 +79,15 @@ export type UniswapV3SimpleSwapParams = | UniswapV3SimpleSwapSellParam | UniswapV3SimpleSwapBuyParam; +export type SolidlyV3SimpleSwapParams = { + recipient: string; + zeroForOne: boolean; + amountSpecified: NumberAsString; + sqrtPriceLimitX96: NumberAsString; + amountLimit: NumberAsString; + deadline: string; +} + export type UniswapV3Param = [ fromToken: Address, toToken: Address, From 182ab1855857ca997dc3429eba3af16c88e6786e Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sat, 23 Sep 2023 15:36:29 -0400 Subject: [PATCH 355/833] add tokenB -> tokenA --- src/dex/solidly-v3/solidly-v3-e2e.test.ts | 38 ++++++++++++++++++----- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-e2e.test.ts b/src/dex/solidly-v3/solidly-v3-e2e.test.ts index 1fccaaeac..ad5da48d5 100644 --- a/src/dex/solidly-v3/solidly-v3-e2e.test.ts +++ b/src/dex/solidly-v3/solidly-v3-e2e.test.ts @@ -81,16 +81,17 @@ describe('SolidlyV3 E2E', () => { // ContractMethod.directUniV3Swap, ], ], - // [ - // SwapSide.BUY, - // [ - // ContractMethod.simpleBuy, - // ContractMethod.buy, - // ContractMethod.directUniV3Buy, - // ], - // ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + // ContractMethod.buy, + // ContractMethod.directUniV3Buy, + ], + ], ]); + // tokenA -> tokenB sideToContractMethods.forEach((contractMethods, side) => contractMethods.forEach((contractMethod: ContractMethod) => { describe(`${contractMethod}`, () => { @@ -110,5 +111,26 @@ describe('SolidlyV3 E2E', () => { }); }), ); + + // tokenB -> tokenA + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${tokenBSymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenBSymbol], + tokens[tokenASymbol], + holders[tokenBSymbol], + side === SwapSide.SELL ? tokenBAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); }); }); From c5d25b96f096cf39cd4c715e0d3cf9f3fb7b4bbe Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sat, 23 Sep 2023 21:13:42 -0400 Subject: [PATCH 356/833] add Flash --- src/dex/solidly-v3/solidly-v3-events.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dex/solidly-v3/solidly-v3-events.test.ts b/src/dex/solidly-v3/solidly-v3-events.test.ts index 864b1fe3f..73571eed5 100644 --- a/src/dex/solidly-v3/solidly-v3-events.test.ts +++ b/src/dex/solidly-v3/solidly-v3-events.test.ts @@ -88,7 +88,8 @@ describe('SolidlyV3 Event', function () { ['Mint']: [18189645, 18189685, 18190653], ['Collect']: [18185393], //topic0 0x0eb63f4a36d6bdeee05aa00020a97d80c3e84f1b5b3ebf345fb67262e62b0f33 - ['SetFee']: [18180677, 18181047, 18182317, 18185660, 18186351, 18188882, 18193229] + ['SetFee']: [18180677, 18181047, 18182317, 18185660, 18186351, 18188882, 18193229], + ['Flash']: [18202148], } describe('SolidlyV3EventPool', function () { From ee94eda66640e024e872c36a49854a64e1d28dc8 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sun, 24 Sep 2023 23:53:35 -0400 Subject: [PATCH 357/833] add CollectProtocol event tests --- src/dex/solidly-v3/solidly-v3-events.test.ts | 21 ++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-events.test.ts b/src/dex/solidly-v3/solidly-v3-events.test.ts index 73571eed5..f6214ae75 100644 --- a/src/dex/solidly-v3/solidly-v3-events.test.ts +++ b/src/dex/solidly-v3/solidly-v3-events.test.ts @@ -80,16 +80,17 @@ describe('SolidlyV3 Event', function () { const blockNumbers: { [eventName: string]: number[] } = { // topic0 - 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67 - ['Swap']: [ - 18185415, 18185632, 18185654, 18186489, 18186623, 18186845, 18186959, 18187709, 18187816, - 18187818, 18187846, 18187849, 18187881 - ], - ['Burn']: [18185393], - ['Mint']: [18189645, 18189685, 18190653], - ['Collect']: [18185393], - //topic0 0x0eb63f4a36d6bdeee05aa00020a97d80c3e84f1b5b3ebf345fb67262e62b0f33 - ['SetFee']: [18180677, 18181047, 18182317, 18185660, 18186351, 18188882, 18193229], - ['Flash']: [18202148], + // ['Swap']: [ + // 18185415, 18185632, 18185654, 18186489, 18186623, 18186845, 18186959, 18187709, 18187816, + // 18187818, 18187846, 18187849, 18187881 + // ], + // ['Burn']: [18185393], + // ['Mint']: [18189645, 18189685, 18190653], + // ['Collect']: [18185393], + // //topic0 0x0eb63f4a36d6bdeee05aa00020a97d80c3e84f1b5b3ebf345fb67262e62b0f33 + // ['SetFee']: [18180677, 18181047, 18182317, 18185660, 18186351, 18188882, 18193229], + // ['Flash']: [18202148], + ['CollectProtocol']: [18203357, 18209933], } describe('SolidlyV3EventPool', function () { From 512ec8b68effce0d27c10871f23ba40a5f9fecb9 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Mon, 25 Sep 2023 00:37:46 -0400 Subject: [PATCH 358/833] remove pricingFromRpc. uncomment some stuff i accidentally commented --- src/dex/solidly-v3/solidly-v3-events.test.ts | 20 +-- src/dex/solidly-v3/solidly-v3.ts | 157 +------------------ 2 files changed, 11 insertions(+), 166 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-events.test.ts b/src/dex/solidly-v3/solidly-v3-events.test.ts index f6214ae75..4563e9e5c 100644 --- a/src/dex/solidly-v3/solidly-v3-events.test.ts +++ b/src/dex/solidly-v3/solidly-v3-events.test.ts @@ -80,16 +80,16 @@ describe('SolidlyV3 Event', function () { const blockNumbers: { [eventName: string]: number[] } = { // topic0 - 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67 - // ['Swap']: [ - // 18185415, 18185632, 18185654, 18186489, 18186623, 18186845, 18186959, 18187709, 18187816, - // 18187818, 18187846, 18187849, 18187881 - // ], - // ['Burn']: [18185393], - // ['Mint']: [18189645, 18189685, 18190653], - // ['Collect']: [18185393], - // //topic0 0x0eb63f4a36d6bdeee05aa00020a97d80c3e84f1b5b3ebf345fb67262e62b0f33 - // ['SetFee']: [18180677, 18181047, 18182317, 18185660, 18186351, 18188882, 18193229], - // ['Flash']: [18202148], + ['Swap']: [ + 18185415, 18185632, 18185654, 18186489, 18186623, 18186845, 18186959, 18187709, 18187816, + 18187818, 18187846, 18187849, 18187881 + ], + ['Burn']: [18185393], + ['Mint']: [18189645, 18189685, 18190653], + ['Collect']: [18185393], + //topic0 0x0eb63f4a36d6bdeee05aa00020a97d80c3e84f1b5b3ebf345fb67262e62b0f33 + ['SetFee']: [18180677, 18181047, 18182317, 18185660, 18186351, 18188882, 18193229], + ['Flash']: [18202148], ['CollectProtocol']: [18203357, 18209933], } diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index df5d7528c..8787742c9 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -372,141 +372,6 @@ export class SolidlyV3 ); } - async getPricingFromRpc( - from: Token, - to: Token, - amounts: bigint[], - side: SwapSide, - pools: SolidlyV3EventPool[], - ): Promise | null> { - if (pools.length === 0) { - return null; - } - this.logger.warn(`fallback to rpc for ${pools.length} pool(s)`); - - const requests = pools.map( - pool => ({ - owner: pool.poolAddress, - asset: side == SwapSide.SELL ? from.address : to.address, - assetType: AssetType.ERC20, - ids: [ - { - id: DEFAULT_ID_ERC20, - spenders: [], - }, - ], - }), - [], - ); - - const balances = await getBalances(this.dexHelper.multiWrapper, requests); - - pools = pools.filter((pool, index) => { - const balance = balances[index].amounts[DEFAULT_ID_ERC20_AS_STRING]; - if (balance >= amounts[amounts.length - 1]) { - return true; - } - this.logger.warn( - `[${this.network}][${pool.parentName}] have no balance ${pool.poolAddress} ${from.address} ${to.address}. (Balance: ${balance})`, - ); - return false; - }); - - pools.forEach(pool => { - this.logger.warn( - `[${this.network}][${pool.parentName}] fallback to rpc for ${pool.name}`, - ); - }); - - const unitVolume = getBigIntPow( - (side === SwapSide.SELL ? from : to).decimals, - ); - - const chunks = amounts.length - 1; - - const _width = Math.floor(chunks / this.config.chunksCount); - - const _amounts = [unitVolume].concat( - Array.from(Array(this.config.chunksCount).keys()).map( - i => amounts[(i + 1) * _width], - ), - ); - - const calldata = pools.map(pool => - _amounts.map(_amount => ({ - target: pool._poolAddress, - gasLimit: UNISWAPV3_QUOTE_GASLIMIT, - callData: - side === SwapSide.SELL - ? this.quoterIface.encodeFunctionData('quoteExactInputSingle', [ - [ - from.address, - to.address, - _amount.toString(), - pool.tickSpacingAsString, - 0, //sqrtPriceLimitX96 - ], - ]) - : this.quoterIface.encodeFunctionData('quoteExactOutputSingle', [ - [ - from.address, - to.address, - _amount.toString(), - pool.tickSpacingAsString, - 0, //sqrtPriceLimitX96 - ], - ]), - })), - ); - - const data = await this.uniswapMulti.methods - .multicall(calldata.flat()) - .call(); - - const decode = (j: number): bigint => { - if (!data.returnData[j].success) { - return 0n; - } - const decoded = defaultAbiCoder.decode( - ['uint256'], - data.returnData[j].returnData, - ); - return BigInt(decoded[0].toString()); - }; - - let i = 0; - const result = pools.map(pool => { - const _rates = _amounts.map(() => decode(i++)); - const unit: bigint = _rates[0]; - - const prices = interpolate( - _amounts.slice(1), - _rates.slice(1), - amounts, - side, - ); - - return { - prices, - unit, - data: { - zeroForOne: pool.token0.toLowerCase() == from.address.toLowerCase() ? true: false, - poolAddress: pool.poolAddress - }, - poolIdentifier: this.getPoolIdentifier( - pool.token0, - pool.token1, - pool.tickSpacing, - ), - exchange: this.dexKey, - gasCost: prices.map(p => (p === 0n ? 0 : UNISWAPV3_QUOTE_GASLIMIT)), - poolAddresses: [pool.poolAddress], - }; - }); - - return result; - } - async getPricesVolume( srcToken: Token, destToken: Token, @@ -586,10 +451,7 @@ export class SolidlyV3 (acc, pool) => { let state = pool.getState(blockNumber); if (state === null) { - this.logger.trace( - `${this.dexKey}: State === null. Fallback to rpc ${pool.name}`, - ); - acc.poolWithoutState.push(pool); + throw new Error("Unable to retrieve pool state."); } else { acc.poolWithState.push(pool); } @@ -601,14 +463,6 @@ export class SolidlyV3 }, ); - const rpcResultsPromise = this.getPricingFromRpc( - _srcToken, - _destToken, - amounts, - side, - this.network === Network.ZKEVM ? [] : poolsToUse.poolWithoutState, - ); - const states = poolsToUse.poolWithState.map( p => p.getState(blockNumber)!, ); @@ -693,20 +547,11 @@ export class SolidlyV3 }; }), ); - const rpcResults = await rpcResultsPromise; const notNullResult = result.filter( res => res !== null, ) as ExchangePrices; - if (rpcResults) { - rpcResults.forEach(r => { - if (r) { - notNullResult.push(r); - } - }); - } - return notNullResult; } catch (e) { this.logger.error( From 39bea6365bfd74b3f72ad5fada63bc4a5df986c7 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Mon, 25 Sep 2023 03:44:38 -0400 Subject: [PATCH 359/833] remove some unused code --- src/dex/solidly-v3/solidly-v3.ts | 85 -------------------------------- 1 file changed, 85 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index 8787742c9..5918d383a 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -678,74 +678,6 @@ export class SolidlyV3 ]; } - getDirectParam( - srcToken: Address, - destToken: Address, - srcAmount: NumberAsString, - destAmount: NumberAsString, - expectedAmount: NumberAsString, - data: SolidlyV3Data, - side: SwapSide, - permit: string, - uuid: string, - feePercent: NumberAsString, - deadline: NumberAsString, - partner: string, - beneficiary: string, - contractMethod?: string, - ): TxInfo { - if ( - contractMethod !== DirectMethods.directSell && - contractMethod !== DirectMethods.directBuy - ) { - throw new Error(`Invalid contract method ${contractMethod}`); - } - - let isApproved: boolean = !!data.isApproved; - if (data.isApproved === undefined) { - this.logger.warn(`isApproved is undefined, defaulting to false`); - } - - // const path = this._encodePath(data.path, side); - const path = ''; - - const swapParams: UniswapV3Param = [ - srcToken, - destToken, - this.config.router, - srcAmount, - destAmount, - expectedAmount, - feePercent, - deadline, - partner, - isApproved, - beneficiary, - path, - permit, - uuidToBytes16(uuid), - ]; - - const encoder = (...params: UniswapV3Param) => { - return this.directSwapIface.encodeFunctionData( - side === SwapSide.SELL - ? DirectMethods.directSell - : DirectMethods.directBuy, - [params], - ); - }; - - return { - params: swapParams, - encoder, - networkFee: '0', - }; - } - - static getDirectFunctionName(): string[] { - return [DirectMethods.directSell, DirectMethods.directBuy]; - } - async getSimpleParam( srcToken: string, destToken: string, @@ -756,23 +688,6 @@ export class SolidlyV3 ): Promise { const swapFunction = this.poolIface.getFunction('swap(address,bool,int256,uint160,uint256,uint256)'); - // const path = this._encodePath(data.path, side); - // const swapFunctionParams: UniswapV3SimpleSwapParams = - // side === SwapSide.SELL - // ? { - // recipient: this.augustusAddress, - // deadline: getLocalDeadlineAsFriendlyPlaceholder(), - // amountIn: srcAmount, - // amountOutMinimum: destAmount, - // path, - // } - // : { - // recipient: this.augustusAddress, - // deadline: getLocalDeadlineAsFriendlyPlaceholder(), - // amountOut: destAmount, - // amountInMaximum: srcAmount, - // path, - // }; const swapFunctionParams: SolidlyV3SimpleSwapParams = { recipient: this.augustusAddress, zeroForOne: data.zeroForOne, From ac92b1fe9277f8d677f7503d9012851a71d555b2 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Mon, 25 Sep 2023 04:09:43 -0400 Subject: [PATCH 360/833] add yarn checks back to pre commit --- .husky/pre-commit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index 7e07d664d..9163e8448 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" -#yarn checks && yarn build +yarn checks && yarn build From fcf66486c9d0258fe0e95f1a0cd93df358c111c9 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 25 Sep 2023 11:48:45 +0300 Subject: [PATCH 361/833] update subgraph url for SushiV3 on Base chain --- src/dex/balancer-v2/balancer-v2-e2e.test.ts | 123 +++++++++++++++++++- src/dex/balancer-v2/config.ts | 7 +- src/dex/uniswap-v3/config.ts | 2 +- tests/constants-e2e.ts | 10 ++ 4 files changed, 139 insertions(+), 3 deletions(-) diff --git a/src/dex/balancer-v2/balancer-v2-e2e.test.ts b/src/dex/balancer-v2/balancer-v2-e2e.test.ts index 1f7de204b..5cc919399 100644 --- a/src/dex/balancer-v2/balancer-v2-e2e.test.ts +++ b/src/dex/balancer-v2/balancer-v2-e2e.test.ts @@ -2,7 +2,7 @@ import dotenv from 'dotenv'; dotenv.config(); import { testE2E } from '../../../tests/utils-e2e'; -import { Holders, Tokens } from '../../../tests/constants-e2e'; +import { Holders, NativeTokenSymbols, Tokens } from '../../../tests/constants-e2e'; import { ContractMethod, Network, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; @@ -10,6 +10,105 @@ import { generateConfig } from '../../config'; jest.setTimeout(50 * 1000); +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, + slippage?: number | undefined, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ], + ], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + 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, + 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, + network, + provider, + undefined, + undefined, + undefined, + slippage, + ); + }); + }); + }); + }), + ); + }); +} + describe('BalancerV2 E2E', () => { describe('BalancerV2 MAINNET', () => { const dexKey = 'BalancerV2'; @@ -1195,6 +1294,28 @@ describe('BalancerV2 E2E', () => { }); }); + describe('BalancerV2 Base', () => { + const dexKey = 'BalancerV2'; + const network = Network.BASE; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'GOLD'; + + const tokenAAmount: string = '11110010'; + const tokenBAmount: string = '210000000000000000000'; + const nativeTokenAmount = '1000000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + describe('BeetsFi OPTIMISM', () => { const dexKey = 'BeetsFi'; const network = Network.OPTIMISM; diff --git a/src/dex/balancer-v2/config.ts b/src/dex/balancer-v2/config.ts index 27897fadc..86e7e2930 100644 --- a/src/dex/balancer-v2/config.ts +++ b/src/dex/balancer-v2/config.ts @@ -23,7 +23,12 @@ export const BalancerConfig: DexConfigMap = { subgraphURL: 'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-avalanche-v2', vaultAddress: '0xBA12222222228d8Ba445958a75a0704d566BF2C8', - } + }, + [Network.BASE]: { + subgraphURL: + 'https://api.studio.thegraph.com/query/24660/balancer-base-v2/version/latest', + vaultAddress: '0xBA12222222228d8Ba445958a75a0704d566BF2C8', + }, }, BeetsFi: { [Network.FANTOM]: { diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index a967b754a..4a419d9b8 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -221,7 +221,7 @@ export const UniswapV3Config: DexConfigMap = { initRetryFrequency: 10, initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, subgraphURL: - 'https://api.thegraph.com/subgraphs/name/sushi-v3/v3-base', // incorrect url + 'https://api.studio.thegraph.com/query/32073/v3-base/v0.0.1', }, }, ChronosV3: { diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index afcfce24f..f596301db 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -908,6 +908,14 @@ export const Tokens: { address: '0x50c5725949a6f0c72e6c4a641f24049a917db0cb', decimals: 18, }, + BAL: { + address: '0x4158734d47fc9692176b5085e0f52ee0da5d47f1', + decimals: 18, + }, + GOLD: { + address: '0xbeFD5C25A59ef2C1316c5A4944931171F30Cd3E4', + decimals: 18, + }, ETH: { address: ETHER_ADDRESS, decimals: 18 }, }, }; @@ -1137,6 +1145,8 @@ export const Holders: { USDC: '0xaac391f166f33cdaefaa4afa6616a3bea66b694d', USDbC: '0xc9d05a1c3c8e01dcb701d6185cdc21a5bb94becb', DAI: '0x20f03e26968b179025f65c1f4afadfd3959c8d03', + BAL: '0x854b004700885a61107b458f11ecc169a019b764', + GOLD: '0x1374c25b3710758c326ee0c70ec48b595d5ccf8c', }, }; From 3902d7ecae13f0cf8ec5b551ec74e463791d9703 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 25 Sep 2023 13:52:52 +0300 Subject: [PATCH 362/833] add implementation for BalancerV2 on Base chain --- src/config.ts | 4 ++-- src/dex/uniswap-v2/uniswap-v2.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/config.ts b/src/config.ts index b76504267..6a8c7c397 100644 --- a/src/config.ts +++ b/src/config.ts @@ -362,8 +362,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', hashFlowDisabledMMs: [], adapterAddresses: { - BaseAdapter01: '0x77b1E160ABD2276D5741B4419A66ab34DbF0294d', - BaseBuyAdapter: '0x28c1F8948e9D18a6850832dDc966f36428fc5892', + BaseAdapter01: '0x5F23023f66eFbC55ffC86E62f0f7898D9Ac9FD38', + BaseBuyAdapter: '0x683778fAc3144eb6bE0df14325036c5a0DD81F92', }, uniswapV2ExchangeRouterAddress: '0x75d199EfB540e47D27D52c62Da3E7daC2B9e834F', diff --git a/src/dex/uniswap-v2/uniswap-v2.ts b/src/dex/uniswap-v2/uniswap-v2.ts index 1eb6521a6..134a3b40c 100644 --- a/src/dex/uniswap-v2/uniswap-v2.ts +++ b/src/dex/uniswap-v2/uniswap-v2.ts @@ -293,7 +293,6 @@ export class UniswapV2 priceParams: UniswapV2PoolOrderedParams, srcAmount: bigint, ): Promise { - console.log('GET SELL PRICE'); return Uniswapv2ConstantProductPool.getSellPrice( priceParams, srcAmount, From 1982b62e236be60c889cfa7d4ced370a0f2c02d0 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 25 Sep 2023 14:35:48 +0300 Subject: [PATCH 363/833] add implementation for WoofiV2 --- src/config.ts | 4 +- src/dex/maverick-v1/config.ts | 12 ++--- src/dex/woo-fi-v2/config.ts | 10 ++++ src/dex/woo-fi-v2/woo-fi-v2-e2e.test.ts | 64 +++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 8 deletions(-) diff --git a/src/config.ts b/src/config.ts index 6a8c7c397..2273e572a 100644 --- a/src/config.ts +++ b/src/config.ts @@ -362,8 +362,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', hashFlowDisabledMMs: [], adapterAddresses: { - BaseAdapter01: '0x5F23023f66eFbC55ffC86E62f0f7898D9Ac9FD38', - BaseBuyAdapter: '0x683778fAc3144eb6bE0df14325036c5a0DD81F92', + BaseAdapter01: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', + BaseBuyAdapter: '0xB11bCA7B01b425afD0743A4D77B4f593883f94C0', }, uniswapV2ExchangeRouterAddress: '0x75d199EfB540e47D27D52c62Da3E7daC2B9e834F', diff --git a/src/dex/maverick-v1/config.ts b/src/dex/maverick-v1/config.ts index 90d1489f5..8a9863f3a 100644 --- a/src/dex/maverick-v1/config.ts +++ b/src/dex/maverick-v1/config.ts @@ -14,12 +14,12 @@ export const MaverickV1Config: DexConfigMap = { routerAddress: '0x4a585e0f7c18e2c414221d6402652d5e0990e5f8', poolInspectorAddress: '0xaA5BF61a664109e959D69C38734d4EA7dF74e456', }, - [Network.BASE]: { - subgraphURL: - 'https://api.studio.thegraph.com/query/42519/maverick-base/version/latest', - routerAddress: '0x32AED3Bce901DA12ca8489788F3A99fCe1056e14', - poolInspectorAddress: '0x550056A68cB155b6Cc3DeF4A7FA656260e7842e2', - }, + // [Network.BASE]: { + // subgraphURL: + // 'https://api.studio.thegraph.com/query/42519/maverick-base/version/latest', + // routerAddress: '0x32AED3Bce901DA12ca8489788F3A99fCe1056e14', + // poolInspectorAddress: '0x550056A68cB155b6Cc3DeF4A7FA656260e7842e2', + // }, }, }; diff --git a/src/dex/woo-fi-v2/config.ts b/src/dex/woo-fi-v2/config.ts index 560c6c267..3d020f99a 100644 --- a/src/dex/woo-fi-v2/config.ts +++ b/src/dex/woo-fi-v2/config.ts @@ -64,6 +64,16 @@ export const WooFiV2Config: DexConfigMap = { decimals: 6, }, }, + [Network.BASE]: { + wooPPV2Address: '0xb130a49065178465931d4f887056328CeA5D723f', + wooOracleV2Address: '0x2Fe5E5D341cFFa606a5d9DA1B6B646a381B0f7ec', + integrationHelperAddress: '0xC4E9B633685461E7B7A807D12a246C81f96F31B8', + // USDbC + quoteToken: { + address: '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA', + decimals: 6, + }, + }, }, }; diff --git a/src/dex/woo-fi-v2/woo-fi-v2-e2e.test.ts b/src/dex/woo-fi-v2/woo-fi-v2-e2e.test.ts index 915364c7d..4f0ba65d6 100644 --- a/src/dex/woo-fi-v2/woo-fi-v2-e2e.test.ts +++ b/src/dex/woo-fi-v2/woo-fi-v2-e2e.test.ts @@ -213,4 +213,68 @@ describe('WooFiV2 E2E', () => { tokenQuoteAmount, ); }); + + describe('Base', () => { + const network = Network.BASE; + + const baseATokenSymbol = 'USDbC'; + const baseBTokenSymbol = 'ETH'; + + const tokenBaseAAmount = '100000000'; + const tokenBaseBAmount = '1000000000000000000'; + + const tokens = Tokens[network]; + const holders = Holders[network]; + + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${baseATokenSymbol} -> ${baseBTokenSymbol}`, async () => { + await testE2E( + tokens[baseATokenSymbol], + tokens[baseBTokenSymbol], + holders[baseATokenSymbol], + tokenBaseAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${baseBTokenSymbol} -> ${baseATokenSymbol}`, async () => { + await testE2E( + tokens[baseBTokenSymbol], + tokens[baseATokenSymbol], + holders[baseBTokenSymbol], + tokenBaseBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }), + ); + }); }); From 5af229d421bc84e8eef4a47351da0a654e16568f Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 25 Sep 2023 14:44:18 +0300 Subject: [PATCH 364/833] 2.35.7-multiple-dex-base-chain --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 24dcb0c9c..a0e309b33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.6", + "version": "2.35.7-multiple-dex-base-chain", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 0b3eb4c1f2c0387de28404d7936ef5459afde2b5 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 25 Sep 2023 15:13:24 +0300 Subject: [PATCH 365/833] uupdate config for Maverick on Base chain --- src/dex/maverick-v1/config.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dex/maverick-v1/config.ts b/src/dex/maverick-v1/config.ts index 8a9863f3a..6c4c2185f 100644 --- a/src/dex/maverick-v1/config.ts +++ b/src/dex/maverick-v1/config.ts @@ -14,12 +14,12 @@ export const MaverickV1Config: DexConfigMap = { routerAddress: '0x4a585e0f7c18e2c414221d6402652d5e0990e5f8', poolInspectorAddress: '0xaA5BF61a664109e959D69C38734d4EA7dF74e456', }, - // [Network.BASE]: { - // subgraphURL: - // 'https://api.studio.thegraph.com/query/42519/maverick-base/version/latest', - // routerAddress: '0x32AED3Bce901DA12ca8489788F3A99fCe1056e14', - // poolInspectorAddress: '0x550056A68cB155b6Cc3DeF4A7FA656260e7842e2', - // }, + [Network.BASE]: { + subgraphURL: + 'https://api.studio.thegraph.com/query/42519/maverick-base/version/latest', + routerAddress: '0x32AED3Bce901DA12ca8489788F3A99fCe1056e14', + poolInspectorAddress: '0x65A3AD03Be97619284bA7AA1E3Ca05638B9d6364', + }, }, }; From b4dde2878383135262393701f8fb1507bdf485a0 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 25 Sep 2023 15:15:01 +0300 Subject: [PATCH 366/833] 2.35.7-multiple-dex-base-chain.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a0e309b33..04eecde2e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.7-multiple-dex-base-chain", + "version": "2.35.7-multiple-dex-base-chain.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From cb93e899c1e60001d118139ad9d9b213e06b17cc Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Mon, 25 Sep 2023 14:08:36 +0100 Subject: [PATCH 367/833] chore: update mainnet rfq address + abi --- src/abi/dexalot/DexalotMainnetRFQ.json | 88 -------------------------- src/dex/dexalot/config.ts | 2 +- 2 files changed, 1 insertion(+), 89 deletions(-) diff --git a/src/abi/dexalot/DexalotMainnetRFQ.json b/src/abi/dexalot/DexalotMainnetRFQ.json index 6c3e212b2..7815c2516 100644 --- a/src/abi/dexalot/DexalotMainnetRFQ.json +++ b/src/abi/dexalot/DexalotMainnetRFQ.json @@ -366,24 +366,6 @@ "outputs": [], "stateMutability": "nonpayable" }, - { - "name": "addTrustedContract", - "type": "function", - "inputs": [ - { - "name": "_contract", - "type": "address", - "internalType": "address" - }, - { - "name": "_organization", - "type": "string", - "internalType": "string" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, { "name": "batchClaimBalance", "type": "function", @@ -575,25 +557,6 @@ ], "stateMutability": "view" }, - { - "name": "isTrustedContract", - "type": "function", - "inputs": [ - { - "name": "_contract", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, { "name": "isValidSignature", "type": "function", @@ -702,19 +665,6 @@ "outputs": [], "stateMutability": "nonpayable" }, - { - "name": "removeTrustedContract", - "type": "function", - "inputs": [ - { - "name": "_contract", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, { "name": "renounceRole", "type": "function", @@ -882,44 +832,6 @@ ], "stateMutability": "view" }, - { - "name": "trustedContractToIntegrator", - "type": "function", - "inputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "string", - "internalType": "string" - } - ], - "stateMutability": "view" - }, - { - "name": "trustedContracts", - "type": "function", - "inputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, { "name": "unpause", "type": "function", diff --git a/src/dex/dexalot/config.ts b/src/dex/dexalot/config.ts index 258d5f1a0..e69582b0e 100644 --- a/src/dex/dexalot/config.ts +++ b/src/dex/dexalot/config.ts @@ -5,7 +5,7 @@ import { Network } from '../../constants'; export const DexalotConfig: DexConfigMap = { Dexalot: { [Network.AVALANCHE]: { - mainnetRFQAddress: '0xd62f9E53Be8884C21f5aa523B3c7D6F9a0050af5', + mainnetRFQAddress: '0xEed3c159F3A96aB8d41c8B9cA49EE1e5071A7cdD', }, }, }; From 85409289bffe2d6a6c1324358988d2413b87bd45 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 25 Sep 2023 17:06:48 +0300 Subject: [PATCH 368/833] aadd Equalizer on Base chain --- src/dex/solidly/config.ts | 13 +++- src/dex/solidly/forks-override/aerodrome.ts | 2 +- src/dex/solidly/solidly-e2e.test.ts | 66 ++++++++++++++++++++- src/dex/solidly/solidly-integration.test.ts | 66 +++++++++++++++++++++ 4 files changed, 143 insertions(+), 4 deletions(-) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index b7143ffa7..c4dccd96b 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -168,6 +168,15 @@ export const SolidlyConfig: DexConfigMap = { feeCode: 0, poolGasCost: 180 * 1000, }, + [Network.BASE]: { + factoryAddress: '0xed8db60acc29e14bc867a497d94ca6e3ceb5ec04', + router: '0xDCf4EE5B700e2a5Fec458e06B763A4a3E3004494', + initCode: + '0x7ba31a081e879b8e7f06d4e8bf5ee26b5c2680669c5701f4cdbdcde51727b275', + feeCode: 0, + feeFactor: 1e18, + poolGasCost: 180 * 1000, + }, }, }; @@ -176,7 +185,7 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'PolygonAdapter02', index: 3 }], // dystopia }, [Network.FANTOM]: { - [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 10 }], // solidly + spiritSwapV2 + Equalizer + [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 10 }], // solidly, spiritSwapV2, equalizer }, [Network.OPTIMISM]: { [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 8 }], // velodrome @@ -194,6 +203,6 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'ArbitrumAdapter02', index: 1 }], // chronos, ramses }, [Network.BASE]: { - [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 3 }], // aerodrome + [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 3 }], // aerodrome, equalizer } }; diff --git a/src/dex/solidly/forks-override/aerodrome.ts b/src/dex/solidly/forks-override/aerodrome.ts index dbc82685e..ae09c0930 100644 --- a/src/dex/solidly/forks-override/aerodrome.ts +++ b/src/dex/solidly/forks-override/aerodrome.ts @@ -3,7 +3,7 @@ import { Network, NULL_ADDRESS } from '../../../constants'; import { getDexKeysWithNetwork } from '../../../utils'; import _ from 'lodash'; import { SolidlyConfig } from '../config'; -import { Address, Token } from '../../../types'; +import { Token } from '../../../types'; import { IDexHelper } from '../../../dex-helper'; import AerodromeFactoryABI from '../../../abi/aerodrome/aerodrome-pool-factory.json'; diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index d9e11541a..79bfc833a 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -1426,6 +1426,70 @@ describe('Solidly E2E', () => { tokenBAmount, nativeTokenAmount, ); - }) + }); + + describe('Equalizer', () => { + const dexKey = 'Equalizer'; + const network = Network.BASE; + + const tokenASymbol: string = 'USDbC'; + const tokenAAmount: string = '1111100000'; + const nativeTokenAmount = '110000000000000000'; + + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + // TODO: Add any direct swap contractMethod name if it exists + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }), + ); + }); }); }); diff --git a/src/dex/solidly/solidly-integration.test.ts b/src/dex/solidly/solidly-integration.test.ts index 73f50a127..73fce1d7d 100644 --- a/src/dex/solidly/solidly-integration.test.ts +++ b/src/dex/solidly/solidly-integration.test.ts @@ -1202,4 +1202,70 @@ describe('Solidly integration tests', () => { }); }); }); + + describe('Base', () => { + const network = Network.BASE; + const dexHelper = new DummyDexHelper(network); + const checkOnChainPricing = constructCheckOnChainPricing(dexHelper); + + describe('Equalizer', () => { + const dexKey = 'Equalizer'; + const equalizer = new Equalizer(network, dexKey, dexHelper); + + describe('UniswapV2 like pool', function () { + const TokenASymbol = 'USDbC'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'ETH'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts18; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await equalizer.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await equalizer.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + + for (const poolPrice of poolPrices || []) { + await checkOnChainPricing( + equalizer, + 'getAmountOut', + blocknumber, + poolPrice.prices, + poolPrice.poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + }); + }); + }); }); From a67fa6823bfb23f06f9d4b097df0570eb4f565fd Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 25 Sep 2023 20:15:15 +0300 Subject: [PATCH 369/833] add a fix for Maverick getCalldataGasCost --- src/dex/maverick-v1/maverick-v1.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/dex/maverick-v1/maverick-v1.ts b/src/dex/maverick-v1/maverick-v1.ts index 9209f49dc..b8d6b0779 100644 --- a/src/dex/maverick-v1/maverick-v1.ts +++ b/src/dex/maverick-v1/maverick-v1.ts @@ -182,8 +182,17 @@ export class MaverickV1 getCalldataGasCost( poolPrices: PoolPrices, ): number | number[] { - // TODO: update if there is any payload in getAdapterParam - return CALLDATA_GAS_COST.DEX_NO_PAYLOAD; + const gasCost = CALLDATA_GAS_COST.DEX_NO_PAYLOAD; + + const arr = new Array(poolPrices.prices.length); + poolPrices.prices.forEach((p, index) => { + if (p == 0n) { + arr[index] = 0; + } else { + arr[index] = gasCost; + } + }); + return arr; } // Returns pool prices for amounts. From 69e77d0e45c6d23d498aa96293e09f4a75064df9 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 25 Sep 2023 20:16:01 +0300 Subject: [PATCH 370/833] 2.35.7-multiple-dex-base-chain.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 04eecde2e..e3ac3a91b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.7-multiple-dex-base-chain.1", + "version": "2.35.7-multiple-dex-base-chain.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 8af918c6ad0a4e06dd209024677907861cbd4a05 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 26 Sep 2023 14:46:35 +0300 Subject: [PATCH 371/833] 2.36.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e3ac3a91b..605af44fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.7-multiple-dex-base-chain.2", + "version": "2.36.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From daeba943be39eb7f16d50e8c1d0cf9f87a89d80b Mon Sep 17 00:00:00 2001 From: Verisana Date: Tue, 26 Sep 2023 17:11:15 +0100 Subject: [PATCH 372/833] 2.35.3-quick-perps-proxy.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a9f9539aa..d81a81948 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.3-quick-perps-proxy.3", + "version": "2.35.3-quick-perps-proxy.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From b8635836370d55eff0625cb00d867c3fec389ada Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 27 Sep 2023 12:22:15 +0100 Subject: [PATCH 373/833] chore: set latest version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d81a81948..605af44fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.35.3-quick-perps-proxy.4", + "version": "2.36.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e0e23e452006278c81682f05773d4ea7e69953aa Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 27 Sep 2023 12:36:08 +0100 Subject: [PATCH 374/833] 2.36.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 605af44fd..6e65d672e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.0", + "version": "2.36.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1dcf2470a588350d2d63abcb29ae25f59cfd2b36 Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Wed, 27 Sep 2023 15:57:07 +0100 Subject: [PATCH 375/833] chore: remove token rate fetcher --- src/dex/dexalot/constants.ts | 2 - src/dex/dexalot/rate-fetcher.ts | 84 ++++++++++++--------------------- 2 files changed, 31 insertions(+), 55 deletions(-) diff --git a/src/dex/dexalot/constants.ts b/src/dex/dexalot/constants.ts index e46d3b0fb..b7f385620 100644 --- a/src/dex/dexalot/constants.ts +++ b/src/dex/dexalot/constants.ts @@ -10,8 +10,6 @@ export const DEXALOT_API_PRICES_POLLING_INTERVAL_MS = 1000; export const DEXALOT_API_PAIRS_POLLING_INTERVAL_MS = 1000 * 60 * 10; // 10 mins -export const DEXALOT_API_TOKENS_POLLING_INTERVAL_MS = 1000 * 60 * 10; // 10 mins - export const DEXALOT_API_BLACKLIST_POLLING_INTERVAL_MS = 1000 * 60 * 60; // 1 hour export const DEXALOT_API_URL = 'https://api.dexalot.com'; diff --git a/src/dex/dexalot/rate-fetcher.ts b/src/dex/dexalot/rate-fetcher.ts index 5b1cbf75c..5cba7f322 100644 --- a/src/dex/dexalot/rate-fetcher.ts +++ b/src/dex/dexalot/rate-fetcher.ts @@ -8,13 +8,11 @@ import { PairDataMap, DexalotPricesResponse, PriceDataMap, - DexalotTokensResponse, DexalotBlacklistResponse, } from './types'; import { pricesResponseValidator, pairsResponseValidator, - tokensResponseValidator, blacklistResponseValidator, } from './validators'; import { Network } from '../../constants'; @@ -28,7 +26,6 @@ export class RateFetcher { private pricesCacheKey: string; private pricesCacheTTL: number; - private tokensFetcher: Fetcher; private tokensAddrCacheKey: string; private tokensCacheKey: string; private tokensCacheTTL: number; @@ -88,24 +85,6 @@ export class RateFetcher { logger, ); - this.tokensFetcher = new Fetcher( - dexHelper.httpRequest, - { - info: { - requestOptions: config.rateConfig.tokensReqParams, - caster: (data: unknown) => { - return validateAndCast( - data, - tokensResponseValidator, - ); - }, - }, - handler: this.handleTokensResponse.bind(this), - }, - config.rateConfig.tokensIntervalMs, - logger, - ); - this.blacklistFetcher = new Fetcher( dexHelper.httpRequest, { @@ -128,22 +107,36 @@ export class RateFetcher { start() { this.pairsFetcher.startPolling(); this.rateFetcher.startPolling(); - this.tokensFetcher.startPolling(); this.blacklistFetcher.startPolling(); } stop() { this.pairsFetcher.stopPolling(); this.rateFetcher.stopPolling(); - this.tokensFetcher.stopPolling(); this.blacklistFetcher.stopPolling(); } private handlePairsResponse(resp: DexalotPairsResponse): void { - const { pairs } = resp; + const pairs = resp; const dexPairs: PairDataMap = {}; + const tokenMap: { [address: string]: Token } = {}; + const tokenAddrMap: { [symbol: string]: string } = {}; Object.keys(pairs).forEach(pair => { dexPairs[pair.toLowerCase()] = pairs[pair]; + tokenAddrMap[pairs[pair].base.toLowerCase()] = + pairs[pair].baseAddress.toLowerCase(); + tokenAddrMap[pairs[pair].quote.toLowerCase()] = + pairs[pair].quoteAddress.toLowerCase(); + tokenMap[pairs[pair].baseAddress.toLowerCase()] = { + address: pairs[pair].baseAddress.toLowerCase(), + symbol: pairs[pair].base, + decimals: pairs[pair].baseDecimals, + }; + tokenMap[pairs[pair].quoteAddress.toLowerCase()] = { + address: pairs[pair].quoteAddress.toLowerCase(), + symbol: pairs[pair].quote, + decimals: pairs[pair].quoteDecimals, + }; }); this.dexHelper.cache.setex( this.dexKey, @@ -152,6 +145,20 @@ export class RateFetcher { this.pairsCacheTTL, JSON.stringify(dexPairs), ); + this.dexHelper.cache.setex( + this.dexKey, + this.network, + this.tokensCacheKey, + this.tokensCacheTTL, + JSON.stringify(tokenMap), + ); + this.dexHelper.cache.setex( + this.dexKey, + this.network, + this.tokensAddrCacheKey, + this.tokensCacheTTL, + JSON.stringify(tokenAddrMap), + ); } private handleRatesResponse(resp: DexalotPricesResponse): void { @@ -169,35 +176,6 @@ export class RateFetcher { ); } - private handleTokensResponse(resp: DexalotTokensResponse): void { - const { tokens } = resp; - const tokenMap: { [address: string]: Token } = {}; - const tokenAddrMap: { [pair: string]: string } = {}; - Object.keys(tokens).forEach(symbol => { - const token = tokens[symbol]; - tokenMap[token.address.toLowerCase()] = { - address: token.address.toLowerCase(), - symbol: token.symbol, - decimals: token.decimals, - }; - tokenAddrMap[token.symbol.toLowerCase()] = token.address.toLowerCase(); - }); - this.dexHelper.cache.setex( - this.dexKey, - this.network, - this.tokensCacheKey, - this.tokensCacheTTL, - JSON.stringify(tokenMap), - ); - this.dexHelper.cache.setex( - this.dexKey, - this.network, - this.tokensAddrCacheKey, - this.tokensCacheTTL, - JSON.stringify(tokenAddrMap), - ); - } - private async handleBlacklistResponse( resp: DexalotBlacklistResponse, ): Promise { From c07f6c7004b80f03f49f1b8513b32d1696e41401 Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Wed, 27 Sep 2023 16:31:25 +0100 Subject: [PATCH 376/833] chore: modify api resp + add chainid --- src/dex/dexalot/dexalot.ts | 17 ++++++++--------- src/dex/dexalot/types.ts | 36 +++++++++++++---------------------- src/dex/dexalot/validators.ts | 13 ++++++++----- 3 files changed, 29 insertions(+), 37 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index b9bcc537d..505ba89af 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -47,13 +47,11 @@ import { DEXALOT_GAS_COST, DEXALOT_PAIRS_CACHES_TTL_S, DEXALOT_API_PAIRS_POLLING_INTERVAL_MS, - DEXALOT_API_TOKENS_POLLING_INTERVAL_MS, DEXALOT_TOKENS_CACHES_TTL_S, DEXALOT_API_BLACKLIST_POLLING_INTERVAL_MS, DEXALOT_RATE_LIMITED_TTL_S, } from './constants'; import { BI_MAX_UINT256 } from '../../bigint-constants'; -import { TooStrictSlippageCheckError } from '../generic-rfq/types'; import { ethers } from 'ethers'; import BigNumber from 'bignumber.js'; @@ -111,24 +109,23 @@ export class Dexalot extends SimpleExchange implements IDex { rateConfig: { pairsIntervalMs: DEXALOT_API_PAIRS_POLLING_INTERVAL_MS, pricesIntervalMs: DEXALOT_API_PRICES_POLLING_INTERVAL_MS, - tokensIntervalMs: DEXALOT_API_TOKENS_POLLING_INTERVAL_MS, blacklistIntervalMs: DEXALOT_API_BLACKLIST_POLLING_INTERVAL_MS, pairsReqParams: { url: `${DEXALOT_API_URL}/api/rfq/pairs`, headers: { 'x-apikey': this.dexalotAuthToken, }, + params: { + chainid: this.network, + }, }, pricesReqParams: { url: `${DEXALOT_API_URL}/api/rfq/prices`, headers: { 'x-apikey': this.dexalotAuthToken, }, - }, - tokensReqParams: { - url: `${DEXALOT_API_URL}/api/rfq/tokens`, - headers: { - 'x-apikey': this.dexalotAuthToken, + params: { + chainid: this.network, }, }, blacklistReqParams: { @@ -505,6 +502,7 @@ export class Dexalot extends SimpleExchange implements IDex { takerAmount: side === SwapSide.SELL ? optimalSwapExchange.srcAmount : undefined, userAddress: options.txOrigin, + chainid: this.network, }; const rfq: RFQResponse = await this.dexHelper.httpRequest.post( @@ -518,9 +516,10 @@ export class Dexalot extends SimpleExchange implements IDex { 'Missing quote data', `RFQ ${swapIdentifier} ${JSON.stringify(rfq)}`, ); - } else if (!rfq.order.signature) { + } else if (!rfq.signature) { this.generateRFQError('Missing signature', swapIdentifier); } + rfq.order.signature = rfq.signature; const { order } = rfq; diff --git a/src/dex/dexalot/types.ts b/src/dex/dexalot/types.ts index fba44c1cd..841fcddf6 100644 --- a/src/dex/dexalot/types.ts +++ b/src/dex/dexalot/types.ts @@ -10,11 +10,12 @@ type RFQOrder = { taker: string; makerAmount: string; takerAmount: string; - signature: string; + signature?: string; }; export type RFQResponse = { order: RFQOrder; + signature: string; }; export type RFQResponseError = { @@ -52,8 +53,18 @@ export type PairDataMap = { [pair: string]: PairData; }; +export type PairDataResp = { + base: string; + quote: string; + liquidityUSD: number; + baseAddress: string; + quoteAddress: string; + baseDecimals: number; + quoteDecimals: number; +}; + export type DexalotPairsResponse = { - pairs: PairDataMap; + [pair: string]: PairDataResp; }; type PriceData = { @@ -73,25 +84,10 @@ export type TokenAddrDataMap = { [symbol: string]: string; }; -type TokenData = { - symbol: string; - name: string; - description: string; - address: any; - decimals: number; - type: string; -}; - export type TokenDataMap = { [address: string]: Token; }; -export type DexalotTokensResponse = { - tokens: { - [token: string]: TokenData; - }; -}; - export type DexalotBlacklistResponse = { blacklist: string[]; }; @@ -108,11 +104,6 @@ export type DexalotRateFetcherConfig = { headers?: RequestHeaders; params?: any; }; - tokensReqParams: { - url: string; - headers?: RequestHeaders; - params?: any; - }; blacklistReqParams: { url: string; headers?: RequestHeaders; @@ -120,7 +111,6 @@ export type DexalotRateFetcherConfig = { }; pairsIntervalMs: number; pricesIntervalMs: number; - tokensIntervalMs: number; blacklistIntervalMs: number; pairsCacheKey: string; pricesCacheKey: string; diff --git a/src/dex/dexalot/validators.ts b/src/dex/dexalot/validators.ts index 52ca64a57..89a2e11e1 100644 --- a/src/dex/dexalot/validators.ts +++ b/src/dex/dexalot/validators.ts @@ -4,17 +4,20 @@ const pairValidator = joi.object({ base: joi.string().min(1).required(), quote: joi.string().min(1).required(), liquidityUSD: joi.number().min(0).required(), + baseAddress: joi.string().min(1).required(), + quoteAddress: joi.string().min(1).required(), + baseDecimals: joi.number().min(0).required(), + quoteDecimals: joi.number().min(0).required(), }); -export const pairsResponseValidator = joi.object({ - pairs: joi.object().pattern(joi.string(), pairValidator), -}); +export const pairsResponseValidator = joi + .object() + .pattern(joi.string(), pairValidator); const orderbookRecordValidator = joi .array() .items(joi.string().min(1)) - .length(2) - .required(); + .length(2); const orderbookValidator = joi.object({ bids: joi.array().items(orderbookRecordValidator).required(), From 145603fea1c50d877b7e7e63dae89da90cea8146 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 27 Sep 2023 21:33:54 +0300 Subject: [PATCH 377/833] add minor fixes --- src/dex/dexalot/dexalot-e2e.test.ts | 4 ++-- src/dex/dexalot/dexalot.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/dex/dexalot/dexalot-e2e.test.ts b/src/dex/dexalot/dexalot-e2e.test.ts index 59a872f47..c81393c9f 100644 --- a/src/dex/dexalot/dexalot-e2e.test.ts +++ b/src/dex/dexalot/dexalot-e2e.test.ts @@ -32,8 +32,8 @@ function testForNetwork( const sleepMs = 5000; const sideToContractMethods = new Map([ - [SwapSide.SELL, [ContractMethod.simpleSwap]], - [SwapSide.BUY, [ContractMethod.simpleBuy]], + [SwapSide.SELL, [ContractMethod.simpleSwap, ContractMethod.megaSwap, ContractMethod.multiSwap]], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], ]); describe(`${network}`, () => { diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index b9bcc537d..1d7d6aa7c 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -371,7 +371,7 @@ export class Dexalot extends SimpleExchange implements IDex { return null; } - if (limitPools && limitPools.length != 1) { + if (limitPools && limitPools.length !== 1) { return null; } @@ -438,7 +438,6 @@ export class Dexalot extends SimpleExchange implements IDex { }, ]; } catch (e: unknown) { - this.logger.error(e); this.logger.error( `Error_getPricesVolume ${srcToken.symbol || srcToken.address}, ${ destToken.symbol || destToken.address From 94e98088fdd5d9de2a3805806ac5224eaa9b7b19 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 28 Sep 2023 01:14:22 +0300 Subject: [PATCH 378/833] feat: implement uniswapv3, pancakev3 factories & setup pool creation subscription --- .../PancakeswapV3Factory.abi.json | 300 ++++++++++++++++++ src/dex/algebra/algebra-factory.ts | 3 +- src/dex/algebra/algebra.ts | 10 +- src/dex/my-test-dex/config.ts | 15 + src/dex/my-test-dex/my-test-dex-e2e.test.ts | 162 ++++++++++ .../my-test-dex/my-test-dex-events.test.ts | 106 +++++++ .../my-test-dex-integration.test.ts | 251 +++++++++++++++ src/dex/my-test-dex/my-test-dex-pool.ts | 91 ++++++ src/dex/my-test-dex/my-test-dex.ts | 178 +++++++++++ src/dex/my-test-dex/types.ts | 22 ++ .../pancakeswap-v3/pancakeswap-v3-factory.ts | 69 ++++ src/dex/pancakeswap-v3/pancakeswap-v3.ts | 39 +++ src/dex/uniswap-v3/uniswap-v3-factory.ts | 69 ++++ src/dex/uniswap-v3/uniswap-v3.ts | 36 +++ 14 files changed, 1347 insertions(+), 4 deletions(-) create mode 100644 src/abi/pancakeswap-v3/PancakeswapV3Factory.abi.json create mode 100644 src/dex/my-test-dex/config.ts create mode 100644 src/dex/my-test-dex/my-test-dex-e2e.test.ts create mode 100644 src/dex/my-test-dex/my-test-dex-events.test.ts create mode 100644 src/dex/my-test-dex/my-test-dex-integration.test.ts create mode 100644 src/dex/my-test-dex/my-test-dex-pool.ts create mode 100644 src/dex/my-test-dex/my-test-dex.ts create mode 100644 src/dex/my-test-dex/types.ts create mode 100644 src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts create mode 100644 src/dex/uniswap-v3/uniswap-v3-factory.ts diff --git a/src/abi/pancakeswap-v3/PancakeswapV3Factory.abi.json b/src/abi/pancakeswap-v3/PancakeswapV3Factory.abi.json new file mode 100644 index 000000000..aaaddbdab --- /dev/null +++ b/src/abi/pancakeswap-v3/PancakeswapV3Factory.abi.json @@ -0,0 +1,300 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "_poolDeployer", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "indexed": true, + "internalType": "int24", + "name": "tickSpacing", + "type": "int24" + } + ], + "name": "FeeAmountEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "indexed": false, + "internalType": "bool", + "name": "whitelistRequested", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "FeeAmountExtraInfoUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnerChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint24", + "name": "fee", + "type": "uint24" + }, + { + "indexed": false, + "internalType": "int24", + "name": "tickSpacing", + "type": "int24" + }, + { + "indexed": false, + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "lmPoolDeployer", + "type": "address" + } + ], + "name": "SetLmPoolDeployer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "verified", + "type": "bool" + } + ], + "name": "WhiteListAdded", + "type": "event" + }, + { + "inputs": [ + { "internalType": "address", "name": "pool", "type": "address" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { + "internalType": "uint128", + "name": "amount0Requested", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Requested", + "type": "uint128" + } + ], + "name": "collectProtocol", + "outputs": [ + { "internalType": "uint128", "name": "amount0", "type": "uint128" }, + { "internalType": "uint128", "name": "amount1", "type": "uint128" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenA", "type": "address" }, + { "internalType": "address", "name": "tokenB", "type": "address" }, + { "internalType": "uint24", "name": "fee", "type": "uint24" } + ], + "name": "createPool", + "outputs": [ + { "internalType": "address", "name": "pool", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint24", "name": "fee", "type": "uint24" }, + { "internalType": "int24", "name": "tickSpacing", "type": "int24" } + ], + "name": "enableFeeAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint24", "name": "", "type": "uint24" }], + "name": "feeAmountTickSpacing", + "outputs": [{ "internalType": "int24", "name": "", "type": "int24" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint24", "name": "", "type": "uint24" }], + "name": "feeAmountTickSpacingExtraInfo", + "outputs": [ + { "internalType": "bool", "name": "whitelistRequested", "type": "bool" }, + { "internalType": "bool", "name": "enabled", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "uint24", "name": "", "type": "uint24" } + ], + "name": "getPool", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lmPoolDeployer", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolDeployer", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint24", "name": "fee", "type": "uint24" }, + { "internalType": "bool", "name": "whitelistRequested", "type": "bool" }, + { "internalType": "bool", "name": "enabled", "type": "bool" } + ], + "name": "setFeeAmountExtraInfo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pool", "type": "address" }, + { "internalType": "uint32", "name": "feeProtocol0", "type": "uint32" }, + { "internalType": "uint32", "name": "feeProtocol1", "type": "uint32" } + ], + "name": "setFeeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "pool", "type": "address" }, + { "internalType": "address", "name": "lmPool", "type": "address" } + ], + "name": "setLmPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_lmPoolDeployer", + "type": "address" + } + ], + "name": "setLmPoolDeployer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_owner", "type": "address" } + ], + "name": "setOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "user", "type": "address" }, + { "internalType": "bool", "name": "verified", "type": "bool" } + ], + "name": "setWhiteListAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/dex/algebra/algebra-factory.ts b/src/dex/algebra/algebra-factory.ts index 328936431..8abb0cf14 100644 --- a/src/dex/algebra/algebra-factory.ts +++ b/src/dex/algebra/algebra-factory.ts @@ -4,6 +4,7 @@ import FactoryABI from '../../abi/algebra/AlgebraFactory-v1_1.abi.json'; import { IDexHelper } from '../../dex-helper/idex-helper'; import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; import { Address, Log, Logger } from '../../types'; +import { LogDescription } from 'ethers/lib/utils'; export type OnPoolCreatedCallback = ({ token0, @@ -56,7 +57,7 @@ export class AlgebraFactory extends StatefulEventSubscriber { return null; } - handleNewPool(event: any) { + handleNewPool(event: LogDescription) { const token0 = event.args.token0; const token1 = event.args.token1; diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 69de19639..bc18ddd4d 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -60,6 +60,7 @@ const MAX_STALE_STATE_BLOCK_AGE = { type IAlgebraEventPool = AlgebraEventPoolV1_1 | AlgebraEventPoolV1_9; export class Algebra extends SimpleExchange implements IDex { + private readonly factory: AlgebraFactory; readonly isFeeOnTransferSupported: boolean = false; protected eventPools: Record = {}; @@ -116,12 +117,12 @@ export class Algebra extends SimpleExchange implements IDex { this.AlgebraPoolImplem = config.version === 'v1.1' ? AlgebraEventPoolV1_1 : AlgebraEventPoolV1_9; - new AlgebraFactory( + this.factory = new AlgebraFactory( dexHelper, dexKey, this.config.factory, this.logger, - this.onPoolCreatedDeleteFromNonExistingSet, + this.onPoolCreatedDeleteFromNonExistingSet.bind(this), ); } @@ -135,6 +136,9 @@ export class Algebra extends SimpleExchange implements IDex { } async initializePricing(blockNumber: number) { + // Init listening to new pools creation + this.factory.initialize(blockNumber); + if (!this.dexHelper.config.isSlave) { const cleanExpiredNotExistingPoolsKeys = async () => { const maxTimestamp = @@ -154,7 +158,7 @@ export class Algebra extends SimpleExchange implements IDex { } /* - * When a non exisiting pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls + * When a non existing pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls * Once the pool is created, it gets immediately flagged */ onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ diff --git a/src/dex/my-test-dex/config.ts b/src/dex/my-test-dex/config.ts new file mode 100644 index 000000000..8392c2da8 --- /dev/null +++ b/src/dex/my-test-dex/config.ts @@ -0,0 +1,15 @@ +import { DexParams } from './types'; +import { DexConfigMap, AdapterMappings } from '../../types'; +import { Network, SwapSide } from '../../constants'; + +export const MyTestDexConfig: DexConfigMap = { + MyTestDex: { + // TODO: complete me! + }, +}; + +export const Adapters: Record = { + // TODO: add adapters for each chain + // This is an example to copy + [Network.MAINNET]: { [SwapSide.SELL]: [{ name: '', index: 0 }] }, +}; diff --git a/src/dex/my-test-dex/my-test-dex-e2e.test.ts b/src/dex/my-test-dex/my-test-dex-e2e.test.ts new file mode 100644 index 000000000..cf46cb26d --- /dev/null +++ b/src/dex/my-test-dex/my-test-dex-e2e.test.ts @@ -0,0 +1,162 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { testE2E } from '../../../tests/utils-e2e'; +import { + Tokens, + Holders, + NativeTokenSymbols, +} from '../../../tests/constants-e2e'; +import { Network, ContractMethod, SwapSide } from '../../constants'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; + +/* + README + ====== + + This test script should add e2e tests for MyTestDex. The tests + should cover as many cases as possible. Most of the DEXes follow + the following test structure: + - DexName + - ForkName + Network + - ContractMethod + - ETH -> Token swap + - Token -> ETH swap + - Token -> Token swap + + The template already enumerates the basic structure which involves + testing simpleSwap, multiSwap, megaSwap contract methods for + ETH <> TOKEN and TOKEN <> TOKEN swaps. You should replace tokenA and + tokenB with any two highly liquid tokens on MyTestDex for the tests + to work. If the tokens that you would like to use are not defined in + Tokens or Holders map, you can update the './tests/constants-e2e' + + Other than the standard cases that are already added by the template + it is highly recommended to add test cases which could be specific + to testing MyTestDex (Eg. Tests based on poolType, special tokens, + etc). + + You can run this individual test script by running: + `npx jest src/dex//-e2e.test.ts` + + e2e tests use the Tenderly fork api. Please add the following to your + .env file: + TENDERLY_TOKEN=Find this under Account>Settings>Authorization. + TENDERLY_ACCOUNT_ID=Your Tenderly account name. + TENDERLY_PROJECT=Name of a Tenderly project you have created in your + dashboard. + + (This comment should be removed from the final implementation) +*/ + +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + // TODO: Add any direct swap contractMethod name if it exists + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + // TODO: If buy is not supported remove the buy contract methods + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + 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, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }), + ); + }); +} + +describe('MyTestDex E2E', () => { + const dexKey = 'MyTestDex'; + + describe('Mainnet', () => { + const network = Network.MAINNET; + + // TODO: Modify the tokenASymbol, tokenBSymbol, tokenAAmount; + const tokenASymbol: string = 'tokenASymbol'; + const tokenBSymbol: string = 'tokenBSymbol'; + + const tokenAAmount: string = 'tokenAAmount'; + const tokenBAmount: string = 'tokenBAmount'; + const nativeTokenAmount = '1000000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + + // TODO: Add any additional test cases required to test MyTestDex + }); +}); diff --git a/src/dex/my-test-dex/my-test-dex-events.test.ts b/src/dex/my-test-dex/my-test-dex-events.test.ts new file mode 100644 index 000000000..54032410d --- /dev/null +++ b/src/dex/my-test-dex/my-test-dex-events.test.ts @@ -0,0 +1,106 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { MyTestDexEventPool } from './my-test-dex-pool'; +import { Network } from '../../constants'; +import { Address } from '../../types'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { testEventSubscriber } from '../../../tests/utils-events'; +import { PoolState } from './types'; + +/* + README + ====== + + This test script adds unit tests for MyTestDex event based + system. This is done by fetching the state on-chain before the + event block, manually pushing the block logs to the event-subscriber, + comparing the local state with on-chain state. + + Most of the logic for testing is abstracted by `testEventSubscriber`. + You need to do two things to make the tests work: + + 1. Fetch the block numbers where certain events were released. You + can modify the `./scripts/fetch-event-blocknumber.ts` to get the + block numbers for different events. Make sure to get sufficient + number of blockNumbers to cover all possible cases for the event + mutations. + + 2. Complete the implementation for fetchPoolState function. The + function should fetch the on-chain state of the event subscriber + using just the blocknumber. + + The template tests only include the test for a single event + subscriber. There can be cases where multiple event subscribers + exist for a single DEX. In such cases additional tests should be + added. + + You can run this individual test script by running: + `npx jest src/dex//-events.test.ts` + + (This comment should be removed from the final implementation) +*/ + +jest.setTimeout(50 * 1000); + +async function fetchPoolState( + myTestDexPools: MyTestDexEventPool, + blockNumber: number, + poolAddress: string, +): Promise { + // TODO: complete me! + return {}; +} + +// eventName -> blockNumbers +type EventMappings = Record; + +describe('MyTestDex EventPool Mainnet', function () { + const dexKey = 'MyTestDex'; + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + const logger = dexHelper.getLogger(dexKey); + let myTestDexPool: MyTestDexEventPool; + + // poolAddress -> EventMappings + const eventsToTest: Record = { + // TODO: complete me! + }; + + beforeEach(async () => { + myTestDexPool = new MyTestDexEventPool( + dexKey, + network, + dexHelper, + logger, + /* TODO: Put here additional constructor arguments if needed */ + ); + }); + + Object.entries(eventsToTest).forEach( + ([poolAddress, events]: [string, EventMappings]) => { + describe(`Events for ${poolAddress}`, () => { + Object.entries(events).forEach( + ([eventName, blockNumbers]: [string, number[]]) => { + describe(`${eventName}`, () => { + blockNumbers.forEach((blockNumber: number) => { + it(`State after ${blockNumber}`, async function () { + await testEventSubscriber( + myTestDexPool, + myTestDexPool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolState(myTestDexPool, _blockNumber, poolAddress), + blockNumber, + `${dexKey}_${poolAddress}`, + dexHelper.provider, + ); + }); + }); + }); + }, + ); + }); + }, + ); +}); diff --git a/src/dex/my-test-dex/my-test-dex-integration.test.ts b/src/dex/my-test-dex/my-test-dex-integration.test.ts new file mode 100644 index 000000000..5520bc110 --- /dev/null +++ b/src/dex/my-test-dex/my-test-dex-integration.test.ts @@ -0,0 +1,251 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { Interface, Result } from '@ethersproject/abi'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { Network, SwapSide } from '../../constants'; +import { BI_POWS } from '../../bigint-constants'; +import { MyTestDex } from './my-test-dex'; +import { + checkPoolPrices, + checkPoolsLiquidity, + checkConstantPoolPrices, +} from '../../../tests/utils'; +import { Tokens } from '../../../tests/constants-e2e'; + +/* + README + ====== + + This test script adds tests for MyTestDex general integration + with the DEX interface. The test cases below are example tests. + It is recommended to add tests which cover MyTestDex specific + logic. + + You can run this individual test script by running: + `npx jest src/dex//-integration.test.ts` + + (This comment should be removed from the final implementation) +*/ + +function getReaderCalldata( + exchangeAddress: string, + readerIface: Interface, + amounts: bigint[], + funcName: string, + // TODO: Put here additional arguments you need +) { + return amounts.map(amount => ({ + target: exchangeAddress, + callData: readerIface.encodeFunctionData(funcName, [ + // TODO: Put here additional arguments to encode them + amount, + ]), + })); +} + +function decodeReaderResult( + results: Result, + readerIface: Interface, + funcName: string, +) { + // TODO: Adapt this function for your needs + return results.map(result => { + const parsed = readerIface.decodeFunctionResult(funcName, result); + return BigInt(parsed[0]._hex); + }); +} + +async function checkOnChainPricing( + myTestDex: MyTestDex, + funcName: string, + blockNumber: number, + prices: bigint[], + amounts: bigint[], +) { + const exchangeAddress = ''; // TODO: Put here the real exchange address + + // TODO: Replace dummy interface with the real one + // Normally you can get it from myTestDex.Iface or from eventPool. + // It depends on your implementation + const readerIface = new Interface(''); + + const readerCallData = getReaderCalldata( + exchangeAddress, + readerIface, + amounts.slice(1), + funcName, + ); + const readerResult = ( + await myTestDex.dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blockNumber) + ).returnData; + + const expectedPrices = [0n].concat( + decodeReaderResult(readerResult, readerIface, funcName), + ); + + expect(prices).toEqual(expectedPrices); +} + +async function testPricingOnNetwork( + myTestDex: MyTestDex, + network: Network, + dexKey: string, + blockNumber: number, + srcTokenSymbol: string, + destTokenSymbol: string, + side: SwapSide, + amounts: bigint[], + funcNameToCheck: string, +) { + const networkTokens = Tokens[network]; + + const pools = await myTestDex.getPoolIdentifiers( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + side, + blockNumber, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await myTestDex.getPricesVolume( + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + amounts, + side, + blockNumber, + pools, + ); + console.log( + `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + if (myTestDex.hasConstantPriceLargeAmounts) { + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + } else { + checkPoolPrices(poolPrices!, amounts, side, dexKey); + } + + // Check if onchain pricing equals to calculated ones + await checkOnChainPricing( + myTestDex, + funcNameToCheck, + blockNumber, + poolPrices![0].prices, + amounts, + ); +} + +describe('MyTestDex', function () { + const dexKey = 'MyTestDex'; + let blockNumber: number; + let myTestDex: MyTestDex; + + describe('Mainnet', () => { + const network = Network.MAINNET; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + + // TODO: Put here token Symbol to check against + // Don't forget to update relevant tokens in constant-e2e.ts + const srcTokenSymbol = 'srcTokenSymbol'; + const destTokenSymbol = 'destTokenSymbol'; + + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals], + 2n * BI_POWS[tokens[destTokenSymbol].decimals], + 3n * BI_POWS[tokens[destTokenSymbol].decimals], + 4n * BI_POWS[tokens[destTokenSymbol].decimals], + 5n * BI_POWS[tokens[destTokenSymbol].decimals], + 6n * BI_POWS[tokens[destTokenSymbol].decimals], + 7n * BI_POWS[tokens[destTokenSymbol].decimals], + 8n * BI_POWS[tokens[destTokenSymbol].decimals], + 9n * BI_POWS[tokens[destTokenSymbol].decimals], + 10n * BI_POWS[tokens[destTokenSymbol].decimals], + ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + myTestDex = new MyTestDex(network, dexKey, dexHelper); + if (myTestDex.initializePricing) { + await myTestDex.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + myTestDex, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + '', // TODO: Put here proper function name to check pricing + ); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + myTestDex, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + '', // TODO: Put here proper function name to check pricing + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newMyTestDex = new MyTestDex(network, dexKey, dexHelper); + if (newMyTestDex.updatePoolState) { + await newMyTestDex.updatePoolState(); + } + const poolLiquidity = await newMyTestDex.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newMyTestDex.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); + }); +}); diff --git a/src/dex/my-test-dex/my-test-dex-pool.ts b/src/dex/my-test-dex/my-test-dex-pool.ts new file mode 100644 index 000000000..f46402ec8 --- /dev/null +++ b/src/dex/my-test-dex/my-test-dex-pool.ts @@ -0,0 +1,91 @@ +import { Interface } from '@ethersproject/abi'; +import { DeepReadonly } from 'ts-essentials'; +import { Log, Logger } from '../../types'; +import { catchParseLogError } from '../../utils'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { PoolState } from './types'; + +export class MyTestDexEventPool extends StatefulEventSubscriber { + handlers: { + [event: string]: ( + event: any, + state: DeepReadonly, + log: Readonly, + ) => DeepReadonly | null; + } = {}; + + logDecoder: (log: Log) => any; + + addressesSubscribed: string[]; + + constructor( + readonly parentName: string, + protected network: number, + protected dexHelper: IDexHelper, + logger: Logger, + protected myTestDexIface = new Interface( + '' /* TODO: Import and put here MyTestDex ABI */, + ), // TODO: add any additional params required for event subscriber + ) { + // TODO: Add pool name + super(parentName, 'POOL_NAME', dexHelper, logger); + + // TODO: make logDecoder decode logs that + this.logDecoder = (log: Log) => this.myTestDexIface.parseLog(log); + this.addressesSubscribed = [ + /* subscribed addresses */ + ]; + + // Add handlers + this.handlers['myEvent'] = this.handleMyEvent.bind(this); + } + + /** + * The function is called every time any of the subscribed + * addresses release log. The function accepts the current + * state, updates the state according to the log, and returns + * the updated state. + * @param state - Current state of event subscriber + * @param log - Log released by one of the subscribed addresses + * @returns Updates state of the event subscriber after the log + */ + protected processLog( + state: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + try { + const event = this.logDecoder(log); + if (event.name in this.handlers) { + return this.handlers[event.name](event, state, log); + } + } catch (e) { + catchParseLogError(e, this.logger); + } + + return null; + } + + /** + * The function generates state using on-chain calls. This + * function is called to regenerate state if the event based + * system fails to fetch events and the local state is no + * more correct. + * @param blockNumber - Blocknumber for which the state should + * should be generated + * @returns state of the event subscriber at blocknumber + */ + async generateState(blockNumber: number): Promise> { + // TODO: complete me! + return {}; + } + + // Its just a dummy example + handleMyEvent( + event: any, + state: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + return null; + } +} diff --git a/src/dex/my-test-dex/my-test-dex.ts b/src/dex/my-test-dex/my-test-dex.ts new file mode 100644 index 000000000..80adef17f --- /dev/null +++ b/src/dex/my-test-dex/my-test-dex.ts @@ -0,0 +1,178 @@ +import { AsyncOrSync } from 'ts-essentials'; +import { + Token, + Address, + ExchangePrices, + PoolPrices, + AdapterExchangeParam, + SimpleExchangeParam, + PoolLiquidity, + Logger, +} from '../../types'; +import { SwapSide, Network } from '../../constants'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { getDexKeysWithNetwork } from '../../utils'; +import { IDex } from '../../dex/idex'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { MyTestDexData } from './types'; +import { SimpleExchange } from '../simple-exchange'; +import { MyTestDexConfig, Adapters } from './config'; +import { MyTestDexEventPool } from './my-test-dex-pool'; + +export class MyTestDex extends SimpleExchange implements IDex { + protected eventPools: MyTestDexEventPool; + + readonly hasConstantPriceLargeAmounts = false; + // TODO: set true here if protocols works only with wrapped asset + readonly needWrapNative = true; + + readonly isFeeOnTransferSupported = false; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(MyTestDexConfig); + + logger: Logger; + + constructor( + readonly network: Network, + readonly dexKey: string, + readonly dexHelper: IDexHelper, + protected adapters = Adapters[network] || {}, // TODO: add any additional optional params to support other fork DEXes + ) { + super(dexHelper, dexKey); + this.logger = dexHelper.getLogger(dexKey); + this.eventPools = new MyTestDexEventPool( + dexKey, + network, + dexHelper, + this.logger, + ); + } + + // Initialize pricing is called once in the start of + // pricing service. It is intended to setup the integration + // for pricing requests. It is optional for a DEX to + // implement this function + async initializePricing(blockNumber: number) { + // TODO: complete me! + } + + // Returns the list of contract adapters (name and index) + // for a buy/sell. Return null if there are no adapters. + getAdapters(side: SwapSide): { name: string; index: number }[] | null { + return this.adapters[side] ? this.adapters[side] : null; + } + + // Returns list of pool identifiers that can be used + // for a given swap. poolIdentifiers must be unique + // across DEXes. It is recommended to use + // ${dexKey}_${poolAddress} as a poolIdentifier + async getPoolIdentifiers( + srcToken: Token, + destToken: Token, + side: SwapSide, + blockNumber: number, + ): Promise { + // TODO: complete me! + return []; + } + + // Returns pool prices for amounts. + // If limitPools is defined only pools in limitPools + // should be used. If limitPools is undefined then + // any pools can be used. + async getPricesVolume( + srcToken: Token, + destToken: Token, + amounts: bigint[], + side: SwapSide, + blockNumber: number, + limitPools?: string[], + ): Promise> { + // TODO: complete me! + return null; + } + + // Returns estimated gas cost of calldata for this DEX in multiSwap + getCalldataGasCost(poolPrices: PoolPrices): number | number[] { + // TODO: update if there is any payload in getAdapterParam + return CALLDATA_GAS_COST.DEX_NO_PAYLOAD; + } + + // Encode params required by the exchange adapter + // Used for multiSwap, buy & megaSwap + // Hint: abiCoder.encodeParameter() could be useful + getAdapterParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: MyTestDexData, + side: SwapSide, + ): AdapterExchangeParam { + // TODO: complete me! + const { exchange } = data; + + // Encode here the payload for adapter + const payload = ''; + + return { + targetExchange: exchange, + payload, + networkFee: '0', + }; + } + + // Encode call data used by simpleSwap like routers + // Used for simpleSwap & simpleBuy + // Hint: this.buildSimpleParamWithoutWETHConversion + // could be useful + async getSimpleParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: MyTestDexData, + side: SwapSide, + ): Promise { + // TODO: complete me! + const { exchange } = data; + + // Encode here the transaction arguments + const swapData = ''; + + return this.buildSimpleParamWithoutWETHConversion( + srcToken, + srcAmount, + destToken, + destAmount, + swapData, + exchange, + ); + } + + // This is called once before getTopPoolsForToken is + // called for multiple tokens. This can be helpful to + // update common state required for calculating + // getTopPoolsForToken. It is optional for a DEX + // to implement this + async updatePoolState(): Promise { + // TODO: complete me! + } + + // Returns list of top pools based on liquidity. Max + // limit number pools should be returned. + async getTopPoolsForToken( + tokenAddress: Address, + limit: number, + ): Promise { + //TODO: complete me! + return []; + } + + // This is optional function in case if your implementation has acquired any resources + // you need to release for graceful shutdown. For example, it may be any interval timer + releaseResources(): AsyncOrSync { + // TODO: complete me! + } +} diff --git a/src/dex/my-test-dex/types.ts b/src/dex/my-test-dex/types.ts new file mode 100644 index 000000000..85bd58ae3 --- /dev/null +++ b/src/dex/my-test-dex/types.ts @@ -0,0 +1,22 @@ +import { Address } from '../../types'; + +export type PoolState = { + // TODO: poolState is the state of event + // subscriber. This should be the minimum + // set of parameters required to compute + // pool prices. Complete me! +}; + +export type MyTestDexData = { + // TODO: MyTestDexData is the dex data that is + // returned by the API that can be used for + // tx building. The data structure should be minimal. + // Complete me! + exchange: Address; +}; + +export type DexParams = { + // TODO: DexParams is set of parameters the can + // be used to initiate a DEX fork. + // Complete me! +}; diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts b/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts new file mode 100644 index 000000000..4cd6f1b18 --- /dev/null +++ b/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts @@ -0,0 +1,69 @@ +import { Interface } from '@ethersproject/abi'; +import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; +import FactoryABI from '../../abi/pancakeswap-v3/PancakeswapV3Factory.abi.json'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { Address, Log, Logger } from '../../types'; +import { LogDescription } from 'ethers/lib/utils'; + +export type OnPoolCreatedCallback = ({ + token0, + token1, + fee, +}: { + token0: string; + token1: string; + fee: bigint; +}) => AsyncOrSync; + +/* + * Stateless event subscriber in order to capture "Pool" event on new pools created. + */ +export class PancakeswapV3Factory extends StatefulEventSubscriber { + handlers: { + [event: string]: (event: any) => DeepReadonly | null; + } = {}; + + logDecoder: (log: Log) => any; + + public readonly factoryIface = new Interface(FactoryABI); + + constructor( + readonly dexHelper: IDexHelper, + parentName: string, + protected readonly factoryAddress: Address, + logger: Logger, + protected readonly onPoolCreated: OnPoolCreatedCallback, + mapKey: string = '', + ) { + super(parentName, `factory`, dexHelper, logger, true, mapKey); + + this.addressesSubscribed = [factoryAddress]; + + this.logDecoder = (log: Log) => this.factoryIface.parseLog(log); + + this.handlers['PoolCreated'] = this.handleNewPool.bind(this); + } + + generateState(): AsyncOrSync {} + + protected processLog( + _: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + const event = this.logDecoder(log); + if (event.name in this.handlers) { + this.handlers[event.name](event); + } + + return null; + } + + handleNewPool(event: LogDescription) { + const token0 = event.args.token0; + const token1 = event.args.token1; + const fee = event.args.fee; + + this.onPoolCreated({ token0, token1, fee }); + } +} diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 41d2de86e..38991a5bb 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -56,6 +56,10 @@ import { DEFAULT_ID_ERC20, DEFAULT_ID_ERC20_AS_STRING, } from '../../lib/tokens/types'; +import { + OnPoolCreatedCallback, + PancakeswapV3Factory, +} from './pancakeswap-v3-factory'; type PoolPairsInfo = { token0: Address; @@ -71,6 +75,7 @@ export class PancakeswapV3 extends SimpleExchange implements IDex { + private readonly factory: PancakeswapV3Factory; readonly isFeeOnTransferSupported: boolean = false; readonly eventPools: Record = {}; @@ -117,6 +122,14 @@ export class PancakeswapV3 this.notExistingPoolSetKey = `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); + + this.factory = new PancakeswapV3Factory( + dexHelper, + dexKey, + this.config.factory, + this.logger, + this.onPoolCreatedDeleteFromNonExistingSet.bind(this), + ); } get supportedFees() { @@ -133,6 +146,9 @@ export class PancakeswapV3 } async initializePricing(blockNumber: number) { + // Init listening to new pools creation + this.factory.initialize(blockNumber); + if (!this.dexHelper.config.isSlave) { const cleanExpiredNotExistingPoolsKeys = async () => { const maxTimestamp = @@ -151,6 +167,29 @@ export class PancakeswapV3 } } + /* + * When a non existing pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls + * Once the pool is created, it gets immediately flagged + */ + onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ + token0, + token1, + fee, + }) => { + const [_token0, _token1] = this._sortTokens(token0, token1); + const poolKey = `${token0}_${token1}_${fee}`.toLowerCase(); + + // consider doing it only from master pool for less calls to distant cache + + try { + // delete pool record from set + await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); + } catch (e) {} + + // delete entry locally to let local instance discover the pool + delete this.eventPools[this.getPoolIdentifier(_token0, _token1, fee)]; + }; + async getPool( srcAddress: Address, destAddress: Address, diff --git a/src/dex/uniswap-v3/uniswap-v3-factory.ts b/src/dex/uniswap-v3/uniswap-v3-factory.ts new file mode 100644 index 000000000..a1a41c73b --- /dev/null +++ b/src/dex/uniswap-v3/uniswap-v3-factory.ts @@ -0,0 +1,69 @@ +import { Interface } from '@ethersproject/abi'; +import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; +import FactoryABI from '../../abi/uniswap-v3/UniswapV3Factory.abi.json'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { Address, Log, Logger } from '../../types'; +import { LogDescription } from 'ethers/lib/utils'; + +export type OnPoolCreatedCallback = ({ + token0, + token1, + fee, +}: { + token0: string; + token1: string; + fee: bigint; +}) => AsyncOrSync; + +/* + * Stateless event subscriber in order to capture "Pool" event on new pools created. + */ +export class UniswapV3Factory extends StatefulEventSubscriber { + handlers: { + [event: string]: (event: any) => DeepReadonly | null; + } = {}; + + logDecoder: (log: Log) => any; + + public readonly factoryIface = new Interface(FactoryABI); + + constructor( + readonly dexHelper: IDexHelper, + parentName: string, + protected readonly factoryAddress: Address, + logger: Logger, + protected readonly onPoolCreated: OnPoolCreatedCallback, + mapKey: string = '', + ) { + super(parentName, `factory`, dexHelper, logger, true, mapKey); + + this.addressesSubscribed = [factoryAddress]; + + this.logDecoder = (log: Log) => this.factoryIface.parseLog(log); + + this.handlers['PoolCreated'] = this.handleNewPool.bind(this); + } + + generateState(): AsyncOrSync {} + + protected processLog( + _: DeepReadonly, + log: Readonly, + ): DeepReadonly | null { + const event = this.logDecoder(log); + if (event.name in this.handlers) { + this.handlers[event.name](event); + } + + return null; + } + + handleNewPool(event: LogDescription) { + const token0 = event.args.token0; + const token1 = event.args.token1; + const fee = event.args.fee; + + this.onPoolCreated({ token0, token1, fee }); + } +} diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index b99a30ef4..4426d0c85 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -64,6 +64,7 @@ import { DEFAULT_ID_ERC20_AS_STRING, } from '../../lib/tokens/types'; import { OptimalSwapExchange } from '@paraswap/core'; +import { OnPoolCreatedCallback, UniswapV3Factory } from './uniswap-v3-factory'; type PoolPairsInfo = { token0: Address; @@ -79,6 +80,7 @@ export class UniswapV3 extends SimpleExchange implements IDex { + private readonly factory: UniswapV3Factory; readonly isFeeOnTransferSupported: boolean = false; readonly eventPools: Record = {}; @@ -138,6 +140,14 @@ export class UniswapV3 this.notExistingPoolSetKey = `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); + + this.factory = new UniswapV3Factory( + dexHelper, + dexKey, + this.config.factory, + this.logger, + this.onPoolCreatedDeleteFromNonExistingSet.bind(this), + ); } get supportedFees() { @@ -154,6 +164,9 @@ export class UniswapV3 } async initializePricing(blockNumber: number) { + // Init listening to new pools creation + this.factory.initialize(blockNumber); + // This is only for testing, because cold pool fetching is goes out of // FETCH_POOL_INDENTIFIER_TIMEOUT range await Promise.all( @@ -184,6 +197,29 @@ export class UniswapV3 } } + /* + * When a non existing pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls + * Once the pool is created, it gets immediately flagged + */ + onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ + token0, + token1, + fee, + }) => { + const [_token0, _token1] = this._sortTokens(token0, token1); + const poolKey = `${token0}_${token1}_${fee}`.toLowerCase(); + + // consider doing it only from master pool for less calls to distant cache + + try { + // delete pool record from set + await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); + } catch (e) {} + + // delete entry locally to let local instance discover the pool + delete this.eventPools[this.getPoolIdentifier(_token0, _token1, fee)]; + }; + async getPool( srcAddress: Address, destAddress: Address, From fa7084b12c63a6dc6971ca0816c85ba49f2d4f04 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 28 Sep 2023 01:15:42 +0300 Subject: [PATCH 379/833] fix: delete test-dex --- src/dex/my-test-dex/config.ts | 15 -- src/dex/my-test-dex/my-test-dex-e2e.test.ts | 162 ----------- .../my-test-dex/my-test-dex-events.test.ts | 106 -------- .../my-test-dex-integration.test.ts | 251 ------------------ src/dex/my-test-dex/my-test-dex-pool.ts | 91 ------- src/dex/my-test-dex/my-test-dex.ts | 178 ------------- src/dex/my-test-dex/types.ts | 22 -- 7 files changed, 825 deletions(-) delete mode 100644 src/dex/my-test-dex/config.ts delete mode 100644 src/dex/my-test-dex/my-test-dex-e2e.test.ts delete mode 100644 src/dex/my-test-dex/my-test-dex-events.test.ts delete mode 100644 src/dex/my-test-dex/my-test-dex-integration.test.ts delete mode 100644 src/dex/my-test-dex/my-test-dex-pool.ts delete mode 100644 src/dex/my-test-dex/my-test-dex.ts delete mode 100644 src/dex/my-test-dex/types.ts diff --git a/src/dex/my-test-dex/config.ts b/src/dex/my-test-dex/config.ts deleted file mode 100644 index 8392c2da8..000000000 --- a/src/dex/my-test-dex/config.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { DexParams } from './types'; -import { DexConfigMap, AdapterMappings } from '../../types'; -import { Network, SwapSide } from '../../constants'; - -export const MyTestDexConfig: DexConfigMap = { - MyTestDex: { - // TODO: complete me! - }, -}; - -export const Adapters: Record = { - // TODO: add adapters for each chain - // This is an example to copy - [Network.MAINNET]: { [SwapSide.SELL]: [{ name: '', index: 0 }] }, -}; diff --git a/src/dex/my-test-dex/my-test-dex-e2e.test.ts b/src/dex/my-test-dex/my-test-dex-e2e.test.ts deleted file mode 100644 index cf46cb26d..000000000 --- a/src/dex/my-test-dex/my-test-dex-e2e.test.ts +++ /dev/null @@ -1,162 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); - -import { testE2E } from '../../../tests/utils-e2e'; -import { - Tokens, - Holders, - NativeTokenSymbols, -} from '../../../tests/constants-e2e'; -import { Network, ContractMethod, SwapSide } from '../../constants'; -import { StaticJsonRpcProvider } from '@ethersproject/providers'; -import { generateConfig } from '../../config'; - -/* - README - ====== - - This test script should add e2e tests for MyTestDex. The tests - should cover as many cases as possible. Most of the DEXes follow - the following test structure: - - DexName - - ForkName + Network - - ContractMethod - - ETH -> Token swap - - Token -> ETH swap - - Token -> Token swap - - The template already enumerates the basic structure which involves - testing simpleSwap, multiSwap, megaSwap contract methods for - ETH <> TOKEN and TOKEN <> TOKEN swaps. You should replace tokenA and - tokenB with any two highly liquid tokens on MyTestDex for the tests - to work. If the tokens that you would like to use are not defined in - Tokens or Holders map, you can update the './tests/constants-e2e' - - Other than the standard cases that are already added by the template - it is highly recommended to add test cases which could be specific - to testing MyTestDex (Eg. Tests based on poolType, special tokens, - etc). - - You can run this individual test script by running: - `npx jest src/dex//-e2e.test.ts` - - e2e tests use the Tenderly fork api. Please add the following to your - .env file: - TENDERLY_TOKEN=Find this under Account>Settings>Authorization. - TENDERLY_ACCOUNT_ID=Your Tenderly account name. - TENDERLY_PROJECT=Name of a Tenderly project you have created in your - dashboard. - - (This comment should be removed from the final implementation) -*/ - -function testForNetwork( - network: Network, - dexKey: string, - tokenASymbol: string, - tokenBSymbol: string, - tokenAAmount: string, - tokenBAmount: string, - nativeTokenAmount: string, -) { - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - const tokens = Tokens[network]; - const holders = Holders[network]; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - // TODO: Add any direct swap contractMethod name if it exists - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ], - ], - // TODO: If buy is not supported remove the buy contract methods - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - ]); - - describe(`${network}`, () => { - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - 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, - network, - provider, - ); - }); - it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }); - }), - ); - }); -} - -describe('MyTestDex E2E', () => { - const dexKey = 'MyTestDex'; - - describe('Mainnet', () => { - const network = Network.MAINNET; - - // TODO: Modify the tokenASymbol, tokenBSymbol, tokenAAmount; - const tokenASymbol: string = 'tokenASymbol'; - const tokenBSymbol: string = 'tokenBSymbol'; - - const tokenAAmount: string = 'tokenAAmount'; - const tokenBAmount: string = 'tokenBAmount'; - const nativeTokenAmount = '1000000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - - // TODO: Add any additional test cases required to test MyTestDex - }); -}); diff --git a/src/dex/my-test-dex/my-test-dex-events.test.ts b/src/dex/my-test-dex/my-test-dex-events.test.ts deleted file mode 100644 index 54032410d..000000000 --- a/src/dex/my-test-dex/my-test-dex-events.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); - -import { MyTestDexEventPool } from './my-test-dex-pool'; -import { Network } from '../../constants'; -import { Address } from '../../types'; -import { DummyDexHelper } from '../../dex-helper/index'; -import { testEventSubscriber } from '../../../tests/utils-events'; -import { PoolState } from './types'; - -/* - README - ====== - - This test script adds unit tests for MyTestDex event based - system. This is done by fetching the state on-chain before the - event block, manually pushing the block logs to the event-subscriber, - comparing the local state with on-chain state. - - Most of the logic for testing is abstracted by `testEventSubscriber`. - You need to do two things to make the tests work: - - 1. Fetch the block numbers where certain events were released. You - can modify the `./scripts/fetch-event-blocknumber.ts` to get the - block numbers for different events. Make sure to get sufficient - number of blockNumbers to cover all possible cases for the event - mutations. - - 2. Complete the implementation for fetchPoolState function. The - function should fetch the on-chain state of the event subscriber - using just the blocknumber. - - The template tests only include the test for a single event - subscriber. There can be cases where multiple event subscribers - exist for a single DEX. In such cases additional tests should be - added. - - You can run this individual test script by running: - `npx jest src/dex//-events.test.ts` - - (This comment should be removed from the final implementation) -*/ - -jest.setTimeout(50 * 1000); - -async function fetchPoolState( - myTestDexPools: MyTestDexEventPool, - blockNumber: number, - poolAddress: string, -): Promise { - // TODO: complete me! - return {}; -} - -// eventName -> blockNumbers -type EventMappings = Record; - -describe('MyTestDex EventPool Mainnet', function () { - const dexKey = 'MyTestDex'; - const network = Network.MAINNET; - const dexHelper = new DummyDexHelper(network); - const logger = dexHelper.getLogger(dexKey); - let myTestDexPool: MyTestDexEventPool; - - // poolAddress -> EventMappings - const eventsToTest: Record = { - // TODO: complete me! - }; - - beforeEach(async () => { - myTestDexPool = new MyTestDexEventPool( - dexKey, - network, - dexHelper, - logger, - /* TODO: Put here additional constructor arguments if needed */ - ); - }); - - Object.entries(eventsToTest).forEach( - ([poolAddress, events]: [string, EventMappings]) => { - describe(`Events for ${poolAddress}`, () => { - Object.entries(events).forEach( - ([eventName, blockNumbers]: [string, number[]]) => { - describe(`${eventName}`, () => { - blockNumbers.forEach((blockNumber: number) => { - it(`State after ${blockNumber}`, async function () { - await testEventSubscriber( - myTestDexPool, - myTestDexPool.addressesSubscribed, - (_blockNumber: number) => - fetchPoolState(myTestDexPool, _blockNumber, poolAddress), - blockNumber, - `${dexKey}_${poolAddress}`, - dexHelper.provider, - ); - }); - }); - }); - }, - ); - }); - }, - ); -}); diff --git a/src/dex/my-test-dex/my-test-dex-integration.test.ts b/src/dex/my-test-dex/my-test-dex-integration.test.ts deleted file mode 100644 index 5520bc110..000000000 --- a/src/dex/my-test-dex/my-test-dex-integration.test.ts +++ /dev/null @@ -1,251 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); - -import { Interface, Result } from '@ethersproject/abi'; -import { DummyDexHelper } from '../../dex-helper/index'; -import { Network, SwapSide } from '../../constants'; -import { BI_POWS } from '../../bigint-constants'; -import { MyTestDex } from './my-test-dex'; -import { - checkPoolPrices, - checkPoolsLiquidity, - checkConstantPoolPrices, -} from '../../../tests/utils'; -import { Tokens } from '../../../tests/constants-e2e'; - -/* - README - ====== - - This test script adds tests for MyTestDex general integration - with the DEX interface. The test cases below are example tests. - It is recommended to add tests which cover MyTestDex specific - logic. - - You can run this individual test script by running: - `npx jest src/dex//-integration.test.ts` - - (This comment should be removed from the final implementation) -*/ - -function getReaderCalldata( - exchangeAddress: string, - readerIface: Interface, - amounts: bigint[], - funcName: string, - // TODO: Put here additional arguments you need -) { - return amounts.map(amount => ({ - target: exchangeAddress, - callData: readerIface.encodeFunctionData(funcName, [ - // TODO: Put here additional arguments to encode them - amount, - ]), - })); -} - -function decodeReaderResult( - results: Result, - readerIface: Interface, - funcName: string, -) { - // TODO: Adapt this function for your needs - return results.map(result => { - const parsed = readerIface.decodeFunctionResult(funcName, result); - return BigInt(parsed[0]._hex); - }); -} - -async function checkOnChainPricing( - myTestDex: MyTestDex, - funcName: string, - blockNumber: number, - prices: bigint[], - amounts: bigint[], -) { - const exchangeAddress = ''; // TODO: Put here the real exchange address - - // TODO: Replace dummy interface with the real one - // Normally you can get it from myTestDex.Iface or from eventPool. - // It depends on your implementation - const readerIface = new Interface(''); - - const readerCallData = getReaderCalldata( - exchangeAddress, - readerIface, - amounts.slice(1), - funcName, - ); - const readerResult = ( - await myTestDex.dexHelper.multiContract.methods - .aggregate(readerCallData) - .call({}, blockNumber) - ).returnData; - - const expectedPrices = [0n].concat( - decodeReaderResult(readerResult, readerIface, funcName), - ); - - expect(prices).toEqual(expectedPrices); -} - -async function testPricingOnNetwork( - myTestDex: MyTestDex, - network: Network, - dexKey: string, - blockNumber: number, - srcTokenSymbol: string, - destTokenSymbol: string, - side: SwapSide, - amounts: bigint[], - funcNameToCheck: string, -) { - const networkTokens = Tokens[network]; - - const pools = await myTestDex.getPoolIdentifiers( - networkTokens[srcTokenSymbol], - networkTokens[destTokenSymbol], - side, - blockNumber, - ); - console.log( - `${srcTokenSymbol} <> ${destTokenSymbol} Pool Identifiers: `, - pools, - ); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await myTestDex.getPricesVolume( - networkTokens[srcTokenSymbol], - networkTokens[destTokenSymbol], - amounts, - side, - blockNumber, - pools, - ); - console.log( - `${srcTokenSymbol} <> ${destTokenSymbol} Pool Prices: `, - poolPrices, - ); - - expect(poolPrices).not.toBeNull(); - if (myTestDex.hasConstantPriceLargeAmounts) { - checkConstantPoolPrices(poolPrices!, amounts, dexKey); - } else { - checkPoolPrices(poolPrices!, amounts, side, dexKey); - } - - // Check if onchain pricing equals to calculated ones - await checkOnChainPricing( - myTestDex, - funcNameToCheck, - blockNumber, - poolPrices![0].prices, - amounts, - ); -} - -describe('MyTestDex', function () { - const dexKey = 'MyTestDex'; - let blockNumber: number; - let myTestDex: MyTestDex; - - describe('Mainnet', () => { - const network = Network.MAINNET; - const dexHelper = new DummyDexHelper(network); - - const tokens = Tokens[network]; - - // TODO: Put here token Symbol to check against - // Don't forget to update relevant tokens in constant-e2e.ts - const srcTokenSymbol = 'srcTokenSymbol'; - const destTokenSymbol = 'destTokenSymbol'; - - const amountsForSell = [ - 0n, - 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - 10n * BI_POWS[tokens[srcTokenSymbol].decimals], - ]; - - const amountsForBuy = [ - 0n, - 1n * BI_POWS[tokens[destTokenSymbol].decimals], - 2n * BI_POWS[tokens[destTokenSymbol].decimals], - 3n * BI_POWS[tokens[destTokenSymbol].decimals], - 4n * BI_POWS[tokens[destTokenSymbol].decimals], - 5n * BI_POWS[tokens[destTokenSymbol].decimals], - 6n * BI_POWS[tokens[destTokenSymbol].decimals], - 7n * BI_POWS[tokens[destTokenSymbol].decimals], - 8n * BI_POWS[tokens[destTokenSymbol].decimals], - 9n * BI_POWS[tokens[destTokenSymbol].decimals], - 10n * BI_POWS[tokens[destTokenSymbol].decimals], - ]; - - beforeAll(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - myTestDex = new MyTestDex(network, dexKey, dexHelper); - if (myTestDex.initializePricing) { - await myTestDex.initializePricing(blockNumber); - } - }); - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - await testPricingOnNetwork( - myTestDex, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.SELL, - amountsForSell, - '', // TODO: Put here proper function name to check pricing - ); - }); - - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - await testPricingOnNetwork( - myTestDex, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.BUY, - amountsForBuy, - '', // TODO: Put here proper function name to check pricing - ); - }); - - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - const newMyTestDex = new MyTestDex(network, dexKey, dexHelper); - if (newMyTestDex.updatePoolState) { - await newMyTestDex.updatePoolState(); - } - const poolLiquidity = await newMyTestDex.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, - ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - - if (!newMyTestDex.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, - dexKey, - ); - } - }); - }); -}); diff --git a/src/dex/my-test-dex/my-test-dex-pool.ts b/src/dex/my-test-dex/my-test-dex-pool.ts deleted file mode 100644 index f46402ec8..000000000 --- a/src/dex/my-test-dex/my-test-dex-pool.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Interface } from '@ethersproject/abi'; -import { DeepReadonly } from 'ts-essentials'; -import { Log, Logger } from '../../types'; -import { catchParseLogError } from '../../utils'; -import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { PoolState } from './types'; - -export class MyTestDexEventPool extends StatefulEventSubscriber { - handlers: { - [event: string]: ( - event: any, - state: DeepReadonly, - log: Readonly, - ) => DeepReadonly | null; - } = {}; - - logDecoder: (log: Log) => any; - - addressesSubscribed: string[]; - - constructor( - readonly parentName: string, - protected network: number, - protected dexHelper: IDexHelper, - logger: Logger, - protected myTestDexIface = new Interface( - '' /* TODO: Import and put here MyTestDex ABI */, - ), // TODO: add any additional params required for event subscriber - ) { - // TODO: Add pool name - super(parentName, 'POOL_NAME', dexHelper, logger); - - // TODO: make logDecoder decode logs that - this.logDecoder = (log: Log) => this.myTestDexIface.parseLog(log); - this.addressesSubscribed = [ - /* subscribed addresses */ - ]; - - // Add handlers - this.handlers['myEvent'] = this.handleMyEvent.bind(this); - } - - /** - * The function is called every time any of the subscribed - * addresses release log. The function accepts the current - * state, updates the state according to the log, and returns - * the updated state. - * @param state - Current state of event subscriber - * @param log - Log released by one of the subscribed addresses - * @returns Updates state of the event subscriber after the log - */ - protected processLog( - state: DeepReadonly, - log: Readonly, - ): DeepReadonly | null { - try { - const event = this.logDecoder(log); - if (event.name in this.handlers) { - return this.handlers[event.name](event, state, log); - } - } catch (e) { - catchParseLogError(e, this.logger); - } - - return null; - } - - /** - * The function generates state using on-chain calls. This - * function is called to regenerate state if the event based - * system fails to fetch events and the local state is no - * more correct. - * @param blockNumber - Blocknumber for which the state should - * should be generated - * @returns state of the event subscriber at blocknumber - */ - async generateState(blockNumber: number): Promise> { - // TODO: complete me! - return {}; - } - - // Its just a dummy example - handleMyEvent( - event: any, - state: DeepReadonly, - log: Readonly, - ): DeepReadonly | null { - return null; - } -} diff --git a/src/dex/my-test-dex/my-test-dex.ts b/src/dex/my-test-dex/my-test-dex.ts deleted file mode 100644 index 80adef17f..000000000 --- a/src/dex/my-test-dex/my-test-dex.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { AsyncOrSync } from 'ts-essentials'; -import { - Token, - Address, - ExchangePrices, - PoolPrices, - AdapterExchangeParam, - SimpleExchangeParam, - PoolLiquidity, - Logger, -} from '../../types'; -import { SwapSide, Network } from '../../constants'; -import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { getDexKeysWithNetwork } from '../../utils'; -import { IDex } from '../../dex/idex'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { MyTestDexData } from './types'; -import { SimpleExchange } from '../simple-exchange'; -import { MyTestDexConfig, Adapters } from './config'; -import { MyTestDexEventPool } from './my-test-dex-pool'; - -export class MyTestDex extends SimpleExchange implements IDex { - protected eventPools: MyTestDexEventPool; - - readonly hasConstantPriceLargeAmounts = false; - // TODO: set true here if protocols works only with wrapped asset - readonly needWrapNative = true; - - readonly isFeeOnTransferSupported = false; - - public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(MyTestDexConfig); - - logger: Logger; - - constructor( - readonly network: Network, - readonly dexKey: string, - readonly dexHelper: IDexHelper, - protected adapters = Adapters[network] || {}, // TODO: add any additional optional params to support other fork DEXes - ) { - super(dexHelper, dexKey); - this.logger = dexHelper.getLogger(dexKey); - this.eventPools = new MyTestDexEventPool( - dexKey, - network, - dexHelper, - this.logger, - ); - } - - // Initialize pricing is called once in the start of - // pricing service. It is intended to setup the integration - // for pricing requests. It is optional for a DEX to - // implement this function - async initializePricing(blockNumber: number) { - // TODO: complete me! - } - - // Returns the list of contract adapters (name and index) - // for a buy/sell. Return null if there are no adapters. - getAdapters(side: SwapSide): { name: string; index: number }[] | null { - return this.adapters[side] ? this.adapters[side] : null; - } - - // Returns list of pool identifiers that can be used - // for a given swap. poolIdentifiers must be unique - // across DEXes. It is recommended to use - // ${dexKey}_${poolAddress} as a poolIdentifier - async getPoolIdentifiers( - srcToken: Token, - destToken: Token, - side: SwapSide, - blockNumber: number, - ): Promise { - // TODO: complete me! - return []; - } - - // Returns pool prices for amounts. - // If limitPools is defined only pools in limitPools - // should be used. If limitPools is undefined then - // any pools can be used. - async getPricesVolume( - srcToken: Token, - destToken: Token, - amounts: bigint[], - side: SwapSide, - blockNumber: number, - limitPools?: string[], - ): Promise> { - // TODO: complete me! - return null; - } - - // Returns estimated gas cost of calldata for this DEX in multiSwap - getCalldataGasCost(poolPrices: PoolPrices): number | number[] { - // TODO: update if there is any payload in getAdapterParam - return CALLDATA_GAS_COST.DEX_NO_PAYLOAD; - } - - // Encode params required by the exchange adapter - // Used for multiSwap, buy & megaSwap - // Hint: abiCoder.encodeParameter() could be useful - getAdapterParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, - data: MyTestDexData, - side: SwapSide, - ): AdapterExchangeParam { - // TODO: complete me! - const { exchange } = data; - - // Encode here the payload for adapter - const payload = ''; - - return { - targetExchange: exchange, - payload, - networkFee: '0', - }; - } - - // Encode call data used by simpleSwap like routers - // Used for simpleSwap & simpleBuy - // Hint: this.buildSimpleParamWithoutWETHConversion - // could be useful - async getSimpleParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, - data: MyTestDexData, - side: SwapSide, - ): Promise { - // TODO: complete me! - const { exchange } = data; - - // Encode here the transaction arguments - const swapData = ''; - - return this.buildSimpleParamWithoutWETHConversion( - srcToken, - srcAmount, - destToken, - destAmount, - swapData, - exchange, - ); - } - - // This is called once before getTopPoolsForToken is - // called for multiple tokens. This can be helpful to - // update common state required for calculating - // getTopPoolsForToken. It is optional for a DEX - // to implement this - async updatePoolState(): Promise { - // TODO: complete me! - } - - // Returns list of top pools based on liquidity. Max - // limit number pools should be returned. - async getTopPoolsForToken( - tokenAddress: Address, - limit: number, - ): Promise { - //TODO: complete me! - return []; - } - - // This is optional function in case if your implementation has acquired any resources - // you need to release for graceful shutdown. For example, it may be any interval timer - releaseResources(): AsyncOrSync { - // TODO: complete me! - } -} diff --git a/src/dex/my-test-dex/types.ts b/src/dex/my-test-dex/types.ts deleted file mode 100644 index 85bd58ae3..000000000 --- a/src/dex/my-test-dex/types.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Address } from '../../types'; - -export type PoolState = { - // TODO: poolState is the state of event - // subscriber. This should be the minimum - // set of parameters required to compute - // pool prices. Complete me! -}; - -export type MyTestDexData = { - // TODO: MyTestDexData is the dex data that is - // returned by the API that can be used for - // tx building. The data structure should be minimal. - // Complete me! - exchange: Address; -}; - -export type DexParams = { - // TODO: DexParams is set of parameters the can - // be used to initiate a DEX fork. - // Complete me! -}; From ac7792cabecc1aaeb0d5bb586b9c284288cc0bc3 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 28 Sep 2023 13:25:06 +0300 Subject: [PATCH 380/833] fix: update cache envs for uniswapv3 & pancakev3 --- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 4 ++-- src/dex/uniswap-v3/uniswap-v3.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 38991a5bb..d72f46dde 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -67,8 +67,8 @@ type PoolPairsInfo = { fee: string; }; -const PANCAKESWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 60 * 60 * 24 * 1000; // 24 hours -const PANCAKESWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 30 * 60 * 1000; // Once in 30 minutes +const PANCAKESWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 3 * 24 * 60 * 60 * 1000; // 3 days +const PANCAKESWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 24 * 60 * 60 * 1000; // Once in a day const PANCAKESWAPV3_QUOTE_GASLIMIT = 200_000; export class PancakeswapV3 diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 4426d0c85..51fc9d4b8 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -72,8 +72,8 @@ type PoolPairsInfo = { fee: string; }; -const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 60 * 60 * 24 * 1000; // 24 hours -const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 30 * 60 * 1000; // Once in 30 minutes +const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 3 * 24 * 60 * 60 * 1000; // 3 days +const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 24 * 60 * 60 * 1000; // Once in a day const UNISWAPV3_QUOTE_GASLIMIT = 200_000; export class UniswapV3 From 508c9bcbf385fd52ed96782b34bddbf91cbaf248 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 29 Sep 2023 18:25:35 +0300 Subject: [PATCH 381/833] add protocol restriction --- src/dex/dexalot/config.ts | 7 +- src/dex/dexalot/constants.ts | 9 ++ src/dex/dexalot/dexalot-e2e.test.ts | 11 +- src/dex/dexalot/dexalot.ts | 173 ++++++++++++++++++++-------- src/dex/dexalot/types.ts | 4 +- 5 files changed, 149 insertions(+), 55 deletions(-) diff --git a/src/dex/dexalot/config.ts b/src/dex/dexalot/config.ts index e69582b0e..658792a20 100644 --- a/src/dex/dexalot/config.ts +++ b/src/dex/dexalot/config.ts @@ -1,6 +1,6 @@ import { DexParams } from './types'; import { DexConfigMap, AdapterMappings } from '../../types'; -import { Network } from '../../constants'; +import { Network, SwapSide } from '../../constants'; export const DexalotConfig: DexConfigMap = { Dexalot: { @@ -11,5 +11,8 @@ export const DexalotConfig: DexConfigMap = { }; export const Adapters: Record = { - [Network.AVALANCHE]: {}, + [Network.AVALANCHE]: { + [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 6 }], + [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 8 }], + }, }; diff --git a/src/dex/dexalot/constants.ts b/src/dex/dexalot/constants.ts index b7f385620..107ac7a18 100644 --- a/src/dex/dexalot/constants.ts +++ b/src/dex/dexalot/constants.ts @@ -1,3 +1,5 @@ +import BigNumber from 'bignumber.js'; + export const DEXALOT_RATE_LIMITED_TTL_S = 60 * 60; // 1 hour export const DEXALOT_PRICES_CACHES_TTL_S = 3; @@ -15,3 +17,10 @@ export const DEXALOT_API_BLACKLIST_POLLING_INTERVAL_MS = 1000 * 60 * 60; // 1 ho export const DEXALOT_API_URL = 'https://api.dexalot.com'; export const DEXALOT_GAS_COST = 120_000; + +export const DEXALOT_RESTRICT_TTL_S = 60 * 30; // 30 minutes + +export const DEXALOT_RESTRICTED_CACHE_KEY = 'restricted'; + +export const DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION = + new BigNumber('0.001'); diff --git a/src/dex/dexalot/dexalot-e2e.test.ts b/src/dex/dexalot/dexalot-e2e.test.ts index c81393c9f..731ad637a 100644 --- a/src/dex/dexalot/dexalot-e2e.test.ts +++ b/src/dex/dexalot/dexalot-e2e.test.ts @@ -32,8 +32,15 @@ function testForNetwork( const sleepMs = 5000; const sideToContractMethods = new Map([ - [SwapSide.SELL, [ContractMethod.simpleSwap, ContractMethod.megaSwap, ContractMethod.multiSwap]], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + [SwapSide.SELL, [ + ContractMethod.simpleSwap, + ContractMethod.megaSwap, + ContractMethod.multiSwap + ]], + [SwapSide.BUY, [ + ContractMethod.simpleBuy, + ContractMethod.buy + ]], ]); describe(`${network}`, () => { diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 1db04599d..e57fd2c88 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -27,13 +27,13 @@ import { PairData, PairDataMap, PriceDataMap, - RfqError, + DexalotRfqError, RFQResponse, RFQResponseError, - SlippageCheckError, TokenAddrDataMap, TokenDataMap, } from './types'; +import { SlippageCheckError, TooStrictSlippageCheckError } from '../generic-rfq/types'; import { SimpleExchange } from '../simple-exchange'; import { Adapters, DexalotConfig } from './config'; import { RateFetcher } from './rate-fetcher'; @@ -50,10 +50,15 @@ import { DEXALOT_TOKENS_CACHES_TTL_S, DEXALOT_API_BLACKLIST_POLLING_INTERVAL_MS, DEXALOT_RATE_LIMITED_TTL_S, + DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION, + DEXALOT_RESTRICTED_CACHE_KEY, + DEXALOT_RESTRICT_TTL_S, } from './constants'; import { BI_MAX_UINT256 } from '../../bigint-constants'; import { ethers } from 'ethers'; import BigNumber from 'bignumber.js'; +import { TokensMap } from '../swaap-v2/types'; +import { normalizeTokenAddress } from '../swaap-v2/utils'; export class Dexalot extends SimpleExchange implements IDex { readonly isStatePollingDex = true; @@ -69,6 +74,7 @@ export class Dexalot extends SimpleExchange implements IDex { private tokensAddrCacheKey: string; private tokensCacheKey: string; private blacklistCacheKey: string; + private tokensMap: TokensMap = {}; public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork(DexalotConfig); @@ -361,9 +367,14 @@ export class Dexalot extends SimpleExchange implements IDex { limitPools?: string[], ): Promise> { try { + if (await this.isRestricted()) { + return null; + } + const normalizedSrcToken = this.normalizeToken(srcToken); const normalizedDestToken = this.normalizeToken(destToken); + this.tokensMap = (await this.getCachedTokens()) || {}; if (normalizedSrcToken.address === normalizedDestToken.address) { return null; } @@ -448,7 +459,7 @@ export class Dexalot extends SimpleExchange implements IDex { generateRFQError(errorStr: string, swapIdentifier: string) { const message = `${this.dexKey}-${this.network}: Failed to fetch RFQ for ${swapIdentifier}. ${errorStr}`; this.logger.warn(message); - throw new RfqError(message); + throw new DexalotRfqError(message); } async preProcessTransaction( @@ -479,7 +490,7 @@ export class Dexalot extends SimpleExchange implements IDex { ); } if (BigInt(optimalSwapExchange.srcAmount) === 0n) { - throw new Error('getFirmRate failed with srcAmount == 0'); + throw new Error('getFirmRate failed with srcAmount === 0'); } const normalizedSrcToken = this.normalizeToken(srcToken); @@ -546,38 +557,62 @@ export class Dexalot extends SimpleExchange implements IDex { const minDeadline = expiryAsBigInt > 0 ? expiryAsBigInt : BI_MAX_UINT256; const slippageFactor = options.slippageFactor; + let isFailOnSlippage = false; + let slippageErrorMessage = ''; + if (side === SwapSide.SELL) { if ( BigInt(order.makerAmount) < BigInt( - new BigNumber(optimalSwapExchange.destAmount) + new BigNumber(optimalSwapExchange.destAmount.toString()) .times(slippageFactor) .toFixed(0), ) ) { + isFailOnSlippage = true; const message = `${this.dexKey}-${this.network}: too much slippage on quote ${side} quoteTokenAmount ${order.makerAmount} / destAmount ${optimalSwapExchange.destAmount} < ${slippageFactor}`; - throw new SlippageCheckError(message); + slippageErrorMessage = message; + this.logger.warn(message); } } else { if ( BigInt(order.takerAmount) > - BigInt( - new BigNumber(optimalSwapExchange.srcAmount) - .times(slippageFactor) - .toFixed(0), - ) + BigInt(slippageFactor.times(optimalSwapExchange.srcAmount.toString()).toFixed(0)) ) { + isFailOnSlippage = true; const message = `${this.dexKey}-${ this.network - }: too much slippage on quote ${side} baseTokenAmount ${ - order.takerAmount - } / srcAmount ${ - optimalSwapExchange.srcAmount - } > ${slippageFactor.toFixed()}`; - throw new SlippageCheckError(message); + }: too much slippage on quote ${side} baseTokenAmount ${order.takerAmount} / srcAmount ${optimalSwapExchange.srcAmount} > ${slippageFactor.toFixed()}`; + slippageErrorMessage = message; + this.logger.warn(message); } } + let isTooStrictSlippage = false; + if ( + isFailOnSlippage && + side === SwapSide.SELL && + new BigNumber(1) + .minus(slippageFactor) + .lt(DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION) + ) { + isTooStrictSlippage = true; + } else if ( + isFailOnSlippage && + side === SwapSide.BUY && + slippageFactor + .minus(1) + .lt(DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION) + ) { + isTooStrictSlippage = true; + } + + if (isFailOnSlippage && isTooStrictSlippage) { + throw new TooStrictSlippageCheckError(slippageErrorMessage); + } else if (isFailOnSlippage && !isTooStrictSlippage) { + throw new SlippageCheckError(slippageErrorMessage); + } + return [ { ...optimalSwapExchange, @@ -600,13 +635,17 @@ export class Dexalot extends SimpleExchange implements IDex { `${this.dexKey}-${this.network}: Failed to fetch RFQ for ${swapIdentifier}: ${errorData.Reason}`, ); } - } else if (e instanceof SlippageCheckError) { - this.logger.warn(e.message); } else { - this.logger.error( - `${this.dexKey}-${this.network}: Failed to fetch RFQ for ${swapIdentifier}:`, - JSON.stringify(e), - ); + if(e instanceof TooStrictSlippageCheckError) { + this.logger.warn( + `${this.dexKey}-${this.network}: failed to build transaction on side ${side} with too strict slippage. Skipping restriction`, + ); + } else { + this.logger.warn( + `${this.dexKey}-${this.network}: protocol is restricted`, + ); + await this.restrict(); + } } throw e; @@ -628,10 +667,9 @@ export class Dexalot extends SimpleExchange implements IDex { ); } - getTokenFromAddress?(address: Address): Token { - // We don't have predefined set of tokens with decimals - // Anyway we don't use decimals, so it is fine to do this - return { address, decimals: 0 }; + getTokenFromAddress(address: Address): Token { + return this.tokensMap[normalizeTokenAddress(address)]; + } getAdapterParam( @@ -649,24 +687,40 @@ export class Dexalot extends SimpleExchange implements IDex { `${this.dexKey}-${this.network}: quoteData undefined`, ); - const swapFunction = 'simpleSwap'; - const swapFunctionParams = [ - [ - quoteData.nonceAndMeta, - quoteData.expiry, - quoteData.makerAsset, - quoteData.takerAsset, - quoteData.maker, - quoteData.taker, - quoteData.makerAmount, - quoteData.takerAmount, - ], + const params = [ + { + nonceAndMeta: quoteData.nonceAndMeta, + expiry: quoteData.expiry, + makerAsset: quoteData.makerAsset, + takerAsset: quoteData.takerAsset, + maker: quoteData.maker, + taker: quoteData.taker, + makerAmount: quoteData.makerAmount, + takerAmount: quoteData.takerAmount, + }, quoteData.signature, ]; - const payload = this.rfqInterface.encodeFunctionData( - swapFunction, - swapFunctionParams, + const payload = this.abiCoder.encodeParameter( + { + ParentStruct: { + order: { + nonceAndMeta: 'uint256', + expiry: 'uint128', + makerAsset: 'address', + takerAsset: 'address', + maker: 'address', + taker: 'address', + makerAmount: 'uint256', + takerAmount: 'uint256', + }, + signature: 'bytes', + }, + }, + { + order: params[0], + signature: params[1], + }, ); return { @@ -676,6 +730,27 @@ export class Dexalot extends SimpleExchange implements IDex { }; } + async restrict(ttl: number = DEXALOT_RESTRICT_TTL_S): Promise { + await this.dexHelper.cache.setex( + this.dexKey, + this.network, + DEXALOT_RESTRICTED_CACHE_KEY, + ttl, + 'true', + ); + return true; + } + + async isRestricted(): Promise { + const result = await this.dexHelper.cache.get( + this.dexKey, + this.network, + DEXALOT_RESTRICTED_CACHE_KEY, + ); + + return result === 'true'; + } + async setBlacklist(txOrigin: Address): Promise { await this.dexHelper.cache.sadd( this.blacklistCacheKey, @@ -764,16 +839,18 @@ export class Dexalot extends SimpleExchange implements IDex { tokenAddress: Address, limit: number, ): Promise { - const normalizedAddress = this.normalizeAddress(tokenAddress); + if (await this.isRestricted()) { + return []; + } const pairs = (await this.getCachedPairs()) || {}; - const tokens = (await this.getCachedTokens()) || {}; + this.tokensMap = (await this.getCachedTokens()) || {}; const tokensAddr = (await this.getCachedTokensAddr()) || {}; - if (!tokens[normalizedAddress]) { + const token = this.getTokenFromAddress(tokenAddress); + if (!token) { return []; } - const token = tokens[normalizedAddress]; const tokenSymbol = token.symbol?.toLowerCase() || ''; let pairsByLiquidity = []; @@ -785,10 +862,10 @@ export class Dexalot extends SimpleExchange implements IDex { } const addr = tokensAddr[tokensInPair[0].toLowerCase()]; - let outputToken = tokens[addr]; + let outputToken = this.getTokenFromAddress(addr); if (tokensInPair[0] === tokenSymbol) { const addr = tokensAddr[tokensInPair[1].toLowerCase()]; - outputToken = tokens[addr]; + outputToken = this.getTokenFromAddress(addr); } const connectorToken = { diff --git a/src/dex/dexalot/types.ts b/src/dex/dexalot/types.ts index 841fcddf6..eb3b37f57 100644 --- a/src/dex/dexalot/types.ts +++ b/src/dex/dexalot/types.ts @@ -38,9 +38,7 @@ export enum ClobSide { ASK = 'ASK', } -export class RfqError extends Error {} - -export class SlippageCheckError extends Error {} +export class DexalotRfqError extends Error {} export type PairData = { base: string; From 87854e1088d3df6528359ef2e87c04779eed1f69 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 29 Sep 2023 18:35:49 +0300 Subject: [PATCH 382/833] refactor --- src/dex/dexalot/constants.ts | 9 +++++++-- src/dex/dexalot/dexalot.ts | 36 +++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/dex/dexalot/constants.ts b/src/dex/dexalot/constants.ts index 107ac7a18..46a21689b 100644 --- a/src/dex/dexalot/constants.ts +++ b/src/dex/dexalot/constants.ts @@ -20,7 +20,12 @@ export const DEXALOT_GAS_COST = 120_000; export const DEXALOT_RESTRICT_TTL_S = 60 * 30; // 30 minutes +export const DEXALOT_BLACKLIST_TTL_S = 60 * 60 * 24; // 24 hours + +export const DEXALOT_BLACKLIST_CACHE_VALUE = 'blacklisted'; + +export const DEXALOT_RATELIMIT_CACHE_VALUE = 'limited'; + export const DEXALOT_RESTRICTED_CACHE_KEY = 'restricted'; -export const DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION = - new BigNumber('0.001'); +export const DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION = new BigNumber('0.001'); diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index e57fd2c88..2388f7e05 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -53,6 +53,9 @@ import { DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION, DEXALOT_RESTRICTED_CACHE_KEY, DEXALOT_RESTRICT_TTL_S, + DEXALOT_BLACKLIST_TTL_S, + DEXALOT_BLACKLIST_CACHE_VALUE, + DEXALOT_RATELIMIT_CACHE_VALUE, } from './constants'; import { BI_MAX_UINT256 } from '../../bigint-constants'; import { ethers } from 'ethers'; @@ -631,6 +634,7 @@ export class Dexalot extends SimpleExchange implements IDex { ); await this.setRateLimited(options.txOrigin, errorData.RetryAfter); } else { + await this.setBlacklist(options.txOrigin); this.logger.error( `${this.dexKey}-${this.network}: Failed to fetch RFQ for ${swapIdentifier}: ${errorData.Reason}`, ); @@ -751,19 +755,29 @@ export class Dexalot extends SimpleExchange implements IDex { return result === 'true'; } - async setBlacklist(txOrigin: Address): Promise { - await this.dexHelper.cache.sadd( - this.blacklistCacheKey, - txOrigin.toLowerCase(), + async setBlacklist(txOrigin: Address, ttl: number = DEXALOT_BLACKLIST_TTL_S, + ): Promise { + await this.dexHelper.cache.setex( + this.dexKey, + this.network, + this.getBlackListKey(txOrigin), + ttl, + DEXALOT_BLACKLIST_CACHE_VALUE, ); return true; } async isBlacklisted(txOrigin: Address): Promise { - return this.dexHelper.cache.sismember( - this.blacklistCacheKey, - txOrigin.toLowerCase(), + const result = await this.dexHelper.cache.get( + this.dexKey, + this.network, + this.getBlackListKey(txOrigin), ); + return result === DEXALOT_BLACKLIST_CACHE_VALUE; + } + + getBlackListKey(address: Address) { + return `blacklist_${address}`.toLowerCase(); } getRateLimitedKey(address: Address) { @@ -776,16 +790,16 @@ export class Dexalot extends SimpleExchange implements IDex { this.network, this.getRateLimitedKey(txOrigin), ); - return result === 'limited'; + return result === DEXALOT_RATELIMIT_CACHE_VALUE; } - async setRateLimited(txOrigin: Address, ttl?: number) { + async setRateLimited(txOrigin: Address, ttl = DEXALOT_RATE_LIMITED_TTL_S) { await this.dexHelper.cache.setex( this.dexKey, this.network, this.getRateLimitedKey(txOrigin), - ttl || DEXALOT_RATE_LIMITED_TTL_S, - 'limited', + ttl, + DEXALOT_RATELIMIT_CACHE_VALUE, ); return true; } From 518343f15f507b0e4033b3c8f2a8e7c416716c94 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 29 Sep 2023 18:59:56 +0300 Subject: [PATCH 383/833] disable adapters --- src/dex/dexalot/config.ts | 8 ++++---- src/dex/dexalot/dexalot-e2e.test.ts | 6 +++--- src/dex/dexalot/dexalot.ts | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/dex/dexalot/config.ts b/src/dex/dexalot/config.ts index 658792a20..ec1830c99 100644 --- a/src/dex/dexalot/config.ts +++ b/src/dex/dexalot/config.ts @@ -11,8 +11,8 @@ export const DexalotConfig: DexConfigMap = { }; export const Adapters: Record = { - [Network.AVALANCHE]: { - [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 6 }], - [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 8 }], - }, + // [Network.AVALANCHE]: { + // [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 6 }], + // [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 8 }], + // }, }; diff --git a/src/dex/dexalot/dexalot-e2e.test.ts b/src/dex/dexalot/dexalot-e2e.test.ts index 731ad637a..b9b9c04b3 100644 --- a/src/dex/dexalot/dexalot-e2e.test.ts +++ b/src/dex/dexalot/dexalot-e2e.test.ts @@ -34,12 +34,12 @@ function testForNetwork( const sideToContractMethods = new Map([ [SwapSide.SELL, [ ContractMethod.simpleSwap, - ContractMethod.megaSwap, - ContractMethod.multiSwap + // ContractMethod.megaSwap, + // ContractMethod.multiSwap ]], [SwapSide.BUY, [ ContractMethod.simpleBuy, - ContractMethod.buy + // ContractMethod.buy ]], ]); diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 2388f7e05..cdd79694c 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -16,6 +16,7 @@ import { Network, ETHER_ADDRESS, CACHE_PREFIX, + NULL_ADDRESS, } from '../../constants'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { getDexKeysWithNetwork, isAxiosError } from '../../utils'; @@ -60,8 +61,6 @@ import { import { BI_MAX_UINT256 } from '../../bigint-constants'; import { ethers } from 'ethers'; import BigNumber from 'bignumber.js'; -import { TokensMap } from '../swaap-v2/types'; -import { normalizeTokenAddress } from '../swaap-v2/utils'; export class Dexalot extends SimpleExchange implements IDex { readonly isStatePollingDex = true; @@ -77,7 +76,7 @@ export class Dexalot extends SimpleExchange implements IDex { private tokensAddrCacheKey: string; private tokensCacheKey: string; private blacklistCacheKey: string; - private tokensMap: TokensMap = {}; + private tokensMap: TokenDataMap = {}; public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork(DexalotConfig); @@ -217,7 +216,9 @@ export class Dexalot extends SimpleExchange implements IDex { } getIdentifier(baseSymbol: string, quoteSymbol: string) { - return `${this.dexKey}_${baseSymbol}_${quoteSymbol}`.toLowerCase(); + // return `${this.dexKey}_${baseSymbol}_${quoteSymbol}`.toLowerCase(); + // To disable Dexalot in multi/mega routes + return this.dexKey; } async getPoolIdentifiers( @@ -294,7 +295,7 @@ export class Dexalot extends SimpleExchange implements IDex { normalizeAddress(address: string): string { return address.toLowerCase() === ETHER_ADDRESS - ? ethers.constants.AddressZero.toLowerCase() + ? NULL_ADDRESS : address.toLowerCase(); } @@ -672,8 +673,7 @@ export class Dexalot extends SimpleExchange implements IDex { } getTokenFromAddress(address: Address): Token { - return this.tokensMap[normalizeTokenAddress(address)]; - + return this.tokensMap[this.normalizeAddress(address)]; } getAdapterParam( From 1cf0a26ec318b36f20829f90f889820856543ec2 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 29 Sep 2023 19:54:19 +0300 Subject: [PATCH 384/833] 2.36.2-dexalot --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 605af44fd..a722d1353 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.0", + "version": "2.36.2-dexalot", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From f9b6c328caff0b8b78950169a42581ce68ed923c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 29 Sep 2023 20:03:47 +0300 Subject: [PATCH 385/833] 2.36.2-dexalot.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a722d1353..510d6e83b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2-dexalot", + "version": "2.36.2-dexalot.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From c6bc7375b5d478537c659030c0b01c19bf9a3c32 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 30 Sep 2023 00:00:05 +0300 Subject: [PATCH 386/833] improve blacklist --- src/dex/dexalot/constants.ts | 8 ++--- src/dex/dexalot/dexalot.ts | 52 +++++++++++++++++++++------------ src/dex/dexalot/rate-fetcher.ts | 16 ++++++++-- src/dex/dexalot/types.ts | 1 + 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/src/dex/dexalot/constants.ts b/src/dex/dexalot/constants.ts index 46a21689b..f45bc8cf0 100644 --- a/src/dex/dexalot/constants.ts +++ b/src/dex/dexalot/constants.ts @@ -4,10 +4,12 @@ export const DEXALOT_RATE_LIMITED_TTL_S = 60 * 60; // 1 hour export const DEXALOT_PRICES_CACHES_TTL_S = 3; -export const DEXALOT_PAIRS_CACHES_TTL_S = 11; +export const DEXALOT_PAIRS_CACHES_TTL_S = 21 * 60; // 21 mins export const DEXALOT_TOKENS_CACHES_TTL_S = 11; +export const DEXALOT_BLACKLIST_CACHES_TTL_S = 3 * 60; // 3 hours + export const DEXALOT_API_PRICES_POLLING_INTERVAL_MS = 1000; export const DEXALOT_API_PAIRS_POLLING_INTERVAL_MS = 1000 * 60 * 10; // 10 mins @@ -20,10 +22,6 @@ export const DEXALOT_GAS_COST = 120_000; export const DEXALOT_RESTRICT_TTL_S = 60 * 30; // 30 minutes -export const DEXALOT_BLACKLIST_TTL_S = 60 * 60 * 24; // 24 hours - -export const DEXALOT_BLACKLIST_CACHE_VALUE = 'blacklisted'; - export const DEXALOT_RATELIMIT_CACHE_VALUE = 'limited'; export const DEXALOT_RESTRICTED_CACHE_KEY = 'restricted'; diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index cdd79694c..7eee6b0a6 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -15,7 +15,6 @@ import { SwapSide, Network, ETHER_ADDRESS, - CACHE_PREFIX, NULL_ADDRESS, } from '../../constants'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; @@ -54,9 +53,8 @@ import { DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION, DEXALOT_RESTRICTED_CACHE_KEY, DEXALOT_RESTRICT_TTL_S, - DEXALOT_BLACKLIST_TTL_S, - DEXALOT_BLACKLIST_CACHE_VALUE, DEXALOT_RATELIMIT_CACHE_VALUE, + DEXALOT_BLACKLIST_CACHES_TTL_S, } from './constants'; import { BI_MAX_UINT256 } from '../../bigint-constants'; import { ethers } from 'ethers'; @@ -102,11 +100,11 @@ export class Dexalot extends SimpleExchange implements IDex { ); this.dexalotAuthToken = authToken; - this.pricesCacheKey = `${CACHE_PREFIX}_prices`; - this.pairsCacheKey = `${CACHE_PREFIX}_pairs`; - this.tokensAddrCacheKey = `${CACHE_PREFIX}_tokens_addr`; - this.tokensCacheKey = `${CACHE_PREFIX}_tokens`; - this.blacklistCacheKey = `${CACHE_PREFIX}_blacklist`; + this.pricesCacheKey = 'prices'; + this.pairsCacheKey = 'pairs'; + this.tokensAddrCacheKey = 'tokens_addr'; + this.tokensCacheKey = 'tokens'; + this.blacklistCacheKey = 'blacklist'; this.rateFetcher = new RateFetcher( this.dexHelper, @@ -150,6 +148,7 @@ export class Dexalot extends SimpleExchange implements IDex { tokensCacheKey: this.tokensCacheKey, tokensCacheTTLSecs: DEXALOT_TOKENS_CACHES_TTL_S, blacklistCacheKey: this.blacklistCacheKey, + blacklistCacheTTLSecs: DEXALOT_BLACKLIST_CACHES_TTL_S, }, }, ); @@ -755,29 +754,44 @@ export class Dexalot extends SimpleExchange implements IDex { return result === 'true'; } - async setBlacklist(txOrigin: Address, ttl: number = DEXALOT_BLACKLIST_TTL_S, - ): Promise { - await this.dexHelper.cache.setex( + async setBlacklist(txOrigin: Address, ttl: number = DEXALOT_BLACKLIST_CACHES_TTL_S,): Promise { + const cachedBlacklist = await this.dexHelper.cache.get( this.dexKey, this.network, - this.getBlackListKey(txOrigin), + this.blacklistCacheKey, + ); + + let blacklist: string[] = []; + if (cachedBlacklist) { + blacklist = JSON.parse(cachedBlacklist); + } + + blacklist.push(txOrigin.toLowerCase()); + + this.dexHelper.cache.setex( + this.dexKey, + this.network, + this.blacklistCacheKey, ttl, - DEXALOT_BLACKLIST_CACHE_VALUE, + JSON.stringify(blacklist), ); + return true; } async isBlacklisted(txOrigin: Address): Promise { - const result = await this.dexHelper.cache.get( + const cachedBlacklist = await this.dexHelper.cache.get( this.dexKey, this.network, - this.getBlackListKey(txOrigin), + this.blacklistCacheKey, ); - return result === DEXALOT_BLACKLIST_CACHE_VALUE; - } - getBlackListKey(address: Address) { - return `blacklist_${address}`.toLowerCase(); + if (cachedBlacklist) { + const blacklist = JSON.parse(cachedBlacklist) as string[]; + return blacklist.includes(txOrigin.toLowerCase()); + } + + return false; } getRateLimitedKey(address: Address) { diff --git a/src/dex/dexalot/rate-fetcher.ts b/src/dex/dexalot/rate-fetcher.ts index 5cba7f322..fac39ae0e 100644 --- a/src/dex/dexalot/rate-fetcher.ts +++ b/src/dex/dexalot/rate-fetcher.ts @@ -32,6 +32,7 @@ export class RateFetcher { private blacklistFetcher: Fetcher; private blacklistCacheKey: string; + private blacklistCacheTTL: number; constructor( private dexHelper: IDexHelper, @@ -48,6 +49,7 @@ export class RateFetcher { this.tokensCacheKey = config.rateConfig.tokensCacheKey; this.tokensCacheTTL = config.rateConfig.tokensCacheTTLSecs; this.blacklistCacheKey = config.rateConfig.blacklistCacheKey; + this.blacklistCacheTTL = config.rateConfig.blacklistCacheTTLSecs; this.pairsFetcher = new Fetcher( dexHelper.httpRequest, @@ -138,6 +140,7 @@ export class RateFetcher { decimals: pairs[pair].quoteDecimals, }; }); + this.dexHelper.cache.setex( this.dexKey, this.network, @@ -145,6 +148,7 @@ export class RateFetcher { this.pairsCacheTTL, JSON.stringify(dexPairs), ); + this.dexHelper.cache.setex( this.dexKey, this.network, @@ -152,6 +156,7 @@ export class RateFetcher { this.tokensCacheTTL, JSON.stringify(tokenMap), ); + this.dexHelper.cache.setex( this.dexKey, this.network, @@ -167,6 +172,7 @@ export class RateFetcher { Object.keys(prices).forEach(pair => { dexPrices[pair.toLowerCase()] = prices[pair]; }); + this.dexHelper.cache.setex( this.dexKey, this.network, @@ -180,8 +186,12 @@ export class RateFetcher { resp: DexalotBlacklistResponse, ): Promise { const { blacklist } = resp; - for (const address of blacklist) { - this.dexHelper.cache.sadd(this.blacklistCacheKey, address.toLowerCase()); - } + this.dexHelper.cache.setex( + this.dexKey, + this.network, + this.blacklistCacheKey, + this.blacklistCacheTTL, + JSON.stringify(blacklist.map((item) => item.toLowerCase())), + ); } } diff --git a/src/dex/dexalot/types.ts b/src/dex/dexalot/types.ts index eb3b37f57..dee55de3a 100644 --- a/src/dex/dexalot/types.ts +++ b/src/dex/dexalot/types.ts @@ -115,6 +115,7 @@ export type DexalotRateFetcherConfig = { tokensAddrCacheKey: string; tokensCacheKey: string; blacklistCacheKey: string; + blacklistCacheTTLSecs: number; pairsCacheTTLSecs: number; pricesCacheTTLSecs: number; tokensCacheTTLSecs: number; From 22fb3fda99dd8fd0e0eeddd5db1a28968e16b3df Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 30 Sep 2023 00:00:35 +0300 Subject: [PATCH 387/833] 2.36.2-dexalot.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 510d6e83b..dd30e9b6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2-dexalot.2", + "version": "2.36.2-dexalot.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From c8dd0a6e12ea3577e229a9ed7350cde8d7b176bf Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 30 Sep 2023 00:24:49 +0300 Subject: [PATCH 388/833] adjust constants --- src/dex/dexalot/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/dexalot/constants.ts b/src/dex/dexalot/constants.ts index f45bc8cf0..c587d8056 100644 --- a/src/dex/dexalot/constants.ts +++ b/src/dex/dexalot/constants.ts @@ -6,7 +6,7 @@ export const DEXALOT_PRICES_CACHES_TTL_S = 3; export const DEXALOT_PAIRS_CACHES_TTL_S = 21 * 60; // 21 mins -export const DEXALOT_TOKENS_CACHES_TTL_S = 11; +export const DEXALOT_TOKENS_CACHES_TTL_S = 21 * 60; // 21 mins export const DEXALOT_BLACKLIST_CACHES_TTL_S = 3 * 60; // 3 hours From 78cb9eb2b401ffd62195a6b67dc0718faebf32a4 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 30 Sep 2023 00:25:19 +0300 Subject: [PATCH 389/833] 2.36.2-dexalot.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dd30e9b6b..a59d7ac2d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2-dexalot.3", + "version": "2.36.2-dexalot.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 53b73f333b94ea80a29f38ca5ae17c6b6fb3f488 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 30 Sep 2023 00:42:44 +0300 Subject: [PATCH 390/833] adjust constants --- src/dex/dexalot/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/dexalot/constants.ts b/src/dex/dexalot/constants.ts index c587d8056..8161eface 100644 --- a/src/dex/dexalot/constants.ts +++ b/src/dex/dexalot/constants.ts @@ -8,7 +8,7 @@ export const DEXALOT_PAIRS_CACHES_TTL_S = 21 * 60; // 21 mins export const DEXALOT_TOKENS_CACHES_TTL_S = 21 * 60; // 21 mins -export const DEXALOT_BLACKLIST_CACHES_TTL_S = 3 * 60; // 3 hours +export const DEXALOT_BLACKLIST_CACHES_TTL_S = 180 * 60; // 3 hours export const DEXALOT_API_PRICES_POLLING_INTERVAL_MS = 1000; From 06df72c39564e19724bf8d8c71e90143dbca15ef Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 30 Sep 2023 00:42:58 +0300 Subject: [PATCH 391/833] 2.36.2-dexalot.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a59d7ac2d..253978531 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2-dexalot.4", + "version": "2.36.2-dexalot.5", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1bec33bfb70ed6b206e0aec37be407007ffbf859 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 30 Sep 2023 01:07:50 +0300 Subject: [PATCH 392/833] refactor --- src/dex/dexalot/dexalot.ts | 40 +++++++++++++++----------------------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 7eee6b0a6..99880a9e2 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -59,6 +59,8 @@ import { import { BI_MAX_UINT256 } from '../../bigint-constants'; import { ethers } from 'ethers'; import BigNumber from 'bignumber.js'; +import { Method } from '../../dex-helper/irequest-wrapper'; +import { SwaapV2APIParameters } from '../swaap-v2/types'; export class Dexalot extends SimpleExchange implements IDex { readonly isStatePollingDex = true; @@ -116,30 +118,9 @@ export class Dexalot extends SimpleExchange implements IDex { pairsIntervalMs: DEXALOT_API_PAIRS_POLLING_INTERVAL_MS, pricesIntervalMs: DEXALOT_API_PRICES_POLLING_INTERVAL_MS, blacklistIntervalMs: DEXALOT_API_BLACKLIST_POLLING_INTERVAL_MS, - pairsReqParams: { - url: `${DEXALOT_API_URL}/api/rfq/pairs`, - headers: { - 'x-apikey': this.dexalotAuthToken, - }, - params: { - chainid: this.network, - }, - }, - pricesReqParams: { - url: `${DEXALOT_API_URL}/api/rfq/prices`, - headers: { - 'x-apikey': this.dexalotAuthToken, - }, - params: { - chainid: this.network, - }, - }, - blacklistReqParams: { - url: `${DEXALOT_API_URL}/api/rfq/blacklist`, - headers: { - 'x-apikey': this.dexalotAuthToken, - }, - }, + pairsReqParams: this.getAPIReqParams('api/rfq/pairs', 'GET'), + pricesReqParams: this.getAPIReqParams('api/rfq/prices', 'GET'), + blacklistReqParams: this.getAPIReqParams('api/rfq/blacklist', 'GET'), pairsCacheKey: this.pairsCacheKey, pairsCacheTTLSecs: DEXALOT_PAIRS_CACHES_TTL_S, pricesCacheKey: this.pricesCacheKey, @@ -917,6 +898,17 @@ export class Dexalot extends SimpleExchange implements IDex { return pairsByLiquidity.slice(0, limit); } + getAPIReqParams(endpoint: string, method: Method): SwaapV2APIParameters { + return { + url: `${DEXALOT_API_URL}/${endpoint}`, + headers: { 'x-apikey': this.dexalotAuthToken }, + params: { + chainid: this.network, + }, + method: method, + }; + } + releaseResources(): void { if (this.rateFetcher) { this.rateFetcher.stop(); From db71a36e3983c2f32405c8047dba5854775c6518 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 30 Sep 2023 01:15:11 +0300 Subject: [PATCH 393/833] order constants --- src/dex/dexalot/constants.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/dexalot/constants.ts b/src/dex/dexalot/constants.ts index 8161eface..b9841a015 100644 --- a/src/dex/dexalot/constants.ts +++ b/src/dex/dexalot/constants.ts @@ -1,7 +1,5 @@ import BigNumber from 'bignumber.js'; -export const DEXALOT_RATE_LIMITED_TTL_S = 60 * 60; // 1 hour - export const DEXALOT_PRICES_CACHES_TTL_S = 3; export const DEXALOT_PAIRS_CACHES_TTL_S = 21 * 60; // 21 mins @@ -20,10 +18,12 @@ export const DEXALOT_API_URL = 'https://api.dexalot.com'; export const DEXALOT_GAS_COST = 120_000; -export const DEXALOT_RESTRICT_TTL_S = 60 * 30; // 30 minutes +export const DEXALOT_RATE_LIMITED_TTL_S = 60 * 60; // 1 hour export const DEXALOT_RATELIMIT_CACHE_VALUE = 'limited'; +export const DEXALOT_RESTRICT_TTL_S = 60 * 30; // 30 minutes + export const DEXALOT_RESTRICTED_CACHE_KEY = 'restricted'; export const DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION = new BigNumber('0.001'); From 934ca8a8e0f54b4d455dc1257a8553c3fc2d12a1 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Sat, 30 Sep 2023 13:44:11 -0400 Subject: [PATCH 394/833] lower constants --- src/dex/solidly-v3/constants.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/dex/solidly-v3/constants.ts b/src/dex/solidly-v3/constants.ts index e9fdeeebb..204e0f25f 100644 --- a/src/dex/solidly-v3/constants.ts +++ b/src/dex/solidly-v3/constants.ts @@ -1,6 +1,6 @@ -export const UNISWAPV3_TICK_GAS_COST = 24_000; // Ceiled -export const UNISWAPV3_TICK_BASE_OVERHEAD = 75_000; -export const UNISWAPV3_POOL_SEARCH_OVERHEAD = 10_000; +export const UNISWAPV3_TICK_GAS_COST = 10_000; // Ceiled +export const UNISWAPV3_TICK_BASE_OVERHEAD = 50_000; +export const UNISWAPV3_POOL_SEARCH_OVERHEAD = 0; // This is used for price calculation. If out of scope, return 0n export const TICK_BITMAP_TO_USE = 4n; @@ -37,4 +37,5 @@ export enum DirectMethods { directBuy = 'directUniV3Buy', } export const MIN_SQRT_RATIO = BigInt(4295128739); -export const MAX_SQRT_RATIO = BigInt(1461446703485210103287273052203988822378723970342); \ No newline at end of file +export const MAX_SQRT_RATIO = + BigInt(1461446703485210103287273052203988822378723970342); From de231dbfe1dadc609ce047cf487fd47a4dff96b1 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Sat, 30 Sep 2023 23:26:57 +0300 Subject: [PATCH 395/833] fix: await init --- src/dex/algebra/algebra.ts | 2 +- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 2 +- src/dex/uniswap-v3/uniswap-v3.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index bc18ddd4d..32efc8326 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -137,7 +137,7 @@ export class Algebra extends SimpleExchange implements IDex { async initializePricing(blockNumber: number) { // Init listening to new pools creation - this.factory.initialize(blockNumber); + await this.factory.initialize(blockNumber); if (!this.dexHelper.config.isSlave) { const cleanExpiredNotExistingPoolsKeys = async () => { diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index d72f46dde..5ec7d2183 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -147,7 +147,7 @@ export class PancakeswapV3 async initializePricing(blockNumber: number) { // Init listening to new pools creation - this.factory.initialize(blockNumber); + await this.factory.initialize(blockNumber); if (!this.dexHelper.config.isSlave) { const cleanExpiredNotExistingPoolsKeys = async () => { diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 51fc9d4b8..1f2a6b613 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -165,7 +165,7 @@ export class UniswapV3 async initializePricing(blockNumber: number) { // Init listening to new pools creation - this.factory.initialize(blockNumber); + await this.factory.initialize(blockNumber); // This is only for testing, because cold pool fetching is goes out of // FETCH_POOL_INDENTIFIER_TIMEOUT range From 674ef92f65d97430c6742a1a28fc71f8a42b0ec3 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Sat, 30 Sep 2023 23:46:49 +0300 Subject: [PATCH 396/833] fix: add pool deletion logging --- src/dex/algebra/algebra.ts | 8 +++++++- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 8 +++++++- src/dex/uniswap-v3/uniswap-v3.ts | 8 +++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 32efc8326..5bb393f83 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -165,15 +165,21 @@ export class Algebra extends SimpleExchange implements IDex { token0, token1, }) => { + const logPrefix = '[Algebra.onPoolCreatedDeleteFromNonExistingSet]'; const [_token0, _token1] = this._sortTokens(token0, token1); const poolKey = `${token0}_${token1}`.toLowerCase(); // consider doing it only from master pool for less calls to distant cache try { + this.logger.info( + `${logPrefix} delete pool from not existing set: ${poolKey}`, + ); // delete pool record from set await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); - } catch (e) {} + } catch (e) { + this.logger.error(`${logPrefix} ERROR deleting pool: ${poolKey}`); + } // delete entry locally to let local instance discover the pool delete this.eventPools[this.getPoolIdentifier(_token0, _token1)]; diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 5ec7d2183..62903a292 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -176,15 +176,21 @@ export class PancakeswapV3 token1, fee, }) => { + const logPrefix = '[PancakeV3.onPoolCreatedDeleteFromNonExistingSet]'; const [_token0, _token1] = this._sortTokens(token0, token1); const poolKey = `${token0}_${token1}_${fee}`.toLowerCase(); // consider doing it only from master pool for less calls to distant cache try { + this.logger.info( + `${logPrefix} delete pool from not existing set: ${poolKey}`, + ); // delete pool record from set await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); - } catch (e) {} + } catch (e) { + this.logger.error(`${logPrefix} ERROR deleting pool: ${poolKey}`); + } // delete entry locally to let local instance discover the pool delete this.eventPools[this.getPoolIdentifier(_token0, _token1, fee)]; diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 1f2a6b613..d4db7efaf 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -206,15 +206,21 @@ export class UniswapV3 token1, fee, }) => { + const logPrefix = '[UniswapV3.onPoolCreatedDeleteFromNonExistingSet]'; const [_token0, _token1] = this._sortTokens(token0, token1); const poolKey = `${token0}_${token1}_${fee}`.toLowerCase(); // consider doing it only from master pool for less calls to distant cache try { + this.logger.info( + `${logPrefix} delete pool from not existing set: ${poolKey}`, + ); // delete pool record from set await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); - } catch (e) {} + } catch (e) { + this.logger.error(`${logPrefix} ERROR deleting pool: ${poolKey}`); + } // delete entry locally to let local instance discover the pool delete this.eventPools[this.getPoolIdentifier(_token0, _token1, fee)]; From fa2990fe2113a07e3ec41b0616d22f91c89f34ba Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 11:52:54 +0300 Subject: [PATCH 397/833] add fix for getTopPoolsForToken --- src/dex/dexalot/dexalot.ts | 61 ++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 99880a9e2..6c0f3626c 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -279,6 +279,12 @@ export class Dexalot extends SimpleExchange implements IDex { : address.toLowerCase(); } + denormalizeAddress(address: string): string { + return address.toLowerCase() === NULL_ADDRESS + ? ETHER_ADDRESS + : address.toLowerCase(); + } + // Dexalot protocol for native token expects 0x00000... instead of 0xeeeee... normalizeToken(token: Token): Token { return { @@ -287,6 +293,13 @@ export class Dexalot extends SimpleExchange implements IDex { }; } + denormalizeToken(token: Token): Token { + return { + address: this.denormalizeAddress(token.address), + decimals: token.decimals, + }; + } + calculateOrderPrice( amounts: bigint[], orderbook: string[][], @@ -864,31 +877,35 @@ export class Dexalot extends SimpleExchange implements IDex { let pairsByLiquidity = []; for (const pairName of Object.keys(pairs)) { - if (pairName.includes(tokenSymbol)) { - const tokensInPair = pairName.split('/'); - if (tokensInPair.length !== 2) { - continue; - } + if (!pairName.includes(tokenSymbol)) { + continue; + } - const addr = tokensAddr[tokensInPair[0].toLowerCase()]; - let outputToken = this.getTokenFromAddress(addr); - if (tokensInPair[0] === tokenSymbol) { - const addr = tokensAddr[tokensInPair[1].toLowerCase()]; - outputToken = this.getTokenFromAddress(addr); - } + const tokensInPair = pairName.split('/'); + if (tokensInPair.length !== 2) { + continue; + } - const connectorToken = { - address: outputToken.address, - decimals: outputToken.decimals, - }; - const pairData: PoolLiquidity = { - exchange: this.dexKey, - address: this.mainnetRFQAddress, - connectorTokens: [connectorToken], - liquidityUSD: pairs[pairName].liquidityUSD, - }; - pairsByLiquidity.push(pairData); + const [ baseToken, quoteToken ] = tokensInPair; + const addr = tokensAddr[baseToken.toLowerCase()]; + let outputToken = this.getTokenFromAddress(addr); + if (baseToken === tokenSymbol) { + const addr = tokensAddr[quoteToken.toLowerCase()]; + outputToken = this.getTokenFromAddress(addr); } + + const denormalizedToken = this.denormalizeToken(outputToken); + const wrappedToken = this.dexHelper.config.wrapETH(denormalizedToken); + + pairsByLiquidity.push({ + exchange: this.dexKey, + address: this.mainnetRFQAddress, + connectorTokens: [{ + address: wrappedToken.address, + decimals: wrappedToken.decimals, + }], + liquidityUSD: pairs[pairName].liquidityUSD, + }); } pairsByLiquidity.sort( From 8c5ec8da952f171a5e8b076fd9eac8f068cd82b5 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 11:53:40 +0300 Subject: [PATCH 398/833] 2.36.2-dexalot.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 253978531..aebea5ceb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2-dexalot.5", + "version": "2.36.2-dexalot.6", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 0c153db9c58397b8ca81867147f8b61097013eed Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 13:00:18 +0300 Subject: [PATCH 399/833] add fixes --- src/dex/dexalot/dexalot.ts | 9 ++++----- src/dex/dexalot/types.ts | 8 ++++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 6c0f3626c..9cda49839 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -28,6 +28,7 @@ import { PairDataMap, PriceDataMap, DexalotRfqError, + DexalotAPIParameters, RFQResponse, RFQResponseError, TokenAddrDataMap, @@ -60,7 +61,6 @@ import { BI_MAX_UINT256 } from '../../bigint-constants'; import { ethers } from 'ethers'; import BigNumber from 'bignumber.js'; import { Method } from '../../dex-helper/irequest-wrapper'; -import { SwaapV2APIParameters } from '../swaap-v2/types'; export class Dexalot extends SimpleExchange implements IDex { readonly isStatePollingDex = true; @@ -895,14 +895,13 @@ export class Dexalot extends SimpleExchange implements IDex { } const denormalizedToken = this.denormalizeToken(outputToken); - const wrappedToken = this.dexHelper.config.wrapETH(denormalizedToken); pairsByLiquidity.push({ exchange: this.dexKey, address: this.mainnetRFQAddress, connectorTokens: [{ - address: wrappedToken.address, - decimals: wrappedToken.decimals, + address: denormalizedToken.address, + decimals: denormalizedToken.decimals, }], liquidityUSD: pairs[pairName].liquidityUSD, }); @@ -915,7 +914,7 @@ export class Dexalot extends SimpleExchange implements IDex { return pairsByLiquidity.slice(0, limit); } - getAPIReqParams(endpoint: string, method: Method): SwaapV2APIParameters { + getAPIReqParams(endpoint: string, method: Method): DexalotAPIParameters { return { url: `${DEXALOT_API_URL}/${endpoint}`, headers: { 'x-apikey': this.dexalotAuthToken }, diff --git a/src/dex/dexalot/types.ts b/src/dex/dexalot/types.ts index dee55de3a..41bc53257 100644 --- a/src/dex/dexalot/types.ts +++ b/src/dex/dexalot/types.ts @@ -1,5 +1,6 @@ import { RequestHeaders } from '../../dex-helper'; import { Token } from '../../types'; +import { Method } from '../../dex-helper/irequest-wrapper'; type RFQOrder = { nonceAndMeta: string; @@ -121,3 +122,10 @@ export type DexalotRateFetcherConfig = { tokensCacheTTLSecs: number; }; }; + +export type DexalotAPIParameters = { + url: string; + headers?: RequestHeaders; + params?: any; + method?: Method; +}; From 38f014e91755b1191ea477829d0887f4925aca1e Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 13:00:45 +0300 Subject: [PATCH 400/833] 2.36.2-dexalot.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index aebea5ceb..b5a47b3ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2-dexalot.6", + "version": "2.36.2-dexalot.7", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From b44ae5c515ee442228429b25db02993643aeade1 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 13:27:45 +0300 Subject: [PATCH 401/833] add a fix --- src/dex/dexalot/dexalot.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 9cda49839..ac9747ed5 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -61,6 +61,7 @@ import { BI_MAX_UINT256 } from '../../bigint-constants'; import { ethers } from 'ethers'; import BigNumber from 'bignumber.js'; import { Method } from '../../dex-helper/irequest-wrapper'; +import { normalizeTokenAddress } from '../swaap-v2/utils'; export class Dexalot extends SimpleExchange implements IDex { readonly isStatePollingDex = true; @@ -865,10 +866,11 @@ export class Dexalot extends SimpleExchange implements IDex { return []; } + const normalizedTokenAddress = normalizeTokenAddress(tokenAddress); const pairs = (await this.getCachedPairs()) || {}; this.tokensMap = (await this.getCachedTokens()) || {}; const tokensAddr = (await this.getCachedTokensAddr()) || {}; - const token = this.getTokenFromAddress(tokenAddress); + const token = this.getTokenFromAddress(normalizedTokenAddress); if (!token) { return []; } From b8048d6b010a347d8fdf60fe2425abcb40a4cf7b Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 13:42:04 +0300 Subject: [PATCH 402/833] 2.36.2-dexalot.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b5a47b3ee..beb74f9c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2-dexalot.7", + "version": "2.36.2-dexalot.8", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1a4b6f66ab497023ea6855946f228d6c96e803b6 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 14:05:55 +0300 Subject: [PATCH 403/833] add a fix --- src/dex/dexalot/dexalot.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index ac9747ed5..e97cb7645 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -897,13 +897,14 @@ export class Dexalot extends SimpleExchange implements IDex { } const denormalizedToken = this.denormalizeToken(outputToken); + const wrappedToken = this.dexHelper.config.wrapETH(denormalizedToken); pairsByLiquidity.push({ exchange: this.dexKey, address: this.mainnetRFQAddress, connectorTokens: [{ - address: denormalizedToken.address, - decimals: denormalizedToken.decimals, + address: wrappedToken.address, + decimals: wrappedToken.decimals, }], liquidityUSD: pairs[pairName].liquidityUSD, }); From eff13c21c73ae46bb523cefa730aca4b983ea444 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 14:06:16 +0300 Subject: [PATCH 404/833] 2.36.2-dexalot.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index beb74f9c4..a9c13056d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2-dexalot.8", + "version": "2.36.2-dexalot.9", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 5cf040b78c6c1578dbd12df68247acd384f94be8 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 15:11:39 +0300 Subject: [PATCH 405/833] add a fix --- src/dex/dexalot/dexalot.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index e97cb7645..ac9747ed5 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -897,14 +897,13 @@ export class Dexalot extends SimpleExchange implements IDex { } const denormalizedToken = this.denormalizeToken(outputToken); - const wrappedToken = this.dexHelper.config.wrapETH(denormalizedToken); pairsByLiquidity.push({ exchange: this.dexKey, address: this.mainnetRFQAddress, connectorTokens: [{ - address: wrappedToken.address, - decimals: wrappedToken.decimals, + address: denormalizedToken.address, + decimals: denormalizedToken.decimals, }], liquidityUSD: pairs[pairName].liquidityUSD, }); From 6d512e38daf547f88ce6ebd54dd42f3f6dfb551f Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 15:12:13 +0300 Subject: [PATCH 406/833] 2.36.2-dexalot.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a9c13056d..f28875171 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2-dexalot.9", + "version": "2.36.2-dexalot.10", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 7de083bcbf211cba031e5db7a29717ad66290763 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 18:11:29 +0300 Subject: [PATCH 407/833] BACK-1315: disable DAI/USDC/FUSDT CurveV1 pool on Fantom --- src/dex/curve-v1/config.ts | 39 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/dex/curve-v1/config.ts b/src/dex/curve-v1/config.ts index 979f6ecde..7fee080d4 100644 --- a/src/dex/curve-v1/config.ts +++ b/src/dex/curve-v1/config.ts @@ -958,25 +958,26 @@ export const CurveV1Config: DexConfigMap = { isMetapool: false, baseToken: '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E', }, - main_iDAI_iUSDC_iFUSDT: { - underlying: [ - '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E', // DAI - '0x04068DA6C83AFCFA0e13ba15A6696662335D5B75', // USDC - '0x049d68029688eAbF473097a2fC38ef61633A3C7A', // fUSDT - ], - coins: [ - '0x04c762a5dF2Fa02FE868F25359E0C259fB811CfE', // iDAI - '0x328A7b4d538A2b3942653a9983fdA3C12c571141', // iUSDC - '0x70faC71debfD67394D1278D98A29dea79DC6E57A', // iFUSDT - ], - address: '0x4FC8D635c3cB1d0aa123859e2B2587d0FF2707b1', - name: 'main_iDAI_iUSDC_iFUSDT', - type: 2, - version: 3, - isLending: true, - isMetapool: false, - baseToken: '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E', - }, + // Disabled pool + // main_iDAI_iUSDC_iFUSDT: { + // underlying: [ + // '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E', // DAI + // '0x04068DA6C83AFCFA0e13ba15A6696662335D5B75', // USDC + // '0x049d68029688eAbF473097a2fC38ef61633A3C7A', // fUSDT + // ], + // coins: [ + // '0x04c762a5dF2Fa02FE868F25359E0C259fB811CfE', // iDAI + // '0x328A7b4d538A2b3942653a9983fdA3C12c571141', // iUSDC + // '0x70faC71debfD67394D1278D98A29dea79DC6E57A', // iFUSDT + // ], + // address: '0x4FC8D635c3cB1d0aa123859e2B2587d0FF2707b1', + // name: 'main_iDAI_iUSDC_iFUSDT', + // type: 2, + // version: 3, + // isLending: true, + // isMetapool: false, + // baseToken: '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E', + // }, }, }, [Network.AVALANCHE]: { From 4979e0c12ad224a05ec8fa1f859623ff15da5aba Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 18:12:42 +0300 Subject: [PATCH 408/833] 2.36.2-curve-v1-disable-pool --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6e65d672e..cc8df8059 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.1", + "version": "2.36.2-curve-v1-disable-pool", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 26a8afa9d662c6ef4880439d979bf50af14e4043 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 2 Oct 2023 18:13:49 +0300 Subject: [PATCH 409/833] fix: add state to all factories --- src/dex/algebra/algebra-factory.ts | 29 +++++++++++------- src/dex/algebra/algebra.ts | 25 ++++++++-------- src/dex/algebra/types.ts | 5 ++++ .../pancakeswap-v3/pancakeswap-v3-factory.ts | 30 ++++++++++++------- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 26 ++++++++-------- src/dex/uniswap-v3/types.ts | 6 ++++ src/dex/uniswap-v3/uniswap-v3-factory.ts | 30 ++++++++++++------- src/dex/uniswap-v3/uniswap-v3.ts | 26 ++++++++-------- 8 files changed, 108 insertions(+), 69 deletions(-) diff --git a/src/dex/algebra/algebra-factory.ts b/src/dex/algebra/algebra-factory.ts index 8abb0cf14..7a34bf23d 100644 --- a/src/dex/algebra/algebra-factory.ts +++ b/src/dex/algebra/algebra-factory.ts @@ -1,10 +1,11 @@ import { Interface } from '@ethersproject/abi'; -import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; +import { DeepReadonly } from 'ts-essentials'; import FactoryABI from '../../abi/algebra/AlgebraFactory-v1_1.abi.json'; import { IDexHelper } from '../../dex-helper/idex-helper'; import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; import { Address, Log, Logger } from '../../types'; import { LogDescription } from 'ethers/lib/utils'; +import { FactoryState } from './types'; export type OnPoolCreatedCallback = ({ token0, @@ -12,14 +13,15 @@ export type OnPoolCreatedCallback = ({ }: { token0: string; token1: string; -}) => AsyncOrSync; +}) => FactoryState | null; /* - * Stateless event subscriber in order to capture "Pool" event on new pools created. + * "Stateless" event subscriber in order to capture "PoolCreated" event on new pools created. + * State is present, but it's a placeholder to actually make the events reach handlers (if there's no previous state - `processBlockLogs` is not called) */ -export class AlgebraFactory extends StatefulEventSubscriber { +export class AlgebraFactory extends StatefulEventSubscriber { handlers: { - [event: string]: (event: any) => DeepReadonly | null; + [event: string]: (event: any) => DeepReadonly | null; } = {}; logDecoder: (log: Log) => any; @@ -34,7 +36,7 @@ export class AlgebraFactory extends StatefulEventSubscriber { protected readonly onPoolCreated: OnPoolCreatedCallback, mapKey: string = '', ) { - super(parentName, `factory`, dexHelper, logger, true, mapKey); + super(parentName, `${parentName} Factory`, dexHelper, logger, true, mapKey); this.addressesSubscribed = [factoryAddress]; @@ -43,15 +45,20 @@ export class AlgebraFactory extends StatefulEventSubscriber { this.handlers['Pool'] = this.handleNewPool.bind(this); } - generateState(): AsyncOrSync {} + generateState(): FactoryState { + return { + token0: '', + token1: '', + }; + } protected processLog( - _: DeepReadonly, + _: DeepReadonly, log: Readonly, - ): DeepReadonly | null { + ): DeepReadonly | null { const event = this.logDecoder(log); if (event.name in this.handlers) { - this.handlers[event.name](event); + return this.handlers[event.name](event); } return null; @@ -61,6 +68,6 @@ export class AlgebraFactory extends StatefulEventSubscriber { const token0 = event.args.token0; const token1 = event.args.token1; - this.onPoolCreated({ token0, token1 }); + return this.onPoolCreated({ token0, token1 }); } } diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 5bb393f83..27c99c1d7 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -159,9 +159,9 @@ export class Algebra extends SimpleExchange implements IDex { /* * When a non existing pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls - * Once the pool is created, it gets immediately flagged + * Once the pool is created, it gets immediately flagged */ - onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ + onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = ({ token0, token1, }) => { @@ -171,18 +171,19 @@ export class Algebra extends SimpleExchange implements IDex { // consider doing it only from master pool for less calls to distant cache - try { - this.logger.info( - `${logPrefix} delete pool from not existing set: ${poolKey}`, - ); - // delete pool record from set - await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); - } catch (e) { - this.logger.error(`${logPrefix} ERROR deleting pool: ${poolKey}`); - } - // delete entry locally to let local instance discover the pool delete this.eventPools[this.getPoolIdentifier(_token0, _token1)]; + + this.logger.info( + `${logPrefix} delete pool from not existing set: ${poolKey}`, + ); + // delete pool record from set, not waiting for result + this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); + + return { + token0: _token0, + token1: _token1, + }; }; async getPool( diff --git a/src/dex/algebra/types.ts b/src/dex/algebra/types.ts index 891983100..e8cb3684e 100644 --- a/src/dex/algebra/types.ts +++ b/src/dex/algebra/types.ts @@ -51,6 +51,11 @@ export type PoolState_v1_9 = { areTicksCompressed: boolean; }; +export type FactoryState = { + token0: string; + token1: string; +}; + export type AlgebraData = { path: { tokenIn: Address; diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts b/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts index 4cd6f1b18..4b0c161c6 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts @@ -1,10 +1,11 @@ import { Interface } from '@ethersproject/abi'; -import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; +import { DeepReadonly } from 'ts-essentials'; import FactoryABI from '../../abi/pancakeswap-v3/PancakeswapV3Factory.abi.json'; import { IDexHelper } from '../../dex-helper/idex-helper'; import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; import { Address, Log, Logger } from '../../types'; import { LogDescription } from 'ethers/lib/utils'; +import { FactoryState } from '../uniswap-v3/types'; export type OnPoolCreatedCallback = ({ token0, @@ -14,14 +15,15 @@ export type OnPoolCreatedCallback = ({ token0: string; token1: string; fee: bigint; -}) => AsyncOrSync; +}) => FactoryState; /* - * Stateless event subscriber in order to capture "Pool" event on new pools created. + * "Stateless" event subscriber in order to capture "PoolCreated" event on new pools created. + * State is present, but it's a placeholder to actually make the events reach handlers (if there's no previous state - `processBlockLogs` is not called) */ -export class PancakeswapV3Factory extends StatefulEventSubscriber { +export class PancakeswapV3Factory extends StatefulEventSubscriber { handlers: { - [event: string]: (event: any) => DeepReadonly | null; + [event: string]: (event: any) => DeepReadonly | null; } = {}; logDecoder: (log: Log) => any; @@ -36,7 +38,7 @@ export class PancakeswapV3Factory extends StatefulEventSubscriber { protected readonly onPoolCreated: OnPoolCreatedCallback, mapKey: string = '', ) { - super(parentName, `factory`, dexHelper, logger, true, mapKey); + super(parentName, `${parentName} Factory`, dexHelper, logger, true, mapKey); this.addressesSubscribed = [factoryAddress]; @@ -45,15 +47,21 @@ export class PancakeswapV3Factory extends StatefulEventSubscriber { this.handlers['PoolCreated'] = this.handleNewPool.bind(this); } - generateState(): AsyncOrSync {} + generateState(): FactoryState { + return { + token0: '', + token1: '', + fee: 0n, + }; + } protected processLog( - _: DeepReadonly, + _: DeepReadonly, log: Readonly, - ): DeepReadonly | null { + ): DeepReadonly | null { const event = this.logDecoder(log); if (event.name in this.handlers) { - this.handlers[event.name](event); + return this.handlers[event.name](event); } return null; @@ -64,6 +72,6 @@ export class PancakeswapV3Factory extends StatefulEventSubscriber { const token1 = event.args.token1; const fee = event.args.fee; - this.onPoolCreated({ token0, token1, fee }); + return this.onPoolCreated({ token0, token1, fee }); } } diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 62903a292..66430b0e3 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -169,9 +169,9 @@ export class PancakeswapV3 /* * When a non existing pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls - * Once the pool is created, it gets immediately flagged + * Once the pool is created, it gets immediately flagged */ - onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ + onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = ({ token0, token1, fee, @@ -182,18 +182,20 @@ export class PancakeswapV3 // consider doing it only from master pool for less calls to distant cache - try { - this.logger.info( - `${logPrefix} delete pool from not existing set: ${poolKey}`, - ); - // delete pool record from set - await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); - } catch (e) { - this.logger.error(`${logPrefix} ERROR deleting pool: ${poolKey}`); - } - // delete entry locally to let local instance discover the pool delete this.eventPools[this.getPoolIdentifier(_token0, _token1, fee)]; + + this.logger.info( + `${logPrefix} delete pool from not existing set: ${poolKey}`, + ); + // delete pool record from set, not waiting for result + this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); + + return { + token0: _token0, + token1: _token1, + fee, + }; }; async getPool( diff --git a/src/dex/uniswap-v3/types.ts b/src/dex/uniswap-v3/types.ts index b7c314500..bdb396d19 100644 --- a/src/dex/uniswap-v3/types.ts +++ b/src/dex/uniswap-v3/types.ts @@ -53,6 +53,12 @@ export type PoolState = { balance1: bigint; }; +export type FactoryState = { + token0: string; + token1: string; + fee: bigint; +}; + export type UniswapV3Data = { path: { tokenIn: Address; diff --git a/src/dex/uniswap-v3/uniswap-v3-factory.ts b/src/dex/uniswap-v3/uniswap-v3-factory.ts index a1a41c73b..db8fc4e80 100644 --- a/src/dex/uniswap-v3/uniswap-v3-factory.ts +++ b/src/dex/uniswap-v3/uniswap-v3-factory.ts @@ -1,10 +1,11 @@ import { Interface } from '@ethersproject/abi'; -import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; +import { DeepReadonly } from 'ts-essentials'; import FactoryABI from '../../abi/uniswap-v3/UniswapV3Factory.abi.json'; import { IDexHelper } from '../../dex-helper/idex-helper'; import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; import { Address, Log, Logger } from '../../types'; import { LogDescription } from 'ethers/lib/utils'; +import { FactoryState } from './types'; export type OnPoolCreatedCallback = ({ token0, @@ -14,14 +15,15 @@ export type OnPoolCreatedCallback = ({ token0: string; token1: string; fee: bigint; -}) => AsyncOrSync; +}) => FactoryState | null; /* - * Stateless event subscriber in order to capture "Pool" event on new pools created. + * "Stateless" event subscriber in order to capture "PoolCreated" event on new pools created. + * State is present, but it's a placeholder to actually make the events reach handlers (if there's no previous state - `processBlockLogs` is not called) */ -export class UniswapV3Factory extends StatefulEventSubscriber { +export class UniswapV3Factory extends StatefulEventSubscriber { handlers: { - [event: string]: (event: any) => DeepReadonly | null; + [event: string]: (event: any) => DeepReadonly | null; } = {}; logDecoder: (log: Log) => any; @@ -36,7 +38,7 @@ export class UniswapV3Factory extends StatefulEventSubscriber { protected readonly onPoolCreated: OnPoolCreatedCallback, mapKey: string = '', ) { - super(parentName, `factory`, dexHelper, logger, true, mapKey); + super(parentName, `${parentName} Factory`, dexHelper, logger, true, mapKey); this.addressesSubscribed = [factoryAddress]; @@ -45,15 +47,21 @@ export class UniswapV3Factory extends StatefulEventSubscriber { this.handlers['PoolCreated'] = this.handleNewPool.bind(this); } - generateState(): AsyncOrSync {} + generateState(): FactoryState { + return { + token0: '', + token1: '', + fee: 0n, + }; + } protected processLog( - _: DeepReadonly, + _: DeepReadonly, log: Readonly, - ): DeepReadonly | null { + ): DeepReadonly | null { const event = this.logDecoder(log); if (event.name in this.handlers) { - this.handlers[event.name](event); + return this.handlers[event.name](event); } return null; @@ -64,6 +72,6 @@ export class UniswapV3Factory extends StatefulEventSubscriber { const token1 = event.args.token1; const fee = event.args.fee; - this.onPoolCreated({ token0, token1, fee }); + return this.onPoolCreated({ token0, token1, fee }); } } diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index d4db7efaf..3c46c2193 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -199,9 +199,9 @@ export class UniswapV3 /* * When a non existing pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls - * Once the pool is created, it gets immediately flagged + * Once the pool is created, it gets immediately flagged */ - onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ + onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = ({ token0, token1, fee, @@ -212,18 +212,20 @@ export class UniswapV3 // consider doing it only from master pool for less calls to distant cache - try { - this.logger.info( - `${logPrefix} delete pool from not existing set: ${poolKey}`, - ); - // delete pool record from set - await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); - } catch (e) { - this.logger.error(`${logPrefix} ERROR deleting pool: ${poolKey}`); - } - // delete entry locally to let local instance discover the pool delete this.eventPools[this.getPoolIdentifier(_token0, _token1, fee)]; + + this.logger.info( + `${logPrefix} delete pool from not existing set: ${poolKey}`, + ); + // delete pool record from set, not waiting for result + this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); + + return { + token0: _token0, + token1: _token1, + fee, + }; }; async getPool( From dd9f4aea0fa0d8c76c09eb531a158b2d0f2b4b07 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 18:34:18 +0300 Subject: [PATCH 410/833] disable one more pool --- src/dex/curve-v1/config.ts | 39 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/dex/curve-v1/config.ts b/src/dex/curve-v1/config.ts index 7fee080d4..45c599a36 100644 --- a/src/dex/curve-v1/config.ts +++ b/src/dex/curve-v1/config.ts @@ -939,25 +939,26 @@ export const CurveV1Config: DexConfigMap = { isMetapool: false, baseToken: '0x321162Cd933E2Be498Cd2267a90534A804051b11', }, - main_gDAI_gUSDC_gUSDT: { - underlying: [ - '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E', // DAI - '0x04068DA6C83AFCFA0e13ba15A6696662335D5B75', // USDC - '0x049d68029688eAbF473097a2fC38ef61633A3C7A', // fUSDT - ], - coins: [ - '0x07E6332dD090D287d3489245038daF987955DCFB', // gDAI - '0xe578C856933D8e1082740bf7661e379Aa2A30b26', // gUSDC - '0x940F41F0ec9ba1A34CF001cc03347ac092F5F6B5', // gUSDT - ], - address: '0x0fa949783947Bf6c1b171DB13AEACBB488845B3f', - name: 'main_gDAI_gUSDC_gUSDT', - type: 2, - version: 3, - isLending: true, - isMetapool: false, - baseToken: '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E', - }, + // Disabled pool + // main_gDAI_gUSDC_gUSDT: { + // underlying: [ + // '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E', // DAI + // '0x04068DA6C83AFCFA0e13ba15A6696662335D5B75', // USDC + // '0x049d68029688eAbF473097a2fC38ef61633A3C7A', // fUSDT + // ], + // coins: [ + // '0x07E6332dD090D287d3489245038daF987955DCFB', // gDAI + // '0xe578C856933D8e1082740bf7661e379Aa2A30b26', // gUSDC + // '0x940F41F0ec9ba1A34CF001cc03347ac092F5F6B5', // gUSDT + // ], + // address: '0x0fa949783947Bf6c1b171DB13AEACBB488845B3f', + // name: 'main_gDAI_gUSDC_gUSDT', + // type: 2, + // version: 3, + // isLending: true, + // isMetapool: false, + // baseToken: '0x8D11eC38a3EB5E956B052f67Da8Bdc9bef8Abf3E', + // }, // Disabled pool // main_iDAI_iUSDC_iFUSDT: { // underlying: [ From b03c6d8579617d8dd1fa798968bb650642a2e2e9 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 18:34:33 +0300 Subject: [PATCH 411/833] 2.36.2-curve-v1-disable-pool.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cc8df8059..b55702bf6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2-curve-v1-disable-pool", + "version": "2.36.2-curve-v1-disable-pool.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 4e5c0f9ffece9762ecdd5872f6e878032bf31c70 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 21:34:35 +0300 Subject: [PATCH 412/833] 2.36.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b55702bf6..1c5e487f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2-curve-v1-disable-pool.2", + "version": "2.36.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 4319b845d59eb4d6f2f12a2a46078b5b62b32558 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 2 Oct 2023 21:52:44 +0300 Subject: [PATCH 413/833] 2.36.3-dexalot --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f28875171..297be3746 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2-dexalot.10", + "version": "2.36.3-dexalot", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From d36f26a1f2b4b6791167b9546297558555ac3d64 Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 3 Oct 2023 09:07:13 +0200 Subject: [PATCH 414/833] feat(config): add smardex base config --- src/dex/smardex/config.ts | 7 +++++++ tests/constants-e2e.ts | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/src/dex/smardex/config.ts b/src/dex/smardex/config.ts index 59572790e..2fcce58a4 100644 --- a/src/dex/smardex/config.ts +++ b/src/dex/smardex/config.ts @@ -38,6 +38,13 @@ export const SmardexConfig: DexConfigMap = { subgraphURL: `${gatewaySubgraph}/polygon`, // feeCode: 0, // this is ignored as Smardex uses dynamic fees }, + [Network.BASE]: { + factoryAddress: '0xdd4536dD9636564D891c919416880a3e250f975A', + router: '0x5C622Dcc96b6D96ac6c154f99CF081815094CBC9', + initCode: layer2InitHash, + subgraphURL: `${gatewaySubgraph}/base`, + // feeCode: 0, // this is ignored as Smardex uses dynamic fees + }, }, }; diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 8b6127120..5d6ad396b 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -932,6 +932,10 @@ export const Tokens: { address: '0xbeFD5C25A59ef2C1316c5A4944931171F30Cd3E4', decimals: 18, }, + SDEX: { + address: '0xFd4330b0312fdEEC6d4225075b82E00493FF2e3f', + decimals: 18, + }, ETH: { address: ETHER_ADDRESS, decimals: 18 }, }, }; From d9baa72fd6fd98c0e461c8739ed159e332b3217d Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 3 Oct 2023 09:08:10 +0200 Subject: [PATCH 415/833] test(integration): add base scenario --- src/dex/smardex/smardex-integration.test.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/dex/smardex/smardex-integration.test.ts b/src/dex/smardex/smardex-integration.test.ts index d7e415ba4..57e0f9d75 100644 --- a/src/dex/smardex/smardex-integration.test.ts +++ b/src/dex/smardex/smardex-integration.test.ts @@ -10,7 +10,7 @@ import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; interface NetworkConfig { - name: 'ethereum' | 'bsc' | 'polygon' | 'arbitrum'; + name: 'ethereum' | 'bsc' | 'polygon' | 'arbitrum' | 'base'; network: Network; tokens: typeof Tokens[Network]; tokenPairs: { src: string; dest: string; sell: number[]; buy: number[] }[]; @@ -149,6 +149,25 @@ const networkConfigs: Array = [ }, ], }, + { + name: 'base', + network: Network.BASE, + tokens: Tokens[Network.BASE], + tokenPairs: [ + { + src: 'WETH', + dest: 'SDEX', + sell: [0, 2, 4, 6, 8, 10], + buy: [0, 100_000, 200_000, 300_000], + }, + { + src: 'WETH', + dest: 'USDbC', + sell: [0, 2, 4, 6, 8, 10], + buy: [0, 10_000, 20_000, 30_000], + }, + ], + }, ]; networkConfigs.forEach(({ name, network, tokens, tokenPairs }) => { From 8e4f2bcead73b9050912453b745640296b25796a Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 3 Oct 2023 09:32:14 +0200 Subject: [PATCH 416/833] test(events): register block number of main pairs --- src/dex/smardex/smardex-events.test.ts | 35 +++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/dex/smardex/smardex-events.test.ts b/src/dex/smardex/smardex-events.test.ts index 5be7eea21..f80a9c423 100644 --- a/src/dex/smardex/smardex-events.test.ts +++ b/src/dex/smardex/smardex-events.test.ts @@ -16,7 +16,7 @@ jest.setTimeout(120 * 1000); const dexKey = 'Smardex'; type NetworkConfig = { - name: 'ethereum' | 'polygon' | 'bsc' | 'arbitrum'; + name: 'ethereum' | 'polygon' | 'bsc' | 'arbitrum' | 'base'; network: Network; tokens: typeof Tokens[Network]; pools: Array<{ @@ -187,6 +187,39 @@ const NETWORK_CONFIGS: NetworkConfig[] = [ }, ], }, + { + name: 'base', + network: Network.BASE, + tokens: Tokens[Network.BASE], + pools: [ + { + address: '0xd70e1bab713d84c3a110ded11e41714542e604ba', + symbol0: 'WETH', + symbol1: 'SDEX', + events: { + ['Swap']: [4761865, 4757945, 4757945, 4757897], + ['Burn']: [4692541], + ['Mint']: [4757945, 4737306, 4701199], + ['FeesChanged']: [], // Fees didn't change on this pool + ['Sync']: [4761865, 4757945, 4757945, 4757897], + ['Transfer']: [4757966, 4737315, 4736210], + }, + }, + { + address: '0x5a60c797993ee91f012260d995e1e6c6ce3dda6d', + symbol0: 'WETH', + symbol1: 'USDbC', + events: { + ['Swap']: [4763447, 4762313, 4762290], + ['Burn']: [4716925, 4338322, 4282294], + ['Mint']: [4758649, 4649129, 4645429], + ['FeesChanged']: [], // Fees didn't change on this pool + ['Sync']: [4763447, 4762313, 4762290], + ['Transfer']: [4758649, 4716850, 4645429], + }, + }, + ], + }, ]; async function fetchPoolStateFromContractAtBlock( From 93a94ba68f2c3310a6ca7459c2dcb62b782348f0 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 3 Oct 2023 11:18:34 +0300 Subject: [PATCH 417/833] fix requested change --- src/dex/dexalot/dexalot.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index ac9747ed5..21d36f43b 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -862,10 +862,6 @@ export class Dexalot extends SimpleExchange implements IDex { tokenAddress: Address, limit: number, ): Promise { - if (await this.isRestricted()) { - return []; - } - const normalizedTokenAddress = normalizeTokenAddress(tokenAddress); const pairs = (await this.getCachedPairs()) || {}; this.tokensMap = (await this.getCachedTokens()) || {}; From 3b91947f4be9d245f2b47d5789a316cdcd2538fc Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 3 Oct 2023 10:29:19 +0200 Subject: [PATCH 418/833] test(e2e): add first sell-buy scenario --- src/dex/smardex/smardex-e2e.test.ts | 49 ++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index af3ae5613..7f7c7356c 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -237,14 +237,53 @@ describe('Smardex E2E', () => { ], ]) .flat(2), + + [Network.BASE]: [ + [ + { + name: 'WETH', + sellAmount: '1500000000000000000', // 1.5 WETH + buyAmount: '2500000000', // 2.5k USDbC + }, + { + name: 'USDbC', + sellAmount: '2500000000', // 2.5k USDbC + buyAmount: '1500000000000000000', // 1.5 WETH + }, + ], + // TenderlySimulation_simulate: Error: Request failed with status code 400 + // [ + // { + // name: 'WETH', + // sellAmount: '1500000000000000000', // 1.5 WETH + // buyAmount: '250000000000000000000000', // 250K SDEX + // }, + // { + // name: 'SDEX', + // sellAmount: '250000000000000000000000', // 250K SDEX + // buyAmount: '1500000000000000000', // 1.5 WETH + // }, + // ], + ] + .map((pair, i, arr) => [ + [pair], + [ + arr[i].map(token => ({ + ...token, + sellAmount: token.sellAmount + '0', + buyAmount: token.buyAmount + '0', + })), + ], + ]) + .flat(2), }; - // TODO add Base network when available const networkKeys = [ - Network.MAINNET, - Network.ARBITRUM, - Network.BSC, - Network.POLYGON, + // Network.MAINNET, + // Network.ARBITRUM, + // Network.BSC, + // Network.POLYGON, + Network.BASE, ]; networkKeys.forEach(network => { const tokens = Tokens[network]; From 174d7297a4845404f018e285a8d7f29a8545662f Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 3 Oct 2023 10:32:31 +0200 Subject: [PATCH 419/833] test(e2e): enable all networks --- src/dex/smardex/smardex-e2e.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index 7f7c7356c..bd8acc443 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -279,10 +279,10 @@ describe('Smardex E2E', () => { }; const networkKeys = [ - // Network.MAINNET, - // Network.ARBITRUM, - // Network.BSC, - // Network.POLYGON, + Network.MAINNET, + Network.ARBITRUM, + Network.BSC, + Network.POLYGON, Network.BASE, ]; networkKeys.forEach(network => { From fb135060e59bd79ce549be48b6ba397df3894595 Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 3 Oct 2023 10:58:50 +0200 Subject: [PATCH 420/833] fix: add SDEX address in the holders paraswap mapping --- src/dex/smardex/smardex-e2e.test.ts | 25 ++++++++++++------------- tests/constants-e2e.ts | 1 + 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index bd8acc443..c88282958 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -251,19 +251,18 @@ describe('Smardex E2E', () => { buyAmount: '1500000000000000000', // 1.5 WETH }, ], - // TenderlySimulation_simulate: Error: Request failed with status code 400 - // [ - // { - // name: 'WETH', - // sellAmount: '1500000000000000000', // 1.5 WETH - // buyAmount: '250000000000000000000000', // 250K SDEX - // }, - // { - // name: 'SDEX', - // sellAmount: '250000000000000000000000', // 250K SDEX - // buyAmount: '1500000000000000000', // 1.5 WETH - // }, - // ], + [ + { + name: 'WETH', + sellAmount: '1500000000000000000', // 1.5 WETH + buyAmount: '250000000000000000000000', // 250K SDEX + }, + { + name: 'SDEX', + sellAmount: '250000000000000000000000', // 250K SDEX + buyAmount: '1500000000000000000', // 1.5 WETH + }, + ], ] .map((pair, i, arr) => [ [pair], diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 5d6ad396b..f419dc232 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1171,6 +1171,7 @@ export const Holders: { DAI: '0x20f03e26968b179025f65c1f4afadfd3959c8d03', BAL: '0x854b004700885a61107b458f11ecc169a019b764', GOLD: '0x1374c25b3710758c326ee0c70ec48b595d5ccf8c', + SDEX: '0xFd4330b0312fdEEC6d4225075b82E00493FF2e3f', }, }; From a465463014f4ea88bbf5eb5978e41aa80bdb9fbc Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 3 Oct 2023 12:13:51 +0200 Subject: [PATCH 421/833] fix(constants-e2e): set a relevant address as SDEX holder --- tests/constants-e2e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index f419dc232..264d5880e 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1171,7 +1171,7 @@ export const Holders: { DAI: '0x20f03e26968b179025f65c1f4afadfd3959c8d03', BAL: '0x854b004700885a61107b458f11ecc169a019b764', GOLD: '0x1374c25b3710758c326ee0c70ec48b595d5ccf8c', - SDEX: '0xFd4330b0312fdEEC6d4225075b82E00493FF2e3f', + SDEX: '0xa5d378c05192e3f1f365d6298921879c4d51c5a3', }, }; From d424cb8477f2a06d298dcf96cb45f9498d8a60e0 Mon Sep 17 00:00:00 2001 From: Esteban Date: Tue, 3 Oct 2023 13:38:47 +0200 Subject: [PATCH 422/833] fix: ethereum holder address --- scripts/dex-integration.ts | 2 +- tests/constants-e2e.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/dex-integration.ts b/scripts/dex-integration.ts index e3487e690..ad04f3b19 100644 --- a/scripts/dex-integration.ts +++ b/scripts/dex-integration.ts @@ -116,7 +116,7 @@ function testIntegration(argv: IOptions) { process.env.NODE_ENV = 'test'; } - require('../node_modules/jest-cli/build/cli').run( + require('../node_modules/jest-cli/build').run( `src\/dex\/${dexNameParam}\/.+\.test\.ts`, ); } diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 264d5880e..34b3517eb 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1004,7 +1004,7 @@ export const Holders: { crvUSD: '0xA920De414eA4Ab66b97dA1bFE9e6EcA7d4219635', GHO: '0x844Dc85EdD8492A56228D293cfEbb823EF3E10EC', wibBTC: '0xFbdCA68601f835b27790D98bbb8eC7f05FDEaA9B', - SDEX: '0xE03c726340ccB2FbBAF6ca91533Ab64e64Fb9d4A', + SDEX: '0xB0470cF15B22a6A32c49a7C20E3821B944A76058', }, [Network.ROPSTEN]: { ETH: '0x43262A12d8610AA70C15DbaeAC321d51613c9071', From 732319cbf5d088955170c1cc1030f7d661dcade2 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 3 Oct 2023 17:08:23 +0300 Subject: [PATCH 423/833] fix: make state empty obj & add logging to cache clearing --- src/dex/algebra/algebra-factory.ts | 21 +++++++--------- src/dex/algebra/algebra.ts | 24 ++++++++++-------- src/dex/algebra/types.ts | 5 +--- .../pancakeswap-v3/pancakeswap-v3-factory.ts | 22 +++++++--------- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 25 ++++++++++--------- src/dex/uniswap-v3/types.ts | 6 +---- src/dex/uniswap-v3/uniswap-v3-factory.ts | 22 +++++++--------- src/dex/uniswap-v3/uniswap-v3.ts | 25 ++++++++++--------- 8 files changed, 68 insertions(+), 82 deletions(-) diff --git a/src/dex/algebra/algebra-factory.ts b/src/dex/algebra/algebra-factory.ts index 7a34bf23d..1650878ad 100644 --- a/src/dex/algebra/algebra-factory.ts +++ b/src/dex/algebra/algebra-factory.ts @@ -13,7 +13,7 @@ export type OnPoolCreatedCallback = ({ }: { token0: string; token1: string; -}) => FactoryState | null; +}) => Promise; /* * "Stateless" event subscriber in order to capture "PoolCreated" event on new pools created. @@ -21,7 +21,7 @@ export type OnPoolCreatedCallback = ({ */ export class AlgebraFactory extends StatefulEventSubscriber { handlers: { - [event: string]: (event: any) => DeepReadonly | null; + [event: string]: (event: any) => Promise; } = {}; logDecoder: (log: Log) => any; @@ -46,28 +46,25 @@ export class AlgebraFactory extends StatefulEventSubscriber { } generateState(): FactoryState { - return { - token0: '', - token1: '', - }; + return {}; } - protected processLog( + protected async processLog( _: DeepReadonly, log: Readonly, - ): DeepReadonly | null { + ): Promise { const event = this.logDecoder(log); if (event.name in this.handlers) { - return this.handlers[event.name](event); + await this.handlers[event.name](event); } - return null; + return {}; } - handleNewPool(event: LogDescription) { + async handleNewPool(event: LogDescription) { const token0 = event.args.token0; const token1 = event.args.token1; - return this.onPoolCreated({ token0, token1 }); + await this.onPoolCreated({ token0, token1 }); } } diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 27c99c1d7..8856d02e6 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -161,7 +161,7 @@ export class Algebra extends SimpleExchange implements IDex { * When a non existing pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls * Once the pool is created, it gets immediately flagged */ - onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = ({ + onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ token0, token1, }) => { @@ -174,16 +174,18 @@ export class Algebra extends SimpleExchange implements IDex { // delete entry locally to let local instance discover the pool delete this.eventPools[this.getPoolIdentifier(_token0, _token1)]; - this.logger.info( - `${logPrefix} delete pool from not existing set: ${poolKey}`, - ); - // delete pool record from set, not waiting for result - this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); - - return { - token0: _token0, - token1: _token1, - }; + try { + this.logger.info( + `${logPrefix} delete pool from not existing set: ${poolKey}`, + ); + // delete pool record from set + await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); + } catch (error) { + this.logger.error( + `${logPrefix} failed to delete pool from set: ${poolKey}`, + error, + ); + } }; async getPool( diff --git a/src/dex/algebra/types.ts b/src/dex/algebra/types.ts index e8cb3684e..ec4227967 100644 --- a/src/dex/algebra/types.ts +++ b/src/dex/algebra/types.ts @@ -51,10 +51,7 @@ export type PoolState_v1_9 = { areTicksCompressed: boolean; }; -export type FactoryState = { - token0: string; - token1: string; -}; +export type FactoryState = Record; export type AlgebraData = { path: { diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts b/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts index 4b0c161c6..8bfc7a46b 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts @@ -15,7 +15,7 @@ export type OnPoolCreatedCallback = ({ token0: string; token1: string; fee: bigint; -}) => FactoryState; +}) => Promise; /* * "Stateless" event subscriber in order to capture "PoolCreated" event on new pools created. @@ -23,7 +23,7 @@ export type OnPoolCreatedCallback = ({ */ export class PancakeswapV3Factory extends StatefulEventSubscriber { handlers: { - [event: string]: (event: any) => DeepReadonly | null; + [event: string]: (event: any) => Promise; } = {}; logDecoder: (log: Log) => any; @@ -48,30 +48,26 @@ export class PancakeswapV3Factory extends StatefulEventSubscriber } generateState(): FactoryState { - return { - token0: '', - token1: '', - fee: 0n, - }; + return {}; } - protected processLog( + protected async processLog( _: DeepReadonly, log: Readonly, - ): DeepReadonly | null { + ): Promise { const event = this.logDecoder(log); if (event.name in this.handlers) { - return this.handlers[event.name](event); + await this.handlers[event.name](event); } - return null; + return {}; } - handleNewPool(event: LogDescription) { + async handleNewPool(event: LogDescription) { const token0 = event.args.token0; const token1 = event.args.token1; const fee = event.args.fee; - return this.onPoolCreated({ token0, token1, fee }); + await this.onPoolCreated({ token0, token1, fee }); } } diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 66430b0e3..c892818dd 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -171,7 +171,7 @@ export class PancakeswapV3 * When a non existing pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls * Once the pool is created, it gets immediately flagged */ - onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = ({ + onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ token0, token1, fee, @@ -185,17 +185,18 @@ export class PancakeswapV3 // delete entry locally to let local instance discover the pool delete this.eventPools[this.getPoolIdentifier(_token0, _token1, fee)]; - this.logger.info( - `${logPrefix} delete pool from not existing set: ${poolKey}`, - ); - // delete pool record from set, not waiting for result - this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); - - return { - token0: _token0, - token1: _token1, - fee, - }; + try { + this.logger.info( + `${logPrefix} delete pool from not existing set: ${poolKey}`, + ); + // delete pool record from set + await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); + } catch (error) { + this.logger.error( + `${logPrefix} failed to delete pool from set :${poolKey}`, + error, + ); + } }; async getPool( diff --git a/src/dex/uniswap-v3/types.ts b/src/dex/uniswap-v3/types.ts index bdb396d19..7dd093292 100644 --- a/src/dex/uniswap-v3/types.ts +++ b/src/dex/uniswap-v3/types.ts @@ -53,11 +53,7 @@ export type PoolState = { balance1: bigint; }; -export type FactoryState = { - token0: string; - token1: string; - fee: bigint; -}; +export type FactoryState = Record; export type UniswapV3Data = { path: { diff --git a/src/dex/uniswap-v3/uniswap-v3-factory.ts b/src/dex/uniswap-v3/uniswap-v3-factory.ts index db8fc4e80..0f568e7ab 100644 --- a/src/dex/uniswap-v3/uniswap-v3-factory.ts +++ b/src/dex/uniswap-v3/uniswap-v3-factory.ts @@ -15,7 +15,7 @@ export type OnPoolCreatedCallback = ({ token0: string; token1: string; fee: bigint; -}) => FactoryState | null; +}) => Promise; /* * "Stateless" event subscriber in order to capture "PoolCreated" event on new pools created. @@ -23,7 +23,7 @@ export type OnPoolCreatedCallback = ({ */ export class UniswapV3Factory extends StatefulEventSubscriber { handlers: { - [event: string]: (event: any) => DeepReadonly | null; + [event: string]: (event: any) => Promise; } = {}; logDecoder: (log: Log) => any; @@ -48,30 +48,26 @@ export class UniswapV3Factory extends StatefulEventSubscriber { } generateState(): FactoryState { - return { - token0: '', - token1: '', - fee: 0n, - }; + return {}; } - protected processLog( + protected async processLog( _: DeepReadonly, log: Readonly, - ): DeepReadonly | null { + ): Promise { const event = this.logDecoder(log); if (event.name in this.handlers) { - return this.handlers[event.name](event); + await this.handlers[event.name](event); } - return null; + return {}; } - handleNewPool(event: LogDescription) { + async handleNewPool(event: LogDescription) { const token0 = event.args.token0; const token1 = event.args.token1; const fee = event.args.fee; - return this.onPoolCreated({ token0, token1, fee }); + await this.onPoolCreated({ token0, token1, fee }); } } diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 3c46c2193..1d1cb8029 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -201,7 +201,7 @@ export class UniswapV3 * When a non existing pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls * Once the pool is created, it gets immediately flagged */ - onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = ({ + onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ token0, token1, fee, @@ -215,17 +215,18 @@ export class UniswapV3 // delete entry locally to let local instance discover the pool delete this.eventPools[this.getPoolIdentifier(_token0, _token1, fee)]; - this.logger.info( - `${logPrefix} delete pool from not existing set: ${poolKey}`, - ); - // delete pool record from set, not waiting for result - this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); - - return { - token0: _token0, - token1: _token1, - fee, - }; + try { + this.logger.info( + `${logPrefix} delete pool from not existing set: ${poolKey}`, + ); + // delete pool record from set + await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); + } catch (error) { + this.logger.error( + `${logPrefix} failed to delete pool from set: ${poolKey}`, + error, + ); + } }; async getPool( From 05bc393bcee8e10a34d988c2312a5d7224fda09e Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 3 Oct 2023 17:30:45 +0300 Subject: [PATCH 424/833] fix requested changes --- src/dex/dexalot/config.ts | 2 +- src/dex/dexalot/dexalot.ts | 63 ++++++++++++++++++++++++++------------ tests/constants-e2e.ts | 2 +- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/dex/dexalot/config.ts b/src/dex/dexalot/config.ts index ec1830c99..2204e82a5 100644 --- a/src/dex/dexalot/config.ts +++ b/src/dex/dexalot/config.ts @@ -1,6 +1,6 @@ import { DexParams } from './types'; import { DexConfigMap, AdapterMappings } from '../../types'; -import { Network, SwapSide } from '../../constants'; +import { Network } from '../../constants'; export const DexalotConfig: DexConfigMap = { Dexalot: { diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 21d36f43b..b57cb6f04 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -61,7 +61,6 @@ import { BI_MAX_UINT256 } from '../../bigint-constants'; import { ethers } from 'ethers'; import BigNumber from 'bignumber.js'; import { Method } from '../../dex-helper/irequest-wrapper'; -import { normalizeTokenAddress } from '../swaap-v2/utils'; export class Dexalot extends SimpleExchange implements IDex { readonly isStatePollingDex = true; @@ -196,8 +195,14 @@ export class Dexalot extends SimpleExchange implements IDex { return null; } - getIdentifier(baseSymbol: string, quoteSymbol: string) { - // return `${this.dexKey}_${baseSymbol}_${quoteSymbol}`.toLowerCase(); + getIdentifier(srcAddress: Address, destAddress: Address) { + // const sortedAddresses = + // srcAddress < destAddress + // ? [srcAddress, destAddress] + // : [destAddress, srcAddress]; + // + // return `${this.dexKey}_${sortedAddresses[0].toLowerCase()}_${sortedAddresses[1].toLowerCase()}`; + // To disable Dexalot in multi/mega routes return this.dexKey; } @@ -215,7 +220,13 @@ export class Dexalot extends SimpleExchange implements IDex { if (!pairData) { return []; } - return [this.getIdentifier(pairData.base, pairData.quote)]; + + const tokensAddr = (await this.getCachedTokensAddr()) || {}; + + return [this.getIdentifier( + tokensAddr[pairData.base.toLowerCase()], + tokensAddr[pairData.quote.toLowerCase()], + )]; } async getCachedPairs(): Promise { @@ -377,7 +388,18 @@ export class Dexalot extends SimpleExchange implements IDex { return null; } - if (limitPools && limitPools.length !== 1) { + const pools = limitPools + ? limitPools.filter( + p => + p === + this.getIdentifier( + normalizedSrcToken.address, + normalizedDestToken.address, + ), + ) + : await this.getPoolIdentifiers(srcToken, destToken, side, blockNumber); + + if (pools.length === 0) { return null; } @@ -394,8 +416,15 @@ export class Dexalot extends SimpleExchange implements IDex { return null; } + const tokensAddr = (await this.getCachedTokensAddr()) || {}; const pairKey = `${pairData.base}/${pairData.quote}`.toLowerCase(); - if (!(pairKey in priceMap)) { + if ( + !(pairKey in priceMap) + || !pools.includes(this.getIdentifier( + tokensAddr[pairData.base.toLowerCase()], + tokensAddr[pairData.quote.toLowerCase()], + )) + ) { return null; } @@ -445,8 +474,8 @@ export class Dexalot extends SimpleExchange implements IDex { ]; } catch (e: unknown) { this.logger.error( - `Error_getPricesVolume ${srcToken.symbol || srcToken.address}, ${ - destToken.symbol || destToken.address + `Error_getPricesVolume ${srcToken.address || srcToken.symbol}, ${ + destToken.address || destToken.symbol }, ${side}:`, e, ); @@ -477,16 +506,7 @@ export class Dexalot extends SimpleExchange implements IDex { }: user=${options.txOrigin.toLowerCase()} is blacklisted`, ); } - if (await this.isRateLimited(options.txOrigin)) { - this.logger.warn( - `${this.dexKey}-${this.network}: rate limited TX Origin address '${options.txOrigin}' trying to build a transaction. Bailing...`, - ); - throw new Error( - `${this.dexKey}-${ - this.network - }: user=${options.txOrigin.toLowerCase()} is rate limited`, - ); - } + if (BigInt(optimalSwapExchange.srcAmount) === 0n) { throw new Error('getFirmRate failed with srcAmount === 0'); } @@ -786,6 +806,11 @@ export class Dexalot extends SimpleExchange implements IDex { return blacklist.includes(txOrigin.toLowerCase()); } + // To not show pricing for rate limited users + if(await this.isRateLimited(txOrigin)) { + return true; + } + return false; } @@ -862,7 +887,7 @@ export class Dexalot extends SimpleExchange implements IDex { tokenAddress: Address, limit: number, ): Promise { - const normalizedTokenAddress = normalizeTokenAddress(tokenAddress); + const normalizedTokenAddress = this.normalizeAddress(tokenAddress); const pairs = (await this.getCachedPairs()) || {}; this.tokensMap = (await this.getCachedTokens()) || {}; const tokensAddr = (await this.getCachedTokensAddr()) || {}; diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index f596301db..a3d7b51a7 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1081,7 +1081,7 @@ export const Holders: { TSD: '0x691A89db352B72dDb249bFe16503494eC0D920A4', THO: '0xc40d16c47394a506d451475c8a7c46c1175c1da1', aAvaUSDT: '0x50B1Ba98Cf117c9682048D56628B294ebbAA4ec2', - USDT: '0x4aeFa39caEAdD662aE31ab0CE7c8C2c9c0a013E8', + USDT: '0x4a58555884297dcd9d2198c9fec52b4cabc90fc6', aAvaWAVAX: '0x1B18Df70863636AEe4BfBAb6F7C70ceBCA9bA404', oldFRAX: '0x4e3376018add04ebe4c46bf6f924ddec8c67aa7b', newFRAX: '0x4e3376018add04ebe4c46bf6f924ddec8c67aa7b', From 2a2e10b0753a51c50c90b621beee843b3278df7c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 3 Oct 2023 17:32:10 +0300 Subject: [PATCH 425/833] 2.36.3-dexalot.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 297be3746..f32362d3b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.3-dexalot", + "version": "2.36.3-dexalot.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 9a72bf24ca5e92123d0f7ffb8dad5a0143bda2a4 Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Wed, 4 Oct 2023 12:33:55 +0300 Subject: [PATCH 426/833] feat(BACK-1314): Add support for sequential transaction preprocessing --- src/dex/hashflow/hashflow.ts | 3 ++- src/dex/idex.ts | 1 + src/dex/index.ts | 6 ++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/dex/hashflow/hashflow.ts b/src/dex/hashflow/hashflow.ts index dc7dbd2ff..e64bf8675 100644 --- a/src/dex/hashflow/hashflow.ts +++ b/src/dex/hashflow/hashflow.ts @@ -62,6 +62,7 @@ export class Hashflow extends SimpleExchange implements IDex { readonly isStatePollingDex = true; readonly hasConstantPriceLargeAmounts = false; readonly needWrapNative = false; + readonly needsSequentialPreprocessing = true; readonly isFeeOnTransferSupported = false; private api: HashflowApi; private rateFetcher: RateFetcher; @@ -737,7 +738,7 @@ export class Hashflow extends SimpleExchange implements IDex { ); await this.setBlacklist(options.txOrigin); } else { - if(e instanceof TooStrictSlippageCheckError) { + if (e instanceof TooStrictSlippageCheckError) { this.logger.warn( `${this.dexKey}-${this.network}: Market Maker ${mm} failed to build transaction on side ${side} with too strict slippage. Skipping restriction`, ); diff --git a/src/dex/idex.ts b/src/dex/idex.ts index a5e35cde4..3dd20f53d 100644 --- a/src/dex/idex.ts +++ b/src/dex/idex.ts @@ -20,6 +20,7 @@ import { IDexHelper } from '../dex-helper/idex-helper'; export interface IDexTxBuilder { needWrapNative: boolean; + needsSequentialPreprocessing?: boolean; // Returns the ETH fee required to swap // It is optional for a DEX to implement this diff --git a/src/dex/index.ts b/src/dex/index.ts index 4595ad24f..389106deb 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -315,4 +315,10 @@ export class DexAdapterService { ? this.sellAdapters[specialDexKey] : this.buyAdapters[specialDexKey]; } + + doesPreProcessingRequireSequentiality(dexKey: string): boolean { + const dex = this.getDexByKey(dexKey); + + return !!dex.needsSequentialPreprocessing; + } } From 389bc3144c9cbac2afe3c57960ddaeb66e84c3d3 Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Wed, 4 Oct 2023 12:34:52 +0300 Subject: [PATCH 427/833] 2.36.3-sequential-preprocessing.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1c5e487f3..5978dccac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2", + "version": "2.36.3-sequential-preprocessing.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 2443c9de76d3308fd4a68106794e45bb155b6b1d Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 4 Oct 2023 13:05:18 +0300 Subject: [PATCH 428/833] 2.36.2-cache-invalidation --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1c5e487f3..c09f1341e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2", + "version": "2.36.2-cache-invalidation", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 36c7b23205d8169f78ab074944513062f103a440 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 4 Oct 2023 16:23:47 +0300 Subject: [PATCH 429/833] return getIdentifier implementation --- src/dex/dexalot/dexalot.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index b57cb6f04..5e0e49b7c 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -196,15 +196,12 @@ export class Dexalot extends SimpleExchange implements IDex { } getIdentifier(srcAddress: Address, destAddress: Address) { - // const sortedAddresses = - // srcAddress < destAddress - // ? [srcAddress, destAddress] - // : [destAddress, srcAddress]; - // - // return `${this.dexKey}_${sortedAddresses[0].toLowerCase()}_${sortedAddresses[1].toLowerCase()}`; - - // To disable Dexalot in multi/mega routes - return this.dexKey; + const sortedAddresses = + srcAddress < destAddress + ? [srcAddress, destAddress] + : [destAddress, srcAddress]; + + return `${this.dexKey}_${sortedAddresses[0].toLowerCase()}_${sortedAddresses[1].toLowerCase()}`; } async getPoolIdentifiers( From 52cbc02743fcd5b0fec3fe41008fbc92c0e2a533 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 4 Oct 2023 16:25:24 +0300 Subject: [PATCH 430/833] 2.36.3-dexalot.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f32362d3b..6b8a60048 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.3-dexalot.2", + "version": "2.36.3-dexalot.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 44e4b63565e5f439260251296059e8d08eaaa24b Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Wed, 4 Oct 2023 16:15:19 +0100 Subject: [PATCH 431/833] chore: modify calculateOrderPrice logic for batch quotes --- src/dex/dexalot/dexalot.ts | 98 +++++++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 27 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 505ba89af..a20dbcc20 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -313,40 +313,84 @@ export class Dexalot extends SimpleExchange implements IDex { continue; } - let totalVolume = 0n; - let combinedPrice = 0n; - - for (let j = 0; j < orderbook.length; j++) { - const order = orderbook[j]; - const priceBN = ethers.utils.parseUnits(order[0], quoteToken.decimals); - const price = BigInt(priceBN.toString()); - const qtyBN = ethers.utils.parseUnits(order[1], baseToken.decimals); - const qty = BigInt(qtyBN.toString()); - let vol = qty; - if (side === ClobSide.BID) { - vol = (qty * price) / BigInt(10 ** baseToken.decimals); + let left = 0, + right = orderbook.length; + let qty = BigInt(0); + + while (left < right) { + let mid = Math.floor((left + right) / 2); + qty = BigInt( + ethers.utils + .parseUnits(orderbook[mid][1], quoteToken.decimals) + .toString(), + ); + if (side === ClobSide.ASK) { + const price = BigInt( + ethers.utils + .parseUnits(orderbook[mid][0], baseToken.decimals) + .toString(), + ); + qty = + (qty * BigInt(10 ** (baseToken.decimals * 2))) / + (price * BigInt(10 ** quoteToken.decimals)); } - if (amt < vol) { - totalVolume += amt; - combinedPrice += amt * price; - amt = 0n; + if (qty <= amt) { + left = mid + 1; } else { - amt -= vol; - totalVolume += vol; - combinedPrice += vol * price; - } - if (amt === 0n) { - break; + right = mid; } } - if (amt > 0n) { - return result; + + let price, + amount = BigInt(0); + if (left === orderbook.length) { + price = BigInt( + ethers.utils + .parseUnits(orderbook[left - 1][0], baseToken.decimals) + .toString(), + ); + amount = qty; + } else if (amounts[i] === qty) { + price = BigInt( + ethers.utils + .parseUnits(orderbook[left][0], baseToken.decimals) + .toString(), + ); + amount = amounts[i]; + } else { + const lPrice = BigInt( + ethers.utils + .parseUnits(orderbook[left][0], baseToken.decimals) + .toString(), + ); + const rPrice = BigInt( + ethers.utils + .parseUnits(orderbook[left + 1][0], baseToken.decimals) + .toString(), + ); + const lQty = qty; + let rQty = BigInt( + ethers.utils + .parseUnits(orderbook[left + 1][1], quoteToken.decimals) + .toString(), + ); + if (side === ClobSide.ASK) { + rQty = (rQty * rPrice) / BigInt(10 ** quoteToken.decimals); + } + price = lPrice + ((rPrice - lPrice) * (amt - lQty)) / (rQty - lQty); + amount = amounts[i]; } - const avgPrice = combinedPrice / totalVolume; + if (side === ClobSide.BID) { - result.push((amounts[i] * BigInt(10 ** baseToken.decimals)) / avgPrice); + result.push( + (amount * BigInt(10 ** (baseToken.decimals * 2))) / + (price * BigInt(10 ** quoteToken.decimals)), + ); } else { - result.push((avgPrice * amounts[i]) / BigInt(10 ** baseToken.decimals)); + result.push( + (price * amount * BigInt(10 ** quoteToken.decimals)) / + BigInt(10 ** (baseToken.decimals * 2)), + ); } } return result; From f6e5e82e261d70de9806463545aaac2b739682f8 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 4 Oct 2023 18:26:11 +0300 Subject: [PATCH 432/833] 2.36.3-dexalot.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6b8a60048..513df14b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.3-dexalot.3", + "version": "2.36.3-dexalot.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 45b9680b3afbe2738f33cbe80364b679b0ae7693 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 5 Oct 2023 11:59:05 +0300 Subject: [PATCH 433/833] add isFirstSwap for getPricesVolume --- src/dex/dexalot/dexalot.ts | 10 +++++++++- src/dex/idex.ts | 2 ++ src/implementations/local-paraswap-sdk.ts | 1 + src/pricing-helper.ts | 2 ++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 9f5083822..89bda5bf6 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -9,7 +9,7 @@ import { Logger, ExchangeTxInfo, OptimalSwapExchange, - PreprocessTransactionOptions, + PreprocessTransactionOptions, TransferFeeParams, } from '../../types'; import { SwapSide, @@ -415,8 +415,16 @@ export class Dexalot extends SimpleExchange implements IDex { side: SwapSide, blockNumber: number, limitPools?: string[], + transferFees?: TransferFeeParams, + isFirstSwap?: boolean, ): Promise> { try { + + // Disable multi/mega routes + if(!isFirstSwap) { + return null; + } + if (await this.isRestricted()) { return null; } diff --git a/src/dex/idex.ts b/src/dex/idex.ts index a5e35cde4..15307fa41 100644 --- a/src/dex/idex.ts +++ b/src/dex/idex.ts @@ -130,9 +130,11 @@ export interface IDexPricing { blockNumber: number, // list of pool identifiers to use for pricing, if undefined use all pools limitPools?: string[], + // I don't like putting this as new params, but in order to not change interface // across all integrations, done it like this transferFees?: TransferFeeParams, + isFirstSwap?: boolean, ): Promise | null>; // Returns estimated gas cost for calldata for DEX when used in multiSwap. diff --git a/src/implementations/local-paraswap-sdk.ts b/src/implementations/local-paraswap-sdk.ts index d1b573beb..3ac07c809 100644 --- a/src/implementations/local-paraswap-sdk.ts +++ b/src/implementations/local-paraswap-sdk.ts @@ -117,6 +117,7 @@ export class LocalParaswapSDK implements IParaSwapSDK { blockNumber, [this.dexKey], poolIdentifiers, + true, transferFees, ); diff --git a/src/pricing-helper.ts b/src/pricing-helper.ts index 3c3343165..754343f20 100644 --- a/src/pricing-helper.ts +++ b/src/pricing-helper.ts @@ -185,6 +185,7 @@ export class PricingHelper { blockNumber: number, dexKeys: string[], limitPoolsMap: { [key: string]: string[] | null } | null, + isFirstSwap: boolean, transferFees: TransferFeeParams = { srcFee: 0, destFee: 0, @@ -226,6 +227,7 @@ export class PricingHelper { blockNumber, limitPools ? limitPools : undefined, transferFees, + isFirstSwap, ) .then(poolPrices => { try { From c700b3bf75baaa26ab4e80feeb3d7c6b0b142bcd Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 5 Oct 2023 12:01:00 +0300 Subject: [PATCH 434/833] 2.36.3-dexalot.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 513df14b2..ac0377e29 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.3-dexalot.4", + "version": "2.36.3-dexalot.5", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 40f0fa789caa5029cdc8aca17d2b48618f738757 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 5 Oct 2023 13:19:19 +0300 Subject: [PATCH 435/833] add e2e and integration tests --- src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 25 +++ .../uniswap-v3/uniswap-v3-integration.test.ts | 144 ++++++++++++++++++ src/dex/uniswap-v3/uniswap-v3.ts | 1 + 3 files changed, 170 insertions(+) diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index 900de38a0..02c0062bf 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -1110,4 +1110,29 @@ describe('UniswapV3 E2E', () => { ); }); }); + + describe('Retro', () => { + const dexKey = 'Retro'; + + describe('POLYGON', () => { + const network = Network.POLYGON; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '1000000000'; + const tokenBAmount: string = '100000000'; + const nativeTokenAmount = '1100000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + }); }); diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index 32a463c97..640ff7546 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -1100,3 +1100,147 @@ describe('SushiSwapV3', () => { }); }); }); + + +describe('Retro', () => { + const dexKey = 'Retro'; + + describe('Polygon', () => { + let blockNumber: number; + let retro: UniswapV3; + + const network = Network.POLYGON; + const dexHelper = new DummyDexHelper(network); + const TokenASymbol = 'USDC'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDT'; + const TokenB = Tokens[network][TokenBSymbol]; + + beforeEach(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + retro = new UniswapV3(network, dexKey, dexHelper); + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + const amounts = [0n, BI_POWS[6], 2000000n]; + + const pools = await retro.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await retro.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = retro.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + retro, + 'quoteExactInputSingle', + blockNumber, + '0xfe08be075758935cb6cb9318d1fbb60920416d4e', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + const amounts = [0n, BI_POWS[6], 2000000n]; + + const pools = await retro.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await retro.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = retro.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + retro, + 'quoteExactOutputSingle', + blockNumber, + '0xfe08be075758935cb6cb9318d1fbb60920416d4e', + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getTopPoolsForToken', async function () { + const poolLiquidity = await retro.getTopPoolsForToken( + TokenB.address, + 10, + ); + console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); + }); + }); + +}); diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index b99a30ef4..79fc4cde1 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -97,6 +97,7 @@ export class UniswapV3 'QuickSwapV3.1', 'RamsesV2', 'ChronosV3', + 'Retro', ]), ); From 48a3395bc7ab8276332c8ee158156d5c13784f25 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 5 Oct 2023 13:19:45 +0300 Subject: [PATCH 436/833] 2.36.3-retro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1c5e487f3..35844eb06 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.2", + "version": "2.36.3-retro", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e4ff83548296cd9652a0174b40dbdbe8588e12e4 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 5 Oct 2023 14:16:18 +0300 Subject: [PATCH 437/833] 2.37.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 35844eb06..c0013a5be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.3-retro", + "version": "2.37.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From adb0865794659d379434b447db15430469bd0167 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 5 Oct 2023 16:02:23 +0300 Subject: [PATCH 438/833] fix: remove unnecessary `.bind` calls --- src/dex/algebra/algebra.ts | 2 +- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 2 +- src/dex/uniswap-v3/uniswap-v3.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 8856d02e6..726cb669d 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -122,7 +122,7 @@ export class Algebra extends SimpleExchange implements IDex { dexKey, this.config.factory, this.logger, - this.onPoolCreatedDeleteFromNonExistingSet.bind(this), + this.onPoolCreatedDeleteFromNonExistingSet, ); } diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index c892818dd..1e4013edd 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -128,7 +128,7 @@ export class PancakeswapV3 dexKey, this.config.factory, this.logger, - this.onPoolCreatedDeleteFromNonExistingSet.bind(this), + this.onPoolCreatedDeleteFromNonExistingSet, ); } diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 1d1cb8029..768f43530 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -146,7 +146,7 @@ export class UniswapV3 dexKey, this.config.factory, this.logger, - this.onPoolCreatedDeleteFromNonExistingSet.bind(this), + this.onPoolCreatedDeleteFromNonExistingSet, ); } From 67cfcd73f98f8dae939945abf518aa335a3b6663 Mon Sep 17 00:00:00 2001 From: paraschiv-r-toptal Date: Thu, 5 Oct 2023 16:59:24 +0300 Subject: [PATCH 439/833] 2.37.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c0013a5be..3eec4438b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.0", + "version": "2.37.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 41f1f45f766753c6c5b8c031706f5635d4280360 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 5 Oct 2023 17:23:02 +0300 Subject: [PATCH 440/833] BACK-1312: use currentFee for RamsesV2 pools --- src/abi/ramses-v2/RamsesV2Pool.abi.json | 1580 +++++++++++++++++ src/dex/uniswap-v3/config.ts | 2 + .../forks/ramses-v2/ramses-v2-pool.ts | 102 ++ src/dex/uniswap-v3/types.ts | 2 + src/dex/uniswap-v3/uniswap-v3-pool.ts | 2 +- src/dex/uniswap-v3/uniswap-v3.ts | 41 +- 6 files changed, 1710 insertions(+), 19 deletions(-) create mode 100644 src/abi/ramses-v2/RamsesV2Pool.abi.json create mode 100644 src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts diff --git a/src/abi/ramses-v2/RamsesV2Pool.abi.json b/src/abi/ramses-v2/RamsesV2Pool.abi.json new file mode 100644 index 000000000..1dc342a1c --- /dev/null +++ b/src/abi/ramses-v2/RamsesV2Pool.abi.json @@ -0,0 +1,1580 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": "sender", + "type": "address" + }, + { + "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": "CollectProtocol", + "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": "uint256", + "name": "period", + "type": "uint256" + } + ], + "name": "boostInfos", + "outputs": [ + { + "internalType": "uint128", + "name": "totalBoostAmount", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "totalVeRamAmount", + "type": "int128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + } + ], + "name": "boostInfos", + "outputs": [ + { + "internalType": "uint128", + "name": "boostAmount", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "veRamAmount", + "type": "int128" + }, + { + "internalType": "int256", + "name": "secondsDebtX96", + "type": "int256" + }, + { + "internalType": "int256", + "name": "boostedSecondsDebtX96", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "boostedLiquidity", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "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": "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": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "veRamTokenId", + "type": "uint256" + } + ], + "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" + } + ], + "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": "uint256", + "name": "index", + "type": "uint256" + }, + { + "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": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint128", + "name": "amount0Requested", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1Requested", + "type": "uint128" + } + ], + "name": "collectProtocol", + "outputs": [ + { + "internalType": "uint128", + "name": "amount0", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "amount1", + "type": "uint128" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentFee", + "outputs": [ + { + "internalType": "uint24", + "name": "", + "type": "uint24" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "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": [ + { + "internalType": "uint16", + "name": "observationCardinalityNext", + "type": "uint16" + } + ], + "name": "increaseObservationCardinalityNext", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_factory", + "type": "address" + }, + { + "internalType": "address", + "name": "_nfpManager", + "type": "address" + }, + { + "internalType": "address", + "name": "_veRam", + "type": "address" + }, + { + "internalType": "address", + "name": "_voter", + "type": "address" + }, + { + "internalType": "address", + "name": "_token0", + "type": "address" + }, + { + "internalType": "address", + "name": "_token1", + "type": "address" + }, + { + "internalType": "uint24", + "name": "_fee", + "type": "uint24" + }, + { + "internalType": "int24", + "name": "_tickSpacing", + "type": "int24" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint160", + "name": "sqrtPriceX96", + "type": "uint160" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "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": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "veRamTokenId", + "type": "uint256" + }, + { + "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": "nfpManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "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" + }, + { + "internalType": "uint160", + "name": "secondsPerBoostedLiquidityPeriodX128", + "type": "uint160" + } + ], + "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[]" + }, + { + "internalType": "uint160[]", + "name": "secondsPerBoostedLiquidityPeriodX128s", + "type": "uint160[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "period", + "type": "uint32" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + } + ], + "name": "periodCumulativesInside", + "outputs": [ + { + "internalType": "uint160", + "name": "secondsPerLiquidityInsideX128", + "type": "uint160" + }, + { + "internalType": "uint160", + "name": "secondsPerBoostedLiquidityInsideX128", + "type": "uint160" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + } + ], + "name": "periods", + "outputs": [ + { + "internalType": "uint32", + "name": "previousPeriod", + "type": "uint32" + }, + { + "internalType": "int24", + "name": "startTick", + "type": "int24" + }, + { + "internalType": "int24", + "name": "lastTick", + "type": "int24" + }, + { + "internalType": "uint160", + "name": "endSecondsPerLiquidityPeriodX128", + "type": "uint160" + }, + { + "internalType": "uint160", + "name": "endSecondsPerBoostedLiquidityPeriodX128", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "boostedInRange", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + } + ], + "name": "positionPeriodDebt", + "outputs": [ + { + "internalType": "int256", + "name": "secondsDebtX96", + "type": "int256" + }, + { + "internalType": "int256", + "name": "boostedSecondsDebtX96", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "int24", + "name": "tickLower", + "type": "int24" + }, + { + "internalType": "int24", + "name": "tickUpper", + "type": "int24" + } + ], + "name": "positionPeriodSecondsInRange", + "outputs": [ + { + "internalType": "uint256", + "name": "periodSecondsInsideX96", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "periodBoostedSecondsInsideX96", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "key", + "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" + }, + { + "internalType": "uint256", + "name": "attachedVeRamId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolFees", + "outputs": [ + { + "internalType": "uint128", + "name": "token0", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "token1", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "slots", + "type": "bytes32[]" + } + ], + "name": "readStorage", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "returnData", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint24", + "name": "_fee", + "type": "uint24" + } + ], + "name": "setFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "setFeeProtocol", + "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": "uint8", + "name": "feeProtocol", + "type": "uint8" + }, + { + "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": "uint160", + "name": "secondsPerBoostedLiquidityInsideX128", + "type": "uint160" + }, + { + "internalType": "uint32", + "name": "secondsInside", + "type": "uint32" + } + ], + "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": "int16", + "name": "tick", + "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": "tick", + "type": "int24" + } + ], + "name": "ticks", + "outputs": [ + { + "internalType": "uint128", + "name": "liquidityGross", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "liquidityNet", + "type": "int128" + }, + { + "internalType": "uint128", + "name": "boostedLiquidityGross", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "boostedLiquidityNet", + "type": "int128" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside0X128", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feeGrowthOutside1X128", + "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": "veRam", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index 816d1d4e0..ace2fccbf 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -5,6 +5,7 @@ import { Address } from '../../types'; import RamsesV2StateMulticallABI from '../../abi/RamsesV2StateMulticall.abi.json'; import { AbiItem } from 'web3-utils'; import { decodeStateMultiCallResultWithRelativeBitmaps } from './forks/ramses-v2/utils'; +import { RamsesV2EventPool } from './forks/ramses-v2/ramses-v2-pool'; const SUPPORTED_FEES = [10000n, 3000n, 500n, 100n]; @@ -251,6 +252,7 @@ export const UniswapV3Config: DexConfigMap = { uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', chunksCount: 10, initRetryFrequency: 10, + eventPoolImplementation: RamsesV2EventPool, decodeStateMultiCallResultWithRelativeBitmaps, initHash: '0x1565b129f2d1790f12d45301b9b084335626f0c92410bc43130763b69971135d', diff --git a/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts new file mode 100644 index 000000000..6c9425c08 --- /dev/null +++ b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts @@ -0,0 +1,102 @@ +import { UniswapV3EventPool } from '../../uniswap-v3-pool'; +import { DecodedStateMultiCallResultWithRelativeBitmaps, PoolState } from '../../types'; +import { assert } from 'ts-essentials'; +import { _reduceTickBitmap, _reduceTicks } from '../../contract-math/utils'; +import { bigIntify } from '../../../../utils'; +import { TickBitMap } from '../../contract-math/TickBitMap'; +import { uint24ToBigInt } from '../../../../lib/decoders'; +import { Interface } from 'ethers/lib/utils'; +import RamsesV2PoolABI from '../../../../abi/ramses-v2/RamsesV2Pool.abi.json'; + +export class RamsesV2EventPool extends UniswapV3EventPool { + + public readonly poolIface = new Interface(RamsesV2PoolABI); + + async generateState(blockNumber: number): Promise> { + const callData = this._getStateRequestCallData(); + + const calldataWithFee = [ + ...callData, + { + target: this.poolAddress, + callData: this.poolIface.encodeFunctionData('currentFee'), + decodeFunction: uint24ToBigInt, + }, + ]; + + const [resBalance0, resBalance1, resState, resCurrentFee] = + await this.dexHelper.multiWrapper.tryAggregate< + bigint | DecodedStateMultiCallResultWithRelativeBitmaps + >( + false, + calldataWithFee, + blockNumber, + this.dexHelper.multiWrapper.defaultBatchSize, + false, + ); + + assert(resState.success, 'Pool does not exist'); + + const [balance0, balance1, _state, fee] = [ + resBalance0.returnData, + resBalance1.returnData, + resState.returnData, + resCurrentFee.returnData, + ] as [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmaps, bigint]; + + const tickBitmap = {}; + const ticks = {}; + + _reduceTickBitmap(tickBitmap, _state.tickBitmap); + _reduceTicks(ticks, _state.ticks); + + const observations = { + [_state.slot0.observationIndex]: { + blockTimestamp: bigIntify(_state.observation.blockTimestamp), + tickCumulative: bigIntify(_state.observation.tickCumulative), + secondsPerLiquidityCumulativeX128: bigIntify( + _state.observation.secondsPerLiquidityCumulativeX128, + ), + initialized: _state.observation.initialized, + }, + }; + + const currentTick = bigIntify(_state.slot0.tick); + const tickSpacing = bigIntify(_state.tickSpacing); + + const startTickBitmap = TickBitMap.position(currentTick / tickSpacing)[0]; + const requestedRange = this.getBitmapRangeToRequest(); + + return { + pool: _state.pool, + blockTimestamp: bigIntify(_state.blockTimestamp), + slot0: { + sqrtPriceX96: bigIntify(_state.slot0.sqrtPriceX96), + tick: currentTick, + observationIndex: +_state.slot0.observationIndex, + observationCardinality: +_state.slot0.observationCardinality, + observationCardinalityNext: +_state.slot0.observationCardinalityNext, + feeProtocol: bigIntify(_state.slot0.feeProtocol), + }, + liquidity: bigIntify(_state.liquidity), + fee, + tickSpacing, + maxLiquidityPerTick: bigIntify(_state.maxLiquidityPerTick), + tickBitmap, + ticks, + observations, + isValid: true, + startTickBitmap, + lowestKnownTick: + (BigInt.asIntN(24, startTickBitmap - requestedRange) << 8n) * + tickSpacing, + highestKnownTick: + ((BigInt.asIntN(24, startTickBitmap + requestedRange) << 8n) + + BigInt.asIntN(24, 255n)) * + tickSpacing, + balance0, + balance1, + }; + } + +} diff --git a/src/dex/uniswap-v3/types.ts b/src/dex/uniswap-v3/types.ts index b7c314500..f34e98867 100644 --- a/src/dex/uniswap-v3/types.ts +++ b/src/dex/uniswap-v3/types.ts @@ -3,6 +3,7 @@ import { NumberAsString } from '../../types'; import { Address } from '../../types'; import { AbiItem } from 'web3-utils'; import { MultiResult } from '../../lib/multi-wrapper'; +import { UniswapV3EventPool } from './uniswap-v3-pool'; export type OracleObservation = { blockTimestamp: bigint; @@ -79,6 +80,7 @@ export type DexParams = { subgraphURL: string; initHash: string; stateMultiCallAbi?: AbiItem[]; + eventPoolImplementation?: typeof UniswapV3EventPool; decodeStateMultiCallResultWithRelativeBitmaps?: DecodeStateMultiCallFunc; }; diff --git a/src/dex/uniswap-v3/uniswap-v3-pool.ts b/src/dex/uniswap-v3/uniswap-v3-pool.ts index 54163da48..8c6616124 100644 --- a/src/dex/uniswap-v3/uniswap-v3-pool.ts +++ b/src/dex/uniswap-v3/uniswap-v3-pool.ts @@ -199,7 +199,7 @@ export class UniswapV3EventPool extends StatefulEventSubscriber { return null; // ignore unrecognized event } - private _getStateRequestCallData() { + protected _getStateRequestCallData() { if (!this._stateRequestCallData) { const callData: MultiCallParams< bigint | DecodedStateMultiCallResultWithRelativeBitmaps diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 79fc4cde1..fe2828908 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -242,25 +242,29 @@ export class UniswapV3 } this.logger.trace(`starting to listen to new pool: ${key}`); + const poolImplementation = + this.config.eventPoolImplementation !== undefined + ? this.config.eventPoolImplementation + : UniswapV3EventPool; pool = pool || - new UniswapV3EventPool( - this.dexHelper, - this.dexKey, - this.stateMultiContract, - this.config.decodeStateMultiCallResultWithRelativeBitmaps, - this.erc20Interface, - this.config.factory, - fee, - token0, - token1, - this.logger, - this.cacheStateKey, - this.config.initHash, + new poolImplementation( + this.dexHelper, + this.dexKey, + this.stateMultiContract, + this.config.decodeStateMultiCallResultWithRelativeBitmaps, + this.erc20Interface, + this.config.factory, + fee, + token0, + token1, + this.logger, + this.cacheStateKey, + this.config.initHash, ); try { - await pool.initialize(blockNumber, { + await pool!.initialize(blockNumber, { initCallback: (state: DeepReadonly) => { //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber pool!.addressesSubscribed[0] = state.pool; @@ -289,10 +293,10 @@ export class UniswapV3 // on unknown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool!.initRetryAttemptCount}`, e, ); - pool.initFailed = true; + pool!.initFailed = true; } } @@ -309,8 +313,8 @@ export class UniswapV3 } this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - pool; - return pool; + pool!; + return pool!; } async addMasterPool(poolKey: string, blockNumber: number): Promise { @@ -1066,6 +1070,7 @@ export class UniswapV3 initHash: this.config.initHash, subgraphURL: this.config.subgraphURL, stateMultiCallAbi: this.config.stateMultiCallAbi, + eventPoolImplementation: this.config.eventPoolImplementation, decodeStateMultiCallResultWithRelativeBitmaps: this.config.decodeStateMultiCallResultWithRelativeBitmaps, }; From 87dbd07a5c0e96f84e8d082ac856e8c6b3d00036 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 5 Oct 2023 17:24:53 +0300 Subject: [PATCH 441/833] 2.37.2-current-fee-ramses-v2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3eec4438b..3d7ac3844 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.1", + "version": "2.37.2-current-fee-ramses-v2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 2921833070e4e1a32cabcf93adeea8d7dad01c60 Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Thu, 5 Oct 2023 16:36:08 +0100 Subject: [PATCH 442/833] chore: update abi with partial swap function --- src/abi/dexalot/DexalotMainnetRFQ.json | 65 ++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/abi/dexalot/DexalotMainnetRFQ.json b/src/abi/dexalot/DexalotMainnetRFQ.json index 7815c2516..b6139cae1 100644 --- a/src/abi/dexalot/DexalotMainnetRFQ.json +++ b/src/abi/dexalot/DexalotMainnetRFQ.json @@ -619,6 +619,71 @@ ], "stateMutability": "view" }, + { + "name": "partialSwap", + "type": "function", + "inputs": [ + { + "name": "_order", + "type": "tuple", + "components": [ + { + "name": "nonceAndMeta", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "expiry", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "makerAsset", + "type": "address", + "internalType": "address" + }, + { + "name": "takerAsset", + "type": "address", + "internalType": "address" + }, + { + "name": "maker", + "type": "address", + "internalType": "address" + }, + { + "name": "taker", + "type": "address", + "internalType": "address" + }, + { + "name": "makerAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "takerAmount", + "type": "uint256", + "internalType": "uint256" + } + ], + "internalType": "struct MainnetRFQ.Order" + }, + { + "name": "_signature", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "_takerAmount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "payable" + }, { "name": "pause", "type": "function", From 7aaf644b4fb7b373aebb7deeb1ab5b792fe1e3f3 Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 5 Oct 2023 16:48:14 +0100 Subject: [PATCH 443/833] fix: not allow to throw --- src/dex/index.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/dex/index.ts b/src/dex/index.ts index 389106deb..157b8664c 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -317,8 +317,11 @@ export class DexAdapterService { } doesPreProcessingRequireSequentiality(dexKey: string): boolean { - const dex = this.getDexByKey(dexKey); - - return !!dex.needsSequentialPreprocessing; + try { + const dex = this.getDexByKey(dexKey); + return !!dex.needsSequentialPreprocessing; + } catch (e) { + return false; + } } } From d3cc6ccc0b1ed18dbc9b26aeab08f7543fecfdd1 Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 5 Oct 2023 16:50:19 +0100 Subject: [PATCH 444/833] 2.37.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3eec4438b..30985642a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.1", + "version": "2.37.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From aa874bba38bb55aa4685c82c4e714c84f5389e5c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 6 Oct 2023 12:26:25 +0300 Subject: [PATCH 445/833] add a fix --- src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts | 7 +++++-- src/dex/uniswap-v3/uniswap-v3-pool.ts | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts index 6c9425c08..015cc489f 100644 --- a/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts +++ b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts @@ -12,6 +12,7 @@ export class RamsesV2EventPool extends UniswapV3EventPool { public readonly poolIface = new Interface(RamsesV2PoolABI); + async generateState(blockNumber: number): Promise> { const callData = this._getStateRequestCallData(); @@ -24,6 +25,8 @@ export class RamsesV2EventPool extends UniswapV3EventPool { }, ]; + this._stateRequestCallData = calldataWithFee; + const [resBalance0, resBalance1, resState, resCurrentFee] = await this.dexHelper.multiWrapper.tryAggregate< bigint | DecodedStateMultiCallResultWithRelativeBitmaps @@ -44,6 +47,7 @@ export class RamsesV2EventPool extends UniswapV3EventPool { resCurrentFee.returnData, ] as [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmaps, bigint]; + this.feeCode = fee; const tickBitmap = {}; const ticks = {}; @@ -79,7 +83,7 @@ export class RamsesV2EventPool extends UniswapV3EventPool { feeProtocol: bigIntify(_state.slot0.feeProtocol), }, liquidity: bigIntify(_state.liquidity), - fee, + fee: this.feeCode, tickSpacing, maxLiquidityPerTick: bigIntify(_state.maxLiquidityPerTick), tickBitmap, @@ -98,5 +102,4 @@ export class RamsesV2EventPool extends UniswapV3EventPool { balance1, }; } - } diff --git a/src/dex/uniswap-v3/uniswap-v3-pool.ts b/src/dex/uniswap-v3/uniswap-v3-pool.ts index 8c6616124..750d4eb59 100644 --- a/src/dex/uniswap-v3/uniswap-v3-pool.ts +++ b/src/dex/uniswap-v3/uniswap-v3-pool.ts @@ -46,7 +46,7 @@ export class UniswapV3EventPool extends StatefulEventSubscriber { private _poolAddress?: Address; - private _stateRequestCallData?: MultiCallParams< + protected _stateRequestCallData?: MultiCallParams< bigint | DecodedStateMultiCallResultWithRelativeBitmaps >[]; @@ -66,7 +66,7 @@ export class UniswapV3EventPool extends StatefulEventSubscriber { | undefined, readonly erc20Interface: Interface, protected readonly factoryAddress: Address, - public readonly feeCode: bigint, + public feeCode: bigint, token0: Address, token1: Address, logger: Logger, From d5cb35e65590f9a340eb0b30b6a8a902dbe9b827 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 6 Oct 2023 12:26:48 +0300 Subject: [PATCH 446/833] 2.37.2-current-fee-ramses-v2.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3d7ac3844..1029da7cc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.2-current-fee-ramses-v2", + "version": "2.37.2-current-fee-ramses-v2.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 4a1a90b795e2022ee08b45c3f6fedbc9254173b6 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 6 Oct 2023 12:38:04 +0300 Subject: [PATCH 447/833] remove emty line --- src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts index 015cc489f..a9e7c0e58 100644 --- a/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts +++ b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts @@ -12,7 +12,6 @@ export class RamsesV2EventPool extends UniswapV3EventPool { public readonly poolIface = new Interface(RamsesV2PoolABI); - async generateState(blockNumber: number): Promise> { const callData = this._getStateRequestCallData(); From 7067dbf8a7ff1d9703b4b74f5b2ffc52ef388d3c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 6 Oct 2023 13:38:21 +0300 Subject: [PATCH 448/833] add a fix --- src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts | 3 ++- src/dex/uniswap-v3/uniswap-v3-pool.ts | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts index a9e7c0e58..2f6c82b7d 100644 --- a/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts +++ b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts @@ -46,7 +46,8 @@ export class RamsesV2EventPool extends UniswapV3EventPool { resCurrentFee.returnData, ] as [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmaps, bigint]; - this.feeCode = fee; + this.updateFeeCode(fee); + const tickBitmap = {}; const ticks = {}; diff --git a/src/dex/uniswap-v3/uniswap-v3-pool.ts b/src/dex/uniswap-v3/uniswap-v3-pool.ts index 750d4eb59..274a28ea1 100644 --- a/src/dex/uniswap-v3/uniswap-v3-pool.ts +++ b/src/dex/uniswap-v3/uniswap-v3-pool.ts @@ -55,7 +55,7 @@ export class UniswapV3EventPool extends StatefulEventSubscriber { public initFailed = false; public initRetryAttemptCount = 0; - public readonly feeCodeAsString; + public feeCodeAsString; constructor( readonly dexHelper: IDexHelper, @@ -516,4 +516,9 @@ export class UniswapV3EventPool extends StatefulEventSubscriber { this.poolInitCodeHash, ); } + + protected updateFeeCode(fee: bigint): void { + this.feeCode = fee; + this.feeCodeAsString = fee.toString(); + } } From a85fee76aa7bff79fd21703f221e2afdc3b66fbb Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 6 Oct 2023 13:38:40 +0300 Subject: [PATCH 449/833] 2.37.2-current-fee-ramses-v2.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1029da7cc..5202d467d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.2-current-fee-ramses-v2.2", + "version": "2.37.2-current-fee-ramses-v2.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 0380c18664bd7e01c2b2ceb0ea9ecf26a7cd3707 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 6 Oct 2023 16:10:23 +0300 Subject: [PATCH 450/833] 2.37.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 30985642a..7dd1af3ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.2", + "version": "2.37.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From f78bb465536a3a5eeb65074b5c32673c9ac4baab Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 6 Oct 2023 16:10:54 +0300 Subject: [PATCH 451/833] add a fix for current fee --- src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts | 5 ++--- src/dex/uniswap-v3/uniswap-v3-pool.ts | 7 ++----- src/dex/uniswap-v3/uniswap-v3.ts | 4 ++-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts index 2f6c82b7d..63f978d38 100644 --- a/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts +++ b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts @@ -46,11 +46,10 @@ export class RamsesV2EventPool extends UniswapV3EventPool { resCurrentFee.returnData, ] as [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmaps, bigint]; - this.updateFeeCode(fee); - const tickBitmap = {}; const ticks = {}; + this.currentFeeCodeAsString = fee.toString(); _reduceTickBitmap(tickBitmap, _state.tickBitmap); _reduceTicks(ticks, _state.ticks); @@ -83,7 +82,7 @@ export class RamsesV2EventPool extends UniswapV3EventPool { feeProtocol: bigIntify(_state.slot0.feeProtocol), }, liquidity: bigIntify(_state.liquidity), - fee: this.feeCode, + fee, tickSpacing, maxLiquidityPerTick: bigIntify(_state.maxLiquidityPerTick), tickBitmap, diff --git a/src/dex/uniswap-v3/uniswap-v3-pool.ts b/src/dex/uniswap-v3/uniswap-v3-pool.ts index 274a28ea1..bb4f2bf4f 100644 --- a/src/dex/uniswap-v3/uniswap-v3-pool.ts +++ b/src/dex/uniswap-v3/uniswap-v3-pool.ts @@ -46,6 +46,8 @@ export class UniswapV3EventPool extends StatefulEventSubscriber { private _poolAddress?: Address; + public currentFeeCodeAsString: string | undefined; + protected _stateRequestCallData?: MultiCallParams< bigint | DecodedStateMultiCallResultWithRelativeBitmaps >[]; @@ -516,9 +518,4 @@ export class UniswapV3EventPool extends StatefulEventSubscriber { this.poolInitCodeHash, ); } - - protected updateFeeCode(fee: bigint): void { - this.feeCode = fee; - this.feeCodeAsString = fee.toString(); - } } diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index fe2828908..0b2295460 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -495,7 +495,7 @@ export class UniswapV3 { tokenIn: from.address, tokenOut: to.address, - fee: pool.feeCodeAsString, + fee: pool.currentFeeCodeAsString ? pool.currentFeeCodeAsString : pool.feeCodeAsString, }, ], exchange: pool.poolAddress, @@ -689,7 +689,7 @@ export class UniswapV3 { tokenIn: _srcAddress, tokenOut: _destAddress, - fee: pool.feeCode.toString(), + fee: pool.currentFeeCodeAsString ? pool.currentFeeCodeAsString : pool.feeCode.toString(), }, ], }, From 974034b4edca79e51bdadaa8ba6ba6fb228481b0 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 6 Oct 2023 16:11:43 +0300 Subject: [PATCH 452/833] 2.37.2-current-fee-ramses-v2.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5202d467d..d1423e4c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.2-current-fee-ramses-v2.3", + "version": "2.37.2-current-fee-ramses-v2.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 8cbd7980648639daadb1ce48a7d8a04be3553e2f Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 6 Oct 2023 16:18:24 +0300 Subject: [PATCH 453/833] 2.37.4-current-fee-ramses-v2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d1423e4c8..bf23840a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.2-current-fee-ramses-v2.4", + "version": "2.37.4-current-fee-ramses-v2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From ac6bb8845c75bbfa9ecf991e5673eb945e8533a0 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 6 Oct 2023 17:20:36 +0300 Subject: [PATCH 454/833] remove isFirstSwap --- src/dex/dexalot/dexalot.ts | 7 ------- src/implementations/local-paraswap-sdk.ts | 1 - src/pricing-helper.ts | 2 -- 3 files changed, 10 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 89bda5bf6..e69cedca0 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -416,15 +416,8 @@ export class Dexalot extends SimpleExchange implements IDex { blockNumber: number, limitPools?: string[], transferFees?: TransferFeeParams, - isFirstSwap?: boolean, ): Promise> { try { - - // Disable multi/mega routes - if(!isFirstSwap) { - return null; - } - if (await this.isRestricted()) { return null; } diff --git a/src/implementations/local-paraswap-sdk.ts b/src/implementations/local-paraswap-sdk.ts index 3ac07c809..d1b573beb 100644 --- a/src/implementations/local-paraswap-sdk.ts +++ b/src/implementations/local-paraswap-sdk.ts @@ -117,7 +117,6 @@ export class LocalParaswapSDK implements IParaSwapSDK { blockNumber, [this.dexKey], poolIdentifiers, - true, transferFees, ); diff --git a/src/pricing-helper.ts b/src/pricing-helper.ts index 754343f20..3c3343165 100644 --- a/src/pricing-helper.ts +++ b/src/pricing-helper.ts @@ -185,7 +185,6 @@ export class PricingHelper { blockNumber: number, dexKeys: string[], limitPoolsMap: { [key: string]: string[] | null } | null, - isFirstSwap: boolean, transferFees: TransferFeeParams = { srcFee: 0, destFee: 0, @@ -227,7 +226,6 @@ export class PricingHelper { blockNumber, limitPools ? limitPools : undefined, transferFees, - isFirstSwap, ) .then(poolPrices => { try { From 257e0d05a18076178ea86d6ef2d56a05e057c0b0 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 7 Oct 2023 12:13:45 +0300 Subject: [PATCH 455/833] return adapters --- src/config.ts | 6 +++--- src/dex/dexalot/config.ts | 10 +++++----- src/dex/dexalot/dexalot-e2e.test.ts | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/config.ts b/src/config.ts index 5cd64635d..362e366c9 100644 --- a/src/config.ts +++ b/src/config.ts @@ -222,9 +222,9 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_43114`]?.split(',') || [], dexalotAuthToken: process.env.API_KEY_DEXALOT_AUTH_TOKEN || '', adapterAddresses: { - AvalancheAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9', - AvalancheAdapter02: '0xFb8773AA4Fd02e54bbd352061D8Be1911FAa210a', - AvalancheBuyAdapter: '0x434C1Cca4842629230067674Dd54E21a14D9FD5D', + AvalancheAdapter01: '0x4ebda7657DBe0f27E377EA26f11279D2b8Ef9a0f', + AvalancheAdapter02: '0x33c0413e149f1e75F6693C1540E108FAB987fb06', + AvalancheBuyAdapter: '0xFeBcd59fE83d40948C0097e8CAd8c6ECD500B1Ac', }, uniswapV2ExchangeRouterAddress: '0x53e693c6C7FFC4446c53B205Cf513105Bf140D7b', diff --git a/src/dex/dexalot/config.ts b/src/dex/dexalot/config.ts index 2204e82a5..658792a20 100644 --- a/src/dex/dexalot/config.ts +++ b/src/dex/dexalot/config.ts @@ -1,6 +1,6 @@ import { DexParams } from './types'; import { DexConfigMap, AdapterMappings } from '../../types'; -import { Network } from '../../constants'; +import { Network, SwapSide } from '../../constants'; export const DexalotConfig: DexConfigMap = { Dexalot: { @@ -11,8 +11,8 @@ export const DexalotConfig: DexConfigMap = { }; export const Adapters: Record = { - // [Network.AVALANCHE]: { - // [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 6 }], - // [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 8 }], - // }, + [Network.AVALANCHE]: { + [SwapSide.SELL]: [{ name: 'AvalancheAdapter02', index: 6 }], + [SwapSide.BUY]: [{ name: 'AvalancheBuyAdapter', index: 8 }], + }, }; diff --git a/src/dex/dexalot/dexalot-e2e.test.ts b/src/dex/dexalot/dexalot-e2e.test.ts index b9b9c04b3..191468e1d 100644 --- a/src/dex/dexalot/dexalot-e2e.test.ts +++ b/src/dex/dexalot/dexalot-e2e.test.ts @@ -33,13 +33,13 @@ function testForNetwork( const sideToContractMethods = new Map([ [SwapSide.SELL, [ - ContractMethod.simpleSwap, - // ContractMethod.megaSwap, - // ContractMethod.multiSwap + // ContractMethod.simpleSwap, + ContractMethod.megaSwap, + ContractMethod.multiSwap ]], [SwapSide.BUY, [ - ContractMethod.simpleBuy, - // ContractMethod.buy + // ContractMethod.simpleBuy, + ContractMethod.buy ]], ]); From d5d0aac501f0cfef072b81224a54d50d6e7fe5b9 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 7 Oct 2023 12:15:46 +0300 Subject: [PATCH 456/833] remove exclamation marks --- src/dex/uniswap-v3/uniswap-v3.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index eb7d87b82..37e66e455 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -309,7 +309,7 @@ export class UniswapV3 ); try { - await pool!.initialize(blockNumber, { + await pool.initialize(blockNumber, { initCallback: (state: DeepReadonly) => { //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber pool!.addressesSubscribed[0] = state.pool; @@ -338,10 +338,10 @@ export class UniswapV3 // on unknown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool!.initRetryAttemptCount}`, + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, e, ); - pool!.initFailed = true; + pool.initFailed = true; } } @@ -358,8 +358,8 @@ export class UniswapV3 } this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - pool!; - return pool!; + pool; + return pool; } async addMasterPool(poolKey: string, blockNumber: number): Promise { From 3373047580243648263d1ae2ded70023ed63a6b7 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 7 Oct 2023 12:17:53 +0300 Subject: [PATCH 457/833] 2.37.4-current-fee-ramses-v2.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bf23840a0..c11d27263 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.4-current-fee-ramses-v2", + "version": "2.37.4-current-fee-ramses-v2.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From d989a3df6d478c1c73e92555cd7abfe71904956f Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 7 Oct 2023 14:29:54 +0300 Subject: [PATCH 458/833] listen to FeeAdjustment event --- src/abi/ramses-v2/RamsesV2Pool.abi.json | 19 +++++++ .../forks/ramses-v2/ramses-v2-pool.ts | 51 ++++++++++++++++++- src/dex/uniswap-v3/types.ts | 1 + src/dex/uniswap-v3/uniswap-v3.ts | 6 ++- 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/abi/ramses-v2/RamsesV2Pool.abi.json b/src/abi/ramses-v2/RamsesV2Pool.abi.json index 1dc342a1c..b5516c8d7 100644 --- a/src/abi/ramses-v2/RamsesV2Pool.abi.json +++ b/src/abi/ramses-v2/RamsesV2Pool.abi.json @@ -4,6 +4,25 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint24", + "name": "oldFee", + "type": "uint24" + }, + { + "indexed": false, + "internalType": "uint24", + "name": "newFee", + "type": "uint24" + } + ], + "name": "FeeAdjustment", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts index 63f978d38..10d4bf4c2 100644 --- a/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts +++ b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts @@ -1,5 +1,5 @@ import { UniswapV3EventPool } from '../../uniswap-v3-pool'; -import { DecodedStateMultiCallResultWithRelativeBitmaps, PoolState } from '../../types'; +import { DecodedStateMultiCallResultWithRelativeBitmaps, DecodeStateMultiCallFunc, PoolState } from '../../types'; import { assert } from 'ts-essentials'; import { _reduceTickBitmap, _reduceTicks } from '../../contract-math/utils'; import { bigIntify } from '../../../../utils'; @@ -7,11 +7,60 @@ import { TickBitMap } from '../../contract-math/TickBitMap'; import { uint24ToBigInt } from '../../../../lib/decoders'; import { Interface } from 'ethers/lib/utils'; import RamsesV2PoolABI from '../../../../abi/ramses-v2/RamsesV2Pool.abi.json'; +import { IDexHelper } from '../../../../dex-helper'; +import { Contract } from 'web3-eth-contract'; +import { Address, Logger } from '../../../../types'; export class RamsesV2EventPool extends UniswapV3EventPool { public readonly poolIface = new Interface(RamsesV2PoolABI); + constructor( + readonly dexHelper: IDexHelper, + parentName: string, + readonly stateMultiContract: Contract, + readonly decodeStateMultiCallResultWithRelativeBitmaps: + | DecodeStateMultiCallFunc + | undefined, + readonly erc20Interface: Interface, + protected readonly factoryAddress: Address, + public feeCode: bigint, + token0: Address, + token1: Address, + logger: Logger, + mapKey: string = '', + readonly poolInitCodeHash: string, + ) { + super( + dexHelper, + parentName, + stateMultiContract, + decodeStateMultiCallResultWithRelativeBitmaps, + erc20Interface, + factoryAddress, + feeCode, + token0, + token1, + logger, + mapKey, + poolInitCodeHash, + ); + + this.handlers['FeeAdjustment'] = this.handleFeeAdjustmentEvent.bind(this); + } + + handleFeeAdjustmentEvent( + event: any, + pool: PoolState, + ): PoolState { + const newFee = bigIntify(event.args.newFee); + + pool.fee = newFee; + this.currentFeeCodeAsString = newFee.toString(); + + return pool; + } + async generateState(blockNumber: number): Promise> { const callData = this._getStateRequestCallData(); diff --git a/src/dex/uniswap-v3/types.ts b/src/dex/uniswap-v3/types.ts index 4d29b5099..967675843 100644 --- a/src/dex/uniswap-v3/types.ts +++ b/src/dex/uniswap-v3/types.ts @@ -61,6 +61,7 @@ export type UniswapV3Data = { tokenIn: Address; tokenOut: Address; fee: NumberAsString; + currentFee?: NumberAsString; }[]; isApproved?: boolean; }; diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 37e66e455..8a6229fb7 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -540,7 +540,8 @@ export class UniswapV3 { tokenIn: from.address, tokenOut: to.address, - fee: pool.currentFeeCodeAsString ? pool.currentFeeCodeAsString : pool.feeCodeAsString, + fee: pool.feeCodeAsString, + currentFee: pool.currentFeeCodeAsString, }, ], exchange: pool.poolAddress, @@ -734,7 +735,8 @@ export class UniswapV3 { tokenIn: _srcAddress, tokenOut: _destAddress, - fee: pool.currentFeeCodeAsString ? pool.currentFeeCodeAsString : pool.feeCode.toString(), + fee: pool.feeCode.toString(), + currentFee: pool.currentFeeCodeAsString, }, ], }, From 3372e2e3c693539ac1710a370b81d7723d44a32f Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 7 Oct 2023 14:31:01 +0300 Subject: [PATCH 459/833] 2.37.4-current-fee-ramses-v2.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c11d27263..1d6e84a3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.4-current-fee-ramses-v2.2", + "version": "2.37.4-current-fee-ramses-v2.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 424844e26f986e599d6bbce19adc95e4203c980f Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 9 Oct 2023 00:00:20 +0300 Subject: [PATCH 460/833] fix: bug with cache key --- src/dex/algebra/algebra.ts | 2 +- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 2 +- src/dex/uniswap-v3/uniswap-v3.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 726cb669d..fc15c59fa 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -167,7 +167,7 @@ export class Algebra extends SimpleExchange implements IDex { }) => { const logPrefix = '[Algebra.onPoolCreatedDeleteFromNonExistingSet]'; const [_token0, _token1] = this._sortTokens(token0, token1); - const poolKey = `${token0}_${token1}`.toLowerCase(); + const poolKey = `${_token0}_${_token1}`.toLowerCase(); // consider doing it only from master pool for less calls to distant cache diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 1e4013edd..7b48f2a56 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -178,7 +178,7 @@ export class PancakeswapV3 }) => { const logPrefix = '[PancakeV3.onPoolCreatedDeleteFromNonExistingSet]'; const [_token0, _token1] = this._sortTokens(token0, token1); - const poolKey = `${token0}_${token1}_${fee}`.toLowerCase(); + const poolKey = `${_token0}_${_token1}_${fee}`.toLowerCase(); // consider doing it only from master pool for less calls to distant cache diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 6b7f8b1fa..4c86f3a50 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -209,7 +209,7 @@ export class UniswapV3 }) => { const logPrefix = '[UniswapV3.onPoolCreatedDeleteFromNonExistingSet]'; const [_token0, _token1] = this._sortTokens(token0, token1); - const poolKey = `${token0}_${token1}_${fee}`.toLowerCase(); + const poolKey = `${_token0}_${_token1}_${fee}`.toLowerCase(); // consider doing it only from master pool for less calls to distant cache From 360a0356ce89a554a2cad099e1c9d0c2fe5e8c42 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 9 Oct 2023 00:01:32 +0300 Subject: [PATCH 461/833] 2.37.4-cache-invalidation-fix --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7dd1af3ba..420868f97 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.3", + "version": "2.37.4-cache-invalidation-fix", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 6643c52ac01dea2ae74e41f814c28a8e7bd77906 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 9 Oct 2023 12:39:51 +0300 Subject: [PATCH 462/833] add a fix --- .../forks/ramses-v2/ramses-v2-pool.ts | 2 - src/dex/uniswap-v3/uniswap-v3-pool.ts | 2 - src/dex/uniswap-v3/uniswap-v3.ts | 51 ++++++++----------- 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts index 10d4bf4c2..c68b71658 100644 --- a/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts +++ b/src/dex/uniswap-v3/forks/ramses-v2/ramses-v2-pool.ts @@ -56,7 +56,6 @@ export class RamsesV2EventPool extends UniswapV3EventPool { const newFee = bigIntify(event.args.newFee); pool.fee = newFee; - this.currentFeeCodeAsString = newFee.toString(); return pool; } @@ -98,7 +97,6 @@ export class RamsesV2EventPool extends UniswapV3EventPool { const tickBitmap = {}; const ticks = {}; - this.currentFeeCodeAsString = fee.toString(); _reduceTickBitmap(tickBitmap, _state.tickBitmap); _reduceTicks(ticks, _state.ticks); diff --git a/src/dex/uniswap-v3/uniswap-v3-pool.ts b/src/dex/uniswap-v3/uniswap-v3-pool.ts index bb4f2bf4f..9f3401710 100644 --- a/src/dex/uniswap-v3/uniswap-v3-pool.ts +++ b/src/dex/uniswap-v3/uniswap-v3-pool.ts @@ -46,8 +46,6 @@ export class UniswapV3EventPool extends StatefulEventSubscriber { private _poolAddress?: Address; - public currentFeeCodeAsString: string | undefined; - protected _stateRequestCallData?: MultiCallParams< bigint | DecodedStateMultiCallResultWithRelativeBitmaps >[]; diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 8a6229fb7..3e6ceef72 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -2,28 +2,22 @@ import { defaultAbiCoder, Interface } from '@ethersproject/abi'; import _ from 'lodash'; import { pack } from '@ethersproject/solidity'; import { - Token, + AdapterExchangeParam, Address, ExchangePrices, - AdapterExchangeParam, - SimpleExchangeParam, - PoolLiquidity, + ExchangeTxInfo, Logger, NumberAsString, + PoolLiquidity, PoolPrices, - TxInfo, PreprocessTransactionOptions, - ExchangeTxInfo, + SimpleExchangeParam, + Token, + TxInfo, } from '../../types'; -import { SwapSide, Network, CACHE_PREFIX } from '../../constants'; +import { CACHE_PREFIX, Network, SwapSide } from '../../constants'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { - getBigIntPow, - getDexKeysWithNetwork, - interpolate, - isTruthy, - uuidToBytes16, -} from '../../utils'; +import { getBigIntPow, getDexKeysWithNetwork, interpolate, isTruthy, uuidToBytes16, } from '../../utils'; import { IDex } from '../../dex/idex'; import { IDexHelper } from '../../dex-helper/idex-helper'; import { @@ -35,11 +29,8 @@ import { UniswapV3Param, UniswapV3SimpleSwapParams, } from './types'; -import { - getLocalDeadlineAsFriendlyPlaceholder, - SimpleExchange, -} from '../simple-exchange'; -import { UniswapV3Config, Adapters, PoolsToPreload } from './config'; +import { getLocalDeadlineAsFriendlyPlaceholder, SimpleExchange, } from '../simple-exchange'; +import { Adapters, PoolsToPreload, UniswapV3Config } from './config'; import { UniswapV3EventPool } from './uniswap-v3-pool'; import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; @@ -58,11 +49,7 @@ import { uniswapV3Math } from './contract-math/uniswap-v3-math'; import { Contract } from 'web3-eth-contract'; import { AbiItem } from 'web3-utils'; import { BalanceRequest, getBalances } from '../../lib/tokens/balancer-fetcher'; -import { - AssetType, - DEFAULT_ID_ERC20, - DEFAULT_ID_ERC20_AS_STRING, -} from '../../lib/tokens/types'; +import { AssetType, DEFAULT_ID_ERC20, DEFAULT_ID_ERC20_AS_STRING, } from '../../lib/tokens/types'; import { OptimalSwapExchange } from '@paraswap/core'; import { OnPoolCreatedCallback, UniswapV3Factory } from './uniswap-v3-factory'; @@ -424,6 +411,7 @@ export class UniswapV3 amounts: bigint[], side: SwapSide, pools: UniswapV3EventPool[], + states: PoolState[], ): Promise | null> { if (pools.length === 0) { return null; @@ -521,7 +509,7 @@ export class UniswapV3 }; let i = 0; - const result = pools.map(pool => { + const result = pools.map((pool, index) => { const _rates = _amounts.map(() => decode(i++)); const unit: bigint = _rates[0]; @@ -541,7 +529,7 @@ export class UniswapV3 tokenIn: from.address, tokenOut: to.address, fee: pool.feeCodeAsString, - currentFee: pool.currentFeeCodeAsString, + currentFee: states[index].fee.toString(), }, ], exchange: pool.poolAddress, @@ -653,16 +641,17 @@ export class UniswapV3 }, ); + const states = poolsToUse.poolWithState.map( + p => p.getState(blockNumber)!, + ); + const rpcResultsPromise = this.getPricingFromRpc( _srcToken, _destToken, amounts, side, this.network === Network.ZKEVM ? [] : poolsToUse.poolWithoutState, - ); - - const states = poolsToUse.poolWithState.map( - p => p.getState(blockNumber)!, + this.network === Network.ZKEVM ? [] : states, ); const unitAmount = getBigIntPow( @@ -736,7 +725,7 @@ export class UniswapV3 tokenIn: _srcAddress, tokenOut: _destAddress, fee: pool.feeCode.toString(), - currentFee: pool.currentFeeCodeAsString, + currentFee: state.fee.toString(), }, ], }, From a501dfed7c022cb67edeac2c4cd61faa06311692 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 9 Oct 2023 12:40:52 +0300 Subject: [PATCH 463/833] 2.37.4-current-fee-ramses-v2.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1d6e84a3a..e233f031c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.4-current-fee-ramses-v2.3", + "version": "2.37.4-current-fee-ramses-v2.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 340a1cf10afc4d1cc1445be962d13e61111775c1 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 9 Oct 2023 14:46:23 +0300 Subject: [PATCH 464/833] 2.37.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e233f031c..7e58a27be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.4-current-fee-ramses-v2.4", + "version": "2.37.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From a112bce97496dac40e244a0cb604916e3ae4bf2a Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 9 Oct 2023 18:25:29 +0300 Subject: [PATCH 465/833] update adapters addresses --- src/config.ts | 6 +++--- src/dex/dexalot/dexalot-e2e.test.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/config.ts b/src/config.ts index 362e366c9..60b254923 100644 --- a/src/config.ts +++ b/src/config.ts @@ -222,9 +222,9 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_43114`]?.split(',') || [], dexalotAuthToken: process.env.API_KEY_DEXALOT_AUTH_TOKEN || '', adapterAddresses: { - AvalancheAdapter01: '0x4ebda7657DBe0f27E377EA26f11279D2b8Ef9a0f', - AvalancheAdapter02: '0x33c0413e149f1e75F6693C1540E108FAB987fb06', - AvalancheBuyAdapter: '0xFeBcd59fE83d40948C0097e8CAd8c6ECD500B1Ac', + AvalancheAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9', + AvalancheAdapter02: '0x2cdB0cDc2a9321ac2ED5b741828a5216C265Be80', + AvalancheBuyAdapter: '0x9Aa41A24A10af2a965A6D406b913a7Cd9C6886ea', }, uniswapV2ExchangeRouterAddress: '0x53e693c6C7FFC4446c53B205Cf513105Bf140D7b', diff --git a/src/dex/dexalot/dexalot-e2e.test.ts b/src/dex/dexalot/dexalot-e2e.test.ts index 191468e1d..731ad637a 100644 --- a/src/dex/dexalot/dexalot-e2e.test.ts +++ b/src/dex/dexalot/dexalot-e2e.test.ts @@ -33,12 +33,12 @@ function testForNetwork( const sideToContractMethods = new Map([ [SwapSide.SELL, [ - // ContractMethod.simpleSwap, + ContractMethod.simpleSwap, ContractMethod.megaSwap, ContractMethod.multiSwap ]], [SwapSide.BUY, [ - // ContractMethod.simpleBuy, + ContractMethod.simpleBuy, ContractMethod.buy ]], ]); From f681b8cd57ef394851b35734198ad6e901d36f7f Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 9 Oct 2023 18:26:09 +0300 Subject: [PATCH 466/833] 2.37.5-dexalot --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ac0377e29..a9759d3d7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.36.3-dexalot.5", + "version": "2.37.5-dexalot", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 2fe4bd7b7f40ecfe7b2a6232011cf18f974ab6fe Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Mon, 9 Oct 2023 11:38:26 -0500 Subject: [PATCH 467/833] use swap with only 4 params --- src/dex/solidly-v3/solidly-v3.ts | 34 ++++++++++++++++---------------- src/dex/solidly-v3/types.ts | 4 +--- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index 5918d383a..99f4db8cb 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -30,7 +30,8 @@ import { DexParams, OutputResult, PoolState, - SolidlyV3Data, SolidlyV3SimpleSwapParams, + SolidlyV3Data, + SolidlyV3SimpleSwapParams, UniswapV3Functions, UniswapV3Param, UniswapV3SimpleSwapParams, @@ -65,7 +66,7 @@ import { DEFAULT_ID_ERC20_AS_STRING, } from '../../lib/tokens/types'; import { OptimalSwapExchange } from '@paraswap/core'; -import { TickMath } from "./contract-math/TickMath"; +import { TickMath } from './contract-math/TickMath'; type PoolPairsInfo = { token0: Address; @@ -92,11 +93,7 @@ export class SolidlyV3 intervalTask?: NodeJS.Timeout; public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork( - _.pick(SolidlyV3Config, [ - 'SolidlyV3', - ]), - ); + getDexKeysWithNetwork(_.pick(SolidlyV3Config, ['SolidlyV3'])); logger: Logger; @@ -451,7 +448,7 @@ export class SolidlyV3 (acc, pool) => { let state = pool.getState(blockNumber); if (state === null) { - throw new Error("Unable to retrieve pool state."); + throw new Error('Unable to retrieve pool state.'); } else { acc.poolWithState.push(pool); } @@ -534,7 +531,7 @@ export class SolidlyV3 prices, data: { zeroForOne, - poolAddress: pool.poolAddress + poolAddress: pool.poolAddress, }, poolIdentifier: this.getPoolIdentifier( pool.token0, @@ -686,23 +683,26 @@ export class SolidlyV3 data: SolidlyV3Data, side: SwapSide, ): Promise { - const swapFunction = this.poolIface.getFunction('swap(address,bool,int256,uint160,uint256,uint256)'); + const swapFunction = this.poolIface.getFunction( + 'swap(address,bool,int256,uint160)', + ); const swapFunctionParams: SolidlyV3SimpleSwapParams = { recipient: this.augustusAddress, zeroForOne: data.zeroForOne, - amountSpecified: side === SwapSide.SELL ? srcAmount.toString() : (-destAmount).toString(), - sqrtPriceLimitX96: data.zeroForOne ? (TickMath.MIN_SQRT_RATIO + BigInt(1)).toString() : (TickMath.MAX_SQRT_RATIO - BigInt(1)).toString(), - amountLimit: '1', - deadline: getLocalDeadlineAsFriendlyPlaceholder(), - } + amountSpecified: + side === SwapSide.SELL + ? srcAmount.toString() + : (-destAmount).toString(), + sqrtPriceLimitX96: data.zeroForOne + ? (TickMath.MIN_SQRT_RATIO + BigInt(1)).toString() + : (TickMath.MAX_SQRT_RATIO - BigInt(1)).toString(), + }; const swapData = this.poolIface.encodeFunctionData(swapFunction, [ swapFunctionParams.recipient, swapFunctionParams.zeroForOne, swapFunctionParams.amountSpecified, swapFunctionParams.sqrtPriceLimitX96, - swapFunctionParams.amountLimit, - swapFunctionParams.deadline, ]); return this.buildSimpleParamWithoutWETHConversion( diff --git a/src/dex/solidly-v3/types.ts b/src/dex/solidly-v3/types.ts index 99fa9aaa3..35b2fa421 100644 --- a/src/dex/solidly-v3/types.ts +++ b/src/dex/solidly-v3/types.ts @@ -84,9 +84,7 @@ export type SolidlyV3SimpleSwapParams = { zeroForOne: boolean; amountSpecified: NumberAsString; sqrtPriceLimitX96: NumberAsString; - amountLimit: NumberAsString; - deadline: string; -} +}; export type UniswapV3Param = [ fromToken: Address, From 15b7a88f38918a18305c72aef0b591b7128d31e2 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 9 Oct 2023 21:09:22 +0300 Subject: [PATCH 468/833] fix: bug in deleting the pool from local state --- src/dex/algebra/algebra-factory.ts | 4 ++-- src/dex/algebra/algebra.ts | 2 +- src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts | 4 ++-- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 2 +- src/dex/uniswap-v3/uniswap-v3-factory.ts | 4 ++-- src/dex/uniswap-v3/uniswap-v3.ts | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/dex/algebra/algebra-factory.ts b/src/dex/algebra/algebra-factory.ts index 1650878ad..41de2a014 100644 --- a/src/dex/algebra/algebra-factory.ts +++ b/src/dex/algebra/algebra-factory.ts @@ -62,8 +62,8 @@ export class AlgebraFactory extends StatefulEventSubscriber { } async handleNewPool(event: LogDescription) { - const token0 = event.args.token0; - const token1 = event.args.token1; + const token0 = event.args.token0.toLowerCase(); + const token1 = event.args.token1.toLowerCase(); await this.onPoolCreated({ token0, token1 }); } diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index fc15c59fa..42ad77520 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -167,7 +167,7 @@ export class Algebra extends SimpleExchange implements IDex { }) => { const logPrefix = '[Algebra.onPoolCreatedDeleteFromNonExistingSet]'; const [_token0, _token1] = this._sortTokens(token0, token1); - const poolKey = `${_token0}_${_token1}`.toLowerCase(); + const poolKey = `${_token0}_${_token1}`; // consider doing it only from master pool for less calls to distant cache diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts b/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts index 8bfc7a46b..5b60cb025 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3-factory.ts @@ -64,8 +64,8 @@ export class PancakeswapV3Factory extends StatefulEventSubscriber } async handleNewPool(event: LogDescription) { - const token0 = event.args.token0; - const token1 = event.args.token1; + const token0 = event.args.token0.toLowerCase(); + const token1 = event.args.token1.toLowerCase(); const fee = event.args.fee; await this.onPoolCreated({ token0, token1, fee }); diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 7b48f2a56..be08718f7 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -178,7 +178,7 @@ export class PancakeswapV3 }) => { const logPrefix = '[PancakeV3.onPoolCreatedDeleteFromNonExistingSet]'; const [_token0, _token1] = this._sortTokens(token0, token1); - const poolKey = `${_token0}_${_token1}_${fee}`.toLowerCase(); + const poolKey = `${_token0}_${_token1}_${fee}`; // consider doing it only from master pool for less calls to distant cache diff --git a/src/dex/uniswap-v3/uniswap-v3-factory.ts b/src/dex/uniswap-v3/uniswap-v3-factory.ts index 0f568e7ab..372020de4 100644 --- a/src/dex/uniswap-v3/uniswap-v3-factory.ts +++ b/src/dex/uniswap-v3/uniswap-v3-factory.ts @@ -64,8 +64,8 @@ export class UniswapV3Factory extends StatefulEventSubscriber { } async handleNewPool(event: LogDescription) { - const token0 = event.args.token0; - const token1 = event.args.token1; + const token0 = event.args.token0.toLowerCase(); + const token1 = event.args.token1.toLowerCase(); const fee = event.args.fee; await this.onPoolCreated({ token0, token1, fee }); diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 4c86f3a50..2b9539f6e 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -209,7 +209,7 @@ export class UniswapV3 }) => { const logPrefix = '[UniswapV3.onPoolCreatedDeleteFromNonExistingSet]'; const [_token0, _token1] = this._sortTokens(token0, token1); - const poolKey = `${_token0}_${_token1}_${fee}`.toLowerCase(); + const poolKey = `${_token0}_${_token1}_${fee}`; // consider doing it only from master pool for less calls to distant cache From 2287786a0da88fe6495f0f56d1c8bf877b03190d Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 9 Oct 2023 21:11:55 +0300 Subject: [PATCH 469/833] 2.37.4-cache-invalidation-fix.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 420868f97..e61f38612 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.4-cache-invalidation-fix", + "version": "2.37.4-cache-invalidation-fix.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From dce432e870241038f6847081fc5ce93a5c04c2fe Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 10 Oct 2023 15:14:37 +0300 Subject: [PATCH 470/833] debug tests --- src/config.ts | 4 ++-- src/dex/dexalot/dexalot-e2e.test.ts | 2 +- tests/constants-e2e.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/config.ts b/src/config.ts index 60b254923..54f38de8f 100644 --- a/src/config.ts +++ b/src/config.ts @@ -223,8 +223,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { dexalotAuthToken: process.env.API_KEY_DEXALOT_AUTH_TOKEN || '', adapterAddresses: { AvalancheAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9', - AvalancheAdapter02: '0x2cdB0cDc2a9321ac2ED5b741828a5216C265Be80', - AvalancheBuyAdapter: '0x9Aa41A24A10af2a965A6D406b913a7Cd9C6886ea', + AvalancheAdapter02: '0x928eE214dB95eeD9241329F889320a21bcED6b65', + AvalancheBuyAdapter: '0x3d3131Ed7A6D4d6E765BC96D5cd416Cf2C2c075C', }, uniswapV2ExchangeRouterAddress: '0x53e693c6C7FFC4446c53B205Cf513105Bf140D7b', diff --git a/src/dex/dexalot/dexalot-e2e.test.ts b/src/dex/dexalot/dexalot-e2e.test.ts index 731ad637a..d0ce438f5 100644 --- a/src/dex/dexalot/dexalot-e2e.test.ts +++ b/src/dex/dexalot/dexalot-e2e.test.ts @@ -29,7 +29,7 @@ function testForNetwork( const tokens = Tokens[network]; const holders = Holders[network]; const nativeTokenSymbol = NativeTokenSymbols[network]; - const sleepMs = 5000; + const sleepMs = 20000; const sideToContractMethods = new Map([ [SwapSide.SELL, [ diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index a3d7b51a7..646f2fd9e 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1065,7 +1065,7 @@ export const Holders: { BETS: '0x8cc2284c90d05578633418f9cde104f402375a65', HATCHY: '0x14ec295ec8def851ec6e2959df872dd24e422631', USDCe: '0x3a2434c698f8d79af1f5a9e43013157ca8b11a66', - USDC: '0xbf14db80d9275fb721383a77c00ae180fc40ae98', + USDC: '0x0d0707963952f2fba59dd06f2b425ace40b492fe', USDTe: '0x84d34f4f83a87596cd3fb6887cff8f17bf5a7b83', WETHe: '0xD291B51f7a1a1F4917D085F2a7731A447E4aF82D', POPS: '0x5268c2331658cb0b2858cfa9db27d8f22f5434bc', @@ -1081,7 +1081,7 @@ export const Holders: { TSD: '0x691A89db352B72dDb249bFe16503494eC0D920A4', THO: '0xc40d16c47394a506d451475c8a7c46c1175c1da1', aAvaUSDT: '0x50B1Ba98Cf117c9682048D56628B294ebbAA4ec2', - USDT: '0x4a58555884297dcd9d2198c9fec52b4cabc90fc6', + USDT: '0x764fe7fb23f0f995c45faef5e32a4526f2028814', aAvaWAVAX: '0x1B18Df70863636AEe4BfBAb6F7C70ceBCA9bA404', oldFRAX: '0x4e3376018add04ebe4c46bf6f924ddec8c67aa7b', newFRAX: '0x4e3376018add04ebe4c46bf6f924ddec8c67aa7b', From 5a4f17372a3d21ee9d2580c3700a20eb7b306d8c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 10 Oct 2023 16:43:04 +0300 Subject: [PATCH 471/833] move event pool class to separate file --- src/dex/smardex/config.ts | 31 ++-- src/dex/smardex/constants.ts | 7 + src/dex/smardex/smardex-event-pool.ts | 185 +++++++++++++++++++++++ src/dex/smardex/smardex.ts | 203 ++------------------------ src/dex/smardex/types.ts | 2 +- 5 files changed, 215 insertions(+), 213 deletions(-) create mode 100644 src/dex/smardex/smardex-event-pool.ts diff --git a/src/dex/smardex/config.ts b/src/dex/smardex/config.ts index 2fcce58a4..b545ff3a5 100644 --- a/src/dex/smardex/config.ts +++ b/src/dex/smardex/config.ts @@ -2,10 +2,10 @@ import { DexParams } from './types'; import { DexConfigMap, AdapterMappings } from '../../types'; import { Network } from '../../constants'; -const gatewaySubgraph = 'https://subgraph.smardex.io'; -const mainnetInitHash = +const GATEWAY_SUBGRAPH = 'https://subgraph.smardex.io'; +const MAINNET_INIT_HASH = '0xb477a06204165d50e6d795c7c216306290eff5d6015f8b65bb46002a8775b548'; -const layer2InitHash = +const LAYER2_INIT_HASH = '0x33bee911475f015247aeb1eebe149d1c6d2669be54126c29d85df6b0abb4c4e9'; export const SmardexConfig: DexConfigMap = { @@ -13,37 +13,32 @@ export const SmardexConfig: DexConfigMap = { [Network.MAINNET]: { factoryAddress: '0x7753F36E711B66a0350a753aba9F5651BAE76A1D', router: '0xEf2f9b48d7EC80440Ab4573dF1A2aBDBE06D3f60', - initCode: mainnetInitHash, - subgraphURL: `${gatewaySubgraph}/ethereum`, - // feeCode: 0, // this is ignored as Smardex uses dynamic fees + initCode: MAINNET_INIT_HASH, + subgraphURL: `${GATEWAY_SUBGRAPH}/ethereum`, }, [Network.ARBITRUM]: { factoryAddress: '0x41A00e3FbE7F479A99bA6822704d9c5dEB611F22', router: '0xdd4536dD9636564D891c919416880a3e250f975A', - initCode: layer2InitHash, - subgraphURL: `${gatewaySubgraph}/arbitrum`, - // feeCode: 0, // this is ignored as Smardex uses dynamic fees + initCode: LAYER2_INIT_HASH, + subgraphURL: `${GATEWAY_SUBGRAPH}/arbitrum`, }, [Network.BSC]: { factoryAddress: '0xA8EF6FEa013034E62E2C4A9Ec1CDb059fE23Af33', router: '0x391BeCc8DAaf32b9ba8e602e9527Bf9DA04C8deb', - initCode: layer2InitHash, - subgraphURL: `${gatewaySubgraph}/bsc`, - // feeCode: 0, // this is ignored as Smardex uses dynamic fees + initCode: LAYER2_INIT_HASH, + subgraphURL: `${GATEWAY_SUBGRAPH}/bsc`, }, [Network.POLYGON]: { factoryAddress: '0x9A1e1681f6D59Ca051776410465AfAda6384398f', router: '0xA8EF6FEa013034E62E2C4A9Ec1CDb059fE23Af33', - initCode: layer2InitHash, - subgraphURL: `${gatewaySubgraph}/polygon`, - // feeCode: 0, // this is ignored as Smardex uses dynamic fees + initCode: LAYER2_INIT_HASH, + subgraphURL: `${GATEWAY_SUBGRAPH}/polygon`, }, [Network.BASE]: { factoryAddress: '0xdd4536dD9636564D891c919416880a3e250f975A', router: '0x5C622Dcc96b6D96ac6c154f99CF081815094CBC9', - initCode: layer2InitHash, - subgraphURL: `${gatewaySubgraph}/base`, - // feeCode: 0, // this is ignored as Smardex uses dynamic fees + initCode: LAYER2_INIT_HASH, + subgraphURL: `${GATEWAY_SUBGRAPH}/base`, }, }, }; diff --git a/src/dex/smardex/constants.ts b/src/dex/smardex/constants.ts index ddfcf015d..95e39fa31 100644 --- a/src/dex/smardex/constants.ts +++ b/src/dex/smardex/constants.ts @@ -1,4 +1,6 @@ // event Sync (uint256 reserve0, uint256 reserve1, uint256 fictiveReserve0, uint256 fictiveReserve1, uint256 priceAverage0, uint256 priceAverage1) +import { SmardexFees } from './types'; + export enum TOPICS { SYNC_EVENT = '0x2a368c7f33bb86e2d999940a3989d849031aff29b750f67947e6b8e8c3d2ffd6', SWAP_EVENT = '0xa4228e1eb11eb9b31069d9ed20e7af9a010ca1a02d4855cee54e08e188fcc32c', @@ -27,3 +29,8 @@ export const directSmardexFunctionName = [ export const SUBGRAPH_TIMEOUT = 20 * 1000; export const DefaultSmardexPoolGasCost = 130 * 1000; + +export const FEES_LAYER_ONE: SmardexFees = { + feesLP: 500n, + feesPool: 200n, +}; diff --git a/src/dex/smardex/smardex-event-pool.ts b/src/dex/smardex/smardex-event-pool.ts new file mode 100644 index 000000000..3b02b45b2 --- /dev/null +++ b/src/dex/smardex/smardex-event-pool.ts @@ -0,0 +1,185 @@ +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { SmardexFees, SmardexPoolState } from './types'; +import { AbiCoder, Interface } from '@ethersproject/abi'; +import { IDexHelper } from '../../dex-helper'; +import { Address, Log, Logger, Token } from '../../types'; +import { DeepReadonly } from 'ts-essentials'; +import { FEES_LAYER_ONE, TOPICS } from './constants'; + +const coder = new AbiCoder(); + +export class SmardexEventPool extends StatefulEventSubscriber { + constructor( + protected poolInterface: Interface, + protected dexHelper: IDexHelper, + public poolAddress: Address, + token0: Token, + token1: Token, + logger: Logger, + protected smardexFeesMultiCallEntry?: { + target: string; + callData: string; + }, + protected smardexFeesMulticallDecoder?: (values: any[]) => SmardexFees, + private isLayerOne = true, + ) { + super( + 'Smardex', + (token0.symbol || token0.address) + + '-' + + (token1.symbol || token1.address) + + ' pool', + dexHelper, + logger, + ); + } + + async fetchPairFeesAndLastTimestamp(blockNumber: number): Promise<{ + feesLP: bigint; + feesPool: bigint; + priceAverageLastTimestamp: number; + }> { + let calldata = [ + { + target: this.poolAddress, + callData: this.poolInterface.encodeFunctionData('getPriceAverage', []), + }, + ]; + if (!this.isLayerOne) { + calldata.push(this.smardexFeesMultiCallEntry!); + } + + const data: { returnData: any[] } = + await this.dexHelper.multiContract.methods + .aggregate(calldata) + .call({}, blockNumber); + + const priceAverageLastTimestamp = coder.decode( + ['uint256', 'uint256', 'uint256'], + data.returnData[0], + )[2]; + + const fees = this.isLayerOne + ? FEES_LAYER_ONE + : this.smardexFeesMulticallDecoder!(data.returnData[1]); + return { + feesLP: fees.feesLP, + feesPool: fees.feesPool, + priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), + }; + } + + // This methode overrides previous state with new state. + // Problem: Smardex Pair state is updated partially on different events + // This is why we must fetch pair's missing state in Events + protected async processLog( + state: DeepReadonly, + log: Readonly, + ): Promise | null> { + if (!Object.values(TOPICS).includes(log.topics[0] as TOPICS)) return null; + const event = this.poolInterface.parseLog(log); + switch (event.name) { + case 'Sync': + const fetchedSync = await this.fetchPairFeesAndLastTimestamp( + log.blockNumber, + ); + return { + reserves0: event.args.reserve0.toString(), + reserves1: event.args.reserve1.toString(), + fictiveReserves0: event.args.fictiveReserve0.toString(), + fictiveReserves1: event.args.fictiveReserve1.toString(), + priceAverage0: event.args.priceAverage0.toString(), + priceAverage1: event.args.priceAverage1.toString(), + priceAverageLastTimestamp: fetchedSync.priceAverageLastTimestamp, + feesLP: fetchedSync.feesLP, + feesPool: fetchedSync.feesPool, + }; + case 'FeesChanged': // only triggerd on L2 + return { + reserves0: state.reserves0, + reserves1: state.reserves1, + fictiveReserves0: state.fictiveReserves0, + fictiveReserves1: state.fictiveReserves1, + priceAverage0: state.priceAverage0, + priceAverage1: state.priceAverage1, + priceAverageLastTimestamp: state.priceAverageLastTimestamp, + feesLP: BigInt(event.args.feesLP), + feesPool: BigInt(event.args.feesPool), + }; + // case 'Swap': + // const fetchedSwap = await this.fetchPairFeesAndLastTimestamp(log.blockNumber); + // return { + // reserves0: state.reserves0, + // reserves1: state.reserves1, + // fictiveReserves0: state.fictiveReserves0, + // fictiveReserves1: state.fictiveReserves1, + // priceAverage0: state.priceAverage0, + // priceAverage1: state.priceAverage1, + // priceAverageLastTimestamp: fetchedSwap.priceAverageLastTimestamp, + // feesLP: fetchedSwap.feesLP, + // feesPool: fetchedSwap.feesPool, + // }; + } + return null; + } + + async generateState( + blockNumber: number | 'latest' = 'latest', + ): Promise> { + const coder = new AbiCoder(); + let calldata = [ + { + target: this.poolAddress, + callData: this.poolInterface.encodeFunctionData('getReserves', []), + }, + { + target: this.poolAddress, + callData: this.poolInterface.encodeFunctionData( + 'getFictiveReserves', + [], + ), + }, + { + target: this.poolAddress, + callData: this.poolInterface.encodeFunctionData('getPriceAverage', []), + }, + ]; + if (!this.isLayerOne) { + calldata.push(this.smardexFeesMultiCallEntry!); + } + + const data: { returnData: any[] } = + await this.dexHelper.multiContract.methods + .aggregate(calldata) + .call({}, blockNumber); + + const [reserves0, reserves1] = coder.decode( + ['uint256', 'uint256'], + data.returnData[0], + ); + + const [fictiveReserve0, fictiveReserve1] = coder.decode( + ['uint256', 'uint256'], + data.returnData[1], + ); + + const [priceAverage0, priceAverage1, priceAverageLastTimestamp] = + coder.decode(['uint256', 'uint256', 'uint256'], data.returnData[2]); + + const fees = this.isLayerOne + ? FEES_LAYER_ONE + : this.smardexFeesMulticallDecoder!(data.returnData[3]); + + return { + reserves0: reserves0.toString(), + reserves1: reserves1.toString(), + fictiveReserves0: fictiveReserve0.toString(), + fictiveReserves1: fictiveReserve1.toString(), + priceAverage0: priceAverage0.toString(), + priceAverage1: priceAverage1.toString(), + priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), + feesLP: fees.feesLP, + feesPool: fees.feesPool, + }; + } +} diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 4c511119a..181ef88d9 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -1,7 +1,6 @@ import { AbiCoder, Interface } from '@ethersproject/abi'; -import _ from 'lodash'; -import { DeepReadonly } from 'ts-essentials'; import { Contract } from 'web3-eth-contract'; +import _ from 'lodash'; import { DEST_TOKEN_PARASWAP_TRANSFERS, ETHER_ADDRESS, @@ -14,7 +13,6 @@ import { AdapterExchangeParam, Address, ExchangePrices, - Log, Logger, NumberAsString, PoolLiquidity, @@ -35,214 +33,31 @@ import { import { getBigIntPow, getDexKeysWithNetwork, isETHAddress } from '../../utils'; import SmardexFactoryLayerOneABI from '../../abi/smardex/layer-1/smardex-factory.json'; import SmardexFactoryLayerTwoABI from '../../abi/smardex/layer-2/smardex-factory.json'; -import SmardexPoolLayerOneABI from '../../abi/smardex/layer-1/smardex-pool.json'; -import SmardexPoolLayerTwoABI from '../../abi/smardex/layer-2/smardex-pool.json'; + import SmardexRouterABI from '../../abi/smardex/all/smardex-router.json'; import { SimpleExchange } from '../simple-exchange'; import { SmardexRouterFunctions, directSmardexFunctionName, - TOPICS, DefaultSmardexPoolGasCost, - SUBGRAPH_TIMEOUT, + SUBGRAPH_TIMEOUT, FEES_LAYER_ONE, } from '../smardex/constants'; import { SmardexData, SmardexParam } from '../smardex/types'; -import { IDex, StatefulEventSubscriber } from '../..'; +import { IDex } from '../..'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { Adapters, SmardexConfig } from './config'; import ParaSwapABI from '../../abi/IParaswap.json'; import { applyTransferFee } from '../../lib/token-transfer-fee'; import { computeAmountIn, computeAmountOut } from './sdk/core'; +import { SmardexEventPool } from './smardex-event-pool'; +import SmardexPoolLayerOneABI from '../../abi/smardex/layer-1/smardex-pool.json'; +import SmardexPoolLayerTwoABI from '../../abi/smardex/layer-2/smardex-pool.json'; const smardexPoolL1 = new Interface(SmardexPoolLayerOneABI); const smardexPoolL2 = new Interface(SmardexPoolLayerTwoABI); -// On layer 1, the fees are not upgradable -const feesLayerOne: SmardexFees = { - feesLP: 500n, - feesPool: 200n, -}; - const coder = new AbiCoder(); -export class SmardexEventPool extends StatefulEventSubscriber { - constructor( - protected poolInterface: Interface, - protected dexHelper: IDexHelper, - public poolAddress: Address, - token0: Token, - token1: Token, - logger: Logger, - protected smardexFeesMultiCallEntry?: { - target: string; - callData: string; - }, - protected smardexFeesMulticallDecoder?: (values: any[]) => SmardexFees, - private isLayerOne = true, - ) { - super( - 'Smardex', - (token0.symbol || token0.address) + - '-' + - (token1.symbol || token1.address) + - ' pool', - dexHelper, - logger, - ); - } - - async fetchPairFeesAndLastTimestamp(blockNumber: number): Promise<{ - feesLP: bigint; - feesPool: bigint; - priceAverageLastTimestamp: number; - }> { - let calldata = [ - { - target: this.poolAddress, - callData: this.poolInterface.encodeFunctionData('getPriceAverage', []), - }, - ]; - if (!this.isLayerOne) { - calldata.push(this.smardexFeesMultiCallEntry!); - } - - const data: { returnData: any[] } = - await this.dexHelper.multiContract.methods - .aggregate(calldata) - .call({}, blockNumber); - - const priceAverageLastTimestamp = coder.decode( - ['uint256', 'uint256', 'uint256'], - data.returnData[0], - )[2]; - - const fees = this.isLayerOne - ? feesLayerOne - : this.smardexFeesMulticallDecoder!(data.returnData[1]); - return { - feesLP: fees.feesLP, - feesPool: fees.feesPool, - priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), - }; - } - - // This methode overrides previous state with new state. - // Problem: Smardex Pair state is updated partially on different events - // This is why we must fetch pair's missing state in Events - protected async processLog( - state: DeepReadonly, - log: Readonly, - ): Promise | null> { - if (!Object.values(TOPICS).includes(log.topics[0] as TOPICS)) return null; - const event = this.isLayerOne - ? smardexPoolL1.parseLog(log) - : smardexPoolL2.parseLog(log); - switch (event.name) { - case 'Sync': - const fetchedSync = await this.fetchPairFeesAndLastTimestamp( - log.blockNumber, - ); - return { - reserves0: event.args.reserve0.toString(), - reserves1: event.args.reserve1.toString(), - fictiveReserves0: event.args.fictiveReserve0.toString(), - fictiveReserves1: event.args.fictiveReserve1.toString(), - priceAverage0: event.args.priceAverage0.toString(), - priceAverage1: event.args.priceAverage1.toString(), - priceAverageLastTimestamp: fetchedSync.priceAverageLastTimestamp, - feesLP: fetchedSync.feesLP, - feesPool: fetchedSync.feesPool, - }; - case 'FeesChanged': // only triggerd on L2 - return { - reserves0: state.reserves0, - reserves1: state.reserves1, - fictiveReserves0: state.fictiveReserves0, - fictiveReserves1: state.fictiveReserves1, - priceAverage0: state.priceAverage0, - priceAverage1: state.priceAverage1, - priceAverageLastTimestamp: state.priceAverageLastTimestamp, - feesLP: BigInt(event.args.feesLP), - feesPool: BigInt(event.args.feesPool), - }; - // case 'Swap': - // const fetchedSwap = await this.fetchPairFeesAndLastTimestamp(log.blockNumber); - // return { - // reserves0: state.reserves0, - // reserves1: state.reserves1, - // fictiveReserves0: state.fictiveReserves0, - // fictiveReserves1: state.fictiveReserves1, - // priceAverage0: state.priceAverage0, - // priceAverage1: state.priceAverage1, - // priceAverageLastTimestamp: fetchedSwap.priceAverageLastTimestamp, - // feesLP: fetchedSwap.feesLP, - // feesPool: fetchedSwap.feesPool, - // }; - } - return null; - } - - async generateState( - blockNumber: number | 'latest' = 'latest', - ): Promise> { - const coder = new AbiCoder(); - let calldata = [ - { - target: this.poolAddress, - callData: this.poolInterface.encodeFunctionData('getReserves', []), - }, - { - target: this.poolAddress, - callData: this.poolInterface.encodeFunctionData( - 'getFictiveReserves', - [], - ), - }, - { - target: this.poolAddress, - callData: this.poolInterface.encodeFunctionData('getPriceAverage', []), - }, - ]; - if (!this.isLayerOne) { - calldata.push(this.smardexFeesMultiCallEntry!); - } - - const data: { returnData: any[] } = - await this.dexHelper.multiContract.methods - .aggregate(calldata) - .call({}, blockNumber); - - const [reserves0, reserves1] = coder.decode( - ['uint256', 'uint256'], - data.returnData[0], - ); - - const [fictiveReserve0, fictiveReserve1] = coder.decode( - ['uint256', 'uint256'], - data.returnData[1], - ); - - const [priceAverage0, priceAverage1, priceAverageLastTimestamp] = - coder.decode(['uint256', 'uint256', 'uint256'], data.returnData[2]); - - const fees = this.isLayerOne - ? feesLayerOne - : this.smardexFeesMulticallDecoder!(data.returnData[3]); - - return { - reserves0: reserves0.toString(), - reserves1: reserves1.toString(), - fictiveReserves0: fictiveReserve0.toString(), - fictiveReserves1: fictiveReserve1.toString(), - priceAverage0: priceAverage0.toString(), - priceAverage1: priceAverage1.toString(), - priceAverageLastTimestamp: priceAverageLastTimestamp.toNumber(), - feesLP: fees.feesLP, - feesPool: fees.feesPool, - }; - } -} - function encodePools( pools: SmardexPool[], // feeFactor: number, @@ -738,10 +553,10 @@ export class Smardex .decode(['uint256', 'uint256', 'uint256'], returnData[i][2])[2] .toString(), feesLP: this.isLayer1() - ? feesLayerOne.feesLP + ? FEES_LAYER_ONE.feesLP : multiCallFeeData[i]!.callDecoder(returnData[i][3]).feesLP, feesPool: this.isLayer1() - ? feesLayerOne.feesPool + ? FEES_LAYER_ONE.feesPool : multiCallFeeData[i]!.callDecoder(returnData[i][3]).feesPool, })); } catch (e) { diff --git a/src/dex/smardex/types.ts b/src/dex/smardex/types.ts index fe80b80d2..a64dadda0 100644 --- a/src/dex/smardex/types.ts +++ b/src/dex/smardex/types.ts @@ -5,7 +5,7 @@ import { UniswapPool, } from '../uniswap-v2/types'; import { UniswapV2Pair } from '../uniswap-v2/uniswap-v2'; -import { type SmardexEventPool } from './smardex'; +import { SmardexEventPool } from './smardex-event-pool'; export interface SmardexPoolState extends SmardexFees { reserves0: string; From 76817f1155ceee194c7342e15c003f48446713ca Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 10 Oct 2023 16:44:07 +0300 Subject: [PATCH 472/833] get tsconfig back to original state --- scripts/dex-integration.ts | 2 +- tsconfig.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/dex-integration.ts b/scripts/dex-integration.ts index ad04f3b19..e3487e690 100644 --- a/scripts/dex-integration.ts +++ b/scripts/dex-integration.ts @@ -116,7 +116,7 @@ function testIntegration(argv: IOptions) { process.env.NODE_ENV = 'test'; } - require('../node_modules/jest-cli/build').run( + require('../node_modules/jest-cli/build/cli').run( `src\/dex\/${dexNameParam}\/.+\.test\.ts`, ); } diff --git a/tsconfig.json b/tsconfig.json index 1511b7216..6318f0667 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,7 @@ "module": "commonjs", "noImplicitAny": true, "outDir": "build", - // "rootDir": "src", + "rootDir": "src", "preserveConstEnums": true, "strictNullChecks": true, "strict": true, From b2079b195bd086c29b9a71a589d201fda75164c1 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 10 Oct 2023 16:51:45 +0300 Subject: [PATCH 473/833] move subgraph api key to config --- src/config.ts | 7 +++++++ src/dex/smardex/smardex.ts | 3 +-- src/types.ts | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index 2273e572a..1d9ddc1e5 100644 --- a/src/config.ts +++ b/src/config.ts @@ -30,6 +30,7 @@ type BaseConfig = { hashFlowAuthToken?: string; hashFlowDisabledMMs: string[]; swaapV2AuthToken?: string; + smardexSubgraphAuthToken?: string; forceRpcFallbackDexs: string[]; }; @@ -58,6 +59,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { '0xF9234CB08edb93c0d4a4d4c70cC3FfD070e78e07', rpcPollingMaxAllowedStateDelayInBlocks: 0, rpcPollingBlocksBackToTriggerUpdate: 0, + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', swaapV2AuthToken: process.env.API_KEY_SWAAP_V2_AUTH_TOKEN || '', hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', hashFlowDisabledMMs: @@ -158,6 +160,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { tokenTransferProxyAddress: '0x216b4b4ba9f3e719726886d34a177484278bfcae', multicallV2Address: '0xC50F4c1E81c873B2204D7eFf7069Ffec6Fbe136D', privateHttpProvider: process.env.HTTP_PROVIDER_56, + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_56`]?.split(',') || [], @@ -186,6 +189,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { tokenTransferProxyAddress: '0x216b4b4ba9f3e719726886d34a177484278bfcae', multicallV2Address: '0x275617327c958bD06b5D6b871E7f491D76113dd8', privateHttpProvider: process.env.HTTP_PROVIDER_137, + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_137`]?.split(',') || [], @@ -272,6 +276,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { tokenTransferProxyAddress: '0x216b4b4ba9f3e719726886d34a177484278bfcae', multicallV2Address: '0x7eCfBaa8742fDf5756DAC92fbc8b90a19b8815bF', privateHttpProvider: process.env.HTTP_PROVIDER_42161, + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], @@ -358,6 +363,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { augustusRFQAddress: '0xa003dFBA51C9e1e56C67ae445b852bdEd7aC5EEd', tokenTransferProxyAddress: '0x93aAAe79a53759cD164340E4C8766E4Db5331cD7', multicallV2Address: '0xeDF6D2a16e8081F777eB623EeB4411466556aF3d', + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', privateHttpProvider: process.env.HTTP_PROVIDER_8453, hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', hashFlowDisabledMMs: [], @@ -415,6 +421,7 @@ export function generateConfig(network: number): Config { hashFlowAuthToken: baseConfig.hashFlowAuthToken, swaapV2AuthToken: baseConfig.swaapV2AuthToken, hashFlowDisabledMMs: baseConfig.hashFlowDisabledMMs, + smardexSubgraphAuthToken: baseConfig.smardexSubgraphAuthToken, forceRpcFallbackDexs: baseConfig.forceRpcFallbackDexs, }; } diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 181ef88d9..314d4cafd 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -76,7 +76,6 @@ export class Smardex implements IDex { pairs: { [key: string]: SmardexPair } = {}; - // feeFactor = 10000; factory: Contract; routerInterface: Interface; @@ -805,7 +804,7 @@ export class Smardex variables: { token: tokenAddress.toLowerCase(), limit }, }, SUBGRAPH_TIMEOUT, - { 'x-api-key': process.env.API_KEY_SMARDEX_SUBGRAPH! }, + { 'x-api-key': this.dexHelper.config.data.smardexSubgraphAuthToken! }, ); if (!(data && data.pools0 && data.pools1)) diff --git a/src/types.ts b/src/types.ts index 922247bd6..612ad2933 100644 --- a/src/types.ts +++ b/src/types.ts @@ -276,6 +276,7 @@ export type Config = { hashFlowDisabledMMs: string[]; uniswapV3EventLoggingSampleRate?: number; swaapV2AuthToken?: string; + smardexSubgraphAuthToken?: string, forceRpcFallbackDexs: string[]; }; From ebc55da28fd69265742d4abe517073efe629926b Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 10 Oct 2023 21:19:11 +0300 Subject: [PATCH 474/833] 2.37.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7e58a27be..2d306b41d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.4", + "version": "2.37.5", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 20dfaf16b18c84cee3ff6dc065a151577d0dbd5f Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 10 Oct 2023 21:18:18 +0200 Subject: [PATCH 475/833] add baseswap (univ2 fork) config --- src/dex/uniswap-v2/config.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/dex/uniswap-v2/config.ts b/src/dex/uniswap-v2/config.ts index 34fb93bc6..9845fc2ec 100644 --- a/src/dex/uniswap-v2/config.ts +++ b/src/dex/uniswap-v2/config.ts @@ -117,6 +117,20 @@ export const Adapters: { }, ], }, + [Network.BASE]: { + [SwapSide.SELL]: [ + { + name: 'BaseAdapter01', + index: 6, + }, + ], + [SwapSide.BUY]: [ + { + name: 'BaseBuyAdapter', + index: 4, + }, + ], + }, }; export const UniswapV2Config: DexConfigMap = { @@ -696,4 +710,13 @@ export const UniswapV2Config: DexConfigMap = { feeCode: 30, }, }, + BaseSwap: { + [Network.BASE]: { + factoryAddress: '0xFDa619b6d20975be80A10332cD39b9a4b0FAa8BB', + initCode: + '0xb618a2730fae167f5f8ac7bd659dd8436d571872655bcb6fd11f2158c8a64a3b', + poolGasCost: 90 * 1000, + feeCode: 25, + }, + }, }; From 8a084886d8ddfb2bfbe2ffe08b2a338796f90199 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 10 Oct 2023 21:19:40 +0200 Subject: [PATCH 476/833] 2.37.6-baseswap.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2d306b41d..cd557a637 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.5", + "version": "2.37.6-baseswap.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 444b16e4c02c08b05afa9014c98a85f0715012b0 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 11 Oct 2023 18:20:04 +0300 Subject: [PATCH 477/833] refactored e2e tests --- src/dex/smardex/config.ts | 24 +- src/dex/smardex/smardex-e2e.test.ts | 417 +++++++++++++--------------- src/dex/smardex/smardex.ts | 3 +- 3 files changed, 209 insertions(+), 235 deletions(-) diff --git a/src/dex/smardex/config.ts b/src/dex/smardex/config.ts index b545ff3a5..f6aa9e127 100644 --- a/src/dex/smardex/config.ts +++ b/src/dex/smardex/config.ts @@ -1,6 +1,6 @@ import { DexParams } from './types'; import { DexConfigMap, AdapterMappings } from '../../types'; -import { Network } from '../../constants'; +import { Network, SwapSide } from '../../constants'; const GATEWAY_SUBGRAPH = 'https://subgraph.smardex.io'; const MAINNET_INIT_HASH = @@ -44,6 +44,24 @@ export const SmardexConfig: DexConfigMap = { }; export const Adapters: Record = { - // This is an example - // [Network.MAINNET]: { [SwapSide.SELL]: [{ name: '', index: 0 }] }, + [Network.MAINNET]: { + [SwapSide.SELL]: [{ name: '', index: 0 }], + [SwapSide.BUY]: [{ name: '', index: 0 }], + }, + [Network.ARBITRUM]: { + [SwapSide.SELL]: [{ name: '', index: 0 }], + [SwapSide.BUY]: [{ name: '', index: 0 }], + }, + [Network.BSC]: { + [SwapSide.SELL]: [{ name: '', index: 0 }], + [SwapSide.BUY]: [{ name: '', index: 0 }], + }, + [Network.POLYGON]: { + [SwapSide.SELL]: [{ name: '', index: 0 }], + [SwapSide.BUY]: [{ name: '', index: 0 }], + }, + [Network.BASE]: { + [SwapSide.SELL]: [{ name: '', index: 0 }], + [SwapSide.BUY]: [{ name: '', index: 0 }], + }, }; diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index c88282958..c486da5d1 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -7,345 +7,300 @@ import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; -interface SmardexE2ePairToken { - name: string; - sellAmount: string; - buyAmount: string; -} -type SmardexE2ePair = SmardexE2ePairToken[]; -describe('Smardex E2E', () => { - // Generate pairs for each network twice: each time with small and big swap amount (x10) - const allPairs: { [key: number]: SmardexE2ePair[] } = { - [Network.MAINNET]: [ +function testForNetwork( + network: Network, + dexKey: string, + pairs: { name: string; sellAmount: string; buyAmount: string }[][], +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, [ - { - name: 'ETH', - sellAmount: '2000000000000000000', // 2 ETH - buyAmount: '300000000000000000000000', // 300K SDEX - }, - { - name: 'SDEX', - sellAmount: '300000000000000000000000', // 300K SDEX - buyAmount: '2000000000000000000', // 2 ETH - }, + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, ], + ], + [ + SwapSide.BUY, [ - { - name: 'WETH', - sellAmount: '1500000000000000000', // 1.5 WETH - buyAmount: '250000000000000000000000', // 250K SDEX - }, - { - name: 'SDEX', - sellAmount: '250000000000000000000000', // 250K SDEX - buyAmount: '1500000000000000000', // 1.5 WETH - }, + ContractMethod.simpleBuy, + // ContractMethod.buy, ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }); + }), + ); +} + +describe('SmarDex E2E', () => { + const dexKey = 'SmarDex'; + + describe('MAINNET', () => { + const network = Network.MAINNET; + + const pairs = [ [ { name: 'USDT', - sellAmount: '1200000000', // 1200 USDT - buyAmount: '300000000000000000000000', // 300K SDEX + sellAmount: '1200000000', + buyAmount: '120000', }, { name: 'SDEX', - sellAmount: '300000000000000000000000', // 300K SDEX - buyAmount: '1200000000', // 1200 USDT - }, - ], - [ - { - name: 'WBTC', - sellAmount: '30000000', // 0.3 WBTC - buyAmount: '2500000000000000000', // 2.5 WETH - }, - { - name: 'WETH', - sellAmount: '2500000000000000000', // 2.5 WETH - buyAmount: '30000000', // 0.3 WBTC + sellAmount: '300000000000000000000000', + buyAmount: '30000000000', }, ], - ] - .map((pair, i, arr) => [ - [pair], - [ - arr[i].map(token => ({ - ...token, - sellAmount: token.sellAmount + '0', - buyAmount: token.buyAmount + '0', - })), - ], - ]) - .flat(2), - [Network.ARBITRUM]: [ [ { - name: 'WETH', - sellAmount: '1500000000000000000', // 1.5 WETH - buyAmount: '250000000000000000000000', // 250K SDEX + name: 'USDT', + sellAmount: '1200000000', + buyAmount: '1200000000', }, { - name: 'SDEX', - sellAmount: '250000000000000000000000', // 250K SDEX - buyAmount: '1500000000000000000', // 1.5 WETH + name: 'ETH', + sellAmount: '11000000000000000', + buyAmount: '1100000000', }, ], + ]; + + testForNetwork( + network, + dexKey, + pairs, + ); + }); + + describe('ARBITRUM', () => { + const network = Network.ARBITRUM; + + const pairs = [ [ { name: 'USDC', - sellAmount: '1200000000', // 1200 USDC - buyAmount: '300000000000000000000000', // 300K SDEX + sellAmount: '1200000000', + buyAmount: '120000', }, { name: 'SDEX', - sellAmount: '300000000000000000000000', // 300K SDEX - buyAmount: '1200000000', // 1200 USDC + sellAmount: '300000000000000000000000', + buyAmount: '30000000000', }, ], [ { - name: 'WBTC', - sellAmount: '5000000', // 0.05 WBTC - buyAmount: '31000000000000000000000', // 31K SDEX + name: 'SDEX', + sellAmount: '300000000000000000000000', + buyAmount: '11000000000000000', }, { - name: 'SDEX', - sellAmount: '31000000000000000000000', // 31K SDEX - buyAmount: '5000000', // 0.05 WBTC + name: 'ETH', + sellAmount: '11000000000000000', + buyAmount: '11000000', }, ], - ] - .map((pair, i, arr) => [ - [pair], - [ - arr[i].map(token => ({ - ...token, - sellAmount: token.sellAmount + '0', - buyAmount: token.buyAmount + '0', - })), - ], - ]) - .flat(2), - [Network.BSC]: [ + ]; + + testForNetwork( + network, + dexKey, + pairs + ); + }); + + describe('BSC', () => { + const network = Network.BSC; + + const pairs = [ [ { name: 'USDT', - sellAmount: '1200000000000000000000', // 1200 USDT - buyAmount: '300000000000000000000000', // 300K SDEX + sellAmount: '1200000000000000000000', + buyAmount: '300000000000000000000000', }, { name: 'SDEX', - sellAmount: '300000000000000000000000', // 300K SDEX - buyAmount: '120000000000000000000', // 1200 USDT + sellAmount: '300000000000000000000000', + buyAmount: '120000000000000000000', }, ], [ { name: 'SDEX', - sellAmount: '300000000000000000000000', // 300K SDEX - buyAmount: '50000000000000000', // 0.05 bBTC + sellAmount: '300000000000000000000000', + buyAmount: '50000000000000000', }, { name: 'bBTC', - sellAmount: '50000000000000000', // 0.05 bBTC - buyAmount: '300000000000000000000000', // 300K SDEX + sellAmount: '50000000000000000', + buyAmount: '300000000000000000000000', }, ], [ { name: 'USDT', - sellAmount: '1500000000000000000000', // 1500 USDT - buyAmount: '20000000000000000000', // 20 BNB + sellAmount: '1500000000000000000000', + buyAmount: '20000000000000000000', }, { name: 'BNB', - sellAmount: '20000000000000000000', // 20 BNB - buyAmount: '1500000000000000000000', // 1500 USDT + sellAmount: '20000000000000000000', + buyAmount: '1500000000000000000000', }, ], - ] - .map((pair, i, arr) => [ - [pair], - [ - arr[i].map(token => ({ - ...token, - sellAmount: token.sellAmount + '0', - buyAmount: token.buyAmount + '0', - })), - ], - ]) - .flat(2), - [Network.POLYGON]: [ + ]; + + testForNetwork( + network, + dexKey, + pairs + ); + }); + + describe('POLYGON', () => { + const network = Network.POLYGON; + + const pairs = [ [ { name: 'WETH', - sellAmount: '1500000000000000000', // 1.5 WETH - buyAmount: '250000000000000000000000', // 250K SDEX + sellAmount: '1500000000000000000', + buyAmount: '250000000000000000000000', }, { name: 'SDEX', - sellAmount: '250000000000000000000000', // 250K SDEX - buyAmount: '1500000000000000000', // 1.5 WETH + sellAmount: '250000000000000000000000', + buyAmount: '1500000000000000000', }, ], [ { name: 'USDC', - sellAmount: '2500000000', // 2500 USDC - buyAmount: '300000000000000000000000', // 300K SDEX + sellAmount: '2500000000', + buyAmount: '300000000000000000000000', }, { name: 'SDEX', - sellAmount: '300000000000000000000000', // 300K SDEX - buyAmount: '2500000000', // 2500 USDC + sellAmount: '300000000000000000000000', + buyAmount: '2500000000', }, ], [ { name: 'USDC', - sellAmount: '2500000000', // 2500 USDC - buyAmount: '8000000000000000000000', // 8000 MATIC + sellAmount: '2500000000', + buyAmount: '8000000000000000000000', }, { name: 'MATIC', - sellAmount: '8000000000000000000000', // 8000 MATIC - buyAmount: '2500000000', // 2500 USDC + sellAmount: '8000000000000000000000', + buyAmount: '2500000000', }, ], [ { name: 'SDEX', - sellAmount: '190000000000000000000000', // 190K SDEX - buyAmount: '8000000', // 0.08 WBTC + sellAmount: '190000000000000000000000', + buyAmount: '8000000', }, { name: 'WBTC', - sellAmount: '8000000', // 0.08 WBTC - buyAmount: '190000000000000000000000', // 190K SDEX + sellAmount: '8000000', + buyAmount: '190000000000000000000000', }, ], - ] - .map((pair, i, arr) => [ - [pair], - [ - arr[i].map(token => ({ - ...token, - sellAmount: token.sellAmount + '0', - buyAmount: token.buyAmount + '0', - })), - ], - ]) - .flat(2), + ]; + + testForNetwork( + network, + dexKey, + pairs, + ); + }); + + describe('BASE', () => { + const network = Network.BASE; - [Network.BASE]: [ + const pairs = [ [ { name: 'WETH', - sellAmount: '1500000000000000000', // 1.5 WETH - buyAmount: '2500000000', // 2.5k USDbC + sellAmount: '1500000000000000000', + buyAmount: '2500000000', }, { name: 'USDbC', - sellAmount: '2500000000', // 2.5k USDbC - buyAmount: '1500000000000000000', // 1.5 WETH + sellAmount: '2500000000', + buyAmount: '1500000000000000000', }, ], [ { name: 'WETH', - sellAmount: '1500000000000000000', // 1.5 WETH - buyAmount: '250000000000000000000000', // 250K SDEX + sellAmount: '1500000000000000000', + buyAmount: '250000000000000000000000', }, { name: 'SDEX', - sellAmount: '250000000000000000000000', // 250K SDEX - buyAmount: '1500000000000000000', // 1.5 WETH + sellAmount: '250000000000000000000000', + buyAmount: '1500000000000000000', }, ], - ] - .map((pair, i, arr) => [ - [pair], - [ - arr[i].map(token => ({ - ...token, - sellAmount: token.sellAmount + '0', - buyAmount: token.buyAmount + '0', - })), - ], - ]) - .flat(2), - }; + ]; - const networkKeys = [ - Network.MAINNET, - Network.ARBITRUM, - Network.BSC, - Network.POLYGON, - Network.BASE, - ]; - networkKeys.forEach(network => { - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, + testForNetwork( network, + dexKey, + pairs, ); - describe(`Smardex Swap on Chain ${network}`, () => { - const dexKey = 'Smardex'; - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - // ContractMethod.multiSwap, // TODO: uncomment when Adapter is ready to enable Multiswap - // ContractMethod.megaSwap, // TODO: uncomment when Adapter is ready to enable Megaswap - ], - ], - [SwapSide.BUY, [ContractMethod.simpleBuy]], - ]); - - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - contractMethods.forEach((contractMethod: ContractMethod) => { - allPairs[network].forEach(pair => { - describe(`${contractMethod}`, () => { - it(`${pair[0].name} -> ${pair[1].name}`, async () => { - await testE2E( - tokens[pair[0].name], - tokens[pair[1].name], - holders[pair[0].name], - side === SwapSide.SELL - ? pair[0].sellAmount - : pair[0].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${pair[1].name} -> ${pair[0].name}`, async () => { - await testE2E( - tokens[pair[1].name], - tokens[pair[0].name], - holders[pair[1].name], - side === SwapSide.SELL - ? pair[1].sellAmount - : pair[1].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }); - }); - }), - ); - }); }); }); diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 314d4cafd..2b50af0f4 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -101,6 +101,7 @@ export class Smardex protected network: Network, dexKey: string, public dexHelper: IDexHelper, + protected adapters = Adapters[network] || {}, ) { super(dexHelper, dexKey); this.logger = dexHelper.getLogger(dexKey); @@ -121,7 +122,7 @@ export class Smardex } getAdapters(side: SwapSide): { name: string; index: number }[] | null { - return Adapters[this.network]?.[side] || null; + return this.adapters[side] ? this.adapters[side] : null; } async getPoolIdentifiers( From 1b6d0466b9ad1c6a5c3225e17e91c5a3a4c1428a Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 11 Oct 2023 19:34:10 +0300 Subject: [PATCH 478/833] update getAdapterParam --- src/dex/smardex/smardex.ts | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 2b50af0f4..0c2d77453 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -678,27 +678,29 @@ export class Smardex }; } - // Encode params required by the exchange adapter - // Used for multiSwap & megaSwap - // Hint: abiCoder.encodeParameter() could be useful + getWETHAddress(srcToken: Address, destToken: Address, weth?: Address) { + if (!isETHAddress(srcToken) && !isETHAddress(destToken)) + return NULL_ADDRESS; + return weth || this.dexHelper.config.data.wrappedNativeTokenAddress; + } + getAdapterParam( srcToken: Address, destToken: Address, srcAmount: NumberAsString, - toAmount: NumberAsString, // required for buy case + toAmount: NumberAsString, data: SmardexData, side: SwapSide, ): AdapterExchangeParam { - const pools = encodePools(data.pools); - const weth = this.getWETHAddress(srcToken, destToken, data.wethAddress); const payload = this.abiCoder.encodeParameter( { ParentStruct: { - weth: 'address', - pools: 'uint256[]', + path: 'address[] calldata', + receiver: 'address', + deadline: 'uint256' }, }, - { pools, weth }, + { path: data.path, receiver: data.receiver, deadline: data.deadline }, ); return { targetExchange: data.router, @@ -707,12 +709,6 @@ export class Smardex }; } - getWETHAddress(srcToken: Address, destToken: Address, weth?: Address) { - if (!isETHAddress(srcToken) && !isETHAddress(destToken)) - return NULL_ADDRESS; - return weth || this.dexHelper.config.data.wrappedNativeTokenAddress; - } - async getSimpleParam( src: Address, dest: Address, From 271decdf1cd000ee6b681d7f65f0dfd12cbade39 Mon Sep 17 00:00:00 2001 From: Verisana Date: Wed, 11 Oct 2023 17:52:46 +0100 Subject: [PATCH 479/833] 2.28.9-take-surplus.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 049280ec1..e86e9e4f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.9-take-surplus.0", + "version": "2.28.9-take-surplus.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 5bdb1055647381a4b21d506de462c9143bad51f5 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 11 Oct 2023 20:43:04 +0300 Subject: [PATCH 480/833] get back adapters addresses --- src/config.ts | 4 ++-- src/dex/dexalot/dexalot.ts | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index 54f38de8f..60b254923 100644 --- a/src/config.ts +++ b/src/config.ts @@ -223,8 +223,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { dexalotAuthToken: process.env.API_KEY_DEXALOT_AUTH_TOKEN || '', adapterAddresses: { AvalancheAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9', - AvalancheAdapter02: '0x928eE214dB95eeD9241329F889320a21bcED6b65', - AvalancheBuyAdapter: '0x3d3131Ed7A6D4d6E765BC96D5cd416Cf2C2c075C', + AvalancheAdapter02: '0x2cdB0cDc2a9321ac2ED5b741828a5216C265Be80', + AvalancheBuyAdapter: '0x9Aa41A24A10af2a965A6D406b913a7Cd9C6886ea', }, uniswapV2ExchangeRouterAddress: '0x53e693c6C7FFC4446c53B205Cf513105Bf140D7b', diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index e69cedca0..d58c4fccf 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -761,6 +761,8 @@ export class Dexalot extends SimpleExchange implements IDex { quoteData.signature, ]; + console.log('PARAMS: ', params); + const payload = this.abiCoder.encodeParameter( { ParentStruct: { From 44e2392cbf729b70951c2a5d781d4811d7d0244a Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 11 Oct 2023 20:46:10 +0300 Subject: [PATCH 481/833] remove console.log --- src/dex/dexalot/dexalot.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index d58c4fccf..e69cedca0 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -761,8 +761,6 @@ export class Dexalot extends SimpleExchange implements IDex { quoteData.signature, ]; - console.log('PARAMS: ', params); - const payload = this.abiCoder.encodeParameter( { ParentStruct: { From 7df586e574dcc2b9c8bbc54d15b0b84db4256e96 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 11 Oct 2023 20:47:18 +0300 Subject: [PATCH 482/833] 2.37.6-dexalot --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a9759d3d7..608866e06 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.5-dexalot", + "version": "2.37.6-dexalot", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e34b89247f41634fda0a21886fcbe8fc84b5f89d Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 12 Oct 2023 12:43:44 +0100 Subject: [PATCH 483/833] chore: set latest published version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e86e9e4f3..2d306b41d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.28.9-take-surplus.1", + "version": "2.37.5", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 68121779e364a3707f7517928dda27d55ce586df Mon Sep 17 00:00:00 2001 From: Verisana Date: Thu, 12 Oct 2023 12:44:18 +0100 Subject: [PATCH 484/833] 2.37.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2d306b41d..18e036cee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.5", + "version": "2.37.6", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 02bc9deb758b2ea54c06a6d6b101f14d4dd6175c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 12 Oct 2023 14:57:10 +0300 Subject: [PATCH 485/833] 2.37.7-dexalot --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 608866e06..d36e13271 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.6-dexalot", + "version": "2.37.7-dexalot", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From aedd038c47958185061aa2474b72061e269144ec Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 13 Oct 2023 10:51:59 +0200 Subject: [PATCH 486/833] 2.37.7-baseswap.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 18e036cee..e8138020a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.6", + "version": "2.37.7-baseswap.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From c915bd66e5e14759de1f048244eb052d1e946078 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 13 Oct 2023 16:11:19 +0100 Subject: [PATCH 487/833] fix: update price feed contract --- src/dex/gmx/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/gmx/config.ts b/src/dex/gmx/config.ts index 5ae6f1a9d..3822ee464 100644 --- a/src/dex/gmx/config.ts +++ b/src/dex/gmx/config.ts @@ -15,7 +15,7 @@ export const GMXConfig: DexConfigMap = { [Network.ARBITRUM]: { vault: '0x489ee077994B6658eAfA855C308275EAd8097C4A', reader: '0x22199a49A999c351eF7927602CFB187ec3cae489', - priceFeed: '0xfe661cbf27da0656b7a1151a761ff194849c387a', + priceFeed: '0x2d68011bca022ed0e474264145f46cc4de96a002', fastPriceFeed: '0x8960d1b45a2d15d063b84b34dfb2fb2ca7535527', fastPriceEvents: '0x4530b7de1958270a2376be192a24175d795e1b07', usdg: '0x45096e7aA921f27590f8F19e457794EB09678141', From be59064ad2fc8dac31f6426698812219a2f433e3 Mon Sep 17 00:00:00 2001 From: Verisana Date: Fri, 13 Oct 2023 16:14:06 +0100 Subject: [PATCH 488/833] 2.37.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 18e036cee..be9da36b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.6", + "version": "2.37.7", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 12e598a27caeb0e464bd8988a62c9990d4fd653b Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 13 Oct 2023 18:40:50 +0300 Subject: [PATCH 489/833] 2.37.8-dexalot --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d36e13271..4cc559c4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.7-dexalot", + "version": "2.37.8-dexalot", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e420372b7d8909b5432bcf69a3e6397771367e24 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 13 Oct 2023 19:09:08 +0200 Subject: [PATCH 490/833] 2.38.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e8138020a..edabbb490 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.7-baseswap.0", + "version": "2.38.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 09b790ab6c140106e664113c8edf64438be3cf25 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 13 Oct 2023 19:16:11 +0200 Subject: [PATCH 491/833] 2.38.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index be9da36b4..edabbb490 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.7", + "version": "2.38.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From bf79f1fd5221313528e6e3a80fadd0fa527c0a05 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 13 Oct 2023 19:17:32 +0200 Subject: [PATCH 492/833] 2.39.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index edabbb490..10c94025b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.38.0", + "version": "2.39.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From eb61a153db24b1d3e298f684307c89ce19252529 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Sat, 14 Oct 2023 10:06:33 +0300 Subject: [PATCH 493/833] 2.39.1-dexalot --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4cc559c4c..1dc272430 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.37.8-dexalot", + "version": "2.39.1-dexalot", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From ef764e5805009f692397c6bb44386bf5be8cd59e Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 16 Oct 2023 16:13:50 +0300 Subject: [PATCH 494/833] add new e2e test --- src/dex/dexalot/dexalot-e2e.test.ts | 73 +++++++++++++++++++---------- tests/constants-e2e.ts | 1 + 2 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/dex/dexalot/dexalot-e2e.test.ts b/src/dex/dexalot/dexalot-e2e.test.ts index d0ce438f5..4fe8aa9ba 100644 --- a/src/dex/dexalot/dexalot-e2e.test.ts +++ b/src/dex/dexalot/dexalot-e2e.test.ts @@ -29,18 +29,18 @@ function testForNetwork( const tokens = Tokens[network]; const holders = Holders[network]; const nativeTokenSymbol = NativeTokenSymbols[network]; - const sleepMs = 20000; + const sleepMs = 10000; const sideToContractMethods = new Map([ [SwapSide.SELL, [ ContractMethod.simpleSwap, - ContractMethod.megaSwap, - ContractMethod.multiSwap - ]], - [SwapSide.BUY, [ - ContractMethod.simpleBuy, - ContractMethod.buy + // ContractMethod.megaSwap, + // ContractMethod.multiSwap ]], + // [SwapSide.BUY, [ + // ContractMethod.simpleBuy, + // ContractMethod.buy + // ]], ]); describe(`${network}`, () => { @@ -67,24 +67,24 @@ function testForNetwork( 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, - ); - }); + // 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( @@ -189,4 +189,27 @@ describe('Dexalot E2E', () => { nativeTokenAmount, ); }); + + describe('BTC.b -> USDC', () => { + const network = Network.AVALANCHE; + + const tokenASymbol: string = 'BTCb'; + const tokenBSymbol: string = 'USDC'; + + const tokenAAmount: string = '30000000'; + // const tokenAAmount: string = '25000000'; + const tokenBAmount: string = '10000000'; + const nativeTokenAmount = '1000000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + true, + ); + }); }); diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 646f2fd9e..599e38882 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1088,6 +1088,7 @@ export const Holders: { nETH: '0xcf2ef00e75558512ae735679ea5df62ad2056786', avWETH: '0x92d78e32b990d10aeca0875dc5585f1a6f958179', YUSD: '0x6c1a5ef2acde1fd2fc68def440d2c1eb35bae24a', + BTCb: '0x84c06d3c27821d0136f66306f5028d43ceac268d', }, [Network.ARBITRUM]: { ARB: '0xb65edba80a3d81903ecd499c8eb9cf0e19096bd0', From ed5edd085aa59a685a0334a2fd594282cbbba19c Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Mon, 16 Oct 2023 15:28:47 +0100 Subject: [PATCH 495/833] fix: correct calculateOrderPrice logic at bounds --- src/dex/dexalot/dexalot.ts | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index e69cedca0..3d6a0be55 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -353,41 +353,41 @@ export class Dexalot extends SimpleExchange implements IDex { } } - let price, + let price = BigInt(0), amount = BigInt(0); - if (left === orderbook.length) { - price = BigInt( - ethers.utils - .parseUnits(orderbook[left - 1][0], baseToken.decimals) - .toString(), - ); - amount = qty; - } else if (amounts[i] === qty) { + if (amounts[i] === qty) { price = BigInt( ethers.utils .parseUnits(orderbook[left][0], baseToken.decimals) .toString(), ); amount = amounts[i]; - } else { + } else if (left < orderbook.length) { const lPrice = BigInt( ethers.utils - .parseUnits(orderbook[left][0], baseToken.decimals) + .parseUnits(orderbook[left - 1][0], baseToken.decimals) .toString(), ); const rPrice = BigInt( ethers.utils - .parseUnits(orderbook[left + 1][0], baseToken.decimals) + .parseUnits(orderbook[left][0], baseToken.decimals) + .toString(), + ); + let lQty = BigInt( + ethers.utils + .parseUnits(orderbook[left - 1][1], quoteToken.decimals) .toString(), ); - const lQty = qty; let rQty = BigInt( ethers.utils - .parseUnits(orderbook[left + 1][1], quoteToken.decimals) + .parseUnits(orderbook[left][1], quoteToken.decimals) .toString(), ); if (side === ClobSide.ASK) { - rQty = (rQty * rPrice) / BigInt(10 ** quoteToken.decimals); + lQty = (lQty * BigInt(10 ** (baseToken.decimals * 2))) / + (lPrice * BigInt(10 ** quoteToken.decimals)); + rQty = (rQty * BigInt(10 ** (baseToken.decimals * 2))) / + (rPrice * BigInt(10 ** quoteToken.decimals));; } price = lPrice + ((rPrice - lPrice) * (amt - lQty)) / (rQty - lQty); amount = amounts[i]; From d89b1179cba17e109d8f0ca4326583a708532623 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 16 Oct 2023 17:39:39 +0300 Subject: [PATCH 496/833] update tests --- src/dex/dexalot/dexalot-e2e.test.ts | 49 ++++++++++++++--------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/dex/dexalot/dexalot-e2e.test.ts b/src/dex/dexalot/dexalot-e2e.test.ts index 4fe8aa9ba..a5a3d86f8 100644 --- a/src/dex/dexalot/dexalot-e2e.test.ts +++ b/src/dex/dexalot/dexalot-e2e.test.ts @@ -34,13 +34,13 @@ function testForNetwork( const sideToContractMethods = new Map([ [SwapSide.SELL, [ ContractMethod.simpleSwap, - // ContractMethod.megaSwap, - // ContractMethod.multiSwap + ContractMethod.megaSwap, + ContractMethod.multiSwap + ]], + [SwapSide.BUY, [ + ContractMethod.simpleBuy, + ContractMethod.buy ]], - // [SwapSide.BUY, [ - // ContractMethod.simpleBuy, - // ContractMethod.buy - // ]], ]); describe(`${network}`, () => { @@ -67,24 +67,24 @@ function testForNetwork( 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, - // ); - // }); + 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( @@ -197,7 +197,6 @@ describe('Dexalot E2E', () => { const tokenBSymbol: string = 'USDC'; const tokenAAmount: string = '30000000'; - // const tokenAAmount: string = '25000000'; const tokenBAmount: string = '10000000'; const nativeTokenAmount = '1000000000000000000'; From a6b72ca3ee04e50f673206a26364d39c440d5b49 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 16 Oct 2023 17:40:19 +0300 Subject: [PATCH 497/833] 2.39.1-dexalot.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1dc272430..5f1ac7028 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.39.1-dexalot", + "version": "2.39.1-dexalot.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From ffe25235105b6f385f873bfc7799cb787f87d024 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 16 Oct 2023 18:38:29 +0300 Subject: [PATCH 498/833] remove semicolon --- src/dex/dexalot/dexalot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 3d6a0be55..b7204de06 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -387,7 +387,7 @@ export class Dexalot extends SimpleExchange implements IDex { lQty = (lQty * BigInt(10 ** (baseToken.decimals * 2))) / (lPrice * BigInt(10 ** quoteToken.decimals)); rQty = (rQty * BigInt(10 ** (baseToken.decimals * 2))) / - (rPrice * BigInt(10 ** quoteToken.decimals));; + (rPrice * BigInt(10 ** quoteToken.decimals)); } price = lPrice + ((rPrice - lPrice) * (amt - lQty)) / (rQty - lQty); amount = amounts[i]; From 36e736a6585d87fe5c7aeb49936a8f11d49331fd Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 17 Oct 2023 16:27:53 +0300 Subject: [PATCH 499/833] fix division by zero error --- src/dex/dexalot/dexalot-e2e.test.ts | 4 ++-- src/dex/dexalot/dexalot.ts | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/dex/dexalot/dexalot-e2e.test.ts b/src/dex/dexalot/dexalot-e2e.test.ts index a5a3d86f8..5834b71b7 100644 --- a/src/dex/dexalot/dexalot-e2e.test.ts +++ b/src/dex/dexalot/dexalot-e2e.test.ts @@ -196,8 +196,8 @@ describe('Dexalot E2E', () => { const tokenASymbol: string = 'BTCb'; const tokenBSymbol: string = 'USDC'; - const tokenAAmount: string = '30000000'; - const tokenBAmount: string = '10000000'; + const tokenAAmount: string = '100'; + const tokenBAmount: string = '9000000000'; const nativeTokenAmount = '1000000000000000000'; testForNetwork( diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index b7204de06..eaa63ed89 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -395,8 +395,10 @@ export class Dexalot extends SimpleExchange implements IDex { if (side === ClobSide.BID) { result.push( - (amount * BigInt(10 ** (baseToken.decimals * 2))) / - (price * BigInt(10 ** quoteToken.decimals)), + price !== 0n // To avoid division by zero error + ? (amount * BigInt(10 ** (baseToken.decimals * 2))) / + (price * BigInt(10 ** quoteToken.decimals)) + : 0n, ); } else { result.push( From 109e9fdc757b7775780abe9505d677c3dec75783 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 17 Oct 2023 16:28:22 +0300 Subject: [PATCH 500/833] 2.39.1-dexalot.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5f1ac7028..e828340d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.39.1-dexalot.1", + "version": "2.39.1-dexalot.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 9f09f99df7481c855190e0e0e743f6ed756ab7eb Mon Sep 17 00:00:00 2001 From: 0xshoehazer <0xshoehazer@gmail.com> Date: Tue, 17 Oct 2023 17:50:25 -0400 Subject: [PATCH 501/833] init v3 imports --- src/dex/baseswap/config.ts | 53 + src/dex/baseswap/constants.ts | 41 + src/dex/baseswap/contract-math/BitMath.ts | 90 ++ .../baseswap/contract-math/FixedPoint128.ts | 3 + .../baseswap/contract-math/FixedPoint96.ts | 4 + src/dex/baseswap/contract-math/FullMath.ts | 30 + .../baseswap/contract-math/LiquidityMath.ts | 17 + src/dex/baseswap/contract-math/Oracle.ts | 226 +++ .../baseswap/contract-math/SqrtPriceMath.ts | 226 +++ src/dex/baseswap/contract-math/SwapMath.ts | 139 ++ src/dex/baseswap/contract-math/Tick.ts | 82 ++ src/dex/baseswap/contract-math/TickBitMap.ts | 123 ++ src/dex/baseswap/contract-math/TickMath.ts | 211 +++ src/dex/baseswap/contract-math/UnsafeMath.ts | 5 + .../baseswap/contract-math/uniswap-v3-math.ts | 666 +++++++++ src/dex/baseswap/contract-math/utils.ts | 55 + src/dex/baseswap/types.ts | 191 +++ src/dex/baseswap/uniswap-v3-factory.ts | 73 + src/dex/baseswap/uniswap-v3-pool.ts | 519 +++++++ src/dex/baseswap/uniswap-v3.ts | 1247 +++++++++++++++++ src/dex/baseswap/utils.ts | 83 ++ 21 files changed, 4084 insertions(+) create mode 100644 src/dex/baseswap/config.ts create mode 100644 src/dex/baseswap/constants.ts create mode 100644 src/dex/baseswap/contract-math/BitMath.ts create mode 100644 src/dex/baseswap/contract-math/FixedPoint128.ts create mode 100644 src/dex/baseswap/contract-math/FixedPoint96.ts create mode 100644 src/dex/baseswap/contract-math/FullMath.ts create mode 100644 src/dex/baseswap/contract-math/LiquidityMath.ts create mode 100644 src/dex/baseswap/contract-math/Oracle.ts create mode 100644 src/dex/baseswap/contract-math/SqrtPriceMath.ts create mode 100644 src/dex/baseswap/contract-math/SwapMath.ts create mode 100644 src/dex/baseswap/contract-math/Tick.ts create mode 100644 src/dex/baseswap/contract-math/TickBitMap.ts create mode 100644 src/dex/baseswap/contract-math/TickMath.ts create mode 100644 src/dex/baseswap/contract-math/UnsafeMath.ts create mode 100644 src/dex/baseswap/contract-math/uniswap-v3-math.ts create mode 100644 src/dex/baseswap/contract-math/utils.ts create mode 100644 src/dex/baseswap/types.ts create mode 100644 src/dex/baseswap/uniswap-v3-factory.ts create mode 100644 src/dex/baseswap/uniswap-v3-pool.ts create mode 100644 src/dex/baseswap/uniswap-v3.ts create mode 100644 src/dex/baseswap/utils.ts diff --git a/src/dex/baseswap/config.ts b/src/dex/baseswap/config.ts new file mode 100644 index 000000000..cbd4ddb81 --- /dev/null +++ b/src/dex/baseswap/config.ts @@ -0,0 +1,53 @@ +import { DexParams } from './types'; +import { DexConfigMap, AdapterMappings } from '../../types'; +import { Network, SwapSide } from '../../constants'; +import { Address } from '../../types'; +// import RamsesV2StateMulticallABI from '../../abi/RamsesV2StateMulticall.abi.json'; +// import { AbiItem } from 'web3-utils'; +// import { decodeStateMultiCallResultWithRelativeBitmaps } from './forks/ramses-v2/utils'; +// import { RamsesV2EventPool } from './forks/ramses-v2/ramses-v2-pool'; + +const SUPPORTED_FEES = [10000n, 2500n, 450n, 80n]; + +// Pools that will be initialized on app startup +// They are added for testing +export const PoolsToPreload: DexConfigMap< + { token0: Address; token1: Address }[] +> = { + UniswapV3: { + [Network.POLYGON]: [ + { + token0: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270'.toLowerCase(), + token1: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174'.toLowerCase(), + }, + { + token0: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619'.toLowerCase(), + token1: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174'.toLowerCase(), + }, + ], + }, +}; + +export const BaseswapV3Config: DexConfigMap = { + UniswapV3: { + [Network.BASE]: { + factory: '0x38015D05f4fEC8AFe15D7cc0386a126574e8077B', + quoter: '0x4fDBD73aD4B1DDde594BF05497C15f76308eFfb9', + router: '0x1B8eea9315bE495187D873DA7773a874545D9D48', + supportedFees: SUPPORTED_FEES, + stateMulticall: '0x7160f736c52e1e78e92FD4eE4D73e21A7Cf4F950', + uniswapMulticall: '0x091e99cb1C49331a94dD62755D168E941AbD0693', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/baseswapfi/v3-base', + }, + }, +}; + +export const Adapters: Record = { + [Network.BASE]: { + [SwapSide.SELL]: [{ name: 'Adapter01', index: 6 }], + [SwapSide.BUY]: [{ name: 'BuyAdapter', index: 2 }], + }, +}; diff --git a/src/dex/baseswap/constants.ts b/src/dex/baseswap/constants.ts new file mode 100644 index 000000000..e625c3882 --- /dev/null +++ b/src/dex/baseswap/constants.ts @@ -0,0 +1,41 @@ +export const UNISWAPV3_TICK_GAS_COST = 24_000; // Ceiled +export const UNISWAPV3_TICK_BASE_OVERHEAD = 75_000; +export const UNISWAPV3_POOL_SEARCH_OVERHEAD = 10_000; + +// This is used for price calculation. If out of scope, return 0n +export const TICK_BITMAP_TO_USE = 4n; + +// This is used to check if the state is still valid. +export const TICK_BITMAP_BUFFER = 8n; + +export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 128; + +export const UNISWAPV3_SUBGRAPH_URL = + 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3'; + +export const UNISWAPV3_EFFICIENCY_FACTOR = 3; + +export const ZERO_TICK_INFO = { + liquidityGross: 0n, + liquidityNet: 0n, + tickCumulativeOutside: 0n, + secondsPerLiquidityOutsideX128: 0n, + secondsOutside: 0n, + initialized: false, +}; + +export const ZERO_ORACLE_OBSERVATION = { + blockTimestamp: 0n, + tickCumulative: 0n, + secondsPerLiquidityCumulativeX128: 0n, + initialized: false, +}; + +export const OUT_OF_RANGE_ERROR_POSTFIX = `INVALID_TICK_BIT_MAP_RANGES`; + +export const DEFAULT_POOL_INIT_CODE_HASH = `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`; + +export enum DirectMethods { + directSell = 'directUniV3Swap', + directBuy = 'directUniV3Buy', +} diff --git a/src/dex/baseswap/contract-math/BitMath.ts b/src/dex/baseswap/contract-math/BitMath.ts new file mode 100644 index 000000000..d7a2e6d9a --- /dev/null +++ b/src/dex/baseswap/contract-math/BitMath.ts @@ -0,0 +1,90 @@ +import { + BI_MAX_UINT128, + BI_MAX_UINT16, + BI_MAX_UINT32, + BI_MAX_UINT64, + BI_MAX_UINT8, +} from '../../../bigint-constants'; +import { _require } from '../../../utils'; + +export class BitMath { + static mostSignificantBit(x: bigint): bigint { + _require(x > 0, '', { x }, 'x > 0'); + let r = 0n; + + if (x >= 0x100000000000000000000000000000000n) { + x >>= 128n; + r += 128n; + } + if (x >= 0x10000000000000000n) { + x >>= 64n; + r += 64n; + } + if (x >= 0x100000000n) { + x >>= 32n; + r += 32n; + } + if (x >= 0x10000n) { + x >>= 16n; + r += 16n; + } + if (x >= 0x100n) { + x >>= 8n; + r += 8n; + } + if (x >= 0x10n) { + x >>= 4n; + r += 4n; + } + if (x >= 0x4n) { + x >>= 2n; + r += 2n; + } + if (x >= 0x2n) r += 1n; + + return r; + } + + static leastSignificantBit(x: bigint): bigint { + _require(x > 0, '', { x }, 'x > 0'); + + let r = 255n; + if ((x & BI_MAX_UINT128) > 0n) { + r -= 128n; + } else { + x >>= 128n; + } + if ((x & BI_MAX_UINT64) > 0n) { + r -= 64n; + } else { + x >>= 64n; + } + if ((x & BI_MAX_UINT32) > 0n) { + r -= 32n; + } else { + x >>= 32n; + } + if ((x & BI_MAX_UINT16) > 0n) { + r -= 16n; + } else { + x >>= 16n; + } + if ((x & BI_MAX_UINT8) > 0n) { + r -= 8n; + } else { + x >>= 8n; + } + if ((x & 0xfn) > 0n) { + r -= 4n; + } else { + x >>= 4n; + } + if ((x & 0x3n) > 0n) { + r -= 2n; + } else { + x >>= 2n; + } + if ((x & 0x1n) > 0n) r -= 1n; + return r; + } +} diff --git a/src/dex/baseswap/contract-math/FixedPoint128.ts b/src/dex/baseswap/contract-math/FixedPoint128.ts new file mode 100644 index 000000000..2058307bd --- /dev/null +++ b/src/dex/baseswap/contract-math/FixedPoint128.ts @@ -0,0 +1,3 @@ +export class FixedPoint128 { + static readonly Q128 = 0x100000000000000000000000000000000n; +} diff --git a/src/dex/baseswap/contract-math/FixedPoint96.ts b/src/dex/baseswap/contract-math/FixedPoint96.ts new file mode 100644 index 000000000..1a551dcb9 --- /dev/null +++ b/src/dex/baseswap/contract-math/FixedPoint96.ts @@ -0,0 +1,4 @@ +export class FixedPoint96 { + static readonly RESOLUTION = 96n; + static readonly Q96 = 0x1000000000000000000000000n; +} diff --git a/src/dex/baseswap/contract-math/FullMath.ts b/src/dex/baseswap/contract-math/FullMath.ts new file mode 100644 index 000000000..7c6a3bdc3 --- /dev/null +++ b/src/dex/baseswap/contract-math/FullMath.ts @@ -0,0 +1,30 @@ +import { BI_MAX_UINT256 } from '../../../bigint-constants'; +import { _require } from '../../../utils'; + +export class FullMath { + static mulDiv(a: bigint, b: bigint, denominator: bigint) { + const result = (a * b) / denominator; + + _require( + result <= BI_MAX_UINT256, + '', + { result, BI_MAX_UINT: BI_MAX_UINT256 }, + 'result <= BI_MAX_UINT', + ); + + return result; + } + + static mulDivRoundingUp(a: bigint, b: bigint, denominator: bigint) { + const result = (a * b + denominator - 1n) / denominator; + + _require( + result <= BI_MAX_UINT256, + '', + { result, BI_MAX_UINT: BI_MAX_UINT256 }, + 'result <= BI_MAX_UINT', + ); + + return result; + } +} diff --git a/src/dex/baseswap/contract-math/LiquidityMath.ts b/src/dex/baseswap/contract-math/LiquidityMath.ts new file mode 100644 index 000000000..a495e55cc --- /dev/null +++ b/src/dex/baseswap/contract-math/LiquidityMath.ts @@ -0,0 +1,17 @@ +import { _require } from '../../../utils'; + +export class LiquidityMath { + static addDelta(x: bigint, y: bigint): bigint { + let z; + if (y < 0) { + const _y = BigInt.asUintN(128, -y); + z = x - _y; + _require(z < x, 'LS', { z, x, y, _y }, 'z < x'); + } else { + const _y = BigInt.asUintN(128, y); + z = x + _y; + _require(z >= x, 'LA', { z, x, y, _y }, 'z >= x'); + } + return z; + } +} diff --git a/src/dex/baseswap/contract-math/Oracle.ts b/src/dex/baseswap/contract-math/Oracle.ts new file mode 100644 index 000000000..19b1918d1 --- /dev/null +++ b/src/dex/baseswap/contract-math/Oracle.ts @@ -0,0 +1,226 @@ +import { + OracleObservation, + OracleObservationCandidates, + PoolState, +} from '../types'; +import { _require } from '../../../utils'; +import { DeepReadonly } from 'ts-essentials'; +import { ZERO_ORACLE_OBSERVATION } from '../constants'; + +function replaceUndefinedObservationWithZero(state: PoolState, index: number) { + if (state.observations[index] === undefined) { + state.observations[index] = { ...ZERO_ORACLE_OBSERVATION }; + } +} + +export class Oracle { + static transform( + state: DeepReadonly, + last: OracleObservation, + blockTimestamp: bigint, + tick: bigint, + liquidity: bigint, + ): OracleObservation { + const delta = blockTimestamp - last.blockTimestamp; + return { + blockTimestamp: state.blockTimestamp, + tickCumulative: last.tickCumulative + BigInt.asIntN(56, tick) * delta, + secondsPerLiquidityCumulativeX128: + last.secondsPerLiquidityCumulativeX128 + + (BigInt.asUintN(160, delta) << 128n) / + (liquidity > 0n ? liquidity : 1n), + initialized: true, + }; + } + + static write( + state: PoolState, + index: number, + blockTimestamp: bigint, + tick: bigint, + liquidity: bigint, + cardinality: number, + cardinalityNext: number, + ): [number, number] { + const last = state.observations[index]; + + if (last.blockTimestamp == state.blockTimestamp) + return [index, cardinality]; + + let indexUpdated = 0; + let cardinalityUpdated = 0; + + if (cardinalityNext > cardinality && index == cardinality - 1) { + cardinalityUpdated = cardinalityNext; + } else { + cardinalityUpdated = cardinality; + } + + indexUpdated = (index + 1) % cardinalityUpdated; + + state.observations[indexUpdated] = Oracle.transform( + state, + last, + blockTimestamp, + tick, + liquidity, + ); + if (indexUpdated !== index) { + delete state.observations[index]; + } + return [indexUpdated, cardinalityUpdated]; + } + + static lte(time: bigint, a: bigint, b: bigint): boolean { + if (a <= time && b <= time) return a <= b; + + const aAdjusted = a > time ? a : a + 2n ** 32n; + const bAdjusted = b > time ? b : b + 2n ** 32n; + return aAdjusted <= bAdjusted; + } + + static binarySearch( + state: DeepReadonly, + time: bigint, + target: bigint, + index: number, + cardinality: number, + ): OracleObservationCandidates { + let l = (index + 1) % cardinality; + let r = l + cardinality - 1; + let i; + + let beforeOrAt; + let atOrAfter; + while (true) { + i = (l + r) / 2; + + beforeOrAt = state.observations[i % cardinality]; + + // we've landed on an uninitialized tick, keep searching higher (more recently) + if (!beforeOrAt.initialized) { + l = i + 1; + continue; + } + + atOrAfter = state.observations[(i + 1) % cardinality]; + + const targetAtOrAfter = Oracle.lte( + time, + beforeOrAt.blockTimestamp, + target, + ); + + // check if we've found the answer! + if (targetAtOrAfter && Oracle.lte(time, target, atOrAfter.blockTimestamp)) + break; + + if (!targetAtOrAfter) r = i - 1; + else l = i + 1; + } + return { beforeOrAt, atOrAfter }; + } + + static getSurroundingObservations( + state: DeepReadonly, + time: bigint, + target: bigint, + tick: bigint, + index: number, + liquidity: bigint, + cardinality: number, + ): OracleObservationCandidates { + let beforeOrAt = state.observations[index]; + + if (Oracle.lte(time, beforeOrAt.blockTimestamp, target)) { + if (beforeOrAt.blockTimestamp === target) { + return { beforeOrAt, atOrAfter: beforeOrAt }; + } else { + return { + beforeOrAt, + atOrAfter: Oracle.transform( + state, + beforeOrAt, + target, + tick, + liquidity, + ), + }; + } + } + + beforeOrAt = state.observations[(index + 1) % cardinality]; + if (!beforeOrAt.initialized) beforeOrAt = state.observations[0]; + + _require( + Oracle.lte(time, beforeOrAt.blockTimestamp, target), + 'OLD', + { time, beforeOrAtBlockTimestamp: beforeOrAt.blockTimestamp, target }, + 'Oracle.lte(time, beforeOrAt.blockTimestamp, target)', + ); + + return Oracle.binarySearch(state, time, target, index, cardinality); + } + + static observeSingle( + state: DeepReadonly, + time: bigint, + secondsAgo: bigint, + tick: bigint, + index: number, + liquidity: bigint, + cardinality: number, + ): [bigint, bigint] { + if (secondsAgo == 0n) { + let last = state.observations[index]; + if (last.blockTimestamp != time) + last = Oracle.transform(state, last, time, tick, liquidity); + return [last.tickCumulative, last.secondsPerLiquidityCumulativeX128]; + } + + const target = time - secondsAgo; + + const { beforeOrAt, atOrAfter } = Oracle.getSurroundingObservations( + state, + time, + target, + tick, + index, + liquidity, + cardinality, + ); + + if (target === beforeOrAt.blockTimestamp) { + return [ + beforeOrAt.tickCumulative, + beforeOrAt.secondsPerLiquidityCumulativeX128, + ]; + } else if (target === atOrAfter.blockTimestamp) { + return [ + atOrAfter.tickCumulative, + atOrAfter.secondsPerLiquidityCumulativeX128, + ]; + } else { + const observationTimeDelta = + atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp; + const targetDelta = target - beforeOrAt.blockTimestamp; + return [ + beforeOrAt.tickCumulative + + ((atOrAfter.tickCumulative - beforeOrAt.tickCumulative) / + observationTimeDelta) * + targetDelta, + beforeOrAt.secondsPerLiquidityCumulativeX128 + + BigInt.asUintN( + 160, + (BigInt.asUintN( + 256, + atOrAfter.secondsPerLiquidityCumulativeX128 - + beforeOrAt.secondsPerLiquidityCumulativeX128, + ) * + targetDelta) / + observationTimeDelta, + ), + ]; + } + } +} diff --git a/src/dex/baseswap/contract-math/SqrtPriceMath.ts b/src/dex/baseswap/contract-math/SqrtPriceMath.ts new file mode 100644 index 000000000..31b801d73 --- /dev/null +++ b/src/dex/baseswap/contract-math/SqrtPriceMath.ts @@ -0,0 +1,226 @@ +import { BI_MAX_UINT160 } from '../../../bigint-constants'; +import { FixedPoint96 } from './FixedPoint96'; +import { FullMath } from './FullMath'; +import { UnsafeMath } from './UnsafeMath'; +import { _require } from '../../../utils'; + +export class SqrtPriceMath { + static getNextSqrtPriceFromAmount0RoundingUp( + sqrtPX96: bigint, + liquidity: bigint, + amount: bigint, + add: boolean, + ): bigint { + if (amount === 0n) return sqrtPX96; + const numerator1 = + BigInt.asUintN(256, liquidity) << FixedPoint96.RESOLUTION; + + const product = amount * sqrtPX96; + if (add) { + if (product / amount === sqrtPX96) { + const denominator = numerator1 + product; + if (denominator >= numerator1) { + return BigInt.asUintN( + 160, + FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator), + ); + } + } + return BigInt.asUintN( + 160, + UnsafeMath.divRoundingUp(numerator1, numerator1 / sqrtPX96 + amount), + ); + } else { + _require( + product / amount === sqrtPX96 && numerator1 > product, + '', + { product, amount, sqrtPX96, numerator1 }, + 'product / amount === sqrtPX96 && numerator1 > product', + ); + const denominator = numerator1 - product; + return BigInt.asUintN( + 160, + FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator), + ); + } + } + + static getNextSqrtPriceFromAmount1RoundingDown( + sqrtPX96: bigint, + liquidity: bigint, + amount: bigint, + add: boolean, + ): bigint { + if (add) { + const quotient = + amount <= BI_MAX_UINT160 + ? (amount << FixedPoint96.RESOLUTION) / liquidity + : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity); + return BigInt.asUintN(160, BigInt.asUintN(256, sqrtPX96) + quotient); + } else { + const quotient = + amount <= BI_MAX_UINT160 + ? UnsafeMath.divRoundingUp( + amount << FixedPoint96.RESOLUTION, + liquidity, + ) + : FullMath.mulDivRoundingUp(amount, FixedPoint96.Q96, liquidity); + + _require( + sqrtPX96 > quotient, + '', + { sqrtPX96, quotient }, + 'sqrtPX96 > quotient', + ); + return BigInt.asUintN(160, sqrtPX96 - quotient); + } + } + + static getNextSqrtPriceFromInput( + sqrtPX96: bigint, + liquidity: bigint, + amountIn: bigint, + zeroForOne: boolean, + ): bigint { + _require(sqrtPX96 > 0n, '', { sqrtPX96 }, 'sqrtPX96 > 0n'); + _require(liquidity > 0n, '', { liquidity }, 'liquidity > 0n'); + + return zeroForOne + ? SqrtPriceMath.getNextSqrtPriceFromAmount0RoundingUp( + sqrtPX96, + liquidity, + amountIn, + true, + ) + : SqrtPriceMath.getNextSqrtPriceFromAmount1RoundingDown( + sqrtPX96, + liquidity, + amountIn, + true, + ); + } + + static getNextSqrtPriceFromOutput( + sqrtPX96: bigint, + liquidity: bigint, + amountOut: bigint, + zeroForOne: boolean, + ): bigint { + _require(sqrtPX96 > 0n, '', { sqrtPX96 }, 'sqrtPX96 > 0n'); + _require(liquidity > 0n, '', { liquidity }, 'liquidity > 0n'); + + return zeroForOne + ? SqrtPriceMath.getNextSqrtPriceFromAmount1RoundingDown( + sqrtPX96, + liquidity, + amountOut, + false, + ) + : SqrtPriceMath.getNextSqrtPriceFromAmount0RoundingUp( + sqrtPX96, + liquidity, + amountOut, + false, + ); + } + + static getAmount0Delta( + sqrtRatioAX96: bigint, + sqrtRatioBX96: bigint, + liquidity: bigint, + roundUp: boolean, + ) { + if (sqrtRatioAX96 > sqrtRatioBX96) { + [sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]; + } + + const numerator1 = + BigInt.asUintN(256, liquidity) << FixedPoint96.RESOLUTION; + const numerator2 = sqrtRatioBX96 - sqrtRatioAX96; + + _require(sqrtRatioAX96 > 0, '', { sqrtRatioAX96 }, 'sqrtRatioAX96 > 0'); + + return roundUp + ? UnsafeMath.divRoundingUp( + FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96), + sqrtRatioAX96, + ) + : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96; + } + + static getAmount1Delta( + sqrtRatioAX96: bigint, + sqrtRatioBX96: bigint, + liquidity: bigint, + roundUp: boolean, + ) { + if (sqrtRatioAX96 > sqrtRatioBX96) + [sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]; + + return roundUp + ? FullMath.mulDivRoundingUp( + liquidity, + sqrtRatioBX96 - sqrtRatioAX96, + FixedPoint96.Q96, + ) + : FullMath.mulDiv( + liquidity, + sqrtRatioBX96 - sqrtRatioAX96, + FixedPoint96.Q96, + ); + } + + // Overloaded with different argument numbers + static _getAmount0DeltaO( + sqrtRatioAX96: bigint, + sqrtRatioBX96: bigint, + liquidity: bigint, + ) { + return liquidity < 0 + ? -BigInt.asIntN( + 256, + SqrtPriceMath.getAmount0Delta( + sqrtRatioAX96, + sqrtRatioBX96, + BigInt.asUintN(128, -liquidity), + false, + ), + ) + : BigInt.asIntN( + 256, + SqrtPriceMath.getAmount0Delta( + sqrtRatioAX96, + sqrtRatioBX96, + BigInt.asUintN(128, liquidity), + true, + ), + ); + } + + // Overloaded with different argument numbers + static _getAmount1DeltaO( + sqrtRatioAX96: bigint, + sqrtRatioBX96: bigint, + liquidity: bigint, + ) { + return liquidity < 0 + ? -BigInt.asIntN( + 256, + SqrtPriceMath.getAmount1Delta( + sqrtRatioAX96, + sqrtRatioBX96, + BigInt.asUintN(128, -liquidity), + false, + ), + ) + : BigInt.asIntN( + 256, + SqrtPriceMath.getAmount1Delta( + sqrtRatioAX96, + sqrtRatioBX96, + BigInt.asUintN(128, liquidity), + true, + ), + ); + } +} diff --git a/src/dex/baseswap/contract-math/SwapMath.ts b/src/dex/baseswap/contract-math/SwapMath.ts new file mode 100644 index 000000000..3f19cf8cb --- /dev/null +++ b/src/dex/baseswap/contract-math/SwapMath.ts @@ -0,0 +1,139 @@ +import { BI_POWS } from '../../../bigint-constants'; +import { FullMath } from './FullMath'; +import { SqrtPriceMath } from './SqrtPriceMath'; + +export class SwapMath { + static computeSwapStep( + sqrtRatioCurrentX96: bigint, + sqrtRatioTargetX96: bigint, + liquidity: bigint, + amountRemaining: bigint, + feePips: bigint, + ): { + sqrtRatioNextX96: bigint; + amountIn: bigint; + amountOut: bigint; + feeAmount: bigint; + } { + const zeroForOne = sqrtRatioCurrentX96 >= sqrtRatioTargetX96; + const exactIn = amountRemaining >= 0n; + + let sqrtRatioNextX96 = 0n; + let amountIn = 0n; + let amountOut = 0n; + let feeAmount = 0n; + + if (exactIn) { + const amountRemainingLessFee = FullMath.mulDiv( + BigInt.asUintN(256, amountRemaining), + BI_POWS[6] - feePips, + BI_POWS[6], + ); + amountIn = zeroForOne + ? SqrtPriceMath.getAmount0Delta( + sqrtRatioTargetX96, + sqrtRatioCurrentX96, + liquidity, + true, + ) + : SqrtPriceMath.getAmount1Delta( + sqrtRatioCurrentX96, + sqrtRatioTargetX96, + liquidity, + true, + ); + if (amountRemainingLessFee >= amountIn) + sqrtRatioNextX96 = sqrtRatioTargetX96; + else + sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromInput( + sqrtRatioCurrentX96, + liquidity, + amountRemainingLessFee, + zeroForOne, + ); + } else { + amountOut = zeroForOne + ? SqrtPriceMath.getAmount1Delta( + sqrtRatioTargetX96, + sqrtRatioCurrentX96, + liquidity, + false, + ) + : SqrtPriceMath.getAmount0Delta( + sqrtRatioCurrentX96, + sqrtRatioTargetX96, + liquidity, + false, + ); + if (BigInt.asUintN(256, -amountRemaining) >= amountOut) + sqrtRatioNextX96 = sqrtRatioTargetX96; + else + sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromOutput( + sqrtRatioCurrentX96, + liquidity, + BigInt.asUintN(256, -amountRemaining), + zeroForOne, + ); + } + + const max = sqrtRatioTargetX96 == sqrtRatioNextX96; + + if (zeroForOne) { + amountIn = + max && exactIn + ? amountIn + : SqrtPriceMath.getAmount0Delta( + sqrtRatioNextX96, + sqrtRatioCurrentX96, + liquidity, + true, + ); + amountOut = + max && !exactIn + ? amountOut + : SqrtPriceMath.getAmount1Delta( + sqrtRatioNextX96, + sqrtRatioCurrentX96, + liquidity, + false, + ); + } else { + amountIn = + max && exactIn + ? amountIn + : SqrtPriceMath.getAmount1Delta( + sqrtRatioCurrentX96, + sqrtRatioNextX96, + liquidity, + true, + ); + amountOut = + max && !exactIn + ? amountOut + : SqrtPriceMath.getAmount0Delta( + sqrtRatioCurrentX96, + sqrtRatioNextX96, + liquidity, + false, + ); + } + + // cap the output amount to not exceed the remaining output amount + if (!exactIn && amountOut > BigInt.asUintN(256, -amountRemaining)) { + amountOut = BigInt.asUintN(256, -amountRemaining); + } + + if (exactIn && sqrtRatioNextX96 != sqrtRatioTargetX96) { + // we didn't reach the target, so take the remainder of the maximum input as fee + feeAmount = BigInt.asUintN(256, amountRemaining) - amountIn; + } else { + feeAmount = FullMath.mulDivRoundingUp( + amountIn, + feePips, + BI_POWS[6] - feePips, + ); + } + + return { sqrtRatioNextX96, amountIn, amountOut, feeAmount }; + } +} diff --git a/src/dex/baseswap/contract-math/Tick.ts b/src/dex/baseswap/contract-math/Tick.ts new file mode 100644 index 000000000..ab2e3c48b --- /dev/null +++ b/src/dex/baseswap/contract-math/Tick.ts @@ -0,0 +1,82 @@ +import { PoolState, TickInfo } from '../types'; +import { LiquidityMath } from './LiquidityMath'; +import { _require } from '../../../utils'; +import { NumberAsString } from '@paraswap/core'; +import { ZERO_TICK_INFO } from '../constants'; + +export class Tick { + static update( + state: Pick, + tick: bigint, + tickCurrent: bigint, + liquidityDelta: bigint, + secondsPerLiquidityCumulativeX128: bigint, + tickCumulative: bigint, + time: bigint, + upper: boolean, + maxLiquidity: bigint, + ): boolean { + let info = state.ticks[Number(tick)]; + + if (info === undefined) { + info = { ...ZERO_TICK_INFO }; + state.ticks[Number(tick)] = info; + } + + const liquidityGrossBefore = info.liquidityGross; + const liquidityGrossAfter = LiquidityMath.addDelta( + liquidityGrossBefore, + liquidityDelta, + ); + + _require( + liquidityGrossAfter <= maxLiquidity, + 'LO', + { liquidityGrossAfter, maxLiquidity }, + 'liquidityGrossAfter <= maxLiquidity', + ); + + const flipped = (liquidityGrossAfter == 0n) != (liquidityGrossBefore == 0n); + + if (liquidityGrossBefore == 0n) { + if (tick <= tickCurrent) { + info.secondsPerLiquidityOutsideX128 = secondsPerLiquidityCumulativeX128; + info.tickCumulativeOutside = tickCumulative; + info.secondsOutside = time; + } + info.initialized = true; + } + + info.liquidityGross = liquidityGrossAfter; + + info.liquidityNet = upper + ? BigInt.asIntN( + 128, + BigInt.asIntN(256, info.liquidityNet) - liquidityDelta, + ) + : BigInt.asIntN( + 128, + BigInt.asIntN(256, info.liquidityNet) + liquidityDelta, + ); + return flipped; + } + + static clear(state: Pick, tick: bigint) { + delete state.ticks[Number(tick)]; + } + + static cross( + ticks: Record, + tick: bigint, + secondsPerLiquidityCumulativeX128: bigint, + tickCumulative: bigint, + time: bigint, + ): bigint { + const info = ticks[Number(tick)]; + info.secondsPerLiquidityOutsideX128 = + secondsPerLiquidityCumulativeX128 - info.secondsPerLiquidityOutsideX128; + info.tickCumulativeOutside = tickCumulative - info.tickCumulativeOutside; + info.secondsOutside = time - info.secondsOutside; + return info.liquidityNet; + } +} diff --git a/src/dex/baseswap/contract-math/TickBitMap.ts b/src/dex/baseswap/contract-math/TickBitMap.ts new file mode 100644 index 000000000..405cfa70e --- /dev/null +++ b/src/dex/baseswap/contract-math/TickBitMap.ts @@ -0,0 +1,123 @@ +import { BI_MAX_UINT8 } from '../../../bigint-constants'; +import { PoolState } from '../types'; +import { BitMath } from './BitMath'; +import { _require } from '../../../utils'; +import { DeepReadonly } from 'ts-essentials'; +import { + OUT_OF_RANGE_ERROR_POSTFIX, + TICK_BITMAP_BUFFER, + TICK_BITMAP_TO_USE, +} from '../constants'; + +function isWordPosOut( + wordPos: bigint, + startTickBitmap: bigint, + // For pricing we use wider range to check price impact. If function called from event + // it must always be within buffer + isPriceQuery: boolean, +) { + let lowerTickBitmapLimit; + let upperTickBitmapLimit; + + if (isPriceQuery) { + lowerTickBitmapLimit = + startTickBitmap - (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE); + upperTickBitmapLimit = + startTickBitmap + (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE); + } else { + lowerTickBitmapLimit = startTickBitmap - TICK_BITMAP_BUFFER; + upperTickBitmapLimit = startTickBitmap + TICK_BITMAP_BUFFER; + } + + _require( + wordPos >= lowerTickBitmapLimit && wordPos <= upperTickBitmapLimit, + `wordPos is out of safe state tickBitmap request range: ${OUT_OF_RANGE_ERROR_POSTFIX}`, + { wordPos }, + `wordPos >= LOWER_TICK_REQUEST_LIMIT && wordPos <= UPPER_TICK_REQUEST_LIMIT`, + ); +} + +export class TickBitMap { + static position(tick: bigint): [bigint, bigint] { + return [BigInt.asIntN(16, tick >> 8n), BigInt.asUintN(8, tick % 256n)]; + } + + static flipTick( + state: Pick, + tick: bigint, + tickSpacing: bigint, + ) { + _require( + tick % tickSpacing === 0n, + '', + { tick, tickSpacing }, + 'tick % tickSpacing == 0n,', + ); + const [wordPos, bitPos] = TickBitMap.position(tick / tickSpacing); + const mask = 1n << bitPos; + + // flipTick is used only in _updatePosition which is always state changing event + // Therefore it is never used in price query + isWordPosOut(wordPos, state.startTickBitmap, false); + + const stringWordPos = wordPos.toString(); + if (state.tickBitmap[stringWordPos] === undefined) { + state.tickBitmap[stringWordPos] = 0n; + } + + state.tickBitmap[stringWordPos] ^= mask; + } + + static nextInitializedTickWithinOneWord( + state: DeepReadonly>, + tick: bigint, + tickSpacing: bigint, + lte: boolean, + isPriceQuery: boolean, + ): [bigint, boolean] { + let compressed = tick / tickSpacing; + if (tick < 0n && tick % tickSpacing != 0n) compressed--; + + let next = 0n; + let initialized = false; + + if (lte) { + const [wordPos, bitPos] = TickBitMap.position(compressed); + const mask = (1n << bitPos) - 1n + (1n << bitPos); + + isWordPosOut(wordPos, state.startTickBitmap, isPriceQuery); + let tickBitmapValue = state.tickBitmap[wordPos.toString()]; + tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; + + const masked = tickBitmapValue & mask; + + initialized = masked != 0n; + next = initialized + ? (compressed - + BigInt.asIntN(24, bitPos - BitMath.mostSignificantBit(masked))) * + tickSpacing + : (compressed - BigInt.asIntN(24, bitPos)) * tickSpacing; + } else { + // start from the word of the next tick, since the current tick state doesn't matter + const [wordPos, bitPos] = TickBitMap.position(compressed + 1n); + const mask = ~((1n << bitPos) - 1n); + + isWordPosOut(wordPos, state.startTickBitmap, isPriceQuery); + let tickBitmapValue = state.tickBitmap[wordPos.toString()]; + tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; + + const masked = tickBitmapValue & mask; + + initialized = masked != 0n; + next = initialized + ? (compressed + + 1n + + BigInt.asIntN(24, BitMath.leastSignificantBit(masked) - bitPos)) * + tickSpacing + : (compressed + 1n + BigInt.asIntN(24, BI_MAX_UINT8 - bitPos)) * + tickSpacing; + } + + return [next, initialized]; + } +} diff --git a/src/dex/baseswap/contract-math/TickMath.ts b/src/dex/baseswap/contract-math/TickMath.ts new file mode 100644 index 000000000..5515ce15c --- /dev/null +++ b/src/dex/baseswap/contract-math/TickMath.ts @@ -0,0 +1,211 @@ +import { gt } from 'lodash'; +import { BI_MAX_UINT256 } from '../../../bigint-constants'; +import { _gt } from './utils'; +import { _require } from '../../../utils'; + +export class TickMath { + static readonly MIN_TICK = -887272n; + static readonly MAX_TICK = -TickMath.MIN_TICK; + static readonly MIN_SQRT_RATIO = 4295128739n; + static readonly MAX_SQRT_RATIO = + 1461446703485210103287273052203988822378723970342n; + + static getSqrtRatioAtTick(tick: bigint): bigint { + const absTick = + tick < 0n + ? BigInt.asUintN(256, -BigInt.asIntN(256, tick)) + : BigInt.asUintN(256, BigInt.asIntN(256, tick)); + _require( + absTick <= BigInt.asUintN(256, TickMath.MAX_TICK), + 'T', + { absTick }, + 'absTick <= BigInt.asUintN(256, TickMath.MAX_TICK)', + ); + + let ratio = + (absTick & 0x1n) !== 0n + ? 0xfffcb933bd6fad37aa2d162d1a594001n + : 0x100000000000000000000000000000000n; + if ((absTick & 0x2n) !== 0n) + ratio = (ratio * 0xfff97272373d413259a46990580e213an) >> 128n; + if ((absTick & 0x4n) !== 0n) + ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdccn) >> 128n; + if ((absTick & 0x8n) !== 0n) + ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0n) >> 128n; + if ((absTick & 0x10n) !== 0n) + ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644n) >> 128n; + if ((absTick & 0x20n) !== 0n) + ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0n) >> 128n; + if ((absTick & 0x40n) !== 0n) + ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861n) >> 128n; + if ((absTick & 0x80n) !== 0n) + ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053n) >> 128n; + if ((absTick & 0x100n) !== 0n) + ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4n) >> 128n; + if ((absTick & 0x200n) !== 0n) + ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54n) >> 128n; + if ((absTick & 0x400n) !== 0n) + ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3n) >> 128n; + if ((absTick & 0x800n) !== 0n) + ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9n) >> 128n; + if ((absTick & 0x1000n) !== 0n) + ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825n) >> 128n; + if ((absTick & 0x2000n) !== 0n) + ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5n) >> 128n; + if ((absTick & 0x4000n) !== 0n) + ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7n) >> 128n; + if ((absTick & 0x8000n) !== 0n) + ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6n) >> 128n; + if ((absTick & 0x10000n) !== 0n) + ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9n) >> 128n; + if ((absTick & 0x20000n) !== 0n) + ratio = (ratio * 0x5d6af8dedb81196699c329225ee604n) >> 128n; + if ((absTick & 0x40000n) !== 0n) + ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98n) >> 128n; + if ((absTick & 0x80000n) !== 0n) + ratio = (ratio * 0x48a170391f7dc42444e8fa2n) >> 128n; + + if (tick > 0) ratio = BI_MAX_UINT256 / ratio; + return BigInt.asUintN( + 160, + (ratio >> 32n) + (ratio % (1n << 32n) == 0n ? 0n : 1n), + ); + } + + static getTickAtSqrtRatio(sqrtPriceX96: bigint): bigint { + _require( + sqrtPriceX96 >= TickMath.MIN_SQRT_RATIO && + sqrtPriceX96 < TickMath.MAX_SQRT_RATIO, + 'R', + { sqrtPriceX96 }, + 'sqrtPriceX96 >= TickMath.MIN_SQRT_RATIO && sqrtPriceX96 < TickMath.MAX_SQRT_RATIO', + ); + + let ratio = BigInt.asUintN(256, sqrtPriceX96) << 32n; + + let r = ratio; + let msb = 0n; + + let f = _gt(r, 0xffffffffffffffffffffffffffffffffn) << 7n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xffffffffffffffffn) << 6n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xffffffffn) << 5n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xffffn) << 4n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xffn) << 3n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0xfn) << 2n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0x3n) << 1n; + msb = msb | f; + r = r >> f; + + f = _gt(r, 0x1n); + msb = msb | f; + + if (msb >= 128n) r = ratio >> (msb - 127n); + else r = ratio << (127n - msb); + + let log_2 = (BigInt.asIntN(256, msb) - 128n) << 64n; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 63n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 62n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 61n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 60n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 59n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 58n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 57n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 56n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 55n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 54n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 53n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 52n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 51n); + r = r >> f; + + r = (r * r) >> 127n; + f = r >> 128n; + log_2 = log_2 | (f << 50n); + + const log_sqrt10001 = log_2 * 255738958999603826347141n; // 128.128 number + + const tickLow = BigInt.asIntN( + 24, + (log_sqrt10001 - 3402992956809132418596140100660247210n) >> 128n, + ); + const tickHi = BigInt.asIntN( + 24, + (log_sqrt10001 + 291339464771989622907027621153398088495n) >> 128n, + ); + + return tickLow === tickHi + ? tickLow + : TickMath.getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 + ? tickHi + : tickLow; + } +} diff --git a/src/dex/baseswap/contract-math/UnsafeMath.ts b/src/dex/baseswap/contract-math/UnsafeMath.ts new file mode 100644 index 000000000..aebd7c579 --- /dev/null +++ b/src/dex/baseswap/contract-math/UnsafeMath.ts @@ -0,0 +1,5 @@ +export class UnsafeMath { + static divRoundingUp(x: bigint, y: bigint) { + return (x + y - 1n) / y; + } +} diff --git a/src/dex/baseswap/contract-math/uniswap-v3-math.ts b/src/dex/baseswap/contract-math/uniswap-v3-math.ts new file mode 100644 index 000000000..d18881006 --- /dev/null +++ b/src/dex/baseswap/contract-math/uniswap-v3-math.ts @@ -0,0 +1,666 @@ +import _ from 'lodash'; +import { OutputResult, PoolState, Slot0, TickInfo } from '../types'; +import { LiquidityMath } from './LiquidityMath'; +import { Oracle } from './Oracle'; +import { SqrtPriceMath } from './SqrtPriceMath'; +import { SwapMath } from './SwapMath'; +import { Tick } from './Tick'; +import { TickBitMap } from './TickBitMap'; +import { TickMath } from './TickMath'; +import { _require } from '../../../utils'; +import { DeepReadonly } from 'ts-essentials'; +import { NumberAsString, SwapSide } from '@paraswap/core'; +import { BI_MAX_INT } from '../../../bigint-constants'; +import { + MAX_PRICING_COMPUTATION_STEPS_ALLOWED, + OUT_OF_RANGE_ERROR_POSTFIX, +} from '../constants'; + +type ModifyPositionParams = { + tickLower: bigint; + tickUpper: bigint; + liquidityDelta: bigint; +}; + +export type PriceComputationState = { + amountSpecifiedRemaining: bigint; + amountCalculated: bigint; + sqrtPriceX96: bigint; + tick: bigint; + protocolFee: bigint; + liquidity: bigint; + isFirstCycleState: boolean; +}; + +export type PriceComputationCache = { + liquidityStart: bigint; + blockTimestamp: bigint; + feeProtocol: bigint; + secondsPerLiquidityCumulativeX128: bigint; + tickCumulative: bigint; + computedLatestObservation: boolean; + tickCount: number; +}; + +export function _updatePriceComputationObjects< + T extends PriceComputationState | PriceComputationCache, +>(toUpdate: T, updateBy: T) { + for (const k of Object.keys(updateBy) as (keyof T)[]) { + toUpdate[k] = updateBy[k]; + } +} + +function _priceComputationCycles( + poolState: DeepReadonly, + ticksCopy: Record, + slot0Start: Slot0, + state: PriceComputationState, + cache: PriceComputationCache, + sqrtPriceLimitX96: bigint, + zeroForOne: boolean, + exactInput: boolean, +): [ + // result + PriceComputationState, + // Latest calculated full cycle state we can use for bigger amounts + { + latestFullCycleState: PriceComputationState; + latestFullCycleCache: PriceComputationCache; + }, +] { + const latestFullCycleState: PriceComputationState = { ...state }; + + if (cache.tickCount == 0) { + cache.tickCount = 1; + } + const latestFullCycleCache: PriceComputationCache = { ...cache }; + + // We save tick before any change. Later we use this to restore + // state before last step + let lastTicksCopy: { index: number; tick: TickInfo } | undefined; + + let i = 0; + for ( + ; + state.amountSpecifiedRemaining !== 0n && + state.sqrtPriceX96 !== sqrtPriceLimitX96; + ++i + ) { + if ( + latestFullCycleCache.tickCount + i > + MAX_PRICING_COMPUTATION_STEPS_ALLOWED + ) { + state.amountSpecifiedRemaining = 0n; + state.amountCalculated = 0n; + break; + } + + const step = { + sqrtPriceStartX96: 0n, + tickNext: 0n, + initialized: false, + sqrtPriceNextX96: 0n, + amountIn: 0n, + amountOut: 0n, + feeAmount: 0n, + }; + + step.sqrtPriceStartX96 = state.sqrtPriceX96; + + try { + [step.tickNext, step.initialized] = + TickBitMap.nextInitializedTickWithinOneWord( + poolState, + state.tick, + poolState.tickSpacing, + zeroForOne, + true, + ); + } catch (e) { + if ( + e instanceof Error && + e.message.endsWith(OUT_OF_RANGE_ERROR_POSTFIX) + ) { + state.amountSpecifiedRemaining = 0n; + state.amountCalculated = 0n; + break; + } + throw e; + } + + if (step.tickNext < TickMath.MIN_TICK) { + step.tickNext = TickMath.MIN_TICK; + } else if (step.tickNext > TickMath.MAX_TICK) { + step.tickNext = TickMath.MAX_TICK; + } + + step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext); + + const swapStepResult = SwapMath.computeSwapStep( + state.sqrtPriceX96, + ( + zeroForOne + ? step.sqrtPriceNextX96 < sqrtPriceLimitX96 + : step.sqrtPriceNextX96 > sqrtPriceLimitX96 + ) + ? sqrtPriceLimitX96 + : step.sqrtPriceNextX96, + state.liquidity, + state.amountSpecifiedRemaining, + poolState.fee, + ); + + state.sqrtPriceX96 = swapStepResult.sqrtRatioNextX96; + step.amountIn = swapStepResult.amountIn; + step.amountOut = swapStepResult.amountOut; + step.feeAmount = swapStepResult.feeAmount; + + if (exactInput) { + state.amountSpecifiedRemaining -= step.amountIn + step.feeAmount; + state.amountCalculated = state.amountCalculated - step.amountOut; + } else { + state.amountSpecifiedRemaining += step.amountOut; + state.amountCalculated = + state.amountCalculated + step.amountIn + step.feeAmount; + } + + if (cache.feeProtocol > 0n) { + const delta = step.feeAmount / cache.feeProtocol; + step.feeAmount -= delta; + state.protocolFee += delta; + } + + if (state.sqrtPriceX96 === step.sqrtPriceNextX96) { + if (step.initialized) { + if (!cache.computedLatestObservation) { + [cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128] = + Oracle.observeSingle( + poolState, + cache.blockTimestamp, + 0n, + slot0Start.tick, + slot0Start.observationIndex, + cache.liquidityStart, + slot0Start.observationCardinality, + ); + cache.computedLatestObservation = true; + } + + if (state.amountSpecifiedRemaining === 0n) { + const castTickNext = Number(step.tickNext); + lastTicksCopy = { + index: castTickNext, + tick: { ...ticksCopy[castTickNext] }, + }; + } + + let liquidityNet = Tick.cross( + ticksCopy, + step.tickNext, + cache.secondsPerLiquidityCumulativeX128, + cache.tickCumulative, + cache.blockTimestamp, + ); + if (zeroForOne) liquidityNet = -liquidityNet; + + state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet); + } + + state.tick = zeroForOne ? step.tickNext - 1n : step.tickNext; + } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) { + state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96); + } + + if (state.amountSpecifiedRemaining !== 0n) { + _updatePriceComputationObjects(latestFullCycleState, state); + _updatePriceComputationObjects(latestFullCycleCache, cache); + // If it last cycle, check if ticks were changed and then restore previous state + // for next calculations + } else if (lastTicksCopy !== undefined) { + ticksCopy[lastTicksCopy.index] = lastTicksCopy.tick; + } + } + + if (i > 1) { + latestFullCycleCache.tickCount += i - 1; + } + + if (state.amountSpecifiedRemaining !== 0n) { + state.amountSpecifiedRemaining = 0n; + state.amountCalculated = 0n; + } + + return [state, { latestFullCycleState, latestFullCycleCache }]; +} + +class UniswapV3Math { + queryOutputs( + poolState: DeepReadonly, + // Amounts must increase + amounts: bigint[], + zeroForOne: boolean, + side: SwapSide, + ): OutputResult { + const slot0Start = poolState.slot0; + + const isSell = side === SwapSide.SELL; + + // While calculating, ticks are changing, so to not change the actual state, + // we use copy + const ticksCopy = _.cloneDeep(poolState.ticks); + + const sqrtPriceLimitX96 = zeroForOne + ? TickMath.MIN_SQRT_RATIO + 1n + : TickMath.MAX_SQRT_RATIO - 1n; + + const cache: PriceComputationCache = { + liquidityStart: poolState.liquidity, + blockTimestamp: this._blockTimestamp(poolState), + feeProtocol: zeroForOne + ? slot0Start.feeProtocol % 16n + : slot0Start.feeProtocol >> 4n, + secondsPerLiquidityCumulativeX128: 0n, + tickCumulative: 0n, + computedLatestObservation: false, + tickCount: 0, + }; + + const state: PriceComputationState = { + // Will be overwritten later + amountSpecifiedRemaining: 0n, + amountCalculated: 0n, + sqrtPriceX96: slot0Start.sqrtPriceX96, + tick: slot0Start.tick, + protocolFee: 0n, + liquidity: cache.liquidityStart, + isFirstCycleState: true, + }; + + let isOutOfRange = false; + let previousAmount = 0n; + + const outputs = new Array(amounts.length); + const tickCounts = new Array(amounts.length); + for (const [i, amount] of amounts.entries()) { + if (amount === 0n) { + outputs[i] = 0n; + tickCounts[i] = 0; + continue; + } + + const amountSpecified = isSell + ? BigInt.asIntN(256, amount) + : -BigInt.asIntN(256, amount); + + if (state.isFirstCycleState) { + // Set first non zero amount + state.amountSpecifiedRemaining = amountSpecified; + state.isFirstCycleState = false; + } else { + state.amountSpecifiedRemaining = + amountSpecified - (previousAmount - state.amountSpecifiedRemaining); + } + + const exactInput = amountSpecified > 0n; + + _require( + zeroForOne + ? sqrtPriceLimitX96 < slot0Start.sqrtPriceX96 && + sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO + : sqrtPriceLimitX96 > slot0Start.sqrtPriceX96 && + sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO, + 'SPL', + { zeroForOne, sqrtPriceLimitX96, slot0Start }, + 'zeroForOne ? sqrtPriceLimitX96 < slot0Start.sqrtPriceX96 && sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO : sqrtPriceLimitX96 > slot0Start.sqrtPriceX96 && sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO', + ); + + if (!isOutOfRange) { + const [finalState, { latestFullCycleState, latestFullCycleCache }] = + _priceComputationCycles( + poolState, + ticksCopy, + slot0Start, + state, + cache, + sqrtPriceLimitX96, + zeroForOne, + exactInput, + ); + if ( + finalState.amountSpecifiedRemaining === 0n && + finalState.amountCalculated === 0n + ) { + isOutOfRange = true; + outputs[i] = 0n; + tickCounts[i] = 0; + continue; + } + + // We use it on next step to correct state.amountSpecifiedRemaining + previousAmount = amountSpecified; + + // First extract calculated values + const [amount0, amount1] = + zeroForOne === exactInput + ? [ + amountSpecified - finalState.amountSpecifiedRemaining, + finalState.amountCalculated, + ] + : [ + finalState.amountCalculated, + amountSpecified - finalState.amountSpecifiedRemaining, + ]; + + // Update for next amount + _updatePriceComputationObjects(state, latestFullCycleState); + _updatePriceComputationObjects(cache, latestFullCycleCache); + + if (isSell) { + outputs[i] = BigInt.asUintN(256, -(zeroForOne ? amount1 : amount0)); + tickCounts[i] = latestFullCycleCache.tickCount; + continue; + } else { + outputs[i] = zeroForOne + ? BigInt.asUintN(256, amount0) + : BigInt.asUintN(256, amount1); + tickCounts[i] = latestFullCycleCache.tickCount; + continue; + } + } else { + outputs[i] = 0n; + tickCounts[i] = 0; + } + } + + return { + outputs, + tickCounts, + }; + } + + swapFromEvent( + poolState: PoolState, + newSqrtPriceX96: bigint, + newTick: bigint, + newLiquidity: bigint, + zeroForOne: boolean, + ): void { + const slot0Start = poolState.slot0; + + const cache = { + liquidityStart: poolState.liquidity, + blockTimestamp: this._blockTimestamp(poolState), + feeProtocol: 0n, + secondsPerLiquidityCumulativeX128: 0n, + tickCumulative: 0n, + computedLatestObservation: false, + }; + + const state = { + // Because I don't have the exact amount user used, set this number to MAX_NUMBER to proceed + // with calculations. I think it is not a problem since in loop I don't rely on this value + amountSpecifiedRemaining: BI_MAX_INT, + amountCalculated: 0n, + sqrtPriceX96: slot0Start.sqrtPriceX96, + tick: slot0Start.tick, + protocolFee: 0n, + liquidity: cache.liquidityStart, + }; + + // Because I didn't have all variables, adapted loop stop with state.tick !== newTick + // condition. This cycle need only to calculate Tick.cross() function values + // It means that we are interested in cycling only if state.tick !== newTick + // When they become equivalent, we proceed with state updating part as normal + // And if assumptions regarding this cycle are correct, we don't need to process + // the last cycle when state.tick === newTick + while (state.tick !== newTick && state.sqrtPriceX96 !== newSqrtPriceX96) { + const step = { + sqrtPriceStartX96: 0n, + tickNext: 0n, + initialized: false, + sqrtPriceNextX96: 0n, + amountIn: 0n, + amountOut: 0n, + feeAmount: 0n, + }; + + step.sqrtPriceStartX96 = state.sqrtPriceX96; + + [step.tickNext, step.initialized] = + TickBitMap.nextInitializedTickWithinOneWord( + poolState, + state.tick, + poolState.tickSpacing, + zeroForOne, + false, + ); + + if (step.tickNext < TickMath.MIN_TICK) { + step.tickNext = TickMath.MIN_TICK; + } else if (step.tickNext > TickMath.MAX_TICK) { + step.tickNext = TickMath.MAX_TICK; + } + + step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext); + + const swapStepResult = SwapMath.computeSwapStep( + state.sqrtPriceX96, + ( + zeroForOne + ? step.sqrtPriceNextX96 < newSqrtPriceX96 + : step.sqrtPriceNextX96 > newSqrtPriceX96 + ) + ? newSqrtPriceX96 + : step.sqrtPriceNextX96, + state.liquidity, + state.amountSpecifiedRemaining, + poolState.fee, + ); + + state.sqrtPriceX96 = swapStepResult.sqrtRatioNextX96; + + if (state.sqrtPriceX96 == step.sqrtPriceNextX96) { + if (step.initialized) { + if (!cache.computedLatestObservation) { + [cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128] = + Oracle.observeSingle( + poolState, + cache.blockTimestamp, + 0n, + slot0Start.tick, + slot0Start.observationIndex, + cache.liquidityStart, + slot0Start.observationCardinality, + ); + cache.computedLatestObservation = true; + } + + let liquidityNet = Tick.cross( + poolState.ticks, + step.tickNext, + cache.secondsPerLiquidityCumulativeX128, + cache.tickCumulative, + cache.blockTimestamp, + ); + + if (zeroForOne) liquidityNet = -liquidityNet; + + state.liquidity = LiquidityMath.addDelta( + state.liquidity, + liquidityNet, + ); + } + + state.tick = zeroForOne ? step.tickNext - 1n : step.tickNext; + } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) { + state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96); + } + } + + if (slot0Start.tick !== newTick) { + const [observationIndex, observationCardinality] = Oracle.write( + poolState, + slot0Start.observationIndex, + this._blockTimestamp(poolState), + slot0Start.tick, + poolState.liquidity, + slot0Start.observationCardinality, + slot0Start.observationCardinalityNext, + ); + + [ + poolState.slot0.sqrtPriceX96, + poolState.slot0.tick, + poolState.slot0.observationIndex, + poolState.slot0.observationCardinality, + ] = [newSqrtPriceX96, newTick, observationIndex, observationCardinality]; + } else { + poolState.slot0.sqrtPriceX96 = newSqrtPriceX96; + } + + if (poolState.liquidity !== newLiquidity) + poolState.liquidity = newLiquidity; + } + + _modifyPosition( + state: PoolState, + params: ModifyPositionParams, + ): [bigint, bigint] { + const _slot0 = state.slot0; + + this._updatePosition( + state, + params.tickLower, + params.tickUpper, + params.liquidityDelta, + _slot0.tick, + ); + + let amount0 = 0n; + let amount1 = 0n; + if (params.liquidityDelta !== 0n) { + if (_slot0.tick < params.tickLower) { + amount0 = SqrtPriceMath._getAmount0DeltaO( + TickMath.getSqrtRatioAtTick(params.tickLower), + TickMath.getSqrtRatioAtTick(params.tickUpper), + params.liquidityDelta, + ); + } else if (_slot0.tick < params.tickUpper) { + const liquidityBefore = state.liquidity; + + [state.slot0.observationIndex, state.slot0.observationCardinality] = + Oracle.write( + state, + _slot0.observationIndex, + this._blockTimestamp(state), + _slot0.tick, + liquidityBefore, + _slot0.observationCardinality, + _slot0.observationCardinalityNext, + ); + + amount0 = SqrtPriceMath._getAmount0DeltaO( + _slot0.sqrtPriceX96, + TickMath.getSqrtRatioAtTick(params.tickUpper), + params.liquidityDelta, + ); + amount1 = SqrtPriceMath._getAmount1DeltaO( + TickMath.getSqrtRatioAtTick(params.tickLower), + _slot0.sqrtPriceX96, + params.liquidityDelta, + ); + + state.liquidity = LiquidityMath.addDelta( + liquidityBefore, + params.liquidityDelta, + ); + } else { + amount1 = SqrtPriceMath._getAmount1DeltaO( + TickMath.getSqrtRatioAtTick(params.tickLower), + TickMath.getSqrtRatioAtTick(params.tickUpper), + params.liquidityDelta, + ); + } + } + return [amount0, amount1]; + } + + private _isTickToProcess(state: PoolState, tick: bigint): boolean { + return tick >= state.lowestKnownTick && tick <= state.highestKnownTick; + } + + private _updatePosition( + state: PoolState, + tickLower: bigint, + tickUpper: bigint, + liquidityDelta: bigint, + tick: bigint, + ): void { + // if we need to update the ticks, do it + let flippedLower = false; + let flippedUpper = false; + if (liquidityDelta !== 0n) { + const time = this._blockTimestamp(state); + const [tickCumulative, secondsPerLiquidityCumulativeX128] = + Oracle.observeSingle( + state, + time, + 0n, + state.slot0.tick, + state.slot0.observationIndex, + state.liquidity, + state.slot0.observationCardinality, + ); + + if (this._isTickToProcess(state, tickLower)) { + flippedLower = Tick.update( + state, + tickLower, + tick, + liquidityDelta, + secondsPerLiquidityCumulativeX128, + tickCumulative, + time, + false, + state.maxLiquidityPerTick, + ); + } + if (this._isTickToProcess(state, tickUpper)) { + flippedUpper = Tick.update( + state, + tickUpper, + tick, + liquidityDelta, + secondsPerLiquidityCumulativeX128, + tickCumulative, + time, + true, + state.maxLiquidityPerTick, + ); + } + + if (flippedLower) { + TickBitMap.flipTick(state, tickLower, state.tickSpacing); + } + if (flippedUpper) { + TickBitMap.flipTick(state, tickUpper, state.tickSpacing); + } + } + + // clear any tick data that is no longer needed + if (liquidityDelta < 0n) { + if (flippedLower) { + Tick.clear(state, tickLower); + } + if (flippedUpper) { + Tick.clear(state, tickUpper); + } + } + } + + private _blockTimestamp(state: DeepReadonly) { + return BigInt.asUintN(32, state.blockTimestamp); + } +} + +export const uniswapV3Math = new UniswapV3Math(); diff --git a/src/dex/baseswap/contract-math/utils.ts b/src/dex/baseswap/contract-math/utils.ts new file mode 100644 index 000000000..65d97736d --- /dev/null +++ b/src/dex/baseswap/contract-math/utils.ts @@ -0,0 +1,55 @@ +import { NumberAsString } from '@paraswap/core'; +import { + TickBitMapMappingsWithBigNumber, + TickInfo, + TickInfoMappingsWithBigNumber, +} from '../types'; +import { bigIntify } from '../../../utils'; + +export function _mulmod(x: bigint, y: bigint, m: bigint): bigint { + return m === 0n ? 0n : (x * y) % m; +} + +export function _lt(x: bigint, y: bigint) { + return x < y ? 1n : 0n; +} + +export function _gt(x: bigint, y: bigint) { + return x > y ? 1n : 0n; +} + +export function _reduceTickBitmap( + tickBitmap: Record, + tickBitmapToReduce: TickBitMapMappingsWithBigNumber[], +) { + return tickBitmapToReduce.reduce>( + (acc, curr) => { + const { index, value } = curr; + acc[index] = bigIntify(value); + return acc; + }, + tickBitmap, + ); +} + +export function _reduceTicks( + ticks: Record, + ticksToReduce: TickInfoMappingsWithBigNumber[], +) { + return ticksToReduce.reduce>((acc, curr) => { + const { index, value } = curr; + if (value.initialized) { + acc[index] = { + liquidityGross: bigIntify(value.liquidityGross), + liquidityNet: bigIntify(value.liquidityNet), + tickCumulativeOutside: bigIntify(value.tickCumulativeOutside), + secondsPerLiquidityOutsideX128: bigIntify( + value.secondsPerLiquidityOutsideX128, + ), + secondsOutside: bigIntify(value.secondsOutside), + initialized: value.initialized, + }; + } + return acc; + }, ticks); +} diff --git a/src/dex/baseswap/types.ts b/src/dex/baseswap/types.ts new file mode 100644 index 000000000..967675843 --- /dev/null +++ b/src/dex/baseswap/types.ts @@ -0,0 +1,191 @@ +import { BigNumber, BytesLike } from 'ethers'; +import { NumberAsString } from '../../types'; +import { Address } from '../../types'; +import { AbiItem } from 'web3-utils'; +import { MultiResult } from '../../lib/multi-wrapper'; +import { UniswapV3EventPool } from './uniswap-v3-pool'; + +export type OracleObservation = { + blockTimestamp: bigint; + tickCumulative: bigint; + secondsPerLiquidityCumulativeX128: bigint; + initialized: boolean; +}; + +export type OracleObservationCandidates = { + beforeOrAt: OracleObservation; + atOrAfter: OracleObservation; +}; + +export type TickInfo = { + liquidityGross: bigint; + liquidityNet: bigint; + tickCumulativeOutside: bigint; + secondsPerLiquidityOutsideX128: bigint; + secondsOutside: bigint; + initialized: boolean; +}; + +export type Slot0 = { + sqrtPriceX96: bigint; + tick: bigint; + observationIndex: number; + observationCardinality: number; + observationCardinalityNext: number; + feeProtocol: bigint; +}; + +export type PoolState = { + pool: string; + blockTimestamp: bigint; + tickSpacing: bigint; + fee: bigint; + slot0: Slot0; + liquidity: bigint; + maxLiquidityPerTick: bigint; + tickBitmap: Record; + ticks: Record; + observations: Record; + isValid: boolean; + startTickBitmap: bigint; + lowestKnownTick: bigint; + highestKnownTick: bigint; + balance0: bigint; + balance1: bigint; +}; + +export type FactoryState = Record; + +export type UniswapV3Data = { + path: { + tokenIn: Address; + tokenOut: Address; + fee: NumberAsString; + currentFee?: NumberAsString; + }[]; + isApproved?: boolean; +}; + +export type DecodeStateMultiCallFunc = ( + result: MultiResult | BytesLike, +) => DecodedStateMultiCallResultWithRelativeBitmaps; + +export type DexParams = { + router: Address; + quoter: Address; + factory: Address; + stateMulticall: Address; + uniswapMulticall: Address; + supportedFees: bigint[]; + chunksCount: number; + initRetryFrequency: number; + deployer?: Address; + subgraphURL: string; + initHash: string; + stateMultiCallAbi?: AbiItem[]; + eventPoolImplementation?: typeof UniswapV3EventPool; + decodeStateMultiCallResultWithRelativeBitmaps?: DecodeStateMultiCallFunc; +}; + +export type UniswapV3SimpleSwapSellParam = { + path: string; + recipient: Address; + deadline: string; + amountIn: NumberAsString; + amountOutMinimum: NumberAsString; +}; + +export type UniswapV3SimpleSwapBuyParam = { + path: string; + recipient: Address; + deadline: string; + amountOut: NumberAsString; + amountInMaximum: NumberAsString; +}; + +export type UniswapV3SimpleSwapParams = + | UniswapV3SimpleSwapSellParam + | UniswapV3SimpleSwapBuyParam; + +export type UniswapV3Param = [ + fromToken: Address, + toToken: Address, + exchange: Address, + fromAmount: NumberAsString, + toAmount: NumberAsString, + expectedAmount: NumberAsString, + feePercent: NumberAsString, + deadline: NumberAsString, + partner: Address, + isApproved: boolean, + beneficiary: Address, + path: string, + permit: string, + uuid: string, +]; + +export enum UniswapV3Functions { + exactInput = 'exactInput', + exactOutput = 'exactOutput', +} + +export type TickInfoMappings = { + index: number; + value: TickInfo; +}; + +export type TickBitMapMappings = { + index: number; + value: bigint; +}; + +export type OutputResult = { + outputs: bigint[]; + tickCounts: number[]; +}; + +// Just rewrote every type with BigNumber basically + +export type TickBitMapMappingsWithBigNumber = { + index: number; + value: BigNumber; +}; + +export type TickInfoWithBigNumber = { + initialized: boolean; + liquidityGross: BigNumber; + liquidityNet: BigNumber; + secondsOutside: number; + secondsPerLiquidityOutsideX128: BigNumber; + tickCumulativeOutside: BigNumber; +}; + +export type TickInfoMappingsWithBigNumber = { + index: number; + value: TickInfoWithBigNumber; +}; + +export type DecodedStateMultiCallResultWithRelativeBitmaps = { + pool: Address; + blockTimestamp: BigNumber; + slot0: { + feeProtocol: number; + observationCardinality: number; + observationCardinalityNext: number; + observationIndex: number; + sqrtPriceX96: BigNumber; + tick: number; + unlocked: boolean; + }; + liquidity: BigNumber; + tickSpacing: number; + maxLiquidityPerTick: BigNumber; + observation: { + blockTimestamp: number; + initialized: boolean; + secondsPerLiquidityCumulativeX128: BigNumber; + tickCumulative: BigNumber; + }; + tickBitmap: TickBitMapMappingsWithBigNumber[]; + ticks: TickInfoMappingsWithBigNumber[]; +}; diff --git a/src/dex/baseswap/uniswap-v3-factory.ts b/src/dex/baseswap/uniswap-v3-factory.ts new file mode 100644 index 000000000..372020de4 --- /dev/null +++ b/src/dex/baseswap/uniswap-v3-factory.ts @@ -0,0 +1,73 @@ +import { Interface } from '@ethersproject/abi'; +import { DeepReadonly } from 'ts-essentials'; +import FactoryABI from '../../abi/uniswap-v3/UniswapV3Factory.abi.json'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { Address, Log, Logger } from '../../types'; +import { LogDescription } from 'ethers/lib/utils'; +import { FactoryState } from './types'; + +export type OnPoolCreatedCallback = ({ + token0, + token1, + fee, +}: { + token0: string; + token1: string; + fee: bigint; +}) => Promise; + +/* + * "Stateless" event subscriber in order to capture "PoolCreated" event on new pools created. + * State is present, but it's a placeholder to actually make the events reach handlers (if there's no previous state - `processBlockLogs` is not called) + */ +export class UniswapV3Factory extends StatefulEventSubscriber { + handlers: { + [event: string]: (event: any) => Promise; + } = {}; + + logDecoder: (log: Log) => any; + + public readonly factoryIface = new Interface(FactoryABI); + + constructor( + readonly dexHelper: IDexHelper, + parentName: string, + protected readonly factoryAddress: Address, + logger: Logger, + protected readonly onPoolCreated: OnPoolCreatedCallback, + mapKey: string = '', + ) { + super(parentName, `${parentName} Factory`, dexHelper, logger, true, mapKey); + + this.addressesSubscribed = [factoryAddress]; + + this.logDecoder = (log: Log) => this.factoryIface.parseLog(log); + + this.handlers['PoolCreated'] = this.handleNewPool.bind(this); + } + + generateState(): FactoryState { + return {}; + } + + protected async processLog( + _: DeepReadonly, + log: Readonly, + ): Promise { + const event = this.logDecoder(log); + if (event.name in this.handlers) { + await this.handlers[event.name](event); + } + + return {}; + } + + async handleNewPool(event: LogDescription) { + const token0 = event.args.token0.toLowerCase(); + const token1 = event.args.token1.toLowerCase(); + const fee = event.args.fee; + + await this.onPoolCreated({ token0, token1, fee }); + } +} diff --git a/src/dex/baseswap/uniswap-v3-pool.ts b/src/dex/baseswap/uniswap-v3-pool.ts new file mode 100644 index 000000000..9f3401710 --- /dev/null +++ b/src/dex/baseswap/uniswap-v3-pool.ts @@ -0,0 +1,519 @@ +import _ from 'lodash'; +import { Contract } from 'web3-eth-contract'; +import { Interface } from '@ethersproject/abi'; +import { ethers } from 'ethers'; +import { assert, DeepReadonly } from 'ts-essentials'; +import { Log, Logger, BlockHeader, Address } from '../../types'; +import { + InitializeStateOptions, + StatefulEventSubscriber, +} from '../../stateful-event-subscriber'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { + PoolState, + DecodedStateMultiCallResultWithRelativeBitmaps, + DecodeStateMultiCallFunc, +} from './types'; +import UniswapV3PoolABI from '../../abi/uniswap-v3/UniswapV3Pool.abi.json'; +import { bigIntify, catchParseLogError, isSampled } from '../../utils'; +import { uniswapV3Math } from './contract-math/uniswap-v3-math'; +import { MultiCallParams } from '../../lib/multi-wrapper'; +import { + OUT_OF_RANGE_ERROR_POSTFIX, + TICK_BITMAP_BUFFER, + TICK_BITMAP_TO_USE, +} from './constants'; +import { TickBitMap } from './contract-math/TickBitMap'; +import { uint256ToBigInt } from '../../lib/decoders'; +import { decodeStateMultiCallResultWithRelativeBitmaps } from './utils'; +import { _reduceTickBitmap, _reduceTicks } from './contract-math/utils'; + +export class UniswapV3EventPool extends StatefulEventSubscriber { + handlers: { + [event: string]: ( + event: any, + pool: PoolState, + log: Log, + blockHeader: Readonly, + ) => PoolState; + } = {}; + + logDecoder: (log: Log) => any; + + readonly token0: Address; + + readonly token1: Address; + + private _poolAddress?: Address; + + protected _stateRequestCallData?: MultiCallParams< + bigint | DecodedStateMultiCallResultWithRelativeBitmaps + >[]; + + public readonly poolIface = new Interface(UniswapV3PoolABI); + + public initFailed = false; + public initRetryAttemptCount = 0; + + public feeCodeAsString; + + constructor( + readonly dexHelper: IDexHelper, + parentName: string, + readonly stateMultiContract: Contract, + readonly decodeStateMultiCallResultWithRelativeBitmaps: + | DecodeStateMultiCallFunc + | undefined, + readonly erc20Interface: Interface, + protected readonly factoryAddress: Address, + public feeCode: bigint, + token0: Address, + token1: Address, + logger: Logger, + mapKey: string = '', + readonly poolInitCodeHash: string, + ) { + super( + parentName, + `${token0}_${token1}_${feeCode}`, + dexHelper, + logger, + true, + mapKey, + ); + this.feeCodeAsString = feeCode.toString(); + this.token0 = token0.toLowerCase(); + this.token1 = token1.toLowerCase(); + this.logDecoder = (log: Log) => this.poolIface.parseLog(log); + this.addressesSubscribed = new Array
(1); + + // Add handlers + this.handlers['Swap'] = this.handleSwapEvent.bind(this); + this.handlers['Burn'] = this.handleBurnEvent.bind(this); + this.handlers['Mint'] = this.handleMintEvent.bind(this); + this.handlers['SetFeeProtocol'] = this.handleSetFeeProtocolEvent.bind(this); + this.handlers['IncreaseObservationCardinalityNext'] = + this.handleIncreaseObservationCardinalityNextEvent.bind(this); + + // Wen need them to keep balance of the pool up to date + this.handlers['Collect'] = this.handleCollectEvent.bind(this); + // Almost the same as Collect, but for pool owners + this.handlers['CollectProtocol'] = this.handleCollectEvent.bind(this); + this.handlers['Flash'] = this.handleFlashEvent.bind(this); + } + + get poolAddress() { + if (this._poolAddress === undefined) { + this._poolAddress = this._computePoolAddress( + this.token0, + this.token1, + this.feeCode, + ); + } + return this._poolAddress; + } + + set poolAddress(address: Address) { + this._poolAddress = address.toLowerCase(); + } + + async initialize( + blockNumber: number, + options?: InitializeStateOptions, + ) { + await super.initialize(blockNumber, options); + } + + protected async processBlockLogs( + state: DeepReadonly, + logs: Readonly[], + blockHeader: Readonly, + ): Promise | null> { + const newState = await super.processBlockLogs(state, logs, blockHeader); + if (newState && !newState.isValid) { + return await this.generateState(blockHeader.number); + } + return newState; + } + + protected processLog( + state: DeepReadonly, + log: Readonly, + blockHeader: Readonly, + ): DeepReadonly | null { + try { + const event = this.logDecoder(log); + + const uniswapV3EventLoggingSampleRate = + this.dexHelper.config.data.uniswapV3EventLoggingSampleRate; + if ( + !this.dexHelper.config.isSlave && + uniswapV3EventLoggingSampleRate && + isSampled(uniswapV3EventLoggingSampleRate) + ) { + this.logger.info( + `event=${event.name} - block=${ + blockHeader.number + }. Log sampled at rate ${uniswapV3EventLoggingSampleRate * 100}%`, + ); + } + + if (event.name in this.handlers) { + // Because we have observations in array which is mutable by nature, there is a + // ts compile error: https://stackoverflow.com/questions/53412934/disable-allowing-assigning-readonly-types-to-non-readonly-types + // And there is no good workaround, so turn off the type checker for this line + const _state = _.cloneDeep(state) as PoolState; + try { + return this.handlers[event.name](event, _state, log, blockHeader); + } catch (e) { + if ( + e instanceof Error && + e.message.endsWith(OUT_OF_RANGE_ERROR_POSTFIX) + ) { + this.logger.warn( + `${this.parentName}: Pool ${this.poolAddress} on ${ + this.dexHelper.config.data.network + } is out of TickBitmap requested range. Re-query the state. ${JSON.stringify( + event, + )}`, + e, + ); + } else { + this.logger.error( + `${this.parentName}: Pool ${this.poolAddress}, ` + + `network=${this.dexHelper.config.data.network}: Unexpected ` + + `error while handling event on blockNumber=${blockHeader.number}, ` + + `blockHash=${blockHeader.hash} and parentHash=${ + blockHeader.parentHash + } for UniswapV3, ${JSON.stringify(event)}`, + e, + ); + } + _state.isValid = false; + return _state; + } + } + } catch (e) { + catchParseLogError(e, this.logger); + } + return null; // ignore unrecognized event + } + + protected _getStateRequestCallData() { + if (!this._stateRequestCallData) { + const callData: MultiCallParams< + bigint | DecodedStateMultiCallResultWithRelativeBitmaps + >[] = [ + { + target: this.token0, + callData: this.erc20Interface.encodeFunctionData('balanceOf', [ + this.poolAddress, + ]), + decodeFunction: uint256ToBigInt, + }, + { + target: this.token1, + callData: this.erc20Interface.encodeFunctionData('balanceOf', [ + this.poolAddress, + ]), + decodeFunction: uint256ToBigInt, + }, + { + target: this.stateMultiContract.options.address, + callData: this.stateMultiContract.methods + .getFullStateWithRelativeBitmaps( + this.factoryAddress, + this.token0, + this.token1, + this.feeCode, + this.getBitmapRangeToRequest(), + this.getBitmapRangeToRequest(), + ) + .encodeABI(), + decodeFunction: + this.decodeStateMultiCallResultWithRelativeBitmaps !== undefined + ? this.decodeStateMultiCallResultWithRelativeBitmaps + : decodeStateMultiCallResultWithRelativeBitmaps, + }, + ]; + + this._stateRequestCallData = callData; + } + return this._stateRequestCallData; + } + + getBitmapRangeToRequest() { + return TICK_BITMAP_TO_USE + TICK_BITMAP_BUFFER; + } + + async generateState(blockNumber: number): Promise> { + const callData = this._getStateRequestCallData(); + + const [resBalance0, resBalance1, resState] = + await this.dexHelper.multiWrapper.tryAggregate< + bigint | DecodedStateMultiCallResultWithRelativeBitmaps + >( + false, + callData, + blockNumber, + this.dexHelper.multiWrapper.defaultBatchSize, + false, + ); + + // Quite ugly solution, but this is the one that fits to current flow. + // I think UniswapV3 callbacks subscriptions are complexified for no reason. + // Need to be revisited later + assert(resState.success, 'Pool does not exist'); + + const [balance0, balance1, _state] = [ + resBalance0.returnData, + resBalance1.returnData, + resState.returnData, + ] as [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmaps]; + + const tickBitmap = {}; + const ticks = {}; + + _reduceTickBitmap(tickBitmap, _state.tickBitmap); + _reduceTicks(ticks, _state.ticks); + + const observations = { + [_state.slot0.observationIndex]: { + blockTimestamp: bigIntify(_state.observation.blockTimestamp), + tickCumulative: bigIntify(_state.observation.tickCumulative), + secondsPerLiquidityCumulativeX128: bigIntify( + _state.observation.secondsPerLiquidityCumulativeX128, + ), + initialized: _state.observation.initialized, + }, + }; + + const currentTick = bigIntify(_state.slot0.tick); + const tickSpacing = bigIntify(_state.tickSpacing); + + const startTickBitmap = TickBitMap.position(currentTick / tickSpacing)[0]; + const requestedRange = this.getBitmapRangeToRequest(); + + return { + pool: _state.pool, + blockTimestamp: bigIntify(_state.blockTimestamp), + slot0: { + sqrtPriceX96: bigIntify(_state.slot0.sqrtPriceX96), + tick: currentTick, + observationIndex: +_state.slot0.observationIndex, + observationCardinality: +_state.slot0.observationCardinality, + observationCardinalityNext: +_state.slot0.observationCardinalityNext, + feeProtocol: bigIntify(_state.slot0.feeProtocol), + }, + liquidity: bigIntify(_state.liquidity), + fee: this.feeCode, + tickSpacing, + maxLiquidityPerTick: bigIntify(_state.maxLiquidityPerTick), + tickBitmap, + ticks, + observations, + isValid: true, + startTickBitmap, + lowestKnownTick: + (BigInt.asIntN(24, startTickBitmap - requestedRange) << 8n) * + tickSpacing, + highestKnownTick: + ((BigInt.asIntN(24, startTickBitmap + requestedRange) << 8n) + + BigInt.asIntN(24, 255n)) * + tickSpacing, + balance0, + balance1, + }; + } + + handleSwapEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const newSqrtPriceX96 = bigIntify(event.args.sqrtPriceX96); + const amount0 = bigIntify(event.args.amount0); + const amount1 = bigIntify(event.args.amount1); + const newTick = bigIntify(event.args.tick); + const newLiquidity = bigIntify(event.args.liquidity); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + if (amount0 <= 0n && amount1 <= 0n) { + this.logger.error( + `${this.parentName}: amount0 <= 0n && amount1 <= 0n for ` + + `${this.poolAddress} and ${blockHeader.number}. Check why it happened`, + ); + pool.isValid = false; + return pool; + } else { + const zeroForOne = amount0 > 0n; + + uniswapV3Math.swapFromEvent( + pool, + newSqrtPriceX96, + newTick, + newLiquidity, + zeroForOne, + ); + + if (zeroForOne) { + if (amount1 < 0n) { + pool.balance1 -= BigInt.asUintN(256, -amount1); + } else { + this.logger.error( + `In swapEvent for pool ${pool.pool} received incorrect values ${zeroForOne} and ${amount1}`, + ); + pool.isValid = false; + } + // This is not correct fully, because pool may get more tokens then it needs, but + // it is not accounted in internal state, it should be good enough + pool.balance0 += BigInt.asUintN(256, amount0); + } else { + if (amount0 < 0n) { + pool.balance0 -= BigInt.asUintN(256, -amount0); + } else { + this.logger.error( + `In swapEvent for pool ${pool.pool} received incorrect values ${zeroForOne} and ${amount0}`, + ); + pool.isValid = false; + } + pool.balance1 += BigInt.asUintN(256, amount1); + } + + return pool; + } + } + + handleBurnEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const amount = bigIntify(event.args.amount); + const tickLower = bigIntify(event.args.tickLower); + const tickUpper = bigIntify(event.args.tickUpper); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + uniswapV3Math._modifyPosition(pool, { + tickLower, + tickUpper, + liquidityDelta: -BigInt.asIntN(128, BigInt.asIntN(256, amount)), + }); + + // From this transaction I conclude that there is no balance change from + // Burn event: https://dashboard.tenderly.co/tx/mainnet/0xfccf5341147ac3ad0e66452273d12dfc3219e81f8fb369a6cdecfb24b9b9d078/logs + // And it aligns with UniswapV3 doc: + // https://github.com/Uniswap/v3-core/blob/05c10bf6d547d6121622ac51c457f93775e1df09/contracts/interfaces/pool/IUniswapV3PoolActions.sol#L59 + // It just updates positions and tokensOwed which may be requested calling collect + // So, we don't need to update pool.balances0 and pool.balances1 here + + return pool; + } + + handleMintEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const amount = bigIntify(event.args.amount); + const tickLower = bigIntify(event.args.tickLower); + const tickUpper = bigIntify(event.args.tickUpper); + const amount0 = bigIntify(event.args.amount0); + const amount1 = bigIntify(event.args.amount1); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + uniswapV3Math._modifyPosition(pool, { + tickLower, + tickUpper, + liquidityDelta: amount, + }); + + pool.balance0 += amount0; + pool.balance1 += amount1; + + return pool; + } + + handleSetFeeProtocolEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const feeProtocol0 = bigIntify(event.args.feeProtocol0New); + const feeProtocol1 = bigIntify(event.args.feeProtocol1New); + pool.slot0.feeProtocol = feeProtocol0 + (feeProtocol1 << 4n); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + return pool; + } + + handleCollectEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const amount0 = bigIntify(event.args.amount0); + const amount1 = bigIntify(event.args.amount1); + pool.balance0 -= amount0; + pool.balance1 -= amount1; + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + return pool; + } + + handleFlashEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + const paid0 = bigIntify(event.args.paid0); + const paid1 = bigIntify(event.args.paid1); + pool.balance0 += paid0; + pool.balance1 += paid1; + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + + return pool; + } + + handleIncreaseObservationCardinalityNextEvent( + event: any, + pool: PoolState, + log: Log, + blockHeader: BlockHeader, + ) { + pool.slot0.observationCardinalityNext = parseInt( + event.args.observationCardinalityNextNew, + 10, + ); + pool.blockTimestamp = bigIntify(blockHeader.timestamp); + return pool; + } + + private _computePoolAddress( + token0: Address, + token1: Address, + fee: bigint, + ): Address { + // https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/PoolAddress.sol + if (token0 > token1) [token0, token1] = [token1, token0]; + + const encodedKey = ethers.utils.keccak256( + ethers.utils.defaultAbiCoder.encode( + ['address', 'address', 'uint24'], + [token0, token1, BigInt.asUintN(24, fee)], + ), + ); + + return ethers.utils.getCreate2Address( + this.factoryAddress, + encodedKey, + this.poolInitCodeHash, + ); + } +} diff --git a/src/dex/baseswap/uniswap-v3.ts b/src/dex/baseswap/uniswap-v3.ts new file mode 100644 index 000000000..ebb921b4f --- /dev/null +++ b/src/dex/baseswap/uniswap-v3.ts @@ -0,0 +1,1247 @@ +import { defaultAbiCoder, Interface } from '@ethersproject/abi'; +import _ from 'lodash'; +import { pack } from '@ethersproject/solidity'; +import { + AdapterExchangeParam, + Address, + ExchangePrices, + ExchangeTxInfo, + Logger, + NumberAsString, + PoolLiquidity, + PoolPrices, + PreprocessTransactionOptions, + SimpleExchangeParam, + Token, + TxInfo, +} from '../../types'; +import { CACHE_PREFIX, Network, SwapSide } from '../../constants'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { + getBigIntPow, + getDexKeysWithNetwork, + interpolate, + isTruthy, + uuidToBytes16, +} from '../../utils'; +import { IDex } from '../../dex/idex'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { + DexParams, + OutputResult, + PoolState, + UniswapV3Data, + UniswapV3Functions, + UniswapV3Param, + UniswapV3SimpleSwapParams, +} from './types'; +import { + getLocalDeadlineAsFriendlyPlaceholder, + SimpleExchange, +} from '../simple-exchange'; +import { Adapters, PoolsToPreload, BaseswapV3Config } from './config'; +import { UniswapV3EventPool } from './uniswap-v3-pool'; +import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; +import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; +import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; +import DirectSwapABI from '../../abi/DirectSwap.json'; +import UniswapV3StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; +import { + DirectMethods, + UNISWAPV3_EFFICIENCY_FACTOR, + UNISWAPV3_POOL_SEARCH_OVERHEAD, + UNISWAPV3_TICK_BASE_OVERHEAD, + UNISWAPV3_TICK_GAS_COST, +} from './constants'; +import { assert, DeepReadonly } from 'ts-essentials'; +import { uniswapV3Math } from './contract-math/uniswap-v3-math'; +import { Contract } from 'web3-eth-contract'; +import { AbiItem } from 'web3-utils'; +import { BalanceRequest, getBalances } from '../../lib/tokens/balancer-fetcher'; +import { + AssetType, + DEFAULT_ID_ERC20, + DEFAULT_ID_ERC20_AS_STRING, +} from '../../lib/tokens/types'; +import { OptimalSwapExchange } from '@paraswap/core'; +import { OnPoolCreatedCallback, UniswapV3Factory } from './uniswap-v3-factory'; + +type PoolPairsInfo = { + token0: Address; + token1: Address; + fee: string; +}; + +const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 3 * 24 * 60 * 60 * 1000; // 3 days +const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 24 * 60 * 60 * 1000; // Once in a day +const UNISWAPV3_QUOTE_GASLIMIT = 200_000; + +export class UniswapV3 + extends SimpleExchange + implements IDex +{ + private readonly factory: UniswapV3Factory; + readonly isFeeOnTransferSupported: boolean = false; + readonly eventPools: Record = {}; + + readonly hasConstantPriceLargeAmounts = false; + readonly needWrapNative = true; + + readonly directSwapIface = new Interface(DirectSwapABI); + + intervalTask?: NodeJS.Timeout; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork( + _.pick(BaseswapV3Config, [ + 'UniswapV3', + 'SushiSwapV3', + 'QuickSwapV3.1', + 'RamsesV2', + 'ChronosV3', + 'Retro', + ]), + ); + + logger: Logger; + + private uniswapMulti: Contract; + private stateMultiContract: Contract; + + private notExistingPoolSetKey: string; + + constructor( + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + protected adapters = Adapters[network] || {}, + readonly routerIface = new Interface(UniswapV3RouterABI), + readonly quoterIface = new Interface(UniswapV3QuoterV2ABI), + protected config = BaseswapV3Config[dexKey][network], + protected poolsToPreload = PoolsToPreload[dexKey]?.[network] || [], + ) { + super(dexHelper, dexKey); + this.logger = dexHelper.getLogger(dexKey + '-' + network); + this.uniswapMulti = new this.dexHelper.web3Provider.eth.Contract( + UniswapV3MultiABI as AbiItem[], + this.config.uniswapMulticall, + ); + this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( + this.config.stateMultiCallAbi !== undefined + ? this.config.stateMultiCallAbi + : (UniswapV3StateMulticallABI as AbiItem[]), + this.config.stateMulticall, + ); + + // To receive revert reasons + this.dexHelper.web3Provider.eth.handleRevert = false; + + // Normalize once all config addresses and use across all scenarios + this.config = this._toLowerForAllConfigAddresses(); + + this.notExistingPoolSetKey = + `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); + + this.factory = new UniswapV3Factory( + dexHelper, + dexKey, + this.config.factory, + this.logger, + this.onPoolCreatedDeleteFromNonExistingSet, + ); + } + + get supportedFees() { + return this.config.supportedFees; + } + + getAdapters(side: SwapSide): { name: string; index: number }[] | null { + return this.adapters[side] ? this.adapters[side] : null; + } + + getPoolIdentifier(srcAddress: Address, destAddress: Address, fee: bigint) { + const tokenAddresses = this._sortTokens(srcAddress, destAddress).join('_'); + return `${this.dexKey}_${tokenAddresses}_${fee}`; + } + + async initializePricing(blockNumber: number) { + // Init listening to new pools creation + await this.factory.initialize(blockNumber); + + // This is only for testing, because cold pool fetching is goes out of + // FETCH_POOL_INDENTIFIER_TIMEOUT range + await Promise.all( + this.poolsToPreload.map(async pool => + Promise.all( + this.config.supportedFees.map(async fee => + this.getPool(pool.token0, pool.token1, fee, blockNumber), + ), + ), + ), + ); + + if (!this.dexHelper.config.isSlave) { + const cleanExpiredNotExistingPoolsKeys = async () => { + const maxTimestamp = + Date.now() - UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS; + await this.dexHelper.cache.zremrangebyscore( + this.notExistingPoolSetKey, + 0, + maxTimestamp, + ); + }; + + this.intervalTask = setInterval( + cleanExpiredNotExistingPoolsKeys.bind(this), + UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS, + ); + } + } + + /* + * When a non existing pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls + * Once the pool is created, it gets immediately flagged + */ + onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ + token0, + token1, + fee, + }) => { + const logPrefix = '[UniswapV3.onPoolCreatedDeleteFromNonExistingSet]'; + const [_token0, _token1] = this._sortTokens(token0, token1); + const poolKey = `${_token0}_${_token1}_${fee}`; + + // consider doing it only from master pool for less calls to distant cache + + // delete entry locally to let local instance discover the pool + delete this.eventPools[this.getPoolIdentifier(_token0, _token1, fee)]; + + try { + this.logger.info( + `${logPrefix} delete pool from not existing set: ${poolKey}`, + ); + // delete pool record from set + await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); + } catch (error) { + this.logger.error( + `${logPrefix} failed to delete pool from set: ${poolKey}`, + error, + ); + } + }; + + async getPool( + srcAddress: Address, + destAddress: Address, + fee: bigint, + blockNumber: number, + ): Promise { + let pool = this.eventPools[ + this.getPoolIdentifier(srcAddress, destAddress, fee) + ] as UniswapV3EventPool | null | undefined; + + if (pool === null) return null; + + if (pool) { + if (!pool.initFailed) { + return pool; + } else { + // if init failed then prefer to early return pool with empty state to fallback to rpc call + if ( + ++pool.initRetryAttemptCount % this.config.initRetryFrequency !== + 0 + ) { + return pool; + } + // else pursue with re-try initialization + } + } + + const [token0, token1] = this._sortTokens(srcAddress, destAddress); + + const key = `${token0}_${token1}_${fee}`.toLowerCase(); + + if (!pool) { + const notExistingPoolScore = await this.dexHelper.cache.zscore( + this.notExistingPoolSetKey, + key, + ); + + const poolDoesNotExist = notExistingPoolScore !== null; + + if (poolDoesNotExist) { + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = + null; + return null; + } + + await this.dexHelper.cache.hset( + this.dexmapKey, + key, + JSON.stringify({ + token0, + token1, + fee: fee.toString(), + }), + ); + } + + this.logger.trace(`starting to listen to new pool: ${key}`); + const poolImplementation = + this.config.eventPoolImplementation !== undefined + ? this.config.eventPoolImplementation + : UniswapV3EventPool; + pool = + pool || + new poolImplementation( + this.dexHelper, + this.dexKey, + this.stateMultiContract, + this.config.decodeStateMultiCallResultWithRelativeBitmaps, + this.erc20Interface, + this.config.factory, + fee, + token0, + token1, + this.logger, + this.cacheStateKey, + this.config.initHash, + ); + + try { + await pool.initialize(blockNumber, { + initCallback: (state: DeepReadonly) => { + //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber + pool!.addressesSubscribed[0] = state.pool; + pool!.poolAddress = state.pool; + pool!.initFailed = false; + pool!.initRetryAttemptCount = 0; + }, + }); + } catch (e) { + if (e instanceof Error && e.message.endsWith('Pool does not exist')) { + // no need to await we want the set to have the pool key but it's not blocking + this.dexHelper.cache.zadd( + this.notExistingPoolSetKey, + [Date.now(), key], + 'NX', + ); + + // Pool does not exist for this feeCode, so we can set it to null + // to prevent more requests for this pool + pool = null; + this.logger.trace( + `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, + e, + ); + } else { + // on unknown error mark as failed and increase retryCount for retry init strategy + // note: state would be null by default which allows to fallback + this.logger.warn( + `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, + e, + ); + pool.initFailed = true; + } + } + + if (pool !== null) { + const allEventPools = Object.values(this.eventPools); + this.logger.info( + `starting to listen to new non-null pool: ${key}. Already following ${allEventPools + // Not that I like this reduce, but since it is done only on initialization, expect this to be ok + .reduce( + (acc, curr) => (curr !== null ? ++acc : acc), + 0, + )} non-null pools or ${allEventPools.length} total pools`, + ); + } + + this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = + pool; + return pool; + } + + async addMasterPool(poolKey: string, blockNumber: number): Promise { + const _pairs = await this.dexHelper.cache.hget(this.dexmapKey, poolKey); + if (!_pairs) { + this.logger.warn( + `did not find poolConfig in for key ${this.dexmapKey} ${poolKey}`, + ); + return false; + } + + const poolInfo: PoolPairsInfo = JSON.parse(_pairs); + + const pool = await this.getPool( + poolInfo.token0, + poolInfo.token1, + BigInt(poolInfo.fee), + blockNumber, + ); + + if (!pool) { + return false; + } + + return true; + } + + async getPoolIdentifiers( + srcToken: Token, + destToken: Token, + side: SwapSide, + blockNumber: number, + ): Promise { + const _srcToken = this.dexHelper.config.wrapETH(srcToken); + const _destToken = this.dexHelper.config.wrapETH(destToken); + + const [_srcAddress, _destAddress] = this._getLoweredAddresses( + _srcToken, + _destToken, + ); + + if (_srcAddress === _destAddress) return []; + + const pools = ( + await Promise.all( + this.supportedFees.map(async fee => + this.getPool(_srcAddress, _destAddress, fee, blockNumber), + ), + ) + ).filter(pool => pool); + + if (pools.length === 0) return []; + + return pools.map(pool => + this.getPoolIdentifier(_srcAddress, _destAddress, pool!.feeCode), + ); + } + + async getPricingFromRpc( + from: Token, + to: Token, + amounts: bigint[], + side: SwapSide, + pools: UniswapV3EventPool[], + states: PoolState[], + ): Promise | null> { + if (pools.length === 0) { + return null; + } + this.logger.warn(`fallback to rpc for ${pools.length} pool(s)`); + + const requests = pools.map( + pool => ({ + owner: pool.poolAddress, + asset: side == SwapSide.SELL ? from.address : to.address, + assetType: AssetType.ERC20, + ids: [ + { + id: DEFAULT_ID_ERC20, + spenders: [], + }, + ], + }), + [], + ); + + const balances = await getBalances(this.dexHelper.multiWrapper, requests); + + pools = pools.filter((pool, index) => { + const balance = balances[index].amounts[DEFAULT_ID_ERC20_AS_STRING]; + if (balance >= amounts[amounts.length - 1]) { + return true; + } + this.logger.warn( + `[${this.network}][${pool.parentName}] have no balance ${pool.poolAddress} ${from.address} ${to.address}. (Balance: ${balance})`, + ); + return false; + }); + + pools.forEach(pool => { + this.logger.warn( + `[${this.network}][${pool.parentName}] fallback to rpc for ${pool.name}`, + ); + }); + + const unitVolume = getBigIntPow( + (side === SwapSide.SELL ? from : to).decimals, + ); + + const chunks = amounts.length - 1; + + const _width = Math.floor(chunks / this.config.chunksCount); + + const _amounts = [unitVolume].concat( + Array.from(Array(this.config.chunksCount).keys()).map( + i => amounts[(i + 1) * _width], + ), + ); + + const calldata = pools.map(pool => + _amounts.map(_amount => ({ + target: this.config.quoter, + gasLimit: UNISWAPV3_QUOTE_GASLIMIT, + callData: + side === SwapSide.SELL + ? this.quoterIface.encodeFunctionData('quoteExactInputSingle', [ + [ + from.address, + to.address, + _amount.toString(), + pool.feeCodeAsString, + 0, //sqrtPriceLimitX96 + ], + ]) + : this.quoterIface.encodeFunctionData('quoteExactOutputSingle', [ + [ + from.address, + to.address, + _amount.toString(), + pool.feeCodeAsString, + 0, //sqrtPriceLimitX96 + ], + ]), + })), + ); + + const data = await this.uniswapMulti.methods + .multicall(calldata.flat()) + .call(); + + const decode = (j: number): bigint => { + if (!data.returnData[j].success) { + return 0n; + } + const decoded = defaultAbiCoder.decode( + ['uint256'], + data.returnData[j].returnData, + ); + return BigInt(decoded[0].toString()); + }; + + let i = 0; + const result = pools.map((pool, index) => { + const _rates = _amounts.map(() => decode(i++)); + const unit: bigint = _rates[0]; + + const prices = interpolate( + _amounts.slice(1), + _rates.slice(1), + amounts, + side, + ); + + return { + prices, + unit, + data: { + path: [ + { + tokenIn: from.address, + tokenOut: to.address, + fee: pool.feeCodeAsString, + currentFee: states[index].fee.toString(), + }, + ], + exchange: pool.poolAddress, + }, + poolIdentifier: this.getPoolIdentifier( + pool.token0, + pool.token1, + pool.feeCode, + ), + exchange: this.dexKey, + gasCost: prices.map(p => (p === 0n ? 0 : UNISWAPV3_QUOTE_GASLIMIT)), + poolAddresses: [pool.poolAddress], + }; + }); + + return result; + } + + async getPricesVolume( + srcToken: Token, + destToken: Token, + amounts: bigint[], + side: SwapSide, + blockNumber: number, + limitPools?: string[], + ): Promise> { + try { + const _srcToken = this.dexHelper.config.wrapETH(srcToken); + const _destToken = this.dexHelper.config.wrapETH(destToken); + + const [_srcAddress, _destAddress] = this._getLoweredAddresses( + _srcToken, + _destToken, + ); + + if (_srcAddress === _destAddress) return null; + + let selectedPools: UniswapV3EventPool[] = []; + + if (!limitPools) { + selectedPools = ( + await Promise.all( + this.supportedFees.map(async fee => { + const locallyFoundPool = + this.eventPools[ + this.getPoolIdentifier(_srcAddress, _destAddress, fee) + ]; + if (locallyFoundPool) return locallyFoundPool; + + const newlyFetchedPool = await this.getPool( + _srcAddress, + _destAddress, + fee, + blockNumber, + ); + return newlyFetchedPool; + }), + ) + ).filter(isTruthy); + } else { + const pairIdentifierWithoutFee = this.getPoolIdentifier( + _srcAddress, + _destAddress, + 0n, + // Trim from 0 fee postfix, so it become comparable + ).slice(0, -1); + + const poolIdentifiers = limitPools.filter(identifier => + identifier.startsWith(pairIdentifierWithoutFee), + ); + + selectedPools = ( + await Promise.all( + poolIdentifiers.map(async identifier => { + let locallyFoundPool = this.eventPools[identifier]; + if (locallyFoundPool) return locallyFoundPool; + + const [, srcAddress, destAddress, fee] = identifier.split('_'); + const newlyFetchedPool = await this.getPool( + srcAddress, + destAddress, + BigInt(fee), + blockNumber, + ); + return newlyFetchedPool; + }), + ) + ).filter(isTruthy); + } + + if (selectedPools.length === 0) return null; + + const poolsToUse = selectedPools.reduce( + (acc, pool) => { + let state = pool.getState(blockNumber); + if (state === null) { + this.logger.trace( + `${this.dexKey}: State === null. Fallback to rpc ${pool.name}`, + ); + acc.poolWithoutState.push(pool); + } else { + acc.poolWithState.push(pool); + } + return acc; + }, + { + poolWithState: [] as UniswapV3EventPool[], + poolWithoutState: [] as UniswapV3EventPool[], + }, + ); + + const states = poolsToUse.poolWithState.map( + p => p.getState(blockNumber)!, + ); + + const rpcResultsPromise = this.getPricingFromRpc( + _srcToken, + _destToken, + amounts, + side, + this.network === Network.ZKEVM ? [] : poolsToUse.poolWithoutState, + this.network === Network.ZKEVM ? [] : states, + ); + + const unitAmount = getBigIntPow( + side == SwapSide.SELL ? _srcToken.decimals : _destToken.decimals, + ); + + const _amounts = [...amounts.slice(1)]; + + const [token0] = this._sortTokens(_srcAddress, _destAddress); + + const zeroForOne = token0 === _srcAddress ? true : false; + + const result = await Promise.all( + poolsToUse.poolWithState.map(async (pool, i) => { + const state = states[i]; + + if (state.liquidity <= 0n) { + if (state.liquidity < 0) { + this.logger.error( + `${this.dexKey}-${this.network}: ${pool.poolAddress} pool has negative liquidity: ${state.liquidity}. Find with key: ${pool.mapKey}`, + ); + } + this.logger.trace(`pool have 0 liquidity`); + return null; + } + + const balanceDestToken = + _destAddress === pool.token0 ? state.balance0 : state.balance1; + + const unitResult = this._getOutputs( + state, + [unitAmount], + zeroForOne, + side, + balanceDestToken, + ); + const pricesResult = this._getOutputs( + state, + _amounts, + zeroForOne, + side, + balanceDestToken, + ); + + if (!unitResult || !pricesResult) { + this.logger.debug('Prices or unit is not calculated'); + return null; + } + + const prices = [0n, ...pricesResult.outputs]; + const gasCost = [ + 0, + ...pricesResult.outputs.map((p, index) => { + if (p == 0n) { + return 0; + } else { + return ( + UNISWAPV3_POOL_SEARCH_OVERHEAD + + UNISWAPV3_TICK_BASE_OVERHEAD + + pricesResult.tickCounts[index] * UNISWAPV3_TICK_GAS_COST + ); + } + }), + ]; + return { + unit: unitResult.outputs[0], + prices, + data: { + path: [ + { + tokenIn: _srcAddress, + tokenOut: _destAddress, + fee: pool.feeCode.toString(), + currentFee: state.fee.toString(), + }, + ], + }, + poolIdentifier: this.getPoolIdentifier( + pool.token0, + pool.token1, + pool.feeCode, + ), + exchange: this.dexKey, + gasCost: gasCost, + poolAddresses: [pool.poolAddress], + }; + }), + ); + const rpcResults = await rpcResultsPromise; + + const notNullResult = result.filter( + res => res !== null, + ) as ExchangePrices; + + if (rpcResults) { + rpcResults.forEach(r => { + if (r) { + notNullResult.push(r); + } + }); + } + + return notNullResult; + } catch (e) { + this.logger.error( + `Error_getPricesVolume ${srcToken.symbol || srcToken.address}, ${ + destToken.symbol || destToken.address + }, ${side}:`, + e, + ); + return null; + } + } + + getAdapterParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: UniswapV3Data, + side: SwapSide, + ): AdapterExchangeParam { + const { path: rawPath } = data; + const path = this._encodePath(rawPath, side); + + const payload = this.abiCoder.encodeParameter( + { + ParentStruct: { + path: 'bytes', + deadline: 'uint256', + }, + }, + { + path, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), // FIXME: more gas efficient to pass block.timestamp in adapter + }, + ); + + return { + targetExchange: this.config.router, + payload, + networkFee: '0', + }; + } + + getCalldataGasCost(poolPrices: PoolPrices): number | number[] { + const gasCost = + CALLDATA_GAS_COST.DEX_OVERHEAD + + CALLDATA_GAS_COST.LENGTH_SMALL + + // ParentStruct header + CALLDATA_GAS_COST.OFFSET_SMALL + + // ParentStruct -> path header + CALLDATA_GAS_COST.OFFSET_SMALL + + // ParentStruct -> deadline + CALLDATA_GAS_COST.TIMESTAMP + + // ParentStruct -> path (20+3+20 = 43 = 32+11 bytes) + CALLDATA_GAS_COST.LENGTH_SMALL + + CALLDATA_GAS_COST.FULL_WORD + + CALLDATA_GAS_COST.wordNonZeroBytes(11); + const arr = new Array(poolPrices.prices.length); + poolPrices.prices.forEach((p, index) => { + if (p == 0n) { + arr[index] = 0; + } else { + arr[index] = gasCost; + } + }); + return arr; + } + + getTokenFromAddress(address: Address): Token { + // In this Dex decimals are not used + return { address, decimals: 0 }; + } + + async preProcessTransaction( + optimalSwapExchange: OptimalSwapExchange, + srcToken: Token, + _0: Token, + _1: SwapSide, + options: PreprocessTransactionOptions, + ): Promise<[OptimalSwapExchange, ExchangeTxInfo]> { + if (!options.isDirectMethod) { + return [ + optimalSwapExchange, + { + deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), + }, + ]; + } + + assert( + optimalSwapExchange.data !== undefined, + `preProcessTransaction: data field is missing`, + ); + + let isApproved: boolean | undefined; + + try { + this.erc20Contract.options.address = + this.dexHelper.config.wrapETH(srcToken).address; + const allowance = await this.erc20Contract.methods + .allowance(this.augustusAddress, this.config.router) + .call(undefined, 'latest'); + isApproved = + BigInt(allowance.toString()) >= BigInt(optimalSwapExchange.srcAmount); + } catch (e) { + this.logger.error( + `preProcessTransaction failed to retrieve allowance info: `, + e, + ); + } + + return [ + { + ...optimalSwapExchange, + data: { + ...optimalSwapExchange.data, + isApproved, + }, + }, + { + deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), + }, + ]; + } + + getDirectParam( + srcToken: Address, + destToken: Address, + srcAmount: NumberAsString, + destAmount: NumberAsString, + expectedAmount: NumberAsString, + data: UniswapV3Data, + side: SwapSide, + permit: string, + uuid: string, + feePercent: NumberAsString, + deadline: NumberAsString, + partner: string, + beneficiary: string, + contractMethod?: string, + ): TxInfo { + if ( + contractMethod !== DirectMethods.directSell && + contractMethod !== DirectMethods.directBuy + ) { + throw new Error(`Invalid contract method ${contractMethod}`); + } + + let isApproved: boolean = !!data.isApproved; + if (data.isApproved === undefined) { + this.logger.warn(`isApproved is undefined, defaulting to false`); + } + + const path = this._encodePath(data.path, side); + + const swapParams: UniswapV3Param = [ + srcToken, + destToken, + this.config.router, + srcAmount, + destAmount, + expectedAmount, + feePercent, + deadline, + partner, + isApproved, + beneficiary, + path, + permit, + uuidToBytes16(uuid), + ]; + + const encoder = (...params: UniswapV3Param) => { + return this.directSwapIface.encodeFunctionData( + side === SwapSide.SELL + ? DirectMethods.directSell + : DirectMethods.directBuy, + [params], + ); + }; + + return { + params: swapParams, + encoder, + networkFee: '0', + }; + } + + static getDirectFunctionName(): string[] { + return [DirectMethods.directSell, DirectMethods.directBuy]; + } + + async getSimpleParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: UniswapV3Data, + side: SwapSide, + ): Promise { + const swapFunction = + side === SwapSide.SELL + ? UniswapV3Functions.exactInput + : UniswapV3Functions.exactOutput; + + const path = this._encodePath(data.path, side); + const swapFunctionParams: UniswapV3SimpleSwapParams = + side === SwapSide.SELL + ? { + recipient: this.augustusAddress, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), + amountIn: srcAmount, + amountOutMinimum: destAmount, + path, + } + : { + recipient: this.augustusAddress, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), + amountOut: destAmount, + amountInMaximum: srcAmount, + path, + }; + const swapData = this.routerIface.encodeFunctionData(swapFunction, [ + swapFunctionParams, + ]); + + return this.buildSimpleParamWithoutWETHConversion( + srcToken, + srcAmount, + destToken, + destAmount, + swapData, + this.config.router, + ); + } + + async getTopPoolsForToken( + tokenAddress: Address, + limit: number, + ): Promise { + const _tokenAddress = tokenAddress.toLowerCase(); + + const res = await this._querySubgraph( + `query ($token: Bytes!, $count: Int) { + pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + }`, + { + token: _tokenAddress, + count: limit, + }, + ); + + if (!(res && res.pools0 && res.pools1)) { + this.logger.error( + `Error_${this.dexKey}_Subgraph: couldn't fetch the pools from the subgraph`, + ); + return []; + } + + const pools0 = _.map(res.pools0, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token1.id.toLowerCase(), + decimals: parseInt(pool.token1.decimals), + }, + ], + liquidityUSD: + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + })); + + const pools1 = _.map(res.pools1, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token0.id.toLowerCase(), + decimals: parseInt(pool.token0.decimals), + }, + ], + liquidityUSD: + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + })); + + const pools = _.slice( + _.sortBy(_.concat(pools0, pools1), [pool => -1 * pool.liquidityUSD]), + 0, + limit, + ); + return pools; + } + + private async _getPoolsFromIdentifiers( + poolIdentifiers: string[], + blockNumber: number, + ): Promise { + const pools = await Promise.all( + poolIdentifiers.map(async identifier => { + const [, srcAddress, destAddress, fee] = identifier.split('_'); + return this.getPool(srcAddress, destAddress, BigInt(fee), blockNumber); + }), + ); + return pools.filter(pool => pool) as UniswapV3EventPool[]; + } + + private _getLoweredAddresses(srcToken: Token, destToken: Token) { + return [srcToken.address.toLowerCase(), destToken.address.toLowerCase()]; + } + + private _sortTokens(srcAddress: Address, destAddress: Address) { + return [srcAddress, destAddress].sort((a, b) => (a < b ? -1 : 1)); + } + + private _toLowerForAllConfigAddresses() { + // If new config property will be added, the TS will throw compile error + const newConfig: DexParams = { + router: this.config.router.toLowerCase(), + quoter: this.config.quoter.toLowerCase(), + factory: this.config.factory.toLowerCase(), + supportedFees: this.config.supportedFees, + stateMulticall: this.config.stateMulticall.toLowerCase(), + chunksCount: this.config.chunksCount, + initRetryFrequency: this.config.initRetryFrequency, + uniswapMulticall: this.config.uniswapMulticall, + deployer: this.config.deployer?.toLowerCase(), + initHash: this.config.initHash, + subgraphURL: this.config.subgraphURL, + stateMultiCallAbi: this.config.stateMultiCallAbi, + eventPoolImplementation: this.config.eventPoolImplementation, + decodeStateMultiCallResultWithRelativeBitmaps: + this.config.decodeStateMultiCallResultWithRelativeBitmaps, + }; + return newConfig; + } + + private _getOutputs( + state: DeepReadonly, + amounts: bigint[], + zeroForOne: boolean, + side: SwapSide, + destTokenBalance: bigint, + ): OutputResult | null { + try { + const outputsResult = uniswapV3Math.queryOutputs( + state, + amounts, + zeroForOne, + side, + ); + + if (side === SwapSide.SELL) { + if (outputsResult.outputs[0] > destTokenBalance) { + return null; + } + + for (let i = 0; i < outputsResult.outputs.length; i++) { + if (outputsResult.outputs[i] > destTokenBalance) { + outputsResult.outputs[i] = 0n; + outputsResult.tickCounts[i] = 0; + } + } + } else { + if (amounts[0] > destTokenBalance) { + return null; + } + + // This may be improved by first checking outputs and requesting outputs + // only for amounts that makes more sense, but I don't think this is really + // important now + for (let i = 0; i < amounts.length; i++) { + if (amounts[i] > destTokenBalance) { + outputsResult.outputs[i] = 0n; + outputsResult.tickCounts[i] = 0; + } + } + } + + return outputsResult; + } catch (e) { + this.logger.debug( + `${this.dexKey}: received error in _getOutputs while calculating outputs`, + e, + ); + return null; + } + } + + private async _querySubgraph( + query: string, + variables: Object, + timeout = 30000, + ) { + try { + const res = await this.dexHelper.httpRequest.post( + this.config.subgraphURL, + { query, variables }, + undefined, + { timeout: timeout }, + ); + return res.data; + } catch (e) { + this.logger.error(`${this.dexKey}: can not query subgraph: `, e); + return {}; + } + } + + private _encodePath( + path: { + tokenIn: Address; + tokenOut: Address; + fee: NumberAsString; + }[], + side: SwapSide, + ): string { + if (path.length === 0) { + this.logger.error( + `${this.dexKey}: Received invalid path=${path} for side=${side} to encode`, + ); + return '0x'; + } + + const { _path, types } = path.reduce( + ( + { _path, types }: { _path: string[]; types: string[] }, + curr, + index, + ): { _path: string[]; types: string[] } => { + if (index === 0) { + return { + types: ['address', 'uint24', 'address'], + _path: [curr.tokenIn, curr.fee, curr.tokenOut], + }; + } else { + return { + types: [...types, 'uint24', 'address'], + _path: [..._path, curr.fee, curr.tokenOut], + }; + } + }, + { _path: [], types: [] }, + ); + + return side === SwapSide.BUY + ? pack(types.reverse(), _path.reverse()) + : pack(types, _path); + } + + releaseResources() { + if (this.intervalTask !== undefined) { + clearInterval(this.intervalTask); + this.intervalTask = undefined; + } + } +} diff --git a/src/dex/baseswap/utils.ts b/src/dex/baseswap/utils.ts new file mode 100644 index 000000000..afd953e07 --- /dev/null +++ b/src/dex/baseswap/utils.ts @@ -0,0 +1,83 @@ +import { BytesLike, ethers } from 'ethers'; +import { assert } from 'ts-essentials'; +import { extractSuccessAndValue } from '../../lib/decoders'; +import { MultiResult } from '../../lib/multi-wrapper'; +import { DexConfigMap } from '../../types'; +import { + DexParams, + DecodedStateMultiCallResultWithRelativeBitmaps, +} from './types'; + +export function getUniswapV3DexKey(UniswapV3Config: DexConfigMap) { + const UniswapV3Keys = Object.keys(UniswapV3Config); + if (UniswapV3Keys.length !== 1) { + throw new Error( + `UniswapV3 key in UniswapV3Config is not unique. Update relevant places (optimizer) or fix config issue. Received: ${JSON.stringify( + UniswapV3Config, + (_0, value) => (typeof value === 'bigint' ? value.toString() : value), + )}`, + ); + } + + return UniswapV3Keys[0].toLowerCase(); +} + +export function decodeStateMultiCallResultWithRelativeBitmaps( + result: MultiResult | BytesLike, +): DecodedStateMultiCallResultWithRelativeBitmaps { + const [isSuccess, toDecode] = extractSuccessAndValue(result); + + assert( + isSuccess && toDecode !== '0x', + `decodeStateMultiCallResultWithRelativeBitmaps failed to get decodable result: ${result}`, + ); + + const decoded = ethers.utils.defaultAbiCoder.decode( + [ + // I don't want to pass here any interface, so I just use it in ethers format + ` + tuple( + address pool, + uint256 blockTimestamp, + tuple( + uint160 sqrtPriceX96, + int24 tick, + uint16 observationIndex, + uint16 observationCardinality, + uint16 observationCardinalityNext, + uint8 feeProtocol, + bool unlocked, + ) slot0, + uint128 liquidity, + int24 tickSpacing, + uint128 maxLiquidityPerTick, + tuple( + uint32 blockTimestamp, + int56 tickCumulative, + uint160 secondsPerLiquidityCumulativeX128, + bool initialized, + ) observation, + tuple( + int16 index, + uint256 value, + )[] tickBitmap, + tuple( + int24 index, + tuple( + uint128 liquidityGross, + int128 liquidityNet, + int56 tickCumulativeOutside, + uint160 secondsPerLiquidityOutsideX128, + uint32 secondsOutside, + bool initialized, + ) value, + )[] ticks + ) + `, + ], + toDecode, + )[0]; + // This conversion is not precise, because when we decode, we have more values + // But I typed only the ones that are used later + return decoded as DecodedStateMultiCallResultWithRelativeBitmaps; +} From f6cbf73f33d3a3dce2650047b82a62fcfadaf128 Mon Sep 17 00:00:00 2001 From: 0xshoehazer <0xshoehazer@gmail.com> Date: Tue, 17 Oct 2023 17:56:29 -0400 Subject: [PATCH 502/833] base items --- ...p-v3-factory.ts => baseswap-v3-factory.ts} | 2 +- ...uniswap-v3-pool.ts => baseswap-v3-pool.ts} | 2 +- .../{uniswap-v3.ts => baseswap-v3.ts} | 36 ++++++++++--------- src/dex/baseswap/config.ts | 14 ++++---- src/dex/baseswap/constants.ts | 2 +- src/dex/baseswap/types.ts | 4 +-- 6 files changed, 32 insertions(+), 28 deletions(-) rename src/dex/baseswap/{uniswap-v3-factory.ts => baseswap-v3-factory.ts} (96%) rename src/dex/baseswap/{uniswap-v3-pool.ts => baseswap-v3-pool.ts} (99%) rename src/dex/baseswap/{uniswap-v3.ts => baseswap-v3.ts} (97%) diff --git a/src/dex/baseswap/uniswap-v3-factory.ts b/src/dex/baseswap/baseswap-v3-factory.ts similarity index 96% rename from src/dex/baseswap/uniswap-v3-factory.ts rename to src/dex/baseswap/baseswap-v3-factory.ts index 372020de4..93b79f3a5 100644 --- a/src/dex/baseswap/uniswap-v3-factory.ts +++ b/src/dex/baseswap/baseswap-v3-factory.ts @@ -21,7 +21,7 @@ export type OnPoolCreatedCallback = ({ * "Stateless" event subscriber in order to capture "PoolCreated" event on new pools created. * State is present, but it's a placeholder to actually make the events reach handlers (if there's no previous state - `processBlockLogs` is not called) */ -export class UniswapV3Factory extends StatefulEventSubscriber { +export class BaseswapV3Factory extends StatefulEventSubscriber { handlers: { [event: string]: (event: any) => Promise; } = {}; diff --git a/src/dex/baseswap/uniswap-v3-pool.ts b/src/dex/baseswap/baseswap-v3-pool.ts similarity index 99% rename from src/dex/baseswap/uniswap-v3-pool.ts rename to src/dex/baseswap/baseswap-v3-pool.ts index 9f3401710..ee4966ee2 100644 --- a/src/dex/baseswap/uniswap-v3-pool.ts +++ b/src/dex/baseswap/baseswap-v3-pool.ts @@ -28,7 +28,7 @@ import { uint256ToBigInt } from '../../lib/decoders'; import { decodeStateMultiCallResultWithRelativeBitmaps } from './utils'; import { _reduceTickBitmap, _reduceTicks } from './contract-math/utils'; -export class UniswapV3EventPool extends StatefulEventSubscriber { +export class BaseswapV3EventPool extends StatefulEventSubscriber { handlers: { [event: string]: ( event: any, diff --git a/src/dex/baseswap/uniswap-v3.ts b/src/dex/baseswap/baseswap-v3.ts similarity index 97% rename from src/dex/baseswap/uniswap-v3.ts rename to src/dex/baseswap/baseswap-v3.ts index ebb921b4f..de4da625b 100644 --- a/src/dex/baseswap/uniswap-v3.ts +++ b/src/dex/baseswap/baseswap-v3.ts @@ -24,7 +24,7 @@ import { isTruthy, uuidToBytes16, } from '../../utils'; -import { IDex } from '../../dex/idex'; +import { IDex } from '../idex'; import { IDexHelper } from '../../dex-helper/idex-helper'; import { DexParams, @@ -40,7 +40,7 @@ import { SimpleExchange, } from '../simple-exchange'; import { Adapters, PoolsToPreload, BaseswapV3Config } from './config'; -import { UniswapV3EventPool } from './uniswap-v3-pool'; +import { BaseswapV3EventPool } from './baseswap-v3-pool'; import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; @@ -64,7 +64,10 @@ import { DEFAULT_ID_ERC20_AS_STRING, } from '../../lib/tokens/types'; import { OptimalSwapExchange } from '@paraswap/core'; -import { OnPoolCreatedCallback, UniswapV3Factory } from './uniswap-v3-factory'; +import { + OnPoolCreatedCallback, + BaseswapV3Factory, +} from './baseswap-v3-factory'; type PoolPairsInfo = { token0: Address; @@ -76,13 +79,13 @@ const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 3 * 24 * 60 * 60 * 1000; // 3 d const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 24 * 60 * 60 * 1000; // Once in a day const UNISWAPV3_QUOTE_GASLIMIT = 200_000; -export class UniswapV3 +export class BaseswapV3 extends SimpleExchange implements IDex { - private readonly factory: UniswapV3Factory; + private readonly factory: BaseswapV3Factory; readonly isFeeOnTransferSupported: boolean = false; - readonly eventPools: Record = {}; + readonly eventPools: Record = {}; readonly hasConstantPriceLargeAmounts = false; readonly needWrapNative = true; @@ -94,6 +97,7 @@ export class UniswapV3 public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork( _.pick(BaseswapV3Config, [ + 'BaseswapV3', 'UniswapV3', 'SushiSwapV3', 'QuickSwapV3.1', @@ -142,7 +146,7 @@ export class UniswapV3 this.notExistingPoolSetKey = `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); - this.factory = new UniswapV3Factory( + this.factory = new BaseswapV3Factory( dexHelper, dexKey, this.config.factory, @@ -235,10 +239,10 @@ export class UniswapV3 destAddress: Address, fee: bigint, blockNumber: number, - ): Promise { + ): Promise { let pool = this.eventPools[ this.getPoolIdentifier(srcAddress, destAddress, fee) - ] as UniswapV3EventPool | null | undefined; + ] as BaseswapV3EventPool | null | undefined; if (pool === null) return null; @@ -290,7 +294,7 @@ export class UniswapV3 const poolImplementation = this.config.eventPoolImplementation !== undefined ? this.config.eventPoolImplementation - : UniswapV3EventPool; + : BaseswapV3EventPool; pool = pool || new poolImplementation( @@ -423,7 +427,7 @@ export class UniswapV3 to: Token, amounts: bigint[], side: SwapSide, - pools: UniswapV3EventPool[], + pools: BaseswapV3EventPool[], states: PoolState[], ): Promise | null> { if (pools.length === 0) { @@ -580,7 +584,7 @@ export class UniswapV3 if (_srcAddress === _destAddress) return null; - let selectedPools: UniswapV3EventPool[] = []; + let selectedPools: BaseswapV3EventPool[] = []; if (!limitPools) { selectedPools = ( @@ -649,8 +653,8 @@ export class UniswapV3 return acc; }, { - poolWithState: [] as UniswapV3EventPool[], - poolWithoutState: [] as UniswapV3EventPool[], + poolWithState: [] as BaseswapV3EventPool[], + poolWithoutState: [] as BaseswapV3EventPool[], }, ); @@ -1086,14 +1090,14 @@ export class UniswapV3 private async _getPoolsFromIdentifiers( poolIdentifiers: string[], blockNumber: number, - ): Promise { + ): Promise { const pools = await Promise.all( poolIdentifiers.map(async identifier => { const [, srcAddress, destAddress, fee] = identifier.split('_'); return this.getPool(srcAddress, destAddress, BigInt(fee), blockNumber); }), ); - return pools.filter(pool => pool) as UniswapV3EventPool[]; + return pools.filter(pool => pool) as BaseswapV3EventPool[]; } private _getLoweredAddresses(srcToken: Token, destToken: Token) { diff --git a/src/dex/baseswap/config.ts b/src/dex/baseswap/config.ts index cbd4ddb81..8e0ed8cbd 100644 --- a/src/dex/baseswap/config.ts +++ b/src/dex/baseswap/config.ts @@ -14,22 +14,22 @@ const SUPPORTED_FEES = [10000n, 2500n, 450n, 80n]; export const PoolsToPreload: DexConfigMap< { token0: Address; token1: Address }[] > = { - UniswapV3: { - [Network.POLYGON]: [ + BaseswapV3: { + [Network.BASE]: [ { - token0: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270'.toLowerCase(), - token1: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174'.toLowerCase(), + token0: ''.toLowerCase(), + token1: ''.toLowerCase(), }, { - token0: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619'.toLowerCase(), - token1: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174'.toLowerCase(), + token0: ''.toLowerCase(), + token1: ''.toLowerCase(), }, ], }, }; export const BaseswapV3Config: DexConfigMap = { - UniswapV3: { + BaseswapV3: { [Network.BASE]: { factory: '0x38015D05f4fEC8AFe15D7cc0386a126574e8077B', quoter: '0x4fDBD73aD4B1DDde594BF05497C15f76308eFfb9', diff --git a/src/dex/baseswap/constants.ts b/src/dex/baseswap/constants.ts index e625c3882..5baae88e6 100644 --- a/src/dex/baseswap/constants.ts +++ b/src/dex/baseswap/constants.ts @@ -11,7 +11,7 @@ export const TICK_BITMAP_BUFFER = 8n; export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 128; export const UNISWAPV3_SUBGRAPH_URL = - 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3'; + 'https://api.thegraph.com/subgraphs/name/baseswapfi/v3-base'; export const UNISWAPV3_EFFICIENCY_FACTOR = 3; diff --git a/src/dex/baseswap/types.ts b/src/dex/baseswap/types.ts index 967675843..cebc762b8 100644 --- a/src/dex/baseswap/types.ts +++ b/src/dex/baseswap/types.ts @@ -3,7 +3,7 @@ import { NumberAsString } from '../../types'; import { Address } from '../../types'; import { AbiItem } from 'web3-utils'; import { MultiResult } from '../../lib/multi-wrapper'; -import { UniswapV3EventPool } from './uniswap-v3-pool'; +import { BaseswapV3EventPool } from './baseswap-v3-pool'; export type OracleObservation = { blockTimestamp: bigint; @@ -83,7 +83,7 @@ export type DexParams = { subgraphURL: string; initHash: string; stateMultiCallAbi?: AbiItem[]; - eventPoolImplementation?: typeof UniswapV3EventPool; + eventPoolImplementation?: typeof BaseswapV3EventPool; decodeStateMultiCallResultWithRelativeBitmaps?: DecodeStateMultiCallFunc; }; From d6f798916ab15ea1136ed196503d9d8f849f72fe Mon Sep 17 00:00:00 2001 From: 0xshoehazer <0xshoehazer@gmail.com> Date: Tue, 17 Oct 2023 18:15:28 -0400 Subject: [PATCH 503/833] added bswap to index --- src/dex/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dex/index.ts b/src/dex/index.ts index 157b8664c..25fffcde3 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -76,6 +76,7 @@ import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3'; import { Algebra } from './algebra/algebra'; import { QuickPerps } from './quick-perps/quick-perps'; import { NomiswapV2 } from './uniswap-v2/nomiswap-v2'; +import { BaseswapV3 } from './baseswap/baseswap-v3'; const LegacyDexes = [ CurveV2, @@ -149,6 +150,7 @@ const Dexes = [ SwaapV2, QuickPerps, NomiswapV2, + BaseswapV3, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< From 1d2b86907671de5fe57cf9d4e1014f763d2fd29e Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 18 Oct 2023 11:10:28 +0300 Subject: [PATCH 504/833] debug --- src/dex/wombat/config.ts | 8 ++++ src/dex/wombat/wombat-e2e.test.ts | 79 +++++++++++-------------------- src/dex/wombat/wombat.ts | 4 +- 3 files changed, 38 insertions(+), 53 deletions(-) diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts index 3dc6f0d6b..d47536d0d 100644 --- a/src/dex/wombat/config.ts +++ b/src/dex/wombat/config.ts @@ -13,6 +13,14 @@ export const WombatConfig: DexConfigMap = { /** @todo add Side and Dynamic pools */ ], }, + [Network.ARBITRUM]: { + pools: [ + { + address: '0xc6bc781E20f9323012F6e422bdf552Ff06bA6CD1', + name: 'Wombat Main Pool', + }, + ], + }, }, }; diff --git a/src/dex/wombat/wombat-e2e.test.ts b/src/dex/wombat/wombat-e2e.test.ts index 550cfd99b..10d5e3039 100644 --- a/src/dex/wombat/wombat-e2e.test.ts +++ b/src/dex/wombat/wombat-e2e.test.ts @@ -11,44 +11,6 @@ import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; -/* - README - ====== - - This test script should add e2e tests for Wombat. The tests - should cover as many cases as possible. Most of the DEXes follow - the following test structure: - - DexName - - ForkName + Network - - ContractMethod - - ETH -> Token swap - - Token -> ETH swap - - Token -> Token swap - - The template already enumerates the basic structure which involves - testing simpleSwap, multiSwap, megaSwap contract methods for - ETH <> TOKEN and TOKEN <> TOKEN swaps. You should replace tokenA and - tokenB with any two highly liquid tokens on Wombat for the tests - to work. If the tokens that you would like to use are not defined in - Tokens or Holders map, you can update the './tests/constants-e2e' - - Other than the standard cases that are already added by the template - it is highly recommended to add test cases which could be specific - to testing Wombat (Eg. Tests based on poolType, special tokens, - etc). - - You can run this individual test script by running: - `npx jest src/dex//-e2e.test.ts` - - e2e tests use the Tenderly fork api. Please add the following to your - .env file: - TENDERLY_TOKEN=Find this under Account>Settings>Authorization. - TENDERLY_ACCOUNT_ID=Your Tenderly account name. - TENDERLY_PROJECT=Name of a Tenderly project you have created in your - dashboard. - - (This comment should be removed from the final implementation) -*/ function testForNetwork( network: Network, @@ -67,18 +29,15 @@ function testForNetwork( const holders = Holders[network]; const nativeTokenSymbol = NativeTokenSymbols[network]; - // TODO: Add any direct swap contractMethod name if it exists const sideToContractMethods = new Map([ [ SwapSide.SELL, [ ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, ], ], - // TODO: If buy is not supported remove the buy contract methods - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], ]); describe(`${network}`, () => { @@ -135,15 +94,14 @@ function testForNetwork( describe('Wombat E2E', () => { const dexKey = 'Wombat'; - describe('Mainnet', () => { - const network = Network.MAINNET; + describe('BSC', () => { + const network = Network.BSC; - // TODO: Modify the tokenASymbol, tokenBSymbol, tokenAAmount; - const tokenASymbol: string = 'tokenASymbol'; - const tokenBSymbol: string = 'tokenBSymbol'; + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; - const tokenAAmount: string = 'tokenAAmount'; - const tokenBAmount: string = 'tokenBAmount'; + const tokenAAmount: string = '100000000'; + const tokenBAmount: string = '100000000'; const nativeTokenAmount = '1000000000000000000'; testForNetwork( @@ -155,7 +113,26 @@ describe('Wombat E2E', () => { tokenBAmount, nativeTokenAmount, ); + }); + + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + + const tokenAAmount: string = '100000000'; + const tokenBAmount: string = '100000000'; + const nativeTokenAmount = '1000000000000000000'; - // TODO: Add any additional test cases required to test Wombat + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); }); }); diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index f05fed12b..744b9c0dc 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -19,7 +19,7 @@ import { getDexKeysWithNetwork, getBigIntPow } from '../../utils'; import { IDex } from '../../dex/idex'; import { IDexHelper } from '../../dex-helper/idex-helper'; import { WombatData, DexParams, WombatConfigInfo, PoolState } from './types'; -import { SimpleExchange } from '../simple-exchange'; +import { getLocalDeadlineAsFriendlyPlaceholder, SimpleExchange } from '../simple-exchange'; import { WombatConfig, Adapters } from './config'; import { WombatEventPool } from './wombat-pool'; import { quoteFrom } from './utils'; @@ -372,7 +372,7 @@ export class Wombat extends SimpleExchange implements IDex { srcAmount, 1 /** @todo assume slippage tolorence is 2% and set the minimum receive accordingly */, this.augustusAddress, - this.getDeadline(), + getLocalDeadlineAsFriendlyPlaceholder(), ]); return this.buildSimpleParamWithoutWETHConversion( From a080925d732384f84111f929042edd783157f36d Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 18 Oct 2023 11:11:23 +0300 Subject: [PATCH 505/833] 2.40.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e828340d9..7e8bb2459 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.39.1-dexalot.2", + "version": "2.40.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1fc91382df3bd45f52293b31d52819dc01cb77f3 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 18 Oct 2023 16:44:31 +0300 Subject: [PATCH 506/833] add e2e tests --- src/dex/wombat/utils.ts | 1 + src/dex/wombat/wombat-e2e.test.ts | 293 ++++++++++++++-------- src/dex/wombat/wombat-integration.test.ts | 8 +- src/dex/wombat/wombat-pool.ts | 16 +- tests/constants-e2e.ts | 4 + tests/utils-e2e.ts | 2 + 6 files changed, 203 insertions(+), 121 deletions(-) diff --git a/src/dex/wombat/utils.ts b/src/dex/wombat/utils.ts index 0a7ffffe0..251912cc7 100644 --- a/src/dex/wombat/utils.ts +++ b/src/dex/wombat/utils.ts @@ -43,6 +43,7 @@ function swapQuoteFunc( return 0n; } // int256 D = Ax + Ay - A.wmul((Lx * Lx) / Ax + (Ly * Ly) / Ay); // flattened _invariantFunc + const d = assetX + assetY - diff --git a/src/dex/wombat/wombat-e2e.test.ts b/src/dex/wombat/wombat-e2e.test.ts index 10d5e3039..02fe27be6 100644 --- a/src/dex/wombat/wombat-e2e.test.ts +++ b/src/dex/wombat/wombat-e2e.test.ts @@ -11,128 +11,203 @@ import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; +// function testForNetwork( +// network: Network, +// dexKey: string, +// tokenASymbol: string, +// tokenBSymbol: string, +// tokenAAmount: string, +// tokenBAmount: string, +// nativeTokenAmount: string, +// ) { +// const provider = new StaticJsonRpcProvider( +// generateConfig(network).privateHttpProvider, +// network, +// ); +// const tokens = Tokens[network]; +// const holders = Holders[network]; +// const nativeTokenSymbol = NativeTokenSymbols[network]; +// +// const sideToContractMethods = new Map([ +// [ +// SwapSide.SELL, +// [ +// ContractMethod.simpleSwap, +// // ContractMethod.multiSwap, +// // ContractMethod.megaSwap, +// ], +// ], +// ]); +// +// describe(`${network}`, () => { +// sideToContractMethods.forEach((contractMethods, side) => +// describe(`${side}`, () => { +// 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, +// network, +// provider, +// ); +// }); +// it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { +// await testE2E( +// tokens[tokenASymbol], +// tokens[nativeTokenSymbol], +// holders[tokenASymbol], +// side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, +// side, +// dexKey, +// contractMethod, +// network, +// provider, +// ); +// }); +// it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { +// await testE2E( +// tokens[tokenASymbol], +// tokens[tokenBSymbol], +// holders[tokenASymbol], +// side === SwapSide.SELL ? tokenAAmount : tokenBAmount, +// side, +// dexKey, +// contractMethod, +// network, +// provider, +// ); +// }); +// }); +// }); +// }), +// ); +// }); +// } -function testForNetwork( - network: Network, - dexKey: string, - tokenASymbol: string, - tokenBSymbol: string, - tokenAAmount: string, - tokenBAmount: string, - nativeTokenAmount: string, -) { - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - const tokens = Tokens[network]; - const holders = Holders[network]; - const nativeTokenSymbol = NativeTokenSymbols[network]; +describe('Wombat E2E', () => { + const dexKey = 'Wombat'; + + describe('BSC', () => { + const network = Network.BSC; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + ], + ], [ - ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + // ContractMethod.buy, + ], ], - ], - ]); + ]); + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = + [ + [ + { + name: 'USDC', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + { + name: 'USDT', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + ], + [ + { + name: 'BNB', + sellAmount: '1000000000000000000', + buyAmount: '1000000000', + }, + { + name: 'BNBx', + sellAmount: '1000000000', + buyAmount: '1000000000000000000', + }, + ], + ]; - describe(`${network}`, () => { sideToContractMethods.forEach((contractMethods, side) => describe(`${side}`, () => { 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, - network, - provider, - ); - }); - it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); }); }); }); }), ); }); -} - -describe('Wombat E2E', () => { - const dexKey = 'Wombat'; - describe('BSC', () => { - const network = Network.BSC; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; - - const tokenAAmount: string = '100000000'; - const tokenBAmount: string = '100000000'; - const nativeTokenAmount = '1000000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); - - describe('Arbitrum', () => { - const network = Network.ARBITRUM; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; - - const tokenAAmount: string = '100000000'; - const tokenBAmount: string = '100000000'; - const nativeTokenAmount = '1000000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); + // describe('Arbitrum', () => { + // const network = Network.ARBITRUM; + // + // const tokenASymbol: string = 'USDC'; + // const tokenBSymbol: string = 'USDT'; + // + // const tokenAAmount: string = '100000000'; + // const tokenBAmount: string = '100000000'; + // const nativeTokenAmount = '1000000000000000000'; + // + // testForNetwork( + // network, + // dexKey, + // tokenASymbol, + // tokenBSymbol, + // tokenAAmount, + // tokenBAmount, + // nativeTokenAmount, + // ); + // }); }); diff --git a/src/dex/wombat/wombat-integration.test.ts b/src/dex/wombat/wombat-integration.test.ts index 21e97cd80..f3976ac4b 100644 --- a/src/dex/wombat/wombat-integration.test.ts +++ b/src/dex/wombat/wombat-integration.test.ts @@ -150,16 +150,16 @@ describe('Wombat', function () { let blockNumber: number; let wombat: Wombat; - describe('Mainnet', () => { - const network = Network.MAINNET; + describe('BSC', () => { + const network = Network.BSC; const dexHelper = new DummyDexHelper(network); const tokens = Tokens[network]; // TODO: Put here token Symbol to check against // Don't forget to update relevant tokens in constant-e2e.ts - const srcTokenSymbol = 'srcTokenSymbol'; - const destTokenSymbol = 'destTokenSymbol'; + const srcTokenSymbol = 'USDC'; + const destTokenSymbol = 'USDT'; const amountsForSell = [ 0n, diff --git a/src/dex/wombat/wombat-pool.ts b/src/dex/wombat/wombat-pool.ts index 7fcf0e627..c21d3ea9a 100644 --- a/src/dex/wombat/wombat-pool.ts +++ b/src/dex/wombat/wombat-pool.ts @@ -145,14 +145,14 @@ export class WombatEventPool extends StatefulEventSubscriber { let i = 0; // 2 A. decode pool params - const ampFactor = WombatEventPool.poolInterface.decodeFunctionResult( + const ampFactor = BigInt(WombatEventPool.poolInterface.decodeFunctionResult( 'ampFactor', returnData[i++], - )[0]; - const haircutRate = WombatEventPool.poolInterface.decodeFunctionResult( + )[0]); + const haircutRate = BigInt(WombatEventPool.poolInterface.decodeFunctionResult( 'haircutRate', returnData[i++], - )[0]; + )[0]); const poolState: PoolState = { params: { ampFactor, @@ -165,14 +165,14 @@ export class WombatEventPool extends StatefulEventSubscriber { for (const [tokenAddress, tokenInfo] of Object.entries( this.poolCfg.tokens, )) { - const cash = WombatEventPool.assetInterface.decodeFunctionResult( + const cash = BigInt(WombatEventPool.assetInterface.decodeFunctionResult( 'cash', returnData[i++], - )[0]; - const liability = WombatEventPool.assetInterface.decodeFunctionResult( + )[0]); + const liability = BigInt(WombatEventPool.assetInterface.decodeFunctionResult( 'liability', returnData[i++], - )[0]; + )[0]); poolState.underlyingAddresses.push(tokenAddress); poolState.asset[tokenAddress] = { cash, diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 599e38882..81c1fa858 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -526,6 +526,10 @@ export const Tokens: { address: '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c', decimals: 18, }, + BNBx: { + address: '0xab824b47806fea52276fef231e5e2d5fb3d4cf4e', + decimals: 9, + }, BUSD: { address: '0xe9e7cea3dedca5984780bafc599bd69add087d56', decimals: 18, diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index ece7ac264..539002508 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -35,6 +35,7 @@ import { SmartToken, StateOverrides } from './smart-tokens'; import { GIFTER_ADDRESS } from './constants-e2e'; import { generateDeployBytecode, sleep } from './utils'; import { assert } from 'ts-essentials'; +import * as util from 'util'; export const testingEndpoint = process.env.E2E_TEST_ENDPOINT; @@ -378,6 +379,7 @@ export async function testE2E( poolIdentifiers, transferFees, ); + console.log('price route: ', util.inspect(priceRoute, false, null, true)); expect(parseFloat(priceRoute.destAmount)).toBeGreaterThan(0); // Calculate slippage. Default is 1% From 73c4eda08dd46ab4a4434157ce1d4246c83c989d Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 18 Oct 2023 20:58:39 +0300 Subject: [PATCH 507/833] add fixes --- src/dex/solidly/config.ts | 2 +- src/dex/solidly/forks-override/fvm.ts | 4 ++-- src/dex/solidly/solidly-e2e.test.ts | 4 ++-- tests/constants-e2e.ts | 2 ++ 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index 9d5ed868d..76da2b157 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -196,7 +196,7 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'PolygonAdapter02', index: 3 }], // dystopia }, [Network.FANTOM]: { - [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 10 }], // solidly, spiritSwapV2, equalizer + [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 10 }], // solidly, spiritSwapV2, equalizer, fvm }, [Network.OPTIMISM]: { [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 8 }], // velodrome diff --git a/src/dex/solidly/forks-override/fvm.ts b/src/dex/solidly/forks-override/fvm.ts index 9ec45bec7..8fabb10a5 100644 --- a/src/dex/solidly/forks-override/fvm.ts +++ b/src/dex/solidly/forks-override/fvm.ts @@ -9,7 +9,7 @@ import _ from 'lodash'; const FvmFactoryABI = [ { - inputs: [{ internalType: 'bool', name: '_stable', type: 'bool' }], + inputs: [{ internalType: '_pair', name: '_stable', type: 'address' }], name: 'getFee', outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], stateMutability: 'view', @@ -39,7 +39,7 @@ export class Fvm extends Solidly { protected getFeesMultiCallData(pair: SolidlyPair) { const callEntry = { target: this.factoryAddress, - callData: fvmFactoryIface.encodeFunctionData('getFee', [pair.stable]), + callData: fvmFactoryIface.encodeFunctionData('getFee', [pair.exchange]), }; const callDecoder = (values: any[]) => parseInt( diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index f422b9866..08e80d765 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -423,8 +423,8 @@ describe('Solidly E2E', () => { const tokenASymbol: string = 'lzUSDC'; const tokenBSymbol: string = 'axlUSDC'; - const tokenAAmount: string = '111110'; - const tokenBAmount: string = '100000'; + const tokenAAmount: string = '1111100'; + const tokenBAmount: string = '1000000'; const nativeTokenAmount = '11000000000000000'; testForNetwork( diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 7bbea9b5b..a0af67fb4 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1054,6 +1054,8 @@ export const Holders: { GDAI: '0x0e2ed73f9c1409e2b36fe6c46e60d4557b7c2ac0', EQUAL: '0x8b187ea19c93091a4d6b426b71871648182b5fac', FVM: '0x07BB65fAaC502d4996532F834A1B7ba5dC32Ff96', + lzUSDC: '0x1e38e2e0e7df3be6592867d0ac2713a4dbda8350', + axlUSDC: '0xccf932cd565c21d2e516c8ff3a4f244eea27e09a', }, [Network.BSC]: { DAI: '0xf68a4b64162906eff0ff6ae34e2bb1cd42fef62d', From c2791381fa99eef52655ccdbbf6dff3afe2dd1a1 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 18 Oct 2023 20:58:59 +0300 Subject: [PATCH 508/833] 2.40.1-fvm --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7e8bb2459..fa7ac03fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.40.0", + "version": "2.40.1-fvm", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From eaa892ab76494bcc9ea80a466033724f46999b4f Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Wed, 18 Oct 2023 21:39:20 +0100 Subject: [PATCH 509/833] fix: add firm quote 2s timeout --- src/dex/dexalot/constants.ts | 2 ++ src/dex/dexalot/dexalot.ts | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/dex/dexalot/constants.ts b/src/dex/dexalot/constants.ts index b9841a015..67ad1f7f9 100644 --- a/src/dex/dexalot/constants.ts +++ b/src/dex/dexalot/constants.ts @@ -27,3 +27,5 @@ export const DEXALOT_RESTRICT_TTL_S = 60 * 30; // 30 minutes export const DEXALOT_RESTRICTED_CACHE_KEY = 'restricted'; export const DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION = new BigNumber('0.001'); + +export const DEXALOT_FIRM_QUOTE_TIMEOUT_MS = 2000; diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index eaa63ed89..90c795153 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -56,6 +56,7 @@ import { DEXALOT_RESTRICT_TTL_S, DEXALOT_RATELIMIT_CACHE_VALUE, DEXALOT_BLACKLIST_CACHES_TTL_S, + DEXALOT_FIRM_QUOTE_TIMEOUT_MS, } from './constants'; import { BI_MAX_UINT256 } from '../../bigint-constants'; import { ethers } from 'ethers'; @@ -580,7 +581,7 @@ export class Dexalot extends SimpleExchange implements IDex { const rfq: RFQResponse = await this.dexHelper.httpRequest.post( `${DEXALOT_API_URL}/api/rfq/firm`, rfqParams, - undefined, + DEXALOT_FIRM_QUOTE_TIMEOUT_MS, { 'x-apikey': this.dexalotAuthToken }, ); if (!rfq) { From fecddc6059fbf8eff08ed5c8d8ebbfc5764796d1 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 19 Oct 2023 13:29:59 +0300 Subject: [PATCH 510/833] get base adapter back --- src/dex/solidly/config.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index 76da2b157..5fcb88bdc 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -213,4 +213,7 @@ export const Adapters: Record = { [Network.ARBITRUM]: { [SwapSide.SELL]: [{ name: 'ArbitrumAdapter02', index: 1 }], // chronos, ramses }, + [Network.BASE]: { + [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 3 }], // aerodrome, equalizer + }, }; From 5d6b6f0c4f815553ab5b1d0895adf070f388decd Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 19 Oct 2023 14:15:58 +0300 Subject: [PATCH 511/833] 2.41.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fa7ac03fb..64a7404df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.40.1-fvm", + "version": "2.41.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 0d46f67b9d247a3a2316bdeb94254b2509a5fb67 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 19 Oct 2023 15:46:51 +0300 Subject: [PATCH 512/833] fix yarn test-integration command --- scripts/dex-integration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/dex-integration.ts b/scripts/dex-integration.ts index e3487e690..ad04f3b19 100644 --- a/scripts/dex-integration.ts +++ b/scripts/dex-integration.ts @@ -116,7 +116,7 @@ function testIntegration(argv: IOptions) { process.env.NODE_ENV = 'test'; } - require('../node_modules/jest-cli/build/cli').run( + require('../node_modules/jest-cli/build').run( `src\/dex\/${dexNameParam}\/.+\.test\.ts`, ); } From dd37b2cd68b226751538dde245cdb61370b75920 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 19 Oct 2023 18:27:11 +0300 Subject: [PATCH 513/833] BACK-1343: integrate FVM on Base chain --- src/dex/solidly/config.ts | 9 ++ src/dex/solidly/solidly-e2e.test.ts | 21 ++++ src/dex/solidly/solidly-integration.test.ts | 115 ++++++++++++++++++++ 3 files changed, 145 insertions(+) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index 5fcb88bdc..c653d8c41 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -188,6 +188,15 @@ export const SolidlyConfig: DexConfigMap = { poolGasCost: 180 * 1000, // just same as other forks // no subgraph }, + [Network.BASE]: { + factoryAddress: '0xe21Aac7F113Bd5DC2389e4d8a8db854a87fD6951', + router: '0xDCf4EE5B700e2a5Fec458e06B763A4a3E3004494', + initCode: + '0xac4013aa7118234c1dd1f9cc4cdd3933d5a426224bc691c1bde3d8930a7e6151', // PairFactory.pairCodeHash + feeCode: 0, // dynamic fees + poolGasCost: 180 * 1000, // just same as other forks + // no subgraph + }, }, }; diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index 08e80d765..dc90a71d1 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -1513,5 +1513,26 @@ describe('Solidly E2E', () => { }), ); }); + + describe('Fvm', () => { + const dexKey = 'Fvm'; + + const tokenASymbol: string = 'USDbC'; + const tokenBSymbol: string = 'DAI'; + + const tokenAAmount: string = '1111100000'; + const tokenBAmount: string = '1111100000'; + const nativeTokenAmount = '100000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); }); }); diff --git a/src/dex/solidly/solidly-integration.test.ts b/src/dex/solidly/solidly-integration.test.ts index 013d0cb15..18e4922ca 100644 --- a/src/dex/solidly/solidly-integration.test.ts +++ b/src/dex/solidly/solidly-integration.test.ts @@ -1438,5 +1438,120 @@ describe('Solidly integration tests', () => { }); }); }); + + describe('Fvm', () => { + const dexKey = 'Fvm'; + const fvm = new Fvm(network, dexKey, dexHelper); + + describe('UniswapV2 like pool', function () { + const TokenASymbol = 'WETH'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'USDbC'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts18; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await fvm.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await fvm.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + + for (const poolPrice of poolPrices || []) { + await checkOnChainPricing( + fvm, + 'getAmountOut', + blocknumber, + poolPrice.prices, + poolPrice.poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + }); + + describe('Curve like stable pool', function () { + const TokenASymbol = 'USDbC'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'USDC'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts6; // amounts6; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await fvm.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await fvm.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + for (const poolPrice of poolPrices || []) { + await checkOnChainPricing( + fvm, + 'getAmountOut', + blocknumber, + poolPrice.prices, + poolPrice.poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + }); + + }); }); }); From 6cbe53c08c82ccea39cec199bf38dbe15dee3de3 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 19 Oct 2023 18:27:57 +0300 Subject: [PATCH 514/833] 2.41.1-fvm-on-base --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 64a7404df..f123cf2db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.41.0", + "version": "2.41.1-fvm-on-base", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From da9929e5020045774803ad8b59c0f74138ba4144 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 19 Oct 2023 12:57:29 -0400 Subject: [PATCH 515/833] change initHash + factory to accomodate callbacks redeploy --- src/dex/solidly-v3/config.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index ba81cea35..e2dfb009d 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -30,7 +30,7 @@ export const SolidlyV3Config: DexConfigMap = { SolidlyV3: { [Network.MAINNET]: { // factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', - factory: '0x735bb16affe83a3dc4dc418abccf179617cf9ff2', + factory: '0x70Fe4a44EA505cFa3A57b95cF2862D4fd5F0f687', quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', supportedTickSpacings: SUPPORTED_TICK_SPACINGS, @@ -38,9 +38,14 @@ export const SolidlyV3Config: DexConfigMap = { uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', chunksCount: 10, initRetryFrequency: 10, + // OG uniswap initHash // initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - initHash: `0x2d6541efe1e24667ba5408a35ae420462924d43db1251d7580804ac81545109b`, - subgraphURL: 'https://api.thegraph.com/subgraphs/name/solidlylabs/solidly-v3', + // Solidly initHash prior to callbacks + // initHash: `0x2d6541efe1e24667ba5408a35ae420462924d43db1251d7580804ac81545109b`, + // Solidly initHash after callbacks + initHash: `0xe9b68c5f77858eecac2e651646e208175e9b1359d68d0e14fc69f8c54e5010bf`, + subgraphURL: + 'https://api.thegraph.com/subgraphs/name/solidlylabs/solidly-v3', }, }, }; From ff92a39338c92f382bf00ae3367e02a745d51087 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 20 Oct 2023 15:24:05 +0300 Subject: [PATCH 516/833] fix: update router --- src/dex/solidly/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index 4c84aab4e..97795f48c 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -194,7 +194,7 @@ export const SolidlyConfig: DexConfigMap = { subgraphURL: 'https://thegraph.com/hosted-service/subgraph/tbotteam/usdfi-dexv2', factoryAddress: '0xB3863573d9f25e6a84895d4685a408db7a488416', - router: '0x226E6a0114729ad4db1c80C55900729D352E2132', + router: '0xc2b5a8082D2E1867A9CBBF41b625E3ae9dF81f8b', initCode: '0x1d770cc32abcf060a45b0de3f0afbd8594effe9f6d836f93d19c05d76b4b4dfa ', // Variable fees. Defaults: From d193f28aa9abf16917543d3e4c8ae9a92356826b Mon Sep 17 00:00:00 2001 From: David Bouba Date: Fri, 20 Oct 2023 17:46:42 +0200 Subject: [PATCH 517/833] feature: added arbitrum support to swaap-v2 --- src/config.ts | 1 + src/dex/swaap-v2/config.ts | 6 +- src/dex/swaap-v2/swaap-v2-e2e.test.ts | 115 +++++++++++++++++--------- 3 files changed, 79 insertions(+), 43 deletions(-) diff --git a/src/config.ts b/src/config.ts index 60b254923..2438a2cac 100644 --- a/src/config.ts +++ b/src/config.ts @@ -275,6 +275,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { multicallV2Address: '0x7eCfBaa8742fDf5756DAC92fbc8b90a19b8815bF', privateHttpProvider: process.env.HTTP_PROVIDER_42161, hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', + swaapV2AuthToken: process.env.API_KEY_SWAAP_V2_AUTH_TOKEN || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], adapterAddresses: { diff --git a/src/dex/swaap-v2/config.ts b/src/dex/swaap-v2/config.ts index 78f9f6222..66d318d27 100644 --- a/src/dex/swaap-v2/config.ts +++ b/src/dex/swaap-v2/config.ts @@ -6,8 +6,7 @@ export const SwaapV2Config: DexConfigMap = { SwaapV2: { [Network.MAINNET]: {}, [Network.POLYGON]: {}, - // Arbitrum will be supported later - // [Network.ARBITRUM]: {}, + [Network.ARBITRUM]: {}, }, }; @@ -20,4 +19,7 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'PolygonAdapter02', index: 8 }], [SwapSide.BUY]: [{ name: 'PolygonBuyAdapter', index: 7 }], }, + [Network.ARBITRUM]: { + // TODO: add the proper adapters + }, }; diff --git a/src/dex/swaap-v2/swaap-v2-e2e.test.ts b/src/dex/swaap-v2/swaap-v2-e2e.test.ts index e02a61f9a..ddbed8204 100644 --- a/src/dex/swaap-v2/swaap-v2-e2e.test.ts +++ b/src/dex/swaap-v2/swaap-v2-e2e.test.ts @@ -224,46 +224,79 @@ describe('SwaapV2 E2E', () => { ); }); - // Arbitrum will be supported later - // describe('Arbitrum', () => { - // const network = Network.ARBITRUM; - // - // const tokenASymbol: string = 'ETH'; - // const tokenBSymbol: string = 'DAI'; - // - // const tokenAAmount: string = '100000000'; - // const tokenBAmount: string = '1000000000000000000'; - // const nativeTokenAmount = '1000000000000000000'; - // - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // nativeTokenAmount, - // ); - // }); + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ + [ + { + name: 'WETH', + sellAmount: '10000000000000000', + buyAmount: '1000000000000000000', + }, + { + name: 'DAI', + sellAmount: '1000000000000000000', + buyAmount: '10000000000000000', + }, + ], + ]; - // Mainnet will be supported later - // describe('Mainnet', () => { - // const network = Network.MAINNET; - // const tokenASymbol: string = 'USDC'; - // const tokenBSymbol: string = 'USDT'; - // - // const tokenAAmount: string = '100000000'; - // const tokenBAmount: string = '1000000000000000000'; - // const nativeTokenAmount = '1000000000000000000'; - // - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // nativeTokenAmount, - // ); - // }); + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + undefined, + undefined, + undefined, + undefined, + sleepMs, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + undefined, + undefined, + undefined, + undefined, + sleepMs, + ); + }); + }); + }); + }); + }), + ); + }); }); From a1a0c5395794f973308d39593d6c40b20bc9bd0c Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Sun, 22 Oct 2023 22:57:15 +0300 Subject: [PATCH 518/833] fix: add tests & fix config --- src/dex/solidly/config.ts | 11 +- src/dex/solidly/forks-override/usdfi.ts | 1 - src/dex/solidly/solidly-e2e.test.ts | 407 +++++++++++--------- src/dex/solidly/solidly-integration.test.ts | 189 +++++++++ tests/constants-e2e.ts | 12 + 5 files changed, 429 insertions(+), 191 deletions(-) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index 97795f48c..f788d1033 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -192,16 +192,15 @@ export const SolidlyConfig: DexConfigMap = { Usdfi: { [Network.BSC]: { subgraphURL: - 'https://thegraph.com/hosted-service/subgraph/tbotteam/usdfi-dexv2', + 'https://api.thegraph.com/subgraphs/name/tbotteam/usdfi-dexv2', factoryAddress: '0xB3863573d9f25e6a84895d4685a408db7a488416', router: '0xc2b5a8082D2E1867A9CBBF41b625E3ae9dF81f8b', initCode: - '0x1d770cc32abcf060a45b0de3f0afbd8594effe9f6d836f93d19c05d76b4b4dfa ', - // Variable fees. Defaults: - // Stable: 10000 (0,01%) ('1' in uniswap) - // Volatile: 2000 (0,05%) ('5' in uniswap) + '0x1d770cc32abcf060a45b0de3f0afbd8594effe9f6d836f93d19c05d76b4b4dfa', + stableFee: 4, // 0.04% + volatileFee: 30, // 0.3% poolGasCost: 180 * 1000, - feeCode: 0, // variable + feeCode: 4, }, }, }; diff --git a/src/dex/solidly/forks-override/usdfi.ts b/src/dex/solidly/forks-override/usdfi.ts index 8ab8e0c6d..78d2f5781 100644 --- a/src/dex/solidly/forks-override/usdfi.ts +++ b/src/dex/solidly/forks-override/usdfi.ts @@ -1,5 +1,4 @@ import { Solidly } from '../solidly'; -import { SolidlyPair } from '../types'; import { Network } from '../../../constants'; import { getDexKeysWithNetwork } from '../../../utils'; import { SolidlyConfig } from '../config'; diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index e8f703f00..eea1898f9 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -1129,193 +1129,232 @@ describe('Solidly E2E', () => { describe('Usdfi', () => { const dexKey = 'Usdfi'; - const usdAmount = '1000000'; - - describe('Usdfi UniswapV2 Pools', () => { - const bnbAmount = '1000000000000000000'; - - describe('simpleSwap', () => { - it('BNB -> TOKEN', async () => { - await testE2E( - tokens.BNB, - tokens.BUSD, - holders.BNB, - bnbAmount, - SwapSide.SELL, - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('Token -> BNB', async () => { - await testE2E( - tokens.USDT, - tokens.BNB, - holders.USDT, - usdAmount, - SwapSide.SELL, - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - - it('Token -> Token', async () => { - await testE2E( - tokens.WBNB, - tokens.CONE, - holders.WBNB, - bnbAmount, - SwapSide.SELL, - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - }); - - describe('multiSwap', () => { - it('BNB -> TOKEN', async () => { - await testE2E( - tokens.BNB, - tokens.BUSD, - holders.BNB, - bnbAmount, - SwapSide.SELL, - dexKey, - ContractMethod.multiSwap, - network, - provider, - ); - }); - - it('Token -> BNB', async () => { - await testE2E( - tokens.USDT, - tokens.BNB, - holders.USDT, - usdAmount, - SwapSide.SELL, - dexKey, - ContractMethod.multiSwap, - network, - provider, - ); - }); - - it('Token -> Token', async () => { - await testE2E( - tokens.WBNB, - tokens.CONE, - holders.WBNB, - bnbAmount, - SwapSide.SELL, - dexKey, - ContractMethod.multiSwap, - network, - provider, - ); - }); - }); - - describe('megaSwap', () => { - it('BNB -> TOKEN', async () => { - await testE2E( - tokens.USDT, - tokens.BNB, - holders.USDT, - usdAmount, - SwapSide.SELL, - dexKey, - ContractMethod.megaSwap, - network, - provider, - ); - }); + const tokenASymbol: string = 'FRAX'; + const tokenBSymbol: string = 'frxETH'; - it('Token -> BNB', async () => { - await testE2E( - tokens.USDT, - tokens.BNB, - holders.USDT, - usdAmount, - SwapSide.SELL, - dexKey, - ContractMethod.megaSwap, - network, - provider, - ); - }); - - it('Token -> Token', async () => { - await testE2E( - tokens.WBNB, - tokens.CONE, - holders.WBNB, - bnbAmount, - SwapSide.SELL, - dexKey, - ContractMethod.megaSwap, - network, - provider, - ); - }); - }); - }); - - describe('Usdfi Stable Pools', () => { - describe('simpleSwap', () => { - it('Token -> Token', async () => { - await testE2E( - tokens.USDC, - tokens.USDT, - holders.USDC, - usdAmount, - SwapSide.SELL, - dexKey, - ContractMethod.simpleSwap, - network, - provider, - ); - }); - }); + const tokenAAmount: string = '1111100000'; + const tokenBAmount: string = '100000000000000000'; + const nativeTokenAmount = '100000000000000000'; - describe('multiSwap', () => { - it('Token -> Token', async () => { - await testE2E( - tokens.USDC, - tokens.USDT, - holders.USDC, - usdAmount, - SwapSide.SELL, - dexKey, - ContractMethod.multiSwap, - network, - provider, - ); - }); - }); + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); - describe('megaSwap', () => { - it('Token -> Token', async () => { - await testE2E( - tokens.USDC, - tokens.USDT, - holders.USDC, - usdAmount, - SwapSide.SELL, - dexKey, - ContractMethod.megaSwap, - network, - provider, - ); - }); - }); - }); + // TODO: Delete + + // const dexKey = 'Usdfi'; + // const usdAmount = '1000000'; + + // const tokenASymbol: string = 'WBNB'; + // const tokenBSymbol: string = 'CONE'; + + // const tokenAAmount: string = '1111100'; + // const tokenBAmount: string = '1000000'; + // const nativeTokenAmount = '1000000000000000000'; + + // testForNetwork( + // network, + // dexKey, + // tokenASymbol, + // tokenBSymbol, + // tokenAAmount, + // tokenBAmount, + // nativeTokenAmount, + // ); + + //// + + // describe('Usdfi UniswapV2 Pools', () => { + // const bnbAmount = '1000000000000000000'; + + // describe('simpleSwap', () => { + // it('BNB -> TOKEN', async () => { + // await testE2E( + // tokens.BNB, + // tokens.BUSD, + // holders.BNB, + // bnbAmount, + // SwapSide.SELL, + // dexKey, + // ContractMethod.simpleSwap, + // network, + // provider, + // ); + // }); + + // it('Token -> BNB', async () => { + // await testE2E( + // tokens.USDT, + // tokens.BNB, + // holders.USDT, + // usdAmount, + // SwapSide.SELL, + // dexKey, + // ContractMethod.simpleSwap, + // network, + // provider, + // ); + // }); + + // it('Token -> Token', async () => { + // await testE2E( + // tokens.WBNB, + // tokens.CONE, + // holders.WBNB, + // bnbAmount, + // SwapSide.SELL, + // dexKey, + // ContractMethod.simpleSwap, + // network, + // provider, + // ); + // }); + // }); + + // describe('multiSwap', () => { + // it('BNB -> TOKEN', async () => { + // await testE2E( + // tokens.BNB, + // tokens.BUSD, + // holders.BNB, + // bnbAmount, + // SwapSide.SELL, + // dexKey, + // ContractMethod.multiSwap, + // network, + // provider, + // ); + // }); + + // it('Token -> BNB', async () => { + // await testE2E( + // tokens.USDT, + // tokens.BNB, + // holders.USDT, + // usdAmount, + // SwapSide.SELL, + // dexKey, + // ContractMethod.multiSwap, + // network, + // provider, + // ); + // }); + + // it('Token -> Token', async () => { + // await testE2E( + // tokens.WBNB, + // tokens.CONE, + // holders.WBNB, + // bnbAmount, + // SwapSide.SELL, + // dexKey, + // ContractMethod.multiSwap, + // network, + // provider, + // ); + // }); + // }); + + // describe('megaSwap', () => { + // it('BNB -> TOKEN', async () => { + // await testE2E( + // tokens.USDT, + // tokens.BNB, + // holders.USDT, + // usdAmount, + // SwapSide.SELL, + // dexKey, + // ContractMethod.megaSwap, + // network, + // provider, + // ); + // }); + + // it('Token -> BNB', async () => { + // await testE2E( + // tokens.USDT, + // tokens.BNB, + // holders.USDT, + // usdAmount, + // SwapSide.SELL, + // dexKey, + // ContractMethod.megaSwap, + // network, + // provider, + // ); + // }); + + // it('Token -> Token', async () => { + // await testE2E( + // tokens.WBNB, + // tokens.CONE, + // holders.WBNB, + // bnbAmount, + // SwapSide.SELL, + // dexKey, + // ContractMethod.megaSwap, + // network, + // provider, + // ); + // }); + // }); + // }); + + // describe('Usdfi Stable Pools', () => { + // describe('simpleSwap', () => { + // it('Token -> Token', async () => { + // await testE2E( + // tokens.USDC, + // tokens.USDT, + // holders.USDC, + // usdAmount, + // SwapSide.SELL, + // dexKey, + // ContractMethod.simpleSwap, + // network, + // provider, + // ); + // }); + // }); + + // describe('multiSwap', () => { + // it('Token -> Token', async () => { + // await testE2E( + // tokens.USDC, + // tokens.USDT, + // holders.USDC, + // usdAmount, + // SwapSide.SELL, + // dexKey, + // ContractMethod.multiSwap, + // network, + // provider, + // ); + // }); + // }); + + // describe('megaSwap', () => { + // it('Token -> Token', async () => { + // await testE2E( + // tokens.USDC, + // tokens.USDT, + // holders.USDC, + // usdAmount, + // SwapSide.SELL, + // dexKey, + // ContractMethod.megaSwap, + // network, + // provider, + // ); + // }); + // }); + // }); }); }); diff --git a/src/dex/solidly/solidly-integration.test.ts b/src/dex/solidly/solidly-integration.test.ts index 013d0cb15..a6fce4c1c 100644 --- a/src/dex/solidly/solidly-integration.test.ts +++ b/src/dex/solidly/solidly-integration.test.ts @@ -18,6 +18,7 @@ import * as util from 'util'; import { VelodromeV2 } from './forks-override/velodromeV2'; import { Equalizer } from './forks-override/equalizer'; import { Fvm } from './forks-override/fvm'; +import { Usdfi } from './forks-override/usdfi'; const amounts18 = [0n, BI_POWS[18], 2000000000000000000n]; const amounts6 = [0n, BI_POWS[6], 2000000n]; @@ -976,6 +977,194 @@ describe('Solidly integration tests', () => { }); }); }); + + describe('Usdfi', function () { + const dexKey = 'Usdfi'; + const usdfi = new Usdfi(network, dexKey, dexHelper); + + describe('UniswapV2 like pool', function () { + const TokenASymbol = 'USDFI'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'USDT'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts18; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await usdfi.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await usdfi.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + + for (const poolPrice of poolPrices || []) { + await checkOnChainPricing( + usdfi, + 'getAmountOut', + blocknumber, + poolPrice.prices, + poolPrice.poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + + it('getTopPoolsForToken', async function () { + const poolLiquidity = await usdfi.getTopPoolsForToken( + tokenA.address, + 10, + ); + console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, tokenA.address, dexKey); + }); + }); + + describe('Curve like stable pool', function () { + const TokenASymbol = 'USDT'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'BUSD'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts6; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await usdfi.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await usdfi.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + for (const poolPrice of poolPrices || []) { + await checkOnChainPricing( + usdfi, + 'getAmountOut', + blocknumber, + poolPrice.prices, + poolPrice.poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + + it('getTopPoolsForToken', async function () { + const poolLiquidity = await usdfi.getTopPoolsForToken( + tokenA.address, + 10, + ); + console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, tokenA.address, dexKey); + }); + }); + + describe('FRAX -> frxETH', () => { + const TokenASymbol = 'FRAX'; + const tokenA = Tokens[network][TokenASymbol]; + const TokenBSymbol = 'frxETH'; + const tokenB = Tokens[network][TokenBSymbol]; + + const amounts = amounts18; + + it('getPoolIdentifiers and getPricesVolume', async function () { + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const pools = await usdfi.getPoolIdentifiers( + tokenA, + tokenB, + SwapSide.SELL, + blocknumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await usdfi.getPricesVolume( + tokenA, + tokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // Check if onchain pricing equals to calculated ones + for (const poolPrice of poolPrices || []) { + await checkOnChainPricing( + usdfi, + 'getAmountOut', + blocknumber, + poolPrice.prices, + poolPrice.poolAddresses![0], + tokenA.address, + amounts, + ); + } + }); + }); + }); }); describe('Arbitrum', () => { diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index a0af67fb4..0c3af9bde 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -583,6 +583,18 @@ export const Tokens: { address: '0x4268B8F0B87b6Eae5d897996E6b845ddbD99Adf3', decimals: 6, }, + FRAX: { + address: '0x90C97F71E18723b0Cf0dfa30ee176Ab653E89F40', + decimals: 18, + }, + frxETH: { + address: '0x64048A7eEcF3a2F1BA9e144aAc3D7dB6e58F555e', + decimals: 18, + }, + USDFI: { + address: '0x11A38e06699b238D6D9A0C7A01f3AC63a07ad318', + decimals: 18, + }, }, [Network.AVALANCHE]: { USDCe: { From 82dadce07ae8b001f5065d1cb22c1de168381d5d Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 23 Oct 2023 12:54:18 +0300 Subject: [PATCH 519/833] BACK-1347: fix Cannot read properties of undefined (reading fee) for UniV3 in getRPCPricing --- src/dex/uniswap-v3/uniswap-v3.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 57c32f5c6..66666e465 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -542,7 +542,7 @@ export class UniswapV3 tokenIn: from.address, tokenOut: to.address, fee: pool.feeCodeAsString, - currentFee: states[index].fee.toString(), + currentFee: states[index] ? states[index].fee.toString() : undefined, }, ], exchange: pool.poolAddress, From 65aad0b37fae9c72030a43a9179674622947b081 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 23 Oct 2023 13:03:38 +0300 Subject: [PATCH 520/833] 2.41.2-univ3-bug --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 64a7404df..5db9d5ad1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.41.0", + "version": "2.41.2-univ3-bug", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From dfd03a047576dec180526507280250b0bf841202 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 23 Oct 2023 13:06:52 +0300 Subject: [PATCH 521/833] update --- src/dex/uniswap-v3/uniswap-v3.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 66666e465..2ab48c822 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -542,7 +542,7 @@ export class UniswapV3 tokenIn: from.address, tokenOut: to.address, fee: pool.feeCodeAsString, - currentFee: states[index] ? states[index].fee.toString() : undefined, + currentFee: states[index]?.fee.toString(), }, ], exchange: pool.poolAddress, From c2926e6c54d2818b56e509ac5fb09bd6cf03fd27 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 23 Oct 2023 13:07:05 +0300 Subject: [PATCH 522/833] 2.41.2-univ3-bug.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5db9d5ad1..a5dd44544 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.41.2-univ3-bug", + "version": "2.41.2-univ3-bug.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 75ab59dba45c6530cb9ea9cc664948a37148391a Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 23 Oct 2023 13:53:19 +0300 Subject: [PATCH 523/833] 2.41.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a5dd44544..6f8d4ec69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.41.2-univ3-bug.2", + "version": "2.41.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From b1f75516a699b1bcb3e4d45d35dcd32e160c6d1c Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 23 Oct 2023 16:04:55 +0300 Subject: [PATCH 524/833] 2.41.2-fvm-on-base --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f123cf2db..f91d6dcd2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.41.1-fvm-on-base", + "version": "2.41.2-fvm-on-base", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 5aa8e705b73dbe67878fc78f2f1d2634d068d6b7 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 23 Oct 2023 16:53:30 +0300 Subject: [PATCH 525/833] fix: tests & config --- src/dex/solidly/config.ts | 4 +- src/dex/solidly/forks-override/usdfi.ts | 5 +- src/dex/solidly/solidly-e2e.test.ts | 214 +----------------------- tests/constants-e2e.ts | 3 + 4 files changed, 8 insertions(+), 218 deletions(-) diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index f788d1033..9981157f2 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -197,10 +197,8 @@ export const SolidlyConfig: DexConfigMap = { router: '0xc2b5a8082D2E1867A9CBBF41b625E3ae9dF81f8b', initCode: '0x1d770cc32abcf060a45b0de3f0afbd8594effe9f6d836f93d19c05d76b4b4dfa', - stableFee: 4, // 0.04% - volatileFee: 30, // 0.3% poolGasCost: 180 * 1000, - feeCode: 4, + feeCode: 0, // dynamic fees }, }, }; diff --git a/src/dex/solidly/forks-override/usdfi.ts b/src/dex/solidly/forks-override/usdfi.ts index 78d2f5781..6ebad08ae 100644 --- a/src/dex/solidly/forks-override/usdfi.ts +++ b/src/dex/solidly/forks-override/usdfi.ts @@ -1,11 +1,10 @@ -import { Solidly } from '../solidly'; import { Network } from '../../../constants'; import { getDexKeysWithNetwork } from '../../../utils'; import { SolidlyConfig } from '../config'; import _ from 'lodash'; +import { SpiritSwapV2 } from './spiritSwapV2'; -export class Usdfi extends Solidly { - feeFactor = 1e4; +export class Usdfi extends SpiritSwapV2 { public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork(_.pick(SolidlyConfig, ['Usdfi'])); } diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index eea1898f9..6cf392a53 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -1132,8 +1132,8 @@ describe('Solidly E2E', () => { const tokenASymbol: string = 'FRAX'; const tokenBSymbol: string = 'frxETH'; - const tokenAAmount: string = '1111100000'; - const tokenBAmount: string = '100000000000000000'; + const tokenAAmount: string = '100000000000000000'; + const tokenBAmount: string = '1111100000'; const nativeTokenAmount = '100000000000000000'; testForNetwork( @@ -1145,216 +1145,6 @@ describe('Solidly E2E', () => { tokenBAmount, nativeTokenAmount, ); - - // TODO: Delete - - // const dexKey = 'Usdfi'; - // const usdAmount = '1000000'; - - // const tokenASymbol: string = 'WBNB'; - // const tokenBSymbol: string = 'CONE'; - - // const tokenAAmount: string = '1111100'; - // const tokenBAmount: string = '1000000'; - // const nativeTokenAmount = '1000000000000000000'; - - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // nativeTokenAmount, - // ); - - //// - - // describe('Usdfi UniswapV2 Pools', () => { - // const bnbAmount = '1000000000000000000'; - - // describe('simpleSwap', () => { - // it('BNB -> TOKEN', async () => { - // await testE2E( - // tokens.BNB, - // tokens.BUSD, - // holders.BNB, - // bnbAmount, - // SwapSide.SELL, - // dexKey, - // ContractMethod.simpleSwap, - // network, - // provider, - // ); - // }); - - // it('Token -> BNB', async () => { - // await testE2E( - // tokens.USDT, - // tokens.BNB, - // holders.USDT, - // usdAmount, - // SwapSide.SELL, - // dexKey, - // ContractMethod.simpleSwap, - // network, - // provider, - // ); - // }); - - // it('Token -> Token', async () => { - // await testE2E( - // tokens.WBNB, - // tokens.CONE, - // holders.WBNB, - // bnbAmount, - // SwapSide.SELL, - // dexKey, - // ContractMethod.simpleSwap, - // network, - // provider, - // ); - // }); - // }); - - // describe('multiSwap', () => { - // it('BNB -> TOKEN', async () => { - // await testE2E( - // tokens.BNB, - // tokens.BUSD, - // holders.BNB, - // bnbAmount, - // SwapSide.SELL, - // dexKey, - // ContractMethod.multiSwap, - // network, - // provider, - // ); - // }); - - // it('Token -> BNB', async () => { - // await testE2E( - // tokens.USDT, - // tokens.BNB, - // holders.USDT, - // usdAmount, - // SwapSide.SELL, - // dexKey, - // ContractMethod.multiSwap, - // network, - // provider, - // ); - // }); - - // it('Token -> Token', async () => { - // await testE2E( - // tokens.WBNB, - // tokens.CONE, - // holders.WBNB, - // bnbAmount, - // SwapSide.SELL, - // dexKey, - // ContractMethod.multiSwap, - // network, - // provider, - // ); - // }); - // }); - - // describe('megaSwap', () => { - // it('BNB -> TOKEN', async () => { - // await testE2E( - // tokens.USDT, - // tokens.BNB, - // holders.USDT, - // usdAmount, - // SwapSide.SELL, - // dexKey, - // ContractMethod.megaSwap, - // network, - // provider, - // ); - // }); - - // it('Token -> BNB', async () => { - // await testE2E( - // tokens.USDT, - // tokens.BNB, - // holders.USDT, - // usdAmount, - // SwapSide.SELL, - // dexKey, - // ContractMethod.megaSwap, - // network, - // provider, - // ); - // }); - - // it('Token -> Token', async () => { - // await testE2E( - // tokens.WBNB, - // tokens.CONE, - // holders.WBNB, - // bnbAmount, - // SwapSide.SELL, - // dexKey, - // ContractMethod.megaSwap, - // network, - // provider, - // ); - // }); - // }); - // }); - - // describe('Usdfi Stable Pools', () => { - // describe('simpleSwap', () => { - // it('Token -> Token', async () => { - // await testE2E( - // tokens.USDC, - // tokens.USDT, - // holders.USDC, - // usdAmount, - // SwapSide.SELL, - // dexKey, - // ContractMethod.simpleSwap, - // network, - // provider, - // ); - // }); - // }); - - // describe('multiSwap', () => { - // it('Token -> Token', async () => { - // await testE2E( - // tokens.USDC, - // tokens.USDT, - // holders.USDC, - // usdAmount, - // SwapSide.SELL, - // dexKey, - // ContractMethod.multiSwap, - // network, - // provider, - // ); - // }); - // }); - - // describe('megaSwap', () => { - // it('Token -> Token', async () => { - // await testE2E( - // tokens.USDC, - // tokens.USDT, - // holders.USDC, - // usdAmount, - // SwapSide.SELL, - // dexKey, - // ContractMethod.megaSwap, - // network, - // provider, - // ); - // }); - // }); - // }); }); }); diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 0c3af9bde..b579b1576 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1083,6 +1083,9 @@ export const Holders: { anyBTC: '0x4ffef8e8a75c20ab0ddf96c50d2457277d27923c', nUSD: '0x28ec0b36f0819ecb5005cab836f4ed5a2eca4d13', axlUSD: '0xc03fbeda9069b22a120ae6a09349a0b5eea5570a', + FRAX: '0xEB4576fE753DAB07635c0Bb6c8f0A355e1Db5d31', + frxETH: '0xf324adC872005197A6f7DAE214d3b63aa0C3625F', + USDFI: '0x2E00D722e091836B39Db3e4dcE6eE51c90c5B221', }, [Network.AVALANCHE]: { AVAX: '0xD6216fC19DB775Df9774a6E33526131dA7D19a2c', From 7d686ab06f45f22e278649a5a2b88011348ae03a Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 23 Oct 2023 17:01:34 +0300 Subject: [PATCH 526/833] 2.41.1-add-usdfi --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6f8d4ec69..eaf13202d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.41.1", + "version": "2.41.1-add-usdfi", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e08ff93675e16f4922f754c2f6f958fe05cbe775 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 24 Oct 2023 11:37:40 +0300 Subject: [PATCH 527/833] 2.41.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f91d6dcd2..90add610b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.41.2-fvm-on-base", + "version": "2.41.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From b823551fd1b856ebaf1a2ce12c9871f07653046f Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 24 Oct 2023 15:39:03 +0300 Subject: [PATCH 528/833] BACK-1348: Rename Fvm -> Velocimeter --- src/dex/index.ts | 4 +- src/dex/solidly/config.ts | 6 +-- .../forks-override/{fvm.ts => velocimeter.ts} | 12 ++--- src/dex/solidly/solidly-e2e.test.ts | 8 ++-- src/dex/solidly/solidly-integration.test.ts | 44 +++++++++---------- src/dex/solidly/solidly.ts | 2 +- 6 files changed, 38 insertions(+), 38 deletions(-) rename src/dex/solidly/forks-override/{fvm.ts => velocimeter.ts} (74%) diff --git a/src/dex/index.ts b/src/dex/index.ts index aaff6a4e3..d6bf2cdfa 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -53,7 +53,7 @@ import { Synthetix } from './synthetix/synthetix'; import { Cone } from './solidly/forks-override/cone'; import { SoliSnek } from './solidly/forks-override/solisnek'; import { Equalizer } from './solidly/forks-override/equalizer'; -import { Fvm } from './solidly/forks-override/fvm'; +import { Velocimeter } from './solidly/forks-override/velocimeter'; import { BalancerV1 } from './balancer-v1/balancer-v1'; import { balancerV1Merge } from './balancer-v1/optimizer'; import { CurveV1 } from './curve-v1/curve-v1'; @@ -142,7 +142,7 @@ const Dexes = [ Cone, SoliSnek, Equalizer, - Fvm, + Velocimeter, Synthetix, CurveV1Factory, SwaapV1, diff --git a/src/dex/solidly/config.ts b/src/dex/solidly/config.ts index c653d8c41..2e51c6a7f 100644 --- a/src/dex/solidly/config.ts +++ b/src/dex/solidly/config.ts @@ -178,7 +178,7 @@ export const SolidlyConfig: DexConfigMap = { poolGasCost: 180 * 1000, }, }, - Fvm: { + Velocimeter: { [Network.FANTOM]: { factoryAddress: '0x472f3C3c9608fe0aE8d702f3f8A2d12c410C881A', router: '0x93d2611EB8b85bE4FDEa9D94Ce9913D90072eC0f', @@ -205,7 +205,7 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'PolygonAdapter02', index: 3 }], // dystopia }, [Network.FANTOM]: { - [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 10 }], // solidly, spiritSwapV2, equalizer, fvm + [SwapSide.SELL]: [{ name: 'FantomAdapter01', index: 10 }], // solidly, spiritSwapV2, equalizer, velocimeter }, [Network.OPTIMISM]: { [SwapSide.SELL]: [{ name: 'OptimismAdapter01', index: 8 }], // velodrome @@ -223,6 +223,6 @@ export const Adapters: Record = { [SwapSide.SELL]: [{ name: 'ArbitrumAdapter02', index: 1 }], // chronos, ramses }, [Network.BASE]: { - [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 3 }], // aerodrome, equalizer + [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 3 }], // aerodrome, equalizer, velocimeter }, }; diff --git a/src/dex/solidly/forks-override/fvm.ts b/src/dex/solidly/forks-override/velocimeter.ts similarity index 74% rename from src/dex/solidly/forks-override/fvm.ts rename to src/dex/solidly/forks-override/velocimeter.ts index 8fabb10a5..9825b42ac 100644 --- a/src/dex/solidly/forks-override/fvm.ts +++ b/src/dex/solidly/forks-override/velocimeter.ts @@ -7,7 +7,7 @@ import { getDexKeysWithNetwork } from '../../../utils'; import { SolidlyConfig } from '../config'; import _ from 'lodash'; -const FvmFactoryABI = [ +const velocimeterFactoryABI = [ { inputs: [{ internalType: '_pair', name: '_stable', type: 'address' }], name: 'getFee', @@ -17,11 +17,11 @@ const FvmFactoryABI = [ }, ]; -const fvmFactoryIface = new Interface(FvmFactoryABI); +const velocimeteractoryIface = new Interface(velocimeterFactoryABI); -export class Fvm extends Solidly { +export class Velocimeter extends Solidly { public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(_.pick(SolidlyConfig, ['Fvm'])); + getDexKeysWithNetwork(_.pick(SolidlyConfig, ['Velocimeter'])); constructor( protected network: Network, @@ -39,11 +39,11 @@ export class Fvm extends Solidly { protected getFeesMultiCallData(pair: SolidlyPair) { const callEntry = { target: this.factoryAddress, - callData: fvmFactoryIface.encodeFunctionData('getFee', [pair.exchange]), + callData: velocimeteractoryIface.encodeFunctionData('getFee', [pair.exchange]), }; const callDecoder = (values: any[]) => parseInt( - fvmFactoryIface.decodeFunctionResult('getFee', values)[0].toString(), + velocimeteractoryIface.decodeFunctionResult('getFee', values)[0].toString(), ); return { diff --git a/src/dex/solidly/solidly-e2e.test.ts b/src/dex/solidly/solidly-e2e.test.ts index dc90a71d1..80e4d8680 100644 --- a/src/dex/solidly/solidly-e2e.test.ts +++ b/src/dex/solidly/solidly-e2e.test.ts @@ -416,8 +416,8 @@ describe('Solidly E2E', () => { ); }); - describe('Fvm', () => { - const dexKey = 'Fvm'; + describe('Velocimeter', () => { + const dexKey = 'Velocimeter'; const network = Network.FANTOM; const tokenASymbol: string = 'lzUSDC'; @@ -1514,8 +1514,8 @@ describe('Solidly E2E', () => { ); }); - describe('Fvm', () => { - const dexKey = 'Fvm'; + describe('Velocimeter', () => { + const dexKey = 'Velocimeter'; const tokenASymbol: string = 'USDbC'; const tokenBSymbol: string = 'DAI'; diff --git a/src/dex/solidly/solidly-integration.test.ts b/src/dex/solidly/solidly-integration.test.ts index 18e4922ca..5acebe97f 100644 --- a/src/dex/solidly/solidly-integration.test.ts +++ b/src/dex/solidly/solidly-integration.test.ts @@ -17,7 +17,7 @@ import { Ramses } from './forks-override/ramses'; import * as util from 'util'; import { VelodromeV2 } from './forks-override/velodromeV2'; import { Equalizer } from './forks-override/equalizer'; -import { Fvm } from './forks-override/fvm'; +import { Velocimeter } from './forks-override/velocimeter'; const amounts18 = [0n, BI_POWS[18], 2000000000000000000n]; const amounts6 = [0n, BI_POWS[6], 2000000n]; @@ -527,9 +527,9 @@ describe('Solidly integration tests', () => { }); }); - describe('Fvm', () => { - const dexKey = 'Fvm'; - const fvm = new Fvm(network, dexKey, dexHelper); + describe('Velocimeter', () => { + const dexKey = 'Velocimeter'; + const velocimeter = new Velocimeter(network, dexKey, dexHelper); describe('UniswapV2 like pool', function () { const TokenASymbol = 'WFTM'; @@ -541,7 +541,7 @@ describe('Solidly integration tests', () => { it('getPoolIdentifiers and getPricesVolume', async function () { const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); - const pools = await fvm.getPoolIdentifiers( + const pools = await velocimeter.getPoolIdentifiers( tokenA, tokenB, SwapSide.SELL, @@ -554,7 +554,7 @@ describe('Solidly integration tests', () => { expect(pools.length).toBeGreaterThan(0); - const poolPrices = await fvm.getPricesVolume( + const poolPrices = await velocimeter.getPricesVolume( tokenA, tokenB, amounts, @@ -574,7 +574,7 @@ describe('Solidly integration tests', () => { for (const poolPrice of poolPrices || []) { await checkOnChainPricing( - fvm, + velocimeter, 'getAmountOut', blocknumber, poolPrice.prices, @@ -596,7 +596,7 @@ describe('Solidly integration tests', () => { it('getPoolIdentifiers and getPricesVolume', async function () { const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); - const pools = await fvm.getPoolIdentifiers( + const pools = await velocimeter.getPoolIdentifiers( tokenA, tokenB, SwapSide.SELL, @@ -609,7 +609,7 @@ describe('Solidly integration tests', () => { expect(pools.length).toBeGreaterThan(0); - const poolPrices = await fvm.getPricesVolume( + const poolPrices = await velocimeter.getPricesVolume( tokenA, tokenB, amounts, @@ -628,7 +628,7 @@ describe('Solidly integration tests', () => { // Check if onchain pricing equals to calculated ones for (const poolPrice of poolPrices || []) { await checkOnChainPricing( - fvm, + velocimeter, 'getAmountOut', blocknumber, poolPrice.prices, @@ -652,7 +652,7 @@ describe('Solidly integration tests', () => { it('getPoolIdentifiers and getPricesVolume', async function () { // const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); const blocknumber = 67666611; - const pools = await fvm.getPoolIdentifiers( + const pools = await velocimeter.getPoolIdentifiers( tokenA, tokenB, SwapSide.SELL, @@ -665,7 +665,7 @@ describe('Solidly integration tests', () => { expect(pools.length).toBeGreaterThan(0); - const poolPrices = await fvm.getPricesVolume( + const poolPrices = await velocimeter.getPricesVolume( tokenA, tokenB, amounts, @@ -684,7 +684,7 @@ describe('Solidly integration tests', () => { // Check if onchain pricing equals to calculated ones for (const poolPrice of poolPrices || []) { await checkOnChainPricing( - fvm, + velocimeter, 'getAmountOut', blocknumber, poolPrice.prices, @@ -1439,9 +1439,9 @@ describe('Solidly integration tests', () => { }); }); - describe('Fvm', () => { - const dexKey = 'Fvm'; - const fvm = new Fvm(network, dexKey, dexHelper); + describe('Velocimeter', () => { + const dexKey = 'Velocimeter'; + const velocimeter = new Velocimeter(network, dexKey, dexHelper); describe('UniswapV2 like pool', function () { const TokenASymbol = 'WETH'; @@ -1453,7 +1453,7 @@ describe('Solidly integration tests', () => { it('getPoolIdentifiers and getPricesVolume', async function () { const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); - const pools = await fvm.getPoolIdentifiers( + const pools = await velocimeter.getPoolIdentifiers( tokenA, tokenB, SwapSide.SELL, @@ -1466,7 +1466,7 @@ describe('Solidly integration tests', () => { expect(pools.length).toBeGreaterThan(0); - const poolPrices = await fvm.getPricesVolume( + const poolPrices = await velocimeter.getPricesVolume( tokenA, tokenB, amounts, @@ -1486,7 +1486,7 @@ describe('Solidly integration tests', () => { for (const poolPrice of poolPrices || []) { await checkOnChainPricing( - fvm, + velocimeter, 'getAmountOut', blocknumber, poolPrice.prices, @@ -1508,7 +1508,7 @@ describe('Solidly integration tests', () => { it('getPoolIdentifiers and getPricesVolume', async function () { const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); - const pools = await fvm.getPoolIdentifiers( + const pools = await velocimeter.getPoolIdentifiers( tokenA, tokenB, SwapSide.SELL, @@ -1521,7 +1521,7 @@ describe('Solidly integration tests', () => { expect(pools.length).toBeGreaterThan(0); - const poolPrices = await fvm.getPricesVolume( + const poolPrices = await velocimeter.getPricesVolume( tokenA, tokenB, amounts, @@ -1540,7 +1540,7 @@ describe('Solidly integration tests', () => { // Check if onchain pricing equals to calculated ones for (const poolPrice of poolPrices || []) { await checkOnChainPricing( - fvm, + velocimeter, 'getAmountOut', blocknumber, poolPrice.prices, diff --git a/src/dex/solidly/solidly.ts b/src/dex/solidly/solidly.ts index aab0a021c..c8f941ce9 100644 --- a/src/dex/solidly/solidly.ts +++ b/src/dex/solidly/solidly.ts @@ -75,7 +75,7 @@ export class Solidly extends UniswapV2 { 'Chronos', 'Ramses', 'Equalizer', - 'Fvm', + 'Velocimeter', ]), ); From 597cc9d0625d0e1fa6d03826604518f3b695ba12 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 24 Oct 2023 15:41:07 +0300 Subject: [PATCH 529/833] 2.41.3-fvm-to-velocimeter --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 90add610b..d4991b1ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.41.2", + "version": "2.41.3-fvm-to-velocimeter", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 8845b2c51d2097bb954381859a5237ad83045403 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 24 Oct 2023 17:19:01 +0300 Subject: [PATCH 530/833] fix typo --- src/dex/solidly/forks-override/velocimeter.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/solidly/forks-override/velocimeter.ts b/src/dex/solidly/forks-override/velocimeter.ts index 9825b42ac..e3a6e5c74 100644 --- a/src/dex/solidly/forks-override/velocimeter.ts +++ b/src/dex/solidly/forks-override/velocimeter.ts @@ -17,7 +17,7 @@ const velocimeterFactoryABI = [ }, ]; -const velocimeteractoryIface = new Interface(velocimeterFactoryABI); +const velocimeterFactoryIface = new Interface(velocimeterFactoryABI); export class Velocimeter extends Solidly { public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = @@ -39,11 +39,11 @@ export class Velocimeter extends Solidly { protected getFeesMultiCallData(pair: SolidlyPair) { const callEntry = { target: this.factoryAddress, - callData: velocimeteractoryIface.encodeFunctionData('getFee', [pair.exchange]), + callData: velocimeterFactoryIface.encodeFunctionData('getFee', [pair.exchange]), }; const callDecoder = (values: any[]) => parseInt( - velocimeteractoryIface.decodeFunctionResult('getFee', values)[0].toString(), + velocimeterFactoryIface.decodeFunctionResult('getFee', values)[0].toString(), ); return { From 18b98d196c98dcad51e707e78e296ef1325825a3 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 24 Oct 2023 17:24:01 +0300 Subject: [PATCH 531/833] fix: add Mainnet support for TraderJoeV2.1 --- src/dex/trader-joe-v2.1.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dex/trader-joe-v2.1.ts b/src/dex/trader-joe-v2.1.ts index 23b21394f..32eb07dfa 100644 --- a/src/dex/trader-joe-v2.1.ts +++ b/src/dex/trader-joe-v2.1.ts @@ -15,6 +15,7 @@ const TRADERJOE_V2_1_ROUTER_ADDRESS: { [network: number]: Address } = { [Network.AVALANCHE]: '0xb4315e873dBcf96Ffd0acd8EA43f689D8c20fB30', [Network.ARBITRUM]: '0xb4315e873dBcf96Ffd0acd8EA43f689D8c20fB30', [Network.BSC]: '0xb4315e873dBcf96Ffd0acd8EA43f689D8c20fB30', + [Network.MAINNET]: '0x9A93a421b74F1c5755b83dD2C211614dC419C44b', }; type RouterPath = [ From f54b1ad2942e328f817220332790511e413fc9c3 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 24 Oct 2023 17:24:58 +0300 Subject: [PATCH 532/833] 2.41.2-traderjoe-on-mainnet --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 90add610b..8e8aa86cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.41.2", + "version": "2.41.2-traderjoe-on-mainnet", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 0c6b63bd6eb973a525b95d8e0a9d0f95d14cbfdc Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 24 Oct 2023 17:27:45 +0300 Subject: [PATCH 533/833] 2.41.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d4991b1ab..c6f3a9779 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.41.3-fvm-to-velocimeter", + "version": "2.41.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 58c0090df862b037cb432614df87aa4b403db0cb Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 24 Oct 2023 17:40:13 +0300 Subject: [PATCH 534/833] 2.41.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c6f3a9779..78a1086fa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.41.3", + "version": "2.41.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e5f45c0fe216083aa321d7633f72e53949a5b129 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 25 Oct 2023 16:37:58 +0300 Subject: [PATCH 535/833] BACK-1349: Integrate PolygonMigrator on Mainnet --- .../PolygonMigration.abi.json | 364 ++++++++++++++++++ src/config.ts | 4 +- src/dex/index.ts | 2 + src/dex/polygon-migrator/config.ts | 25 ++ src/dex/polygon-migrator/constants.ts | 2 + .../polygon-migrator-e2e.test.ts | 102 +++++ src/dex/polygon-migrator/polygon-migrator.ts | 151 ++++++++ src/dex/polygon-migrator/types.ts | 14 + tests/constants-e2e.ts | 10 + 9 files changed, 672 insertions(+), 2 deletions(-) create mode 100644 src/abi/polygon-migration/PolygonMigration.abi.json create mode 100644 src/dex/polygon-migrator/config.ts create mode 100644 src/dex/polygon-migrator/constants.ts create mode 100644 src/dex/polygon-migrator/polygon-migrator-e2e.test.ts create mode 100644 src/dex/polygon-migrator/polygon-migrator.ts create mode 100644 src/dex/polygon-migrator/types.ts diff --git a/src/abi/polygon-migration/PolygonMigration.abi.json b/src/abi/polygon-migration/PolygonMigration.abi.json new file mode 100644 index 000000000..56bace0fb --- /dev/null +++ b/src/abi/polygon-migration/PolygonMigration.abi.json @@ -0,0 +1,364 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "matic_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAddressOrAlreadySet", + "type": "error" + }, + { + "inputs": [], + "name": "UnmigrationLocked", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Migrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Unmigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "lock", + "type": "bool" + } + ], + "name": "UnmigrationLockUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "matic", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "polygon", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "polygon_", + "type": "address" + } + ], + "name": "setPolygonToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "unmigrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "unmigrateTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "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": "unmigrateWithPermit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unmigrationLocked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "unmigrationLocked_", + "type": "bool" + } + ], + "name": "updateUnmigrationLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/src/config.ts b/src/config.ts index 60b254923..b6a7f48b6 100644 --- a/src/config.ts +++ b/src/config.ts @@ -52,8 +52,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { Adapter01: '0x9bE264469eF954c139Da4A45Cf76CbCC5e3A6A73', Adapter02: '0xFC2Ba6E830a04C25e207B8214b26d8C713F6881F', Adapter03: '0xfb2a3de6c7B8c77b520E3da16021f3D8A4E93168', - Adapter04: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', - BuyAdapter: '0x613876f3dE2Ec633f8054fE7a561324c1a01d9cB', + Adapter04: '0x7c71485dC644E8E6c2173029d2403bE3CAA58a67', + BuyAdapter: '0x3206a3138Bb111E89517e0EeF5A6082e08E24e34', }, uniswapV2ExchangeRouterAddress: '0xF9234CB08edb93c0d4a4d4c70cC3FfD070e78e07', diff --git a/src/dex/index.ts b/src/dex/index.ts index b3999f5f5..a4f58e878 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -5,6 +5,7 @@ import { Jarvis } from './jarvis'; import { JarvisV6 } from './jarvis-v6/jarvis-v6'; import { StablePool } from './stable-pool'; import { Weth } from './weth/weth'; +import { PolygonMigrator } from './polygon-migrator/polygon-migrator'; import { ZeroX } from './zerox'; import { UniswapV3 } from './uniswap-v3/uniswap-v3'; import { BalancerV2 } from './balancer-v2/balancer-v2'; @@ -124,6 +125,7 @@ const Dexes = [ AaveV3, KyberDmm, Weth, + PolygonMigrator, MakerPsm, Nerve, Platypus, diff --git a/src/dex/polygon-migrator/config.ts b/src/dex/polygon-migrator/config.ts new file mode 100644 index 000000000..8eef9dc20 --- /dev/null +++ b/src/dex/polygon-migrator/config.ts @@ -0,0 +1,25 @@ +import { DexParams } from './types'; +import { DexConfigMap } from '../../types'; +import { Network } from '../../constants'; +import { SwapSide } from '@paraswap/core'; + +export const PolygonMigratorConfig: DexConfigMap = { + PolygonMigrator: { + [Network.MAINNET]: { + migratorAddress: '0x29e7df7b6a1b2b07b731457f499e1696c60e2c4e', + polTokenAddress: '0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6', + maticTokenAddress: '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0' + }, + }, +}; + +export const Adapters: { + [chainId: number]: { + [side: string]: { name: string; index: number }[]; + }; +} = { + [Network.MAINNET]: { + [SwapSide.SELL]: [{ name: 'Adapter04', index: 4 }], + [SwapSide.BUY]: [{ name: 'BuyAdapter', index: 11 }], + }, +}; diff --git a/src/dex/polygon-migrator/constants.ts b/src/dex/polygon-migrator/constants.ts new file mode 100644 index 000000000..f873a0fce --- /dev/null +++ b/src/dex/polygon-migrator/constants.ts @@ -0,0 +1,2 @@ + +export const POLYGON_MIGRATION_GAS_COST= 90_000; diff --git a/src/dex/polygon-migrator/polygon-migrator-e2e.test.ts b/src/dex/polygon-migrator/polygon-migrator-e2e.test.ts new file mode 100644 index 000000000..8696a078d --- /dev/null +++ b/src/dex/polygon-migrator/polygon-migrator-e2e.test.ts @@ -0,0 +1,102 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { ContractMethod, Network, SwapSide } from '../../constants'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; +import { Holders, Tokens } from '../../../tests/constants-e2e'; +import { testE2E } from '../../../tests/utils-e2e'; + +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + ContractMethod.buy, + ], + ], + ]); + + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[tokenBSymbol], + tokens[tokenASymbol], + holders[tokenBSymbol], + side === SwapSide.SELL ? tokenBAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }), + ); + }); +} + +describe('PolygonMigrator E2E', () => { + const dexKey = 'PolygonMigrator'; + + describe('Mainnet', () => { + const network = Network.MAINNET; + + const tokenASymbol: string = 'POL'; + const tokenBSymbol: string = 'MATIC'; + + const tokenAAmount: string = '10000000000000000000'; + const tokenBAmount: string = '20000000000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + ); + }); +}); diff --git a/src/dex/polygon-migrator/polygon-migrator.ts b/src/dex/polygon-migrator/polygon-migrator.ts new file mode 100644 index 000000000..4dc8b7a68 --- /dev/null +++ b/src/dex/polygon-migrator/polygon-migrator.ts @@ -0,0 +1,151 @@ +import { SimpleExchange } from '../simple-exchange'; +import { IDex } from '../idex'; +import { DexParams, PolygonMigrationData, PolygonMigratorFunctions } from './types'; +import { Network, SwapSide } from '../../constants'; +import { getDexKeysWithNetwork } from '../../utils'; +import { Adapters, PolygonMigratorConfig } from './config'; +import { + AdapterExchangeParam, + Address, + ExchangePrices, + Logger, + PoolLiquidity, + PoolPrices, + SimpleExchangeParam, + Token +} from '../../types'; +import { IDexHelper } from '../../dex-helper'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { BI_POWS } from '../../bigint-constants'; +import { POLYGON_MIGRATION_GAS_COST } from './constants'; +import PolygonMigrationAbi from '../../abi/polygon-migration/PolygonMigration.abi.json'; +import { Interface } from 'ethers/lib/utils'; + +export class PolygonMigrator extends SimpleExchange implements IDex { + readonly hasConstantPriceLargeAmounts = true; + readonly isFeeOnTransferSupported = false; + + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(PolygonMigratorConfig); + + logger: Logger; + + constructor( + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + readonly migratorAddress: string = PolygonMigratorConfig['PolygonMigrator'][network].migratorAddress, + readonly polTokenAddress: string = PolygonMigratorConfig['PolygonMigrator'][network].polTokenAddress, + readonly maticTokenAddress: string = PolygonMigratorConfig['PolygonMigrator'][network].maticTokenAddress, + protected unitPrice = BI_POWS[18], + protected adapters = Adapters[network] || {}, + protected migratorInterface = new Interface(PolygonMigrationAbi), + ) { + super(dexHelper, dexKey); + this.logger = dexHelper.getLogger(dexKey); + } + + getAdapters(side: SwapSide): { name: string; index: number }[] | null { + return this.adapters[side] || null; + } + + isMatic(tokenAddress: Address) { + return this.maticTokenAddress.toLowerCase() === tokenAddress.toLowerCase(); + } + + isPol(tokenAddress: Address) { + return this.polTokenAddress.toLowerCase() === tokenAddress.toLowerCase(); + } + + isAppropriatePair(srcToken: Token, destToken: Token) { + return (this.isMatic(srcToken.address) && this.isPol(destToken.address)) + || (this.isMatic(destToken.address) && this.isPol(srcToken.address)); + } + + async getPoolIdentifiers( + srcToken: Token, + destToken: Token, + side: SwapSide, + blockNumber: number, + ): Promise { + if(this.isAppropriatePair(srcToken, destToken)) { + return [`${this.network}_${srcToken.address}_${destToken.address}`]; + } + + return []; + } + + async getPricesVolume( + srcToken: Token, + destToken: Token, + amounts: bigint[], + side: SwapSide, + blockNumber: number, + limitPools?: string[], + ): Promise> { + if(!this.isAppropriatePair(srcToken, destToken)) { + return null; + } + + return [ + { + prices: amounts, + unit: this.unitPrice, + gasCost: POLYGON_MIGRATION_GAS_COST, + exchange: this.dexKey, + poolAddresses: [this.migratorAddress], + data: null, + }, + ]; + } + + // Returns estimated gas cost of calldata for this DEX in multiSwap + getCalldataGasCost(poolPrices: PoolPrices): number | number[] { + return CALLDATA_GAS_COST.DEX_NO_PAYLOAD; + } + + getAdapterParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: PolygonMigrationData, + side: SwapSide, + ): AdapterExchangeParam { + return { + targetExchange: this.migratorAddress, + payload: '0x', + networkFee: '0', + }; + } + + async getSimpleParam( + srcToken: string, + destToken: string, + srcAmount: string, + destAmount: string, + data: PolygonMigrationData, + side: SwapSide, + ): Promise { + const swapData = this.migratorInterface.encodeFunctionData( + this.isMatic(srcToken) ? PolygonMigratorFunctions.migrate : PolygonMigratorFunctions.unmigrate, + [ srcAmount ], + ); + + return this.buildSimpleParamWithoutWETHConversion( + srcToken, + srcAmount, + destToken, + destAmount, + swapData, + this.migratorAddress, + ); + } + + async getTopPoolsForToken( + tokenAddress: Address, + limit: number, + ): Promise { + return []; + } +} diff --git a/src/dex/polygon-migrator/types.ts b/src/dex/polygon-migrator/types.ts new file mode 100644 index 000000000..d4d23377d --- /dev/null +++ b/src/dex/polygon-migrator/types.ts @@ -0,0 +1,14 @@ +import { Address } from '../../types'; + +export type PolygonMigrationData = null; + +export type DexParams = { + migratorAddress: Address; + polTokenAddress: Address; + maticTokenAddress: Address; +}; + +export enum PolygonMigratorFunctions { + migrate = 'migrate', + unmigrate = 'unmigrate', +} diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index b579b1576..d7f259073 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -311,6 +311,14 @@ export const Tokens: { address: '0x8751d4196027d4e6da63716fa7786b5174f04c15', decimals: 18, }, + MATIC: { + address: '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0', + decimals: 18, + }, + POL: { + address: '0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6', + decimals: 19, + } }, [Network.ROPSTEN]: { DAI: { @@ -1008,6 +1016,8 @@ export const Holders: { crvUSD: '0xA920De414eA4Ab66b97dA1bFE9e6EcA7d4219635', GHO: '0x844Dc85EdD8492A56228D293cfEbb823EF3E10EC', wibBTC: '0xFbdCA68601f835b27790D98bbb8eC7f05FDEaA9B', + MATIC: '0x7073783eee7e9b3e6e4ddac4d7f49dc46044dd9a', + POL: '0xCc56a33BdfCfdec4E35aD1259C1f1A06efa0AAcd', }, [Network.ROPSTEN]: { ETH: '0x43262A12d8610AA70C15DbaeAC321d51613c9071', From b7b3e40c9f3d3288dcf8088349eb2546deb0323f Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 25 Oct 2023 16:53:54 +0300 Subject: [PATCH 536/833] add integration testts --- .../polygon-migrator-integration.test.ts | 140 ++++++++++++++++++ src/dex/polygon-migrator/polygon-migrator.ts | 8 +- 2 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 src/dex/polygon-migrator/polygon-migrator-integration.test.ts diff --git a/src/dex/polygon-migrator/polygon-migrator-integration.test.ts b/src/dex/polygon-migrator/polygon-migrator-integration.test.ts new file mode 100644 index 000000000..9ad346f5f --- /dev/null +++ b/src/dex/polygon-migrator/polygon-migrator-integration.test.ts @@ -0,0 +1,140 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { DummyDexHelper } from '../../dex-helper/index'; +import { Network, SwapSide } from '../../constants'; +import { checkConstantPoolPrices } from '../../../tests/utils'; +import { Tokens } from '../../../tests/constants-e2e'; +import { BI_POWS } from '../../bigint-constants'; +import { PolygonMigrator } from './polygon-migrator'; + +const network = Network.MAINNET; + +const MaticSymbol = 'MATIC'; +const MaticToken = Tokens[network][MaticSymbol]; + +const PolSymbol = 'POL'; +const PolToken = Tokens[network][PolSymbol]; + +const amounts = [0n, BI_POWS[18], 2000000000000000000n]; + +const dexKey = 'PolygonMigrator'; + +describe('PolygonMigrator', function () { + it('getPoolIdentifiers and getPricesVolume MATIC -> POL SELL', async function () { + const dexHelper = new DummyDexHelper(network); + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const polygonMigrator = new PolygonMigrator(network, dexKey, dexHelper); + + const pools = await polygonMigrator.getPoolIdentifiers( + MaticToken, + PolToken, + SwapSide.SELL, + blocknumber, + ); + console.log(`${MaticSymbol} <> ${PolSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await polygonMigrator.getPricesVolume( + MaticToken, + PolToken, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log(`${MaticSymbol} <> ${PolSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + }); + + it('getPoolIdentifiers and getPricesVolume POL -> MATIC SELL', async function () { + const dexHelper = new DummyDexHelper(network); + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const polygonMigrator = new PolygonMigrator(network, dexKey, dexHelper); + + const pools = await polygonMigrator.getPoolIdentifiers( + PolToken, + MaticToken, + SwapSide.SELL, + blocknumber, + ); + console.log(`${PolSymbol} <> ${MaticSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await polygonMigrator.getPricesVolume( + PolToken, + MaticToken, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log(`${PolSymbol} <> ${MaticSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + }); + + it('getPoolIdentifiers and getPricesVolume MATIC -> POL BUY', async function () { + const dexHelper = new DummyDexHelper(network); + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const polygonMigrator = new PolygonMigrator(network, dexKey, dexHelper); + + const pools = await polygonMigrator.getPoolIdentifiers( + MaticToken, + PolToken, + SwapSide.BUY, + blocknumber, + ); + console.log(`${MaticSymbol} <> ${PolSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await polygonMigrator.getPricesVolume( + MaticToken, + PolToken, + amounts, + SwapSide.BUY, + blocknumber, + pools, + ); + console.log(`${MaticSymbol} <> ${PolSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + }); + + it('getPoolIdentifiers and getPricesVolume POL -> MATIC BUY', async function () { + const dexHelper = new DummyDexHelper(network); + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const polygonMigrator = new PolygonMigrator(network, dexKey, dexHelper); + + const pools = await polygonMigrator.getPoolIdentifiers( + PolToken, + MaticToken, + SwapSide.BUY, + blocknumber, + ); + console.log(`${PolSymbol} <> ${MaticSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await polygonMigrator.getPricesVolume( + PolToken, + MaticToken, + amounts, + SwapSide.BUY, + blocknumber, + pools, + ); + console.log(`${PolSymbol} <> ${MaticSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + }); + +}); diff --git a/src/dex/polygon-migrator/polygon-migrator.ts b/src/dex/polygon-migrator/polygon-migrator.ts index 4dc8b7a68..1631248da 100644 --- a/src/dex/polygon-migrator/polygon-migrator.ts +++ b/src/dex/polygon-migrator/polygon-migrator.ts @@ -34,9 +34,9 @@ export class PolygonMigrator extends SimpleExchange implements IDex { if(this.isAppropriatePair(srcToken, destToken)) { - return [`${this.network}_${srcToken.address}_${destToken.address}`]; + return [`${this.dexKey}_${srcToken.address}_${destToken.address}`]; } return []; From fdf644baca83f1f759529dcc6c5fd506be66ac57 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 25 Oct 2023 19:39:09 +0300 Subject: [PATCH 537/833] update adapters addresses --- src/config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index b6a7f48b6..78f2cccdc 100644 --- a/src/config.ts +++ b/src/config.ts @@ -52,8 +52,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { Adapter01: '0x9bE264469eF954c139Da4A45Cf76CbCC5e3A6A73', Adapter02: '0xFC2Ba6E830a04C25e207B8214b26d8C713F6881F', Adapter03: '0xfb2a3de6c7B8c77b520E3da16021f3D8A4E93168', - Adapter04: '0x7c71485dC644E8E6c2173029d2403bE3CAA58a67', - BuyAdapter: '0x3206a3138Bb111E89517e0EeF5A6082e08E24e34', + Adapter04: '0x1A23Aa6f7ff4215Fd2d220EA6f4a0DF45A77fc6C', + BuyAdapter: '0x1310dE2C69e9753bee19B5522bad39c5f788efd9', }, uniswapV2ExchangeRouterAddress: '0xF9234CB08edb93c0d4a4d4c70cC3FfD070e78e07', From 5789119e4d0a00259fde81483366a7601bbcb73f Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 25 Oct 2023 19:42:08 +0300 Subject: [PATCH 538/833] 2.41.5-polygon-migrator --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 78a1086fa..0f0e99a8a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.41.4", + "version": "2.41.5-polygon-migrator", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 01a239916b125e78f3f9fc2c67669dcb97598bca Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 25 Oct 2023 20:06:22 +0300 Subject: [PATCH 539/833] update POL holder --- tests/constants-e2e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index d7f259073..b68ea3a8c 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1017,7 +1017,7 @@ export const Holders: { GHO: '0x844Dc85EdD8492A56228D293cfEbb823EF3E10EC', wibBTC: '0xFbdCA68601f835b27790D98bbb8eC7f05FDEaA9B', MATIC: '0x7073783eee7e9b3e6e4ddac4d7f49dc46044dd9a', - POL: '0xCc56a33BdfCfdec4E35aD1259C1f1A06efa0AAcd', + POL: '0x57B6Ad484ccdd902C4419424bA648ba6Ed45dc68', }, [Network.ROPSTEN]: { ETH: '0x43262A12d8610AA70C15DbaeAC321d51613c9071', From 54e9a22ac8b410972938249733a47a30201b3907 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 25 Oct 2023 21:28:09 +0300 Subject: [PATCH 540/833] 2.42.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f0e99a8a..042dfff36 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.41.5-polygon-migrator", + "version": "2.42.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 2bb7e99ca60ab0d191282c0858d34261416ab592 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 26 Oct 2023 01:25:09 +0300 Subject: [PATCH 541/833] 2.42.0-traderjoe-mainnet --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 042dfff36..78b41a7e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.0", + "version": "2.42.0-traderjoe-mainnet", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 0ef3d4af05920d42981e1a6b74a59f11fd42a729 Mon Sep 17 00:00:00 2001 From: Koala <142200506+koala0814@users.noreply.github.com> Date: Fri, 27 Oct 2023 03:45:34 +0800 Subject: [PATCH 542/833] update pricing for high cov ratio pool and dynamic pool --- src/abi/wombat/asset.json | 94 +- src/abi/wombat/bmw.json | 1247 +++++++++++++++++++++ src/abi/wombat/pool.json | 163 ++- src/dex/wombat/config.ts | 15 +- src/dex/wombat/types.ts | 33 +- src/dex/wombat/utils.ts | 113 +- src/dex/wombat/wombat-bmw.ts | 170 +++ src/dex/wombat/wombat-events.test.ts | 78 +- src/dex/wombat/wombat-integration.test.ts | 40 +- src/dex/wombat/wombat-pool.ts | 371 ++++-- src/dex/wombat/wombat-quoter.ts | 269 +++++ src/dex/wombat/wombat.ts | 355 +++--- 12 files changed, 2506 insertions(+), 442 deletions(-) create mode 100644 src/abi/wombat/bmw.json create mode 100644 src/dex/wombat/wombat-bmw.ts create mode 100644 src/dex/wombat/wombat-quoter.ts diff --git a/src/abi/wombat/asset.json b/src/abi/wombat/asset.json index 9f551aa55..86a045b59 100644 --- a/src/abi/wombat/asset.json +++ b/src/abi/wombat/asset.json @@ -20,6 +20,32 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [], + "name": "ASSET_OVERFLOW", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_FORBIDDEN", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -45,6 +71,12 @@ "name": "Approval", "type": "event" }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -301,6 +333,62 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRelativePrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -559,7 +647,7 @@ "inputs": [ { "internalType": "address", - "name": "recipient", + "name": "to", "type": "address" }, { @@ -583,12 +671,12 @@ "inputs": [ { "internalType": "address", - "name": "sender", + "name": "from", "type": "address" }, { "internalType": "address", - "name": "recipient", + "name": "to", "type": "address" }, { diff --git a/src/abi/wombat/bmw.json b/src/abi/wombat/bmw.json new file mode 100644 index 000000000..f225ba581 --- /dev/null +++ b/src/abi/wombat/bmw.json @@ -0,0 +1,1247 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "lpToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IBoostedMultiRewarder", + "name": "boostedRewarder", + "type": "address" + } + ], + "name": "Add", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DepositFor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "EmergencyWithdraw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "EmergencyWomWithdraw", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Harvest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IBoostedMultiRewarder", + "name": "boostedRewarder", + "type": "address" + } + ], + "name": "SetBoostedRewarder", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IBribeRewarderFactory", + "name": "bribeRewarderFactory", + "type": "address" + } + ], + "name": "SetBribeRewarderFactory", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IMasterWombatV3", + "name": "masterWormbat", + "type": "address" + } + ], + "name": "SetNewMasterWombat", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "contract IMultiRewarder", + "name": "rewarder", + "type": "address" + } + ], + "name": "SetRewarder", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "basePartition", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "boostedPartition", + "type": "uint256" + } + ], + "name": "UpdateEmissionPartition", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "oldVeWOM", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newVeWOM", + "type": "address" + } + ], + "name": "UpdateVeWOM", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "oldVoter", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newVoter", + "type": "address" + } + ], + "name": "UpdateVoter", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "oldWOM", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newWOM", + "type": "address" + } + ], + "name": "UpdateWOM", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "ACC_TOKEN_PRECISION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REWARD_DURATION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOTAL_PARTITION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_lpToken", + "type": "address" + }, + { + "internalType": "contract IBoostedMultiRewarder", + "name": "_boostedRewarder", + "type": "address" + } + ], + "name": "add", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "basePartition", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "boostedPartition", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "boostedRewarders", + "outputs": [ + { + "internalType": "contract IBoostedMultiRewarder", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bribeRewarderFactory", + "outputs": [ + { + "internalType": "contract IBribeRewarderFactory", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "calRewardPerUnit", + "outputs": [ + { + "internalType": "uint256", + "name": "accWomPerShare", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accWomPerFactorShare", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "additionalRewards", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "depositFor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "emergencyWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "emergencyWomWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getAssetPid", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "getSumOfFactors", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_wom", + "type": "address" + }, + { + "internalType": "contract IVeWom", + "name": "_veWom", + "type": "address" + }, + { + "internalType": "address", + "name": "_voter", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_basePartition", + "type": "uint16" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_periodFinish", + "type": "uint256" + } + ], + "name": "lastTimeRewardApplicable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "massUpdatePools", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_pids", + "type": "uint256[]" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "_pids", + "type": "uint256[]" + } + ], + "name": "multiClaim", + "outputs": [ + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "uint256[][]", + "name": "additionalRewards", + "type": "uint256[][]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_lpToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "notifyRewardAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "pendingTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "pendingRewards", + "type": "uint256" + }, + { + "internalType": "contract IERC20[]", + "name": "bonusTokenAddresses", + "type": "address[]" + }, + { + "internalType": "string[]", + "name": "bonusTokenSymbols", + "type": "string[]" + }, + { + "internalType": "uint256[]", + "name": "pendingBonusRewards", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "poolInfo", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "lpToken", + "type": "address" + }, + { + "internalType": "uint96", + "name": "allocPoint", + "type": "uint96" + }, + { + "internalType": "contract IMultiRewarder", + "name": "rewarder", + "type": "address" + }, + { + "internalType": "uint256", + "name": "sumOfFactors", + "type": "uint256" + }, + { + "internalType": "uint104", + "name": "accWomPerShare", + "type": "uint104" + }, + { + "internalType": "uint104", + "name": "accWomPerFactorShare", + "type": "uint104" + }, + { + "internalType": "uint40", + "name": "lastRewardTimestamp", + "type": "uint40" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "poolInfoV3", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "lpToken", + "type": "address" + }, + { + "internalType": "contract IMultiRewarder", + "name": "rewarder", + "type": "address" + }, + { + "internalType": "uint40", + "name": "periodFinish", + "type": "uint40" + }, + { + "internalType": "uint128", + "name": "sumOfFactors", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "rewardRate", + "type": "uint128" + }, + { + "internalType": "uint104", + "name": "accWomPerShare", + "type": "uint104" + }, + { + "internalType": "uint104", + "name": "accWomPerFactorShare", + "type": "uint104" + }, + { + "internalType": "uint40", + "name": "lastRewardTimestamp", + "type": "uint40" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "rewarderBonusTokenInfo", + "outputs": [ + { + "internalType": "contract IERC20[]", + "name": "bonusTokenAddresses", + "type": "address[]" + }, + { + "internalType": "string[]", + "name": "bonusTokenSymbols", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "contract IBoostedMultiRewarder", + "name": "_boostedRewarder", + "type": "address" + } + ], + "name": "setBoostedRewarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IBribeRewarderFactory", + "name": "_bribeRewarderFactory", + "type": "address" + } + ], + "name": "setBribeRewarderFactory", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IMasterWombatV3", + "name": "_newMasterWombat", + "type": "address" + } + ], + "name": "setNewMasterWombat", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "contract IMultiRewarder", + "name": "_rewarder", + "type": "address" + } + ], + "name": "setRewarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVeWom", + "name": "_newVeWom", + "type": "address" + } + ], + "name": "setVeWom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newVoter", + "type": "address" + } + ], + "name": "setVoter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_newWom", + "type": "address" + } + ], + "name": "setWom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "_basePartition", + "type": "uint16" + } + ], + "name": "updateEmissionPartition", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_newVeWomBalance", + "type": "uint256" + } + ], + "name": "updateFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "updatePool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userInfo", + "outputs": [ + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "factor", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "rewardDebt", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "pendingWom", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "veWom", + "outputs": [ + { + "internalType": "contract IVeWom", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "additionalRewards", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "wom", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/abi/wombat/pool.json b/src/abi/wombat/pool.json index 657c631ce..398362857 100644 --- a/src/abi/wombat/pool.json +++ b/src/abi/wombat/pool.json @@ -1,4 +1,79 @@ [ + { + "inputs": [], + "name": "CORE_UNDERFLOW", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_AMOUNT_TOO_LOW", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ASSET_ALREADY_EXIST", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ASSET_ALREADY_PAUSED", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ASSET_NOT_EXISTS", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ASSET_NOT_PAUSED", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_CASH_NOT_ENOUGH", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_COV_RATIO_LIMIT_EXCEEDED", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_EXPIRED", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_FORBIDDEN", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_INVALID_VALUE", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_SAME_ADDRESS", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ZERO_ADDRESS", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ZERO_AMOUNT", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ZERO_LIQUIDITY", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -93,6 +168,19 @@ "name": "FillPool", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -131,7 +219,7 @@ { "indexed": false, "internalType": "address", - "name": "asset", + "name": "token", "type": "address" }, { @@ -328,7 +416,7 @@ { "indexed": false, "internalType": "address", - "name": "asset", + "name": "token", "type": "address" }, { @@ -485,6 +573,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "endCovRatio", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -597,6 +698,25 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "lpDividendRatio", @@ -632,7 +752,13 @@ } ], "name": "mintFee", - "outputs": [], + "outputs": [ + { + "internalType": "uint256", + "name": "feeCollected", + "type": "uint256" + } + ], "stateMutability": "nonpayable", "type": "function" }, @@ -901,6 +1027,24 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "startCovRatio_", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "endCovRatio_", + "type": "uint128" + } + ], + "name": "setCovRatioFeeParam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -984,6 +1128,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "startCovRatio", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts index d47536d0d..dcd25c8d7 100644 --- a/src/dex/wombat/config.ts +++ b/src/dex/wombat/config.ts @@ -5,21 +5,10 @@ import { Network, SwapSide } from '../../constants'; export const WombatConfig: DexConfigMap = { Wombat: { [Network.BSC]: { - pools: [ - { - address: '0x312Bc7eAAF93f1C60Dc5AfC115FcCDE161055fb0', - name: 'Wombat Main Pool', - }, - /** @todo add Side and Dynamic pools */ - ], + bmwAddress: '0x489833311676B566f888119c29bd997Dc6C95830', }, [Network.ARBITRUM]: { - pools: [ - { - address: '0xc6bc781E20f9323012F6e422bdf552Ff06bA6CD1', - name: 'Wombat Main Pool', - }, - ], + bmwAddress: '0x62A83C6791A3d7950D823BB71a38e47252b6b6F4', }, }, }; diff --git a/src/dex/wombat/types.ts b/src/dex/wombat/types.ts index 299dec08e..b552627ee 100644 --- a/src/dex/wombat/types.ts +++ b/src/dex/wombat/types.ts @@ -2,6 +2,10 @@ import { Address } from '../../types'; // State-related types +export type BmwState = { + pools: Address[]; +}; + export type PoolState = { // poolState is the state of event // subscriber. This should be the minimum @@ -13,31 +17,19 @@ export type PoolState = { }; export type AssetState = { + paused: boolean; cash: bigint; liability: bigint; + underlyingTokenDecimals: number; + relativePrice?: bigint; }; export type PoolParams = { + paused: boolean; ampFactor: bigint; haircutRate: bigint; -}; - -// Wombat Config types - -export type WombatConfigInfo = { - poolAddresses: Address[]; - pools: { [poolAddress: string]: WombatPoolConfigInfo }; -}; - -export type WombatPoolConfigInfo = { - tokenAddresses: Address[]; - tokens: { - [tokenAddress: string]: { - tokenSymbol: string; - tokenDecimals: number; - assetAddress: Address; - }; - }; + startCovRatio: bigint; + endCovRatio: bigint; }; export type WombatData = { @@ -50,8 +42,5 @@ export type WombatData = { export type DexParams = { // DexParams is set of parameters that can be used to initiate a DEX fork. - pools: { - address: Address; - name: string; - }[]; + bmwAddress: Address; }; diff --git a/src/dex/wombat/utils.ts b/src/dex/wombat/utils.ts index 251912cc7..cab8abba5 100644 --- a/src/dex/wombat/utils.ts +++ b/src/dex/wombat/utils.ts @@ -1,98 +1,53 @@ import { BI_POWS } from '../../bigint-constants'; -const WAD = BI_POWS[18]; +export const WAD = BI_POWS[18]; -function wmul(x: bigint, y: bigint): bigint { +export function wmul(x: bigint, y: bigint): bigint { return (x * y + WAD / 2n) / WAD; } -function wdiv(x: bigint, y: bigint): bigint { +export function wdiv(x: bigint, y: bigint): bigint { return (x * WAD + y / 2n) / y; } -// Babylonian Method for solving sqrt -function sqrt(y: bigint): bigint { +// Convert x to WAD (18 decimals) from d decimals. +export function toWad(x: bigint, d: bigint): bigint { + if (d < 18n) { + return x * 10n ** (18n - d); + } else if (d > 18n) { + return x / 10n ** (d - 18n); + } + return x; +} +// Convert x from WAD (18 decimals) to d decimals. +export function fromWad(x: bigint, d: bigint): bigint { + if (d < 18n) { + return x / 10n ** (18n - d); + } else if (d > 18n) { + return x * 10n ** (d - 18n); + } + return x; +} + +// Babylonian Method with initial guess (typecast as int) +export function sqrt(y: bigint, guess: bigint): bigint { let z = 0n; if (y > 3) { - let z = y; - let x = y / 2n + 1n; - while (x < z) { + if (guess > 0 && guess <= y) { + z = guess; + } else if (guess < 0 && -guess <= y) { + z = -guess; + } else { + z = y; + } + let x = (y / z + z) / 2n; + while (x != z) { z = x; x = (y / x + x) / 2n; } } else if (y != 0n) { z = 1n; } - return z; -} -function solveQuad(b: bigint, c: bigint): bigint { - return (sqrt(b * b + c * 4n * WAD) - b) / 2n; -} - -function swapQuoteFunc( - assetX: bigint, - assetY: bigint, - liabilityX: bigint, - liabilityY: bigint, - dX: bigint, - a: bigint, -): bigint { - if (liabilityX == 0n || liabilityY == 0n) { - // in case div of 0, CORE_UNDERFLOW - return 0n; - } - // int256 D = Ax + Ay - A.wmul((Lx * Lx) / Ax + (Ly * Ly) / Ay); // flattened _invariantFunc - - const d = - assetX + - assetY - - wmul( - a, - (liabilityX * liabilityX) / assetX + (liabilityY * liabilityY) / assetY, - ); - // int256 rx_ = (Ax + Dx).wdiv(Lx); - const rX = wdiv(assetX + dX, liabilityX); - // int256 b = (Lx * (rx_ - A.wdiv(rx_))) / Ly - D.wdiv(Ly); // flattened _coefficientFunc - const b = - (liabilityX * (rX - wdiv(a, rX))) / liabilityY - wdiv(d, liabilityY); - // int256 ry_ = _solveQuad(b, A); - const rY = solveQuad(b, a); - // int256 Dy = Ly.wmul(ry_) - Ay; - const dY = wmul(liabilityY, rY) - assetY; - // if (Dy < 0) { - // quote = uint256(-Dy); - // } else { - // quote = uint256(Dy); - // } - if (dY < 0n) { - return -dY; - } else { - return dY; - } -} - -export function quoteFrom( - assetX: bigint, - assetY: bigint, - liabilityX: bigint, - liabilityY: bigint, - fromAmount: bigint, - ampFactor: bigint, - haircutRate: bigint, -): bigint { - const idealToAmount = swapQuoteFunc( - assetX, - assetY, - liabilityX, - liabilityY, - fromAmount, - ampFactor, - ); - if (fromAmount > 0n && assetY < idealToAmount) { - return 0n; - } - const haircut = wmul(idealToAmount, haircutRate); - const actualToAmount = idealToAmount - haircut; - return actualToAmount; + return z; } diff --git a/src/dex/wombat/wombat-bmw.ts b/src/dex/wombat/wombat-bmw.ts new file mode 100644 index 000000000..844069805 --- /dev/null +++ b/src/dex/wombat/wombat-bmw.ts @@ -0,0 +1,170 @@ +import { Interface } from '@ethersproject/abi'; +import { BytesLike } from 'ethers'; +import { LogDescription } from 'ethers/lib/utils'; +import Web3EthContract, { Contract } from 'web3-eth-contract'; +import { DeepReadonly } from 'ts-essentials'; +import { Address, Log, Logger, MultiCallInput } from '../../types'; +import { catchParseLogError } from '../../utils'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { IDexHelper } from '../../dex-helper'; +import { BmwState } from './types'; +import BmwABI from '../../abi/wombat/bmw.json'; +import AssetABI from '../../abi/wombat/asset.json'; + +export class WombatBmw extends StatefulEventSubscriber { + static readonly bmwInterface = new Interface(BmwABI); + static readonly assetInterface = new Interface(AssetABI); + + private readonly logDecoder: (log: Log) => any; + private bmwContract: Contract; + private handlers: { + [event: string]: ( + event: any, + state: DeepReadonly, + log: Readonly, + ) => Promise | null>; + } = {}; + + constructor( + dexKey: string, + name: string, + protected network: number, + protected dexHelper: IDexHelper, + logger: Logger, + protected bmwAddress: Address, + protected onPoolAdded: ( + pool: Address, + blockNumber: number, + ) => Promise, + ) { + super( + `${dexKey} ${name}`, + `${dexKey}-${network} ${name}`, + dexHelper, + logger, + ); + + this.logDecoder = (log: Log) => WombatBmw.bmwInterface.parseLog(log); + this.addressesSubscribed = [this.bmwAddress]; + this.bmwContract = new this.dexHelper.web3Provider.eth.Contract( + BmwABI as any, + this.bmwAddress, + ); + + // users-actions handlers + this.handlers['Add'] = this.handleAdd.bind(this); + } + + /** + * The function is called every time any of the subscribed + * addresses release log. The function accepts the current + * state, updates the state according to the log, and returns + * the updated state. + * @param state - Current state of event subscriber + * @param log - Log released by one of the subscribed addresses + * @returns Updates state of the event subscriber after the log + */ + protected async processLog( + state: DeepReadonly, + log: Readonly, + ): Promise | null> { + try { + const event = this.logDecoder(log); + if (event.name in this.handlers) { + await this.handlers[event.name](event, state, log); + } + } catch (e) { + catchParseLogError(e, this.logger); + } + + return null; + } + + /** + * The function generates state using on-chain calls. This + * function is called to regenerate state if the event based + * system fails to fetch events and the local state is no + * more correct. + * should be generated + * @returns state of the event subscriber at blocknumber + */ + async generateState(blockNumber: number): Promise> { + const bmwState: BmwState = { pools: [] }; + let inputs: MultiCallInput[] = []; + + const poolLength = await this.bmwContract.methods + .poolLength() + .call({}, blockNumber); + for (let i = 0; i < poolLength; i++) { + inputs.push({ + target: this.bmwAddress, + callData: WombatBmw.bmwInterface.encodeFunctionData('poolInfo', [i]), + }); + } + let returnData = ( + await this.dexHelper.multiContract.methods + .aggregate(inputs) + .call({}, blockNumber) + ).returnData; + + const lpTokens = returnData.map( + (data: BytesLike) => + WombatBmw.bmwInterface.decodeFunctionResult('poolInfo', data)[0], + ); + + // 2. get all pools and underlying tokens + inputs = lpTokens.map((lpToken: string) => ({ + target: lpToken, + callData: WombatBmw.assetInterface.encodeFunctionData('pool'), + })); + + returnData = ( + await this.dexHelper.multiContract.methods + .aggregate(inputs) + .call({}, blockNumber) + ).returnData; + + const pools = returnData + .map( + (data: BytesLike) => + WombatBmw.assetInterface.decodeFunctionResult('pool', data)[0], + ) + .map((pool: string) => pool.toLowerCase()); + + const promises = []; + for (const pool of pools) { + if (!bmwState.pools.includes(pool)) { + bmwState.pools.push(pool); + promises.push(this.onPoolAdded(pool, blockNumber)); + } + } + + return bmwState; + } + + async handleAdd( + event: LogDescription, + state: DeepReadonly, + log: Readonly, + ): Promise | null> { + const lpToken = event.args.lpToken.toString(); + const data = await this.dexHelper.web3Provider.eth.call({ + to: lpToken, + data: WombatBmw.assetInterface.encodeFunctionData('pool'), + }); + const pool = WombatBmw.assetInterface + .decodeFunctionResult('pool', data)[0] + .toLowerCase(); + + if (!state.pools.includes(pool)) { + await this.onPoolAdded(pool, log.blockNumber); + return { + pools: [...state.pools, pool], + }; + } else { + return { + pools: state.pools, + }; + } + } +} diff --git a/src/dex/wombat/wombat-events.test.ts b/src/dex/wombat/wombat-events.test.ts index 6655ee296..ae297ded9 100644 --- a/src/dex/wombat/wombat-events.test.ts +++ b/src/dex/wombat/wombat-events.test.ts @@ -5,15 +5,12 @@ import { DeepReadonly } from 'ts-essentials'; import { WombatEventPool } from './wombat-pool'; import { Network } from '../../constants'; import { Address } from '../../types'; -import { DummyDexHelper } from '../../dex-helper/index'; -import { - testEventSubscriber, - getSavedConfig, - saveConfig, -} from '../../../tests/utils-events'; -import { PoolState, WombatConfigInfo } from './types'; +import { DummyDexHelper } from '../../dex-helper'; +import { testEventSubscriber } from '../../../tests/utils-events'; +import { BmwState, PoolState } from './types'; import { WombatConfig } from './config'; import { Wombat } from './wombat'; +import { WombatBmw } from './wombat-bmw'; /* README ====== @@ -56,7 +53,12 @@ async function fetchPoolState( ): Promise> { return await wombatPool.generateState(blockNumber); } - +async function fetchBmwState( + wombatBmw: WombatBmw, + blockNumber: number, +): Promise> { + return await wombatBmw.generateState(blockNumber); +} // eventName -> blockNumbers type EventMappings = Record; @@ -66,51 +68,49 @@ describe('Wombat EventPool BSC', function () { const dexHelper = new DummyDexHelper(network); const logger = dexHelper.getLogger(dexKey); let wombatPool: WombatEventPool; - const mainPoolAddress = WombatConfig.Wombat[Network.BSC].pools[0].address; - // poolAddress -> EventMappings + const bmwAddress = WombatConfig.Wombat[Network.BSC].bmwAddress; const eventsToTest: Record = { - // Main pool - [mainPoolAddress]: { - Deposit: [22764190], - // Deposit: [24764190], + [bmwAddress]: { + Add: [24685640, 24685642, 24685644, 24685646, 24685647, 24685649], }, }; + const wombat = new Wombat(network, dexKey, dexHelper); + for (const [poolAddress, events] of Object.entries(eventsToTest)) { describe(`Events for ${poolAddress}`, () => { for (const [eventName, blockNumbers] of Object.entries(events)) { describe(`${eventName}`, () => { for (const blockNumber of blockNumbers) { it(`State after ${blockNumber}`, async function () { - let cfgInfo = getSavedConfig( - blockNumber, - dexKey, - ); - - cfgInfo = undefined; - if (!cfgInfo) { - const dex = new Wombat(network, dexKey, dexHelper); - cfgInfo = await dex.generateConfigInfo(blockNumber); - saveConfig(blockNumber, dexKey, cfgInfo); - } - - wombatPool = new WombatEventPool( - dexKey, - 'Main Pool', - network, - dexHelper, - logger, - poolAddress.toLowerCase(), - cfgInfo.pools[poolAddress.toLowerCase()], - ); + // let cfgInfo = getSavedConfig( + // blockNumber, + // dexKey, + // ); + // + // cfgInfo = undefined; + // if (!cfgInfo) { + // const dex = new Wombat(network, dexKey, dexHelper); + // cfgInfo = await dex.generateConfigInfo(blockNumber); + // saveConfig(blockNumber, dexKey, cfgInfo); + // } + + // wombatPool = new WombatEventPool( + // dexKey, + // 'Main Pool', + // network, + // dexHelper, + // logger, + // poolAddress.toLowerCase(), + // ); await testEventSubscriber( - wombatPool, - wombatPool.addressesSubscribed, + wombat.bmw, + wombat.bmw.addressesSubscribed, (_blockNumber: number) => - fetchPoolState(wombatPool, _blockNumber), + fetchBmwState(wombat.bmw, _blockNumber), blockNumber, - `${dexKey}_${poolAddress}`, + `${dexKey}_${bmwAddress}`, dexHelper.provider, ); }); diff --git a/src/dex/wombat/wombat-integration.test.ts b/src/dex/wombat/wombat-integration.test.ts index f3976ac4b..2a78e7ac2 100644 --- a/src/dex/wombat/wombat-integration.test.ts +++ b/src/dex/wombat/wombat-integration.test.ts @@ -1,4 +1,5 @@ import dotenv from 'dotenv'; + dotenv.config(); import { Interface, Result } from '@ethersproject/abi'; @@ -12,6 +13,8 @@ import { checkConstantPoolPrices, } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; +import { Token } from '../../types'; +import { Address } from '@paraswap/core'; /* README @@ -31,16 +34,26 @@ import { Tokens } from '../../../tests/constants-e2e'; function getReaderCalldata( exchangeAddress: string, readerIface: Interface, + side: SwapSide, + fromToken: Token, + toToken: Token, amounts: bigint[], funcName: string, // TODO: Put here additional arguments you need ) { return amounts.map(amount => ({ target: exchangeAddress, - callData: readerIface.encodeFunctionData(funcName, [ - // TODO: Put here additional arguments to encode them - amount, - ]), + callData: readerIface.encodeFunctionData( + funcName, + side == SwapSide.SELL + ? [ + // TODO: Put here additional arguments to encode them + fromToken.address, + toToken.address, + amount, + ] + : [toToken.address, fromToken.address, -amount], + ), })); } @@ -58,21 +71,28 @@ function decodeReaderResult( async function checkOnChainPricing( wombat: Wombat, + pool: Address, + fromToken: Token, + toToken: Token, + side: SwapSide, funcName: string, blockNumber: number, prices: bigint[], amounts: bigint[], ) { - const exchangeAddress = ''; // TODO: Put here the real exchange address + const exchangeAddress = pool; // TODO: Put here the real exchange address // TODO: Replace dummy interface with the real one // Normally you can get it from wombat.Iface or from eventPool. // It depends on your implementation - const readerIface = new Interface(''); + const readerIface = Wombat.poolInterface; const readerCallData = getReaderCalldata( exchangeAddress, readerIface, + side, + fromToken, + toToken, amounts.slice(1), funcName, ); @@ -138,6 +158,10 @@ async function testPricingOnNetwork( // Check if onchain pricing equals to calculated ones await checkOnChainPricing( wombat, + poolPrices![0].data.exchange, + networkTokens[srcTokenSymbol], + networkTokens[destTokenSymbol], + side, funcNameToCheck, blockNumber, poolPrices![0].prices, @@ -207,7 +231,7 @@ describe('Wombat', function () { destTokenSymbol, SwapSide.SELL, amountsForSell, - '', // TODO: Put here proper function name to check pricing + 'quotePotentialSwap', // TODO: Put here proper function name to check pricing ); }); @@ -221,7 +245,7 @@ describe('Wombat', function () { destTokenSymbol, SwapSide.BUY, amountsForBuy, - '', // TODO: Put here proper function name to check pricing + 'quotePotentialSwap', // TODO: Put here proper function name to check pricing ); }); diff --git a/src/dex/wombat/wombat-pool.ts b/src/dex/wombat/wombat-pool.ts index c21d3ea9a..aacc24d21 100644 --- a/src/dex/wombat/wombat-pool.ts +++ b/src/dex/wombat/wombat-pool.ts @@ -1,5 +1,5 @@ import { Interface } from '@ethersproject/abi'; -import { DeepReadonly } from 'ts-essentials'; +import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; import { Address, Log, @@ -9,8 +9,8 @@ import { } from '../../types'; import { catchParseLogError } from '../../utils'; import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { PoolState, WombatPoolConfigInfo } from './types'; +import { IDexHelper } from '../../dex-helper'; +import { AssetState, PoolState } from './types'; import PoolABI from '../../abi/wombat/pool.json'; import AssetABI from '../../abi/wombat/asset.json'; @@ -18,24 +18,27 @@ export class WombatEventPool extends StatefulEventSubscriber { static readonly poolInterface = new Interface(PoolABI); static readonly assetInterface = new Interface(AssetABI); - handlers: { + private readonly logDecoder: (log: Log) => any; + private handlers: { [event: string]: ( event: any, state: DeepReadonly, log: Readonly, - ) => DeepReadonly | null; + ) => AsyncOrSync | null>; } = {}; - logDecoder: (log: Log) => any; - blankState: PoolState = { asset: {}, underlyingAddresses: [], params: { + paused: false, ampFactor: 0n, haircutRate: 0n, + startCovRatio: 0n, + endCovRatio: 0n, }, }; + constructor( dexKey: string, name: string, @@ -43,7 +46,6 @@ export class WombatEventPool extends StatefulEventSubscriber { protected dexHelper: IDexHelper, logger: Logger, protected poolAddress: Address, - protected poolCfg: WombatPoolConfigInfo, ) { super( `${dexKey} ${name}`, @@ -53,6 +55,7 @@ export class WombatEventPool extends StatefulEventSubscriber { ); this.logDecoder = (log: Log) => WombatEventPool.poolInterface.parseLog(log); + this.addressesSubscribed = [this.poolAddress]; // users-actions handlers this.handlers['Deposit'] = this.handleDeposit.bind(this); @@ -60,13 +63,11 @@ export class WombatEventPool extends StatefulEventSubscriber { this.handlers['Swap'] = this.handleSwap.bind(this); // admin-actions handlers - /** @todo handle dynamically updating params */ - // this.handlers['SetAmpFactor'] = this.handleDeposit.bind(this); - // this.handlers['SetHaircutRate'] = this.handleDeposit.bind(this); + this.handlers['SetAmpFactor'] = this.handleSetAmpFactor.bind(this); + this.handlers['SetHaircutRate'] = this.handleSetHaircutRate.bind(this); - /** @todo handle dynamically adding/removing assets */ - // this.handlers['AssetAdded'] = this.handleAssetAdded.bind(this); - // this.handlers['AssetRemoved'] = this.handleAssetRemoved.bind(this); + this.handlers['AssetAdded'] = this.handleAssetAdded.bind(this); + this.handlers['AssetRemoved'] = this.handleAssetRemoved.bind(this); } /** @@ -78,14 +79,14 @@ export class WombatEventPool extends StatefulEventSubscriber { * @param log - Log released by one of the subscribed addresses * @returns Updates state of the event subscriber after the log */ - protected processLog( + protected async processLog( state: DeepReadonly, log: Readonly, - ): DeepReadonly | null { + ): Promise | null> { try { const event = this.logDecoder(log); if (event.name in this.handlers) { - return this.handlers[event.name](event, state, log); + return await this.handlers[event.name](event, state, log); } } catch (e) { catchParseLogError(e, this.logger); @@ -104,11 +105,13 @@ export class WombatEventPool extends StatefulEventSubscriber { * @returns state of the event subscriber at blocknumber */ async generateState(blockNumber: number): Promise> { - // const multiCallInputs = this.getGenerateStateMultiCallInputs(); - - // 1. Generate multiCallInputs - const multiCallInputs: MultiCallInput[] = []; + let multiCallInputs: MultiCallInput[] = []; // 1 A. pool params + // paused + multiCallInputs.push({ + target: this.poolAddress, + callData: WombatEventPool.poolInterface.encodeFunctionData('paused'), + }); // ampFactor multiCallInputs.push({ target: this.poolAddress, @@ -119,19 +122,22 @@ export class WombatEventPool extends StatefulEventSubscriber { target: this.poolAddress, callData: WombatEventPool.poolInterface.encodeFunctionData('haircutRate'), }); - - // 1 B. asset state: cash and liability - for (const tokenInfo of Object.values(this.poolCfg.tokens)) { - multiCallInputs.push({ - target: tokenInfo.assetAddress, - callData: WombatEventPool.assetInterface.encodeFunctionData('cash'), - }); - multiCallInputs.push({ - target: tokenInfo.assetAddress, - callData: - WombatEventPool.assetInterface.encodeFunctionData('liability'), - }); - } + // startCovRatio + multiCallInputs.push({ + target: this.poolAddress, + callData: + WombatEventPool.poolInterface.encodeFunctionData('startCovRatio'), + }); + // endCovRatio + multiCallInputs.push({ + target: this.poolAddress, + callData: WombatEventPool.poolInterface.encodeFunctionData('endCovRatio'), + }); + // tokens + multiCallInputs.push({ + target: this.poolAddress, + callData: WombatEventPool.poolInterface.encodeFunctionData('getTokens'), + }); // 2. Decode MultiCallOutput let returnData: MultiCallOutput[] = []; @@ -145,47 +151,98 @@ export class WombatEventPool extends StatefulEventSubscriber { let i = 0; // 2 A. decode pool params - const ampFactor = BigInt(WombatEventPool.poolInterface.decodeFunctionResult( - 'ampFactor', - returnData[i++], - )[0]); - const haircutRate = BigInt(WombatEventPool.poolInterface.decodeFunctionResult( - 'haircutRate', - returnData[i++], - )[0]); + const paused = Boolean( + WombatEventPool.poolInterface.decodeFunctionResult( + 'paused', + returnData[i++], + )[0], + ); + const ampFactor = BigInt( + WombatEventPool.poolInterface.decodeFunctionResult( + 'ampFactor', + returnData[i++], + )[0], + ); + const haircutRate = BigInt( + WombatEventPool.poolInterface.decodeFunctionResult( + 'haircutRate', + returnData[i++], + )[0], + ); + const startCovRatio = BigInt( + WombatEventPool.poolInterface.decodeFunctionResult( + 'startCovRatio', + returnData[i++], + )[0], + ); + const endCovRatio = BigInt( + WombatEventPool.poolInterface.decodeFunctionResult( + 'endCovRatio', + returnData[i++], + )[0], + ); + + const tokens = WombatEventPool.poolInterface + .decodeFunctionResult('getTokens', returnData[i++])[0] + .map((tokenAddress: Address) => tokenAddress.toLowerCase()); + const poolState: PoolState = { params: { + paused, ampFactor, haircutRate, + startCovRatio, + endCovRatio, }, - underlyingAddresses: [], + underlyingAddresses: tokens, asset: {}, }; - // 2 B. decode asset state: cash and liability - for (const [tokenAddress, tokenInfo] of Object.entries( - this.poolCfg.tokens, - )) { - const cash = BigInt(WombatEventPool.assetInterface.decodeFunctionResult( - 'cash', - returnData[i++], - )[0]); - const liability = BigInt(WombatEventPool.assetInterface.decodeFunctionResult( - 'liability', - returnData[i++], - )[0]); - poolState.underlyingAddresses.push(tokenAddress); - poolState.asset[tokenAddress] = { - cash, - liability, - }; + + // 1 B. asset state: cash and liability + multiCallInputs = tokens.map((tokenAddress: Address) => ({ + target: this.poolAddress, + callData: WombatEventPool.poolInterface.encodeFunctionData( + 'addressOfAsset', + [tokenAddress], + ), + })); + + // 2. Decode MultiCallOutput + returnData = ( + await this.dexHelper.multiContract.methods + .aggregate(multiCallInputs) + .call({}, blockNumber) + ).returnData; + + const assets: Address[] = returnData.map(data => { + return WombatEventPool.poolInterface.decodeFunctionResult( + 'addressOfAsset', + data, + )[0]; + }); + + const assetState = await this.getAssetState( + this.poolAddress, + assets, + tokens, + blockNumber, + ); + const isMainPool = + assetState.filter(asset => asset.relativePrice === undefined).length > 0; + for (let j = 0; j < tokens.length; j++) { + if (isMainPool) { + assetState[j].relativePrice = undefined; + } + poolState.asset[tokens[j]] = assetState[j]; } + return poolState; } handleDeposit( event: any, state: DeepReadonly, - log: Readonly, + _log: Readonly, ): DeepReadonly | null { const amountAdded = BigInt(event.args.amount.toString()); const tokenAddress = event.args.token.toString(); @@ -201,10 +258,11 @@ export class WombatEventPool extends StatefulEventSubscriber { }, }; } + handleWithdraw( event: any, state: DeepReadonly, - log: Readonly, + _log: Readonly, ): DeepReadonly | null { const amountWithdrew = BigInt(event.args.amount.toString()); const tokenAddress = event.args.token.toString(); @@ -224,7 +282,7 @@ export class WombatEventPool extends StatefulEventSubscriber { handleSwap( event: any, state: DeepReadonly, - log: Readonly, + _log: Readonly, ): DeepReadonly | null { const fromTokenAddress = event.args.fromToken.toString(); const fromAmount = BigInt(event.args.fromAmount.toString()); @@ -244,4 +302,191 @@ export class WombatEventPool extends StatefulEventSubscriber { }, }; } + + handleSetAmpFactor( + event: any, + state: DeepReadonly, + _log: Readonly, + ): DeepReadonly | null { + const ampFactor = BigInt(event.args.value.toString()); + + return { + ...state, + params: { + ...state.params, + ampFactor, + }, + }; + } + + handleSetHaircutRate( + event: any, + state: DeepReadonly, + _log: Readonly, + ): DeepReadonly | null { + const haircutRate = BigInt(event.args.value.toString()); + + return { + ...state, + params: { + ...state.params, + haircutRate, + }, + }; + } + + async handleAssetAdded( + event: any, + state: DeepReadonly, + log: Readonly, + ): Promise | null> { + const token: Address = event.args.token.toString().toLowerCase(); + const asset: Address = event.args.asset.toString().toLowerCase(); + if (state.underlyingAddresses.includes(token)) { + return null; + } + + const assetState = await this.getAssetState( + this.poolAddress, + [asset], + [token], + log.blockNumber, + ); + const poolState = { + ...state, + underlyingAddresses: [...state.underlyingAddresses, token], + asset: { + ...state.asset, + [token]: assetState[0], + }, + }; + + const isMainPool = + Object.values(poolState.asset).filter( + asset => asset.relativePrice === undefined, + ).length > 0; + if (isMainPool) { + for (const underlyingAddress of poolState.underlyingAddresses) { + poolState.asset[underlyingAddress] = { + ...poolState.asset[underlyingAddress], + relativePrice: undefined, + }; + } + } + return poolState; + } + + async handleAssetRemoved( + event: any, + state: DeepReadonly, + _log: Readonly, + ): Promise | null> { + const token = event.args.token.toString(); + if (!state.underlyingAddresses.includes(token)) { + return null; + } + + return { + ...state, + underlyingAddresses: state.underlyingAddresses.filter( + underlyingAddress => underlyingAddress !== token, + ), + asset: { + ...state.asset, + [token]: undefined, + }, + }; + } + + private async getAssetState( + pool: Address, + assets: Address[], + tokens: Address[], + blockNumber: number, + ): Promise { + const assetStates: AssetState[] = []; + const multiCallInputs: MultiCallInput[] = []; + + const methods = [ + 'cash', + 'liability', + 'underlyingTokenDecimals', + 'getRelativePrice', + ]; + + for (let i = 0; i < assets.length; i++) { + const asset = assets[i]; + const token = tokens[i]; + + multiCallInputs.push({ + target: pool, + callData: WombatEventPool.poolInterface.encodeFunctionData('isPaused', [ + token, + ]), + }); + + for (const method of methods) { + multiCallInputs.push({ + target: asset, + callData: WombatEventPool.assetInterface.encodeFunctionData(method), + }); + } + } + + const returnData = await this.dexHelper.multiContract.methods + .tryAggregate(false, multiCallInputs) + .call({}, blockNumber); + + for ( + let i = 0; + i < assets.length * (methods.length + 1); + i += methods.length + 1 + ) { + const paused = returnData[i].success + ? Boolean( + WombatEventPool.poolInterface.decodeFunctionResult( + 'isPaused', + returnData[i].returnData, + )[0], + ) + : false; + const cash = BigInt( + WombatEventPool.assetInterface.decodeFunctionResult( + methods[0], + returnData[i + 1].returnData, + )[0], + ); + const liability = BigInt( + WombatEventPool.assetInterface.decodeFunctionResult( + methods[1], + returnData[i + 2].returnData, + )[0], + ); + const underlyingTokenDecimals = + WombatEventPool.assetInterface.decodeFunctionResult( + methods[2], + returnData[i + 3].returnData, + )[0]; + + let relativePrice: bigint | undefined; + if (returnData[i + 4].success) { + relativePrice = BigInt( + WombatEventPool.assetInterface.decodeFunctionResult( + methods[3], + returnData[i + 4].returnData, + )[0], + ); + } + + assetStates.push({ + paused, + cash, + liability, + underlyingTokenDecimals, + relativePrice, + }); + } + + return assetStates; + } } diff --git a/src/dex/wombat/wombat-quoter.ts b/src/dex/wombat/wombat-quoter.ts new file mode 100644 index 000000000..c7cb12ca1 --- /dev/null +++ b/src/dex/wombat/wombat-quoter.ts @@ -0,0 +1,269 @@ +import { AssetState, PoolParams } from './types'; +import { fromWad, sqrt, toWad, WAD, wdiv, wmul } from './utils'; + +export class WombatQuoter { + private readonly ampFactor: bigint; + private readonly haircutRate: bigint; + private readonly startCovRatio: bigint; + private readonly endCovRatio: bigint; + + constructor(poolParams: PoolParams) { + this.ampFactor = poolParams.ampFactor; + this.haircutRate = poolParams.haircutRate; + this.startCovRatio = poolParams.startCovRatio; + this.endCovRatio = poolParams.endCovRatio; + } + + public getQuote( + fromAsset: AssetState, + toAsset: AssetState, + fromAmount: bigint, + ): bigint { + if (fromAmount === 0n || fromAsset.paused) { + return 0n; + } + + fromAmount = toWad(fromAmount, BigInt(fromAsset.underlyingTokenDecimals)); + + try { + const { actualToAmount, haircut } = this._highCovRatioPoolQuoteFrom( + fromAsset, + toAsset, + fromAmount, + ); + const toCash = toAsset.cash - actualToAmount - haircut; + + if (wdiv(toCash, toAsset.liability) < WAD / 100n) { + return 0n; + } + + return fromWad(actualToAmount, BigInt(toAsset.underlyingTokenDecimals)); + } catch (e) { + return 0n; + } + } + + private _highCovRatioPoolQuoteFrom( + fromAsset: AssetState, + toAsset: AssetState, + fromAmount: bigint, + ): { actualToAmount: bigint; haircut: bigint } { + let { actualToAmount, haircut } = this._quoteFrom( + fromAsset, + toAsset, + fromAmount, + ); + + if (fromAmount > 0n) { + const fromCash = fromAsset.cash; + const fromLiability = fromAsset.liability; + + const finalFromAssetCovRatio = wdiv(fromCash + fromAmount, fromLiability); + if (finalFromAssetCovRatio > this.startCovRatio) { + // charge high cov ratio fee + const highCovRatioFee = wmul( + this._highCovRatioFee( + wdiv(fromCash, fromLiability), + finalFromAssetCovRatio, + ), + actualToAmount, + ); + + actualToAmount -= highCovRatioFee; + haircut += highCovRatioFee; + } + } else { + // reverse quote + const toCash = toAsset.cash; + const toLiability = toAsset.liability; + + const finalToAssetCovRatio = wdiv(toCash + actualToAmount, toLiability); + if (finalToAssetCovRatio <= this.startCovRatio) { + // happy path: no high cov ratio fee is charged + return { actualToAmount, haircut }; + } else if (wdiv(toCash, toLiability) >= this.endCovRatio) { + // the to-asset exceeds it's cov ratio limit, further swap to increase cov ratio is impossible + throw new Error('WOMBAT_COV_RATIO_LIMIT_EXCEEDED'); + } + + // reverse quote: cov ratio of the to-asset exceed endCovRatio. direct reverse quote is not supported + // we binary search for a upper bound + actualToAmount = this._findUpperBound(toAsset, fromAsset, -fromAmount); + const result = this._highCovRatioPoolQuoteFrom( + toAsset, + fromAsset, + actualToAmount, + ); + haircut = result.haircut; + } + + return { actualToAmount, haircut }; + } + + private _highCovRatioFee( + initCovRatio: bigint, + finalCovRatio: bigint, + ): bigint { + const startCovRatio = this.startCovRatio!; + const endCovRatio = this.endCovRatio!; + if (finalCovRatio > endCovRatio) { + // invalid swap + throw new Error('WOMBAT_COV_RATIO_LIMIT_EXCEEDED'); + } else if ( + finalCovRatio <= startCovRatio || + finalCovRatio <= initCovRatio + ) { + return 0n; + } + + // 1. Calculate the area of fee(r) = (r - startCovRatio) / (endCovRatio - startCovRatio) + // when r increase from initCovRatio to finalCovRatio + // 2. Then multiply it by (endCovRatio - startCovRatio) / (finalCovRatio - initCovRatio) + // to get the average fee over the range + const a = + initCovRatio <= startCovRatio + ? 0n + : (initCovRatio - startCovRatio) * (initCovRatio - startCovRatio); + const b = (finalCovRatio - startCovRatio) * (finalCovRatio - startCovRatio); + return wdiv( + (b - a) / (finalCovRatio - initCovRatio) / BigInt(2), + endCovRatio - startCovRatio, + ); + } + + private _quoteFrom( + fromAsset: AssetState, + toAsset: AssetState, + fromAmount: bigint, + ): { actualToAmount: bigint; haircut: bigint } { + if (fromAmount < 0n) { + fromAmount = wdiv(fromAmount, WAD - this.haircutRate); + } + + let fromCash = fromAsset.cash; + const toCash = toAsset.cash; + let fromLiability = fromAsset.liability; + const toLiability = toAsset.liability; + + const scaleFactor = this._quoteFactor(fromAsset, toAsset); + if (scaleFactor !== WAD) { + fromCash = (fromCash * scaleFactor) / WAD; + fromLiability = (fromLiability * scaleFactor) / WAD; + fromAmount = (fromAmount * scaleFactor) / WAD; + } + + const idealToAmount = WombatQuoter.swapQuoteFunc( + fromCash, + toCash, + fromLiability, + toLiability, + fromAmount, + this.ampFactor, + ); + if ( + (fromAmount > 0n && toCash < idealToAmount) || + (fromAmount < 0n && fromCash < -fromAmount) + ) { + throw new Error('WOMBAT_CASH_NOT_ENOUGH'); + } + + let actualToAmount, haircut; + if (fromAmount > 0) { + haircut = wmul(idealToAmount, this.haircutRate); + actualToAmount = idealToAmount - haircut; + } else { + actualToAmount = idealToAmount; + haircut = wmul(-fromAmount, this.haircutRate); + } + + return { actualToAmount, haircut }; + } + + private _findUpperBound( + fromAsset: AssetState, + toAsset: AssetState, + toAmount: bigint, + ): bigint { + const decimals = BigInt(fromAsset.underlyingTokenDecimals); + const toWadFactor = toWad(1n, decimals); + // the search value uses the same number of digits as the token + let high = fromWad( + wmul(fromAsset.liability, this.endCovRatio!) - fromAsset.cash, + decimals, + ); + let low = 1n; + + // verify `high` is a valid upper bound + const { actualToAmount: quote } = this._highCovRatioPoolQuoteFrom( + fromAsset, + toAsset, + high * toWadFactor, + ); + if (quote < toAmount) { + throw new Error('WOMBAT_COV_RATIO_LIMIT_EXCEEDED'); + } + + // Note: we might limit the maximum number of rounds if the request is always rejected by the RPC server + while (low < high) { + const mid = (low + high) / BigInt(2); + const { actualToAmount: quote } = this._highCovRatioPoolQuoteFrom( + fromAsset, + toAsset, + mid * toWadFactor, + ); + if (quote >= toAmount) { + high = mid; + } else { + low = mid + 1n; + } + } + return high * toWadFactor; + } + + private _quoteFactor(fromAsset: AssetState, toAsset: AssetState): bigint { + if (!fromAsset.relativePrice || !toAsset.relativePrice) { + return WAD; + } + return (WAD * fromAsset.relativePrice) / toAsset.relativePrice; + } + + static solveQuad(b: bigint, c: bigint): bigint { + return (sqrt(b * b + c * 4n * WAD, b) - b) / 2n; + } + + static swapQuoteFunc( + aX: bigint, + aY: bigint, + lX: bigint, + lY: bigint, + dX: bigint, + a: bigint, + ): bigint { + if (lX == 0n || lY == 0n) { + // in case div of 0, CORE_UNDERFLOW + return 0n; + } + + // int256 D = Ax + Ay - A.wmul((Lx * Lx) / Ax + (Ly * Ly) / Ay); // flattened _invariantFunc + const d = aX + aY - wmul(a, (lX * lX) / aX + (lY * lY) / aY); + // int256 rx_ = (Ax + Dx).wdiv(Lx); + const rX = wdiv(aX + dX, lX); + // int256 b = (Lx * (rx_ - A.wdiv(rx_))) / Ly - D.wdiv(Ly); // flattened _coefficientFunc + const b = (lX * (rX - wdiv(a, rX))) / lY - wdiv(d, lY); + // int256 ry_ = _solveQuad(b, A); + const rY = WombatQuoter.solveQuad(b, a); + // int256 Dy = Ly.wmul(ry_) - Ay; + const dY = wmul(lY, rY) - aY; + + // if (Dy < 0) { + // quote = uint256(-Dy); + // } else { + // quote = uint256(Dy); + // } + if (dY < 0n) { + return -dY; + } else { + return dY; + } + } +} diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 744b9c0dc..cfad02f9d 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -1,51 +1,58 @@ -import { AsyncOrSync } from 'ts-essentials'; +import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; import { Interface } from '@ethersproject/abi'; -import { DeepReadonly } from 'ts-essentials'; import { - Token, + AdapterExchangeParam, Address, ExchangePrices, + Logger, + PoolLiquidity, PoolPrices, - AdapterExchangeParam, SimpleExchangeParam, - PoolLiquidity, - Logger, - MultiCallInput, + Token, } from '../../types'; -import { SwapSide, Network } from '../../constants'; +import { Network } from '../../constants'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { getDexKeysWithNetwork, getBigIntPow } from '../../utils'; -import { IDex } from '../../dex/idex'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { WombatData, DexParams, WombatConfigInfo, PoolState } from './types'; -import { getLocalDeadlineAsFriendlyPlaceholder, SimpleExchange } from '../simple-exchange'; -import { WombatConfig, Adapters } from './config'; +import { getBigIntPow, getDexKeysWithNetwork } from '../../utils'; +import { IDex } from '../idex'; +import { IDexHelper } from '../../dex-helper'; +import { DexParams, PoolState, WombatData } from './types'; +import { + getLocalDeadlineAsFriendlyPlaceholder, + SimpleExchange, +} from '../simple-exchange'; +import { Adapters, WombatConfig } from './config'; import { WombatEventPool } from './wombat-pool'; -import { quoteFrom } from './utils'; import PoolABI from '../../abi/wombat/pool.json'; import AssetABI from '../../abi/wombat/asset.json'; +import BmwABI from '../../abi/wombat/bmw.json'; import ERC20ABI from '../../abi/erc20.json'; +import { SwapSide } from '@paraswap/core'; +import { WombatQuoter } from './wombat-quoter'; +import { WombatBmw } from './wombat-bmw'; +import { fromWad } from './utils'; export class Wombat extends SimpleExchange implements IDex { // contract interfaces static readonly erc20Interface = new Interface(ERC20ABI); static readonly poolInterface = new Interface(PoolABI); static readonly assetInterface = new Interface(AssetABI); + static readonly bmwInterface = new Interface(BmwABI); protected config: DexParams; - protected cfgInfo?: WombatConfigInfo; protected poolLiquidityUSD?: { [poolAddress: string]: number }; - - protected eventPools?: { [poolAddress: string]: WombatEventPool }; + public bmw: WombatBmw; + public eventPools: { [poolAddress: string]: WombatEventPool } = {}; readonly hasConstantPriceLargeAmounts = false; readonly needWrapNative = true; readonly isFeeOnTransferSupported = false; - public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(WombatConfig); + public static dexKeysWithNetwork: { + key: string; + networks: Network[]; + }[] = getDexKeysWithNetwork(WombatConfig); logger: Logger; @@ -58,102 +65,19 @@ export class Wombat extends SimpleExchange implements IDex { super(dexHelper, dexKey); this.logger = dexHelper.getLogger(dexKey); this.config = WombatConfig[dexKey][network]; - } - - async generateConfigInfo(blockNumber: number): Promise { - const cfgInfo: WombatConfigInfo = { - poolAddresses: [], - pools: {}, - }; - // Need to filter pools in case we are testing against an old block where the pool didn't exist! - for (const p of this.config.pools) { - // When there's no code, getCode should return '0x' but could return '0x0' instead - if ( - (await this.dexHelper.web3Provider.eth.getCode(p.address, blockNumber)) - .length > 3 // it's not '0x' or '0x0' - ) { - cfgInfo.poolAddresses.push(p.address.toLowerCase()); - } - } - // 1. Get tokens in each pool - let inputs: MultiCallInput[] = []; - for (const poolAddress of cfgInfo.poolAddresses) { - inputs.push({ - target: poolAddress, - callData: Wombat.poolInterface.encodeFunctionData('getTokens'), - }); - } - let returnData = ( - await this.dexHelper.multiContract.methods - .aggregate(inputs) - .call({}, blockNumber) - ).returnData; - - let i = 0; - for (const poolAddress of cfgInfo.poolAddresses) { - const tokenAddresses = Wombat.poolInterface - .decodeFunctionResult('getTokens', returnData[i++])[0] - .map((s: string): string => s.toLowerCase()); - cfgInfo.pools[poolAddress] = { - tokenAddresses, - tokens: {}, - }; - } - - // 2. For each pool, get tokens' symbol, decimals, asset (LP token) address - inputs = []; - for (const poolAddress of cfgInfo.poolAddresses) { - for (const tokenAddress of cfgInfo.pools[poolAddress].tokenAddresses) { - inputs.push({ - target: tokenAddress, - callData: Wombat.erc20Interface.encodeFunctionData('symbol'), - }); - inputs.push({ - target: tokenAddress, - callData: Wombat.erc20Interface.encodeFunctionData('decimals'), - }); - inputs.push({ - target: poolAddress, - callData: Wombat.poolInterface.encodeFunctionData('addressOfAsset', [ - tokenAddress, - ]), - }); - } - } - returnData = ( - await this.dexHelper.multiContract.methods - .aggregate(inputs) - .call({}, blockNumber) - ).returnData; - i = 0; - for (const poolAddress of cfgInfo.poolAddresses) { - for (const tokenAddress of cfgInfo.pools[poolAddress].tokenAddresses) { - const tokenSymbol = Wombat.erc20Interface.decodeFunctionResult( - 'symbol', - returnData[i++], - )[0]; - const tokenDecimals = Wombat.erc20Interface.decodeFunctionResult( - 'decimals', - returnData[i++], - )[0]; - const assetAddress = Wombat.poolInterface - .decodeFunctionResult('addressOfAsset', returnData[i++])[0] - .toLowerCase(); - cfgInfo.pools[poolAddress.toLowerCase()].tokens[ - tokenAddress.toLowerCase() - ] = { - tokenSymbol, - tokenDecimals, - assetAddress, - }; - } - } - return cfgInfo; + this.bmw = new WombatBmw( + dexKey, + this.config.bmwAddress, + network, + dexHelper, + this.logger, + this.config.bmwAddress, + this.onPoolAdded.bind(this), + ); } async init(blockNumber: number) { - if (this.cfgInfo) return; - this.cfgInfo = await this.generateConfigInfo(blockNumber); + await this.bmw.initialize(blockNumber); } // Initialize pricing is called once in the start of @@ -162,34 +86,26 @@ export class Wombat extends SimpleExchange implements IDex { // implement this function async initializePricing(blockNumber: number) { await this.init(blockNumber); - if (!this.cfgInfo) - throw new Error('initializePricing: cfgInfo still null after init'); + const bmwState = this.bmw.getState(blockNumber); + if (!bmwState) { + throw new Error('initializePricing: bmwState still null after init'); + } + } - const eventPools: { [poolAddress: string]: WombatEventPool } = {}; - for (const poolAddress of this.cfgInfo.poolAddresses) { - const pool = new WombatEventPool( + onPoolAdded = async (pool: Address, blockNumber: number): Promise => { + if (!this.eventPools[pool]) { + this.eventPools[pool] = new WombatEventPool( this.dexKey, - '' /** @todo pool name */, - // this.config.pools.find( - // p => p.address.toLowerCase() === poolAddress, - // )!.name, - 3 /** @todo network number */, + pool, + this.network, this.dexHelper, this.logger, - poolAddress, - this.cfgInfo.pools[poolAddress], - ); - const state = await pool.generateState(blockNumber); - pool.setState(state, blockNumber); - this.dexHelper.blockManager.subscribeToLogs( pool, - pool.addressesSubscribed, - blockNumber, ); - eventPools[poolAddress] = pool; + + await this.eventPools[pool].initialize(blockNumber); } - this.eventPools = eventPools; - } + }; // Returns the list of contract adapters (name and index) // for a buy/sell. Return null if there are no adapters. @@ -207,11 +123,12 @@ export class Wombat extends SimpleExchange implements IDex { side: SwapSide, blockNumber: number, ): Promise { - /** @todo implement logic for BUY side */ - if (side === SwapSide.BUY) return []; - return this.findPools( - srcToken.address.toLowerCase(), - destToken.address.toLowerCase(), + return ( + await this.findPools( + srcToken.address.toLowerCase(), + destToken.address.toLowerCase(), + blockNumber, + ) ).map(p => this.getPoolIdentifier(p)); } @@ -231,8 +148,6 @@ export class Wombat extends SimpleExchange implements IDex { blockNumber: number, limitPools?: string[], ): Promise> { - /** @todo implement logic for BUY side */ - if (side === SwapSide.BUY) return null; if (!this.eventPools) { this.logger.error( `Missing event pools for ${this.dexKey} in getPricesVolume`, @@ -242,8 +157,14 @@ export class Wombat extends SimpleExchange implements IDex { const srcTokenAddress = srcToken.address.toLowerCase(); const destTokenAddress = destToken.address.toLowerCase(); if (srcTokenAddress === destTokenAddress) return null; + + const pools = await this.findPools( + srcTokenAddress, + destTokenAddress, + blockNumber, + ); return await Promise.all( - this.findPools(srcTokenAddress, destTokenAddress) + pools .filter( poolAddress => !limitPools || @@ -260,12 +181,9 @@ export class Wombat extends SimpleExchange implements IDex { } const [unit, ...prices] = this.computePrices( srcTokenAddress, - this.cfgInfo!.pools[poolAddress].tokens[srcTokenAddress] - .tokenDecimals, destTokenAddress, - this.cfgInfo!.pools[poolAddress].tokens[destTokenAddress] - .tokenDecimals, [getBigIntPow(srcToken.decimals), ...amounts], + side, state, ); return { @@ -288,37 +206,48 @@ export class Wombat extends SimpleExchange implements IDex { // take PoolState to compute price protected computePrices( srcTokenAddress: Address, - srcTokenDecimals: number, destTokenAddress: Address, - destTokenDecimals: number, amounts: bigint[], + side: SwapSide, state: DeepReadonly, ): bigint[] { + const srcAsset = state.asset[srcTokenAddress]; + const destAsset = state.asset[destTokenAddress]; + const quoter = new WombatQuoter(state.params); + return amounts.map(fromAmount => { - return quoteFrom( - state.asset[srcTokenAddress].cash, - state.asset[srcTokenAddress].cash, - state.asset[destTokenAddress].liability, - state.asset[destTokenAddress].liability, - fromAmount, - state.params.ampFactor, - state.params.haircutRate, - ); + return side === SwapSide.SELL + ? quoter.getQuote(srcAsset, destAsset, fromAmount) + : quoter.getQuote(destAsset, srcAsset, -fromAmount); }); } - protected findPools( + protected async findPools( srcTokenAddress: Address, destTokenAddress: Address, - ): Address[] { - if (!this.cfgInfo) return []; - return Object.entries(this.cfgInfo.pools) - .filter( - ([poolAddress, poolConfig]) => - poolConfig.tokenAddresses.includes(srcTokenAddress) && - poolConfig.tokenAddresses.includes(destTokenAddress), - ) - .map(([poolAddress, poolConfig]) => poolAddress); + blockNumber: number, + ): Promise { + const pools: Address[] = []; + for (const [poolAddress, eventPool] of Object.entries(this.eventPools)) { + let state = eventPool.getState(blockNumber); + if (!state) { + state = await eventPool.generateState(blockNumber); + this.eventPools![poolAddress].setState(state, blockNumber); + } + + if ( + state && + !state.params.paused && + state.asset[srcTokenAddress] && + state.asset[srcTokenAddress].liability > 0 && + state.asset[destTokenAddress] && + state.asset[destTokenAddress].liability > 0 + ) { + pools.push(poolAddress); + } + } + + return pools; } // Returns estimated gas cost of calldata for this DEX in multiSwap @@ -392,60 +321,47 @@ export class Wombat extends SimpleExchange implements IDex { async updatePoolState(): Promise { const blockNumber = await this.dexHelper.provider.getBlockNumber(); await this.init(blockNumber); - if (!this.cfgInfo) - throw new Error('updatePoolState: Wombat cfgInfo still null after init'); + const bmwState = this.bmw.getState(blockNumber); + if (!bmwState) { + throw new Error('updatePoolState: bmwState still null after init'); + } // All tokens are USD stablecoins so to estimate liquidity can just add // the cash balances of all the tokens const poolLiquidityUSD: { [poolAddress: string]: number } = {}; - let inputs: MultiCallInput[] = []; - for (const poolAddress of this.cfgInfo.poolAddresses) { - for (const tokenAddress of this.cfgInfo.pools[poolAddress] - .tokenAddresses) { - inputs.push({ - target: - this.cfgInfo.pools[poolAddress].tokens[tokenAddress].assetAddress, - callData: Wombat.assetInterface.encodeFunctionData('cash'), - }); - } - } - const returnData = ( - await this.dexHelper.multiContract.methods - .aggregate(inputs) - .call({}, blockNumber) - ).returnData; const usdPromises = []; - let i = 0; - for (const poolAddress of this.cfgInfo.poolAddresses) { - for (const tokenAddress of this.cfgInfo.pools[poolAddress] - .tokenAddresses) { + const poolStates: { [poolAddress: string]: DeepReadonly } = {}; + for (const [poolAddress, eventPool] of Object.entries(this.eventPools)) { + let state = eventPool.getState(blockNumber); + if (!state) { + state = await eventPool.generateState(blockNumber); + eventPool.setState(state, blockNumber); + } + poolStates[poolAddress] = state; + for (const [tokenAddress, assetState] of Object.entries(state.asset)) { usdPromises.push( this.dexHelper.getTokenUSDPrice( { address: tokenAddress, - decimals: - this.cfgInfo.pools[poolAddress].tokens[tokenAddress] - .tokenDecimals, + decimals: assetState.underlyingTokenDecimals, }, - /** @todo wombat asset addresses always have 18 d.p. need to convert this amount to underlying tokens native d.p. */ - BigInt( - Wombat.assetInterface - .decodeFunctionResult('cash', returnData[i++])[0] - .toString(), + fromWad( + assetState.cash, + BigInt(assetState.underlyingTokenDecimals), ), ), ); } } const usdValues = await Promise.all(usdPromises); - i = 0; - for (const poolAddress of this.cfgInfo.poolAddresses) { + + for (const [poolAddress, poolState] of Object.entries(poolStates)) { poolLiquidityUSD[poolAddress] = 0; - for (const tokenAddress of this.cfgInfo.pools[poolAddress] - .tokenAddresses) { - poolLiquidityUSD[poolAddress] += usdValues[i++]; + for (let i = 0; i < poolState.underlyingAddresses.length; i++) { + poolLiquidityUSD[poolAddress] += usdValues[i]; } } + this.poolLiquidityUSD = poolLiquidityUSD; } @@ -455,23 +371,38 @@ export class Wombat extends SimpleExchange implements IDex { tokenAddress: Address, limit: number, ): Promise { - if (!this.cfgInfo || !this.poolLiquidityUSD) await this.updatePoolState(); + if (!this.poolLiquidityUSD) await this.updatePoolState(); + const blockNumber = await this.dexHelper.provider.getBlockNumber(); tokenAddress = tokenAddress.toLowerCase(); - const pools = this.cfgInfo!.poolAddresses.filter( - poolAddress => !!this.cfgInfo!.pools[poolAddress].tokens[tokenAddress], - ); + const pools: string[] = []; + const poolStates: { [poolAddress: string]: DeepReadonly } = {}; + for (const [poolAddress, eventPool] of Object.entries(this.eventPools)) { + let state = eventPool.getState(blockNumber); + if (!state) { + state = await eventPool.generateState(blockNumber); + eventPool.setState(state, blockNumber); + } + if ( + state.underlyingAddresses.includes(tokenAddress) && + this.poolLiquidityUSD![poolAddress] + ) { + poolStates[poolAddress] = state; + pools.push(poolAddress); + } + } + // sort by liquidity pools.sort((a, b) => this.poolLiquidityUSD![b] - this.poolLiquidityUSD![a]); return pools.slice(0, limit).map(poolAddress => ({ exchange: this.dexKey, address: poolAddress, // other tokens in the same pool - connectorTokens: this.cfgInfo!.pools[poolAddress].tokenAddresses.filter( - t => t !== tokenAddress, - ).map(t => ({ - decimals: this.cfgInfo!.pools[poolAddress].tokens[t].tokenDecimals, - address: t, - })), + connectorTokens: poolStates[poolAddress].underlyingAddresses + .filter(t => t !== tokenAddress) + .map(t => ({ + decimals: poolStates[poolAddress].asset[t].underlyingTokenDecimals, + address: t, + })), liquidityUSD: this.poolLiquidityUSD![poolAddress], })); } From f5c79f3c3b8af837cb3b39ebb6e2d6305bc41b23 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 27 Oct 2023 12:30:53 +0300 Subject: [PATCH 543/833] solve merge conflicts --- package.json | 2 +- src/config.ts | 1 + src/router/buy.ts | 12 ++++++++++++ tests/utils-e2e.ts | 2 -- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 1efc6781d..042dfff36 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.17.0", + "version": "2.42.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", diff --git a/src/config.ts b/src/config.ts index b457ea258..78f2cccdc 100644 --- a/src/config.ts +++ b/src/config.ts @@ -145,6 +145,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { rfqConfigs: {}, rpcPollingMaxAllowedStateDelayInBlocks: 5, rpcPollingBlocksBackToTriggerUpdate: 3, + forceRpcFallbackDexs: [], }, [Network.BSC]: { network: Network.BSC, diff --git a/src/router/buy.ts b/src/router/buy.ts index 1ffe062b2..6063cd1ce 100644 --- a/src/router/buy.ts +++ b/src/router/buy.ts @@ -62,6 +62,18 @@ export class Buy extends PayloadEncoder implements IRouter { minMaxAmount, priceRoute.srcAmount, ); + + const [partner, feePercent] = referrerAddress + ? [referrerAddress, encodeFeePercentForReferrer(SwapSide.BUY)] + : [ + encodePartnerAddressForFeeLogic({ + partnerAddress, + partnerFeePercent, + takeSurplus, + }), + encodeFeePercent(partnerFeePercent, takeSurplus, SwapSide.BUY), + ]; + const buyData: ContractBuyData = { adapter, fromToken: priceRoute.srcToken, diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index 488ec9594..ece7ac264 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -378,8 +378,6 @@ export async function testE2E( poolIdentifiers, transferFees, ); - // uncomment to avoid tenderly simulation - // process.exit() expect(parseFloat(priceRoute.destAmount)).toBeGreaterThan(0); // Calculate slippage. Default is 1% From 9b41472bba2fd79f2b9123c74f75f22aafcdb889 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Fri, 27 Oct 2023 12:32:22 +0300 Subject: [PATCH 544/833] solve merge conflicts --- tests/constants-e2e.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index b2acc4809..e96da7363 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -837,6 +837,14 @@ export const Tokens: { address: '0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f', decimals: 8, }, + LEX: { + address: '0x6bB7A17AcC227fd1F6781D1EEDEAE01B42047eE0', + decimals: 18, + }, + GRAIL: { + address: '0x3d9907f9a368ad0a51be60f7da3b97cf940982d8', + decimals: 18, + }, }, [Network.OPTIMISM]: { DAI: { From 19205fd21a52c8c9dc6a3265c310cdc24b45ce3c Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 27 Oct 2023 13:14:29 +0300 Subject: [PATCH 545/833] fix: update test config adapter addresses --- src/config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index 78f2cccdc..509a420e1 100644 --- a/src/config.ts +++ b/src/config.ts @@ -52,8 +52,9 @@ const baseConfigs: { [network: number]: BaseConfig } = { Adapter01: '0x9bE264469eF954c139Da4A45Cf76CbCC5e3A6A73', Adapter02: '0xFC2Ba6E830a04C25e207B8214b26d8C713F6881F', Adapter03: '0xfb2a3de6c7B8c77b520E3da16021f3D8A4E93168', - Adapter04: '0x1A23Aa6f7ff4215Fd2d220EA6f4a0DF45A77fc6C', + Adapter04: '0x654dE10890f8B2C5bF54E50Af169a7E93165C416', BuyAdapter: '0x1310dE2C69e9753bee19B5522bad39c5f788efd9', + BuyAdapter02: '0xA10c9a84E72d9DfF424Fe2284B6460784bed407E', }, uniswapV2ExchangeRouterAddress: '0xF9234CB08edb93c0d4a4d4c70cC3FfD070e78e07', From ff8d26478c47687cdde5feb16d55448aa1f09823 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 27 Oct 2023 15:06:38 +0300 Subject: [PATCH 546/833] 2.42.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 78b41a7e0..2b0a2bd4b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.0-traderjoe-mainnet", + "version": "2.42.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 2d96a30b4c62122bb72040bf96305d65b3ad2b20 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 27 Oct 2023 19:31:48 +0300 Subject: [PATCH 547/833] fix: add arb support to swaapv2 --- src/config.ts | 4 ++-- src/dex/swaap-v2/config.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/config.ts b/src/config.ts index 2438a2cac..97d7536fb 100644 --- a/src/config.ts +++ b/src/config.ts @@ -280,8 +280,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], adapterAddresses: { ArbitrumAdapter01: '0xD8134ACfc9c71Ab51452b5bA23A31354F4739032', - ArbitrumAdapter02: '0xD1F70c98a78d48A93F0B4dDa49057469dc5aC126', - ArbitrumBuyAdapter: '0x434C1Cca4842629230067674Dd54E21a14D9FD5D', + ArbitrumAdapter02: '0x3a1F07fA88D6D88bbE5Bab462E52A8CD002810d3', + ArbitrumBuyAdapter: '0x34bDD625C494496d78A792fEB37741E3bc90d4eA', }, uniswapV2ExchangeRouterAddress: '0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC', diff --git a/src/dex/swaap-v2/config.ts b/src/dex/swaap-v2/config.ts index 66d318d27..5a43286c6 100644 --- a/src/dex/swaap-v2/config.ts +++ b/src/dex/swaap-v2/config.ts @@ -20,6 +20,7 @@ export const Adapters: Record = { [SwapSide.BUY]: [{ name: 'PolygonBuyAdapter', index: 7 }], }, [Network.ARBITRUM]: { - // TODO: add the proper adapters + [SwapSide.SELL]: [{ name: 'ArbitrumAdapter02', index: 6 }], + [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 8 }], }, }; From 74c25da87e04bf1a58e5f1c388c1f0838101545d Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 27 Oct 2023 19:35:24 +0300 Subject: [PATCH 548/833] 2.42.1-swaapv2-arb --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2b0a2bd4b..94f2c9dbc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.1", + "version": "2.42.1-swaapv2-arb", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 5b72bb6bdf5124d794058cde827908b2a7f77e88 Mon Sep 17 00:00:00 2001 From: 0xshoehazer <0xshoehazer@gmail.com> Date: Fri, 27 Oct 2023 13:24:22 -0400 Subject: [PATCH 549/833] building out test cases --- scripts/dex-integration.ts | 2 +- src/dex/baseswap-v3/baseswap-v3-e2e.test.ts | 208 ++++++++ .../baseswap-v3-factory.ts | 0 .../baseswap-v3-integration.test.ts | 472 ++++++++++++++++++ .../baseswap-v3-pool.ts | 0 src/dex/baseswap-v3/baseswap-v3.test.ts | 472 ++++++++++++++++++ .../{baseswap => baseswap-v3}/baseswap-v3.ts | 64 +-- src/dex/{baseswap => baseswap-v3}/config.ts | 0 .../{baseswap => baseswap-v3}/constants.ts | 0 .../contract-math/BitMath.ts | 0 .../contract-math/FixedPoint128.ts | 0 .../contract-math/FixedPoint96.ts | 0 .../contract-math/FullMath.ts | 0 .../contract-math/LiquidityMath.ts | 0 .../contract-math/Oracle.ts | 0 .../contract-math/SqrtPriceMath.ts | 0 .../contract-math/SwapMath.ts | 0 .../contract-math/Tick.ts | 0 .../contract-math/TickBitMap.ts | 0 .../contract-math/TickMath.ts | 0 .../contract-math/UnsafeMath.ts | 0 .../contract-math/uniswap-v3-math.ts | 0 .../contract-math/utils.ts | 0 src/dex/{baseswap => baseswap-v3}/types.ts | 0 src/dex/{baseswap => baseswap-v3}/utils.ts | 0 src/dex/index.ts | 2 +- 26 files changed, 1187 insertions(+), 33 deletions(-) create mode 100644 src/dex/baseswap-v3/baseswap-v3-e2e.test.ts rename src/dex/{baseswap => baseswap-v3}/baseswap-v3-factory.ts (100%) create mode 100644 src/dex/baseswap-v3/baseswap-v3-integration.test.ts rename src/dex/{baseswap => baseswap-v3}/baseswap-v3-pool.ts (100%) create mode 100644 src/dex/baseswap-v3/baseswap-v3.test.ts rename src/dex/{baseswap => baseswap-v3}/baseswap-v3.ts (97%) rename src/dex/{baseswap => baseswap-v3}/config.ts (100%) rename src/dex/{baseswap => baseswap-v3}/constants.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/BitMath.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/FixedPoint128.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/FixedPoint96.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/FullMath.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/LiquidityMath.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/Oracle.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/SqrtPriceMath.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/SwapMath.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/Tick.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/TickBitMap.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/TickMath.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/UnsafeMath.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/uniswap-v3-math.ts (100%) rename src/dex/{baseswap => baseswap-v3}/contract-math/utils.ts (100%) rename src/dex/{baseswap => baseswap-v3}/types.ts (100%) rename src/dex/{baseswap => baseswap-v3}/utils.ts (100%) diff --git a/scripts/dex-integration.ts b/scripts/dex-integration.ts index e3487e690..dfe2a31da 100644 --- a/scripts/dex-integration.ts +++ b/scripts/dex-integration.ts @@ -116,7 +116,7 @@ function testIntegration(argv: IOptions) { process.env.NODE_ENV = 'test'; } - require('../node_modules/jest-cli/build/cli').run( + require('../node_modules/jest-cli/build/run').run( `src\/dex\/${dexNameParam}\/.+\.test\.ts`, ); } diff --git a/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts b/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts new file mode 100644 index 000000000..52f1de51b --- /dev/null +++ b/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts @@ -0,0 +1,208 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { testE2E } from '../../../tests/utils-e2e'; +import { + Tokens, + Holders, + NativeTokenSymbols, +} from '../../../tests/constants-e2e'; +import { Network, ContractMethod, SwapSide } from '../../constants'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; + +// function testForNetwork( +// network: Network, +// dexKey: string, +// tokenASymbol: string, +// tokenBSymbol: string, +// tokenAAmount: string, +// tokenBAmount: string, +// nativeTokenAmount: string, +// slippage?: number | undefined, +// ) { +// const provider = new StaticJsonRpcProvider( +// generateConfig(network).privateHttpProvider, +// network, +// ); +// const tokens = Tokens[network]; +// const holders = Holders[network]; +// const nativeTokenSymbol = NativeTokenSymbols[network]; + +// const sideToContractMethods = new Map([ +// [ +// SwapSide.SELL, +// [ +// ContractMethod.simpleSwap, +// ContractMethod.multiSwap, +// ContractMethod.megaSwap, +// // ContractMethod.directUniV3Swap, +// ], +// ], +// [ +// SwapSide.BUY, +// [ +// ContractMethod.simpleBuy, +// ContractMethod.buy, +// // ContractMethod.directUniV3Buy, +// ], +// ], +// ]); + +// describe(`${network}`, () => { +// sideToContractMethods.forEach((contractMethods, side) => +// describe(`${side}`, () => { +// 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, +// 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, +// 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, +// network, +// provider, +// undefined, +// undefined, +// undefined, +// slippage, +// ); +// }); +// }); +// }); +// }), +// ); +// }); +// } + +describe('BasewapV3 E2E', () => { + describe('BasewapV3', () => { + const dexKey = 'basewapV3'; + + describe('BaseswapV3 Base', () => { + const network = Network.BASE; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'USDbC'; + const tokenBSymbol: string = 'WETH'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '1000000000'; // 1000 + const tokenBAmount: string = '1000000000000000000'; // 1 + const nativeTokenAmount = '1000000000000000000'; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[nativeTokenSymbol], + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenBSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[tokenBSymbol], + tokens[tokenASymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenBAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); + }); +}); diff --git a/src/dex/baseswap/baseswap-v3-factory.ts b/src/dex/baseswap-v3/baseswap-v3-factory.ts similarity index 100% rename from src/dex/baseswap/baseswap-v3-factory.ts rename to src/dex/baseswap-v3/baseswap-v3-factory.ts diff --git a/src/dex/baseswap-v3/baseswap-v3-integration.test.ts b/src/dex/baseswap-v3/baseswap-v3-integration.test.ts new file mode 100644 index 000000000..058b71d2f --- /dev/null +++ b/src/dex/baseswap-v3/baseswap-v3-integration.test.ts @@ -0,0 +1,472 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { Interface, Result } from '@ethersproject/abi'; +import { DummyDexHelper, IDexHelper } from '../../dex-helper/index'; +import { Network, SwapSide } from '../../constants'; +import { BI_POWS } from '../../bigint-constants'; +import { BaseswapV3 } from './baseswap-v3'; +import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; +import { Tokens } from '../../../tests/constants-e2e'; +import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; +import { Address } from '@paraswap/core'; + +const network = Network.BASE; +const TokenASymbol = 'USDC'; +const TokenA = Tokens[network][TokenASymbol]; + +const QuoterV2 = '0x4fDBD73aD4B1DDde594BF05497C15f76308eFfb9'; + +const TokenBSymbol = 'WETH'; +const TokenB = Tokens[network][TokenBSymbol]; + +const amounts = [ + 0n, + 10_000n * BI_POWS[6], + 20_000n * BI_POWS[6], + 30_000n * BI_POWS[6], +]; + +const amountsBuy = [0n, 1n * BI_POWS[18], 2n * BI_POWS[18], 3n * BI_POWS[18]]; + +const quoterIface = new Interface(UniswapV3QuoterV2ABI); + +function getReaderCalldata( + exchangeAddress: string, + readerIface: Interface, + amounts: bigint[], + funcName: string, + tokenIn: Address, + tokenOut: Address, + fee: bigint, +) { + return amounts.map(amount => ({ + target: exchangeAddress, + callData: readerIface.encodeFunctionData(funcName, [ + [tokenIn, tokenOut, amount.toString(), fee.toString(), 0], + ]), + })); +} + +function decodeReaderResult( + results: Result, + readerIface: Interface, + funcName: string, +) { + return results.map(result => { + const parsed = readerIface.decodeFunctionResult(funcName, result); + return BigInt(parsed[0]._hex); + }); +} + +async function checkOnChainPricing( + dexHelper: IDexHelper, + funcName: string, + blockNumber: number, + exchangeAddress: string, + prices: bigint[], + tokenIn: Address, + tokenOut: Address, + fee: bigint, + _amounts: bigint[], +) { + // const exchangeAddress = '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'; + const readerIface = quoterIface; + + const sum = prices.reduce((acc, curr) => (acc += curr), 0n); + + if (sum === 0n) { + console.log( + `Prices were not calculated for tokenIn=${tokenIn}, tokenOut=${tokenOut}, fee=${fee.toString()}. Most likely price impact is too big for requested amount`, + ); + return false; + } + + const readerCallData = getReaderCalldata( + exchangeAddress, + readerIface, + _amounts.slice(1), + funcName, + tokenIn, + tokenOut, + fee, + ); + + let readerResult; + try { + readerResult = ( + await dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blockNumber) + ).returnData; + } catch (e) { + console.log( + `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, + e, + ); + return false; + } + + const expectedPrices = [0n].concat( + decodeReaderResult(readerResult, readerIface, funcName), + ); + + console.log('EXPECTED PRICES: ', expectedPrices); + + let firstZeroIndex = prices.slice(1).indexOf(0n); + + // we skipped first, so add +1 on result + firstZeroIndex = firstZeroIndex === -1 ? prices.length : firstZeroIndex; + + // Compare only the ones for which we were able to calculate prices + expect(prices.slice(0, firstZeroIndex)).toEqual( + expectedPrices.slice(0, firstZeroIndex), + ); + return true; +} + +describe('BaseswapV3', function () { + const dexHelper = new DummyDexHelper(network); + const dexKey = 'BaseswapV3'; + + let blockNumber: number; + let baseswapV3: BaseswapV3; + let baseswapV3Mainnet: BaseswapV3; + + beforeEach(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + baseswapV3 = new BaseswapV3(network, dexKey, dexHelper); + baseswapV3Mainnet = new BaseswapV3( + Network.BASE, + dexKey, + new DummyDexHelper(Network.BASE), + ); + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + const pools = await baseswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + // const poolPrices = await baseswapV3.getPricesVolume( + // TokenA, + // TokenB, + // amounts, + // SwapSide.SELL, + // blockNumber, + // pools, + // ); + // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + // expect(poolPrices).not.toBeNull(); + // checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + // let falseChecksCounter = 0; + // await Promise.all( + // poolPrices!.map(async price => { + // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; + // const res = await checkOnChainPricing( + // dexHelper, + // 'quoteExactInputSingle', + // blockNumber, + // QuoterV2, + // price.prices, + // TokenA.address, + // TokenB.address, + // fee, + // amounts, + // ); + // if (res === false) falseChecksCounter++; + // }), + // ); + + // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + // it('getPoolIdentifiers and getPricesVolume BUY', async function () { + // const pools = await baseswapV3.getPoolIdentifiers( + // TokenA, + // TokenB, + // SwapSide.BUY, + // blockNumber, + // ); + // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + // expect(pools.length).toBeGreaterThan(0); + + // const poolPrices = await baseswapV3.getPricesVolume( + // TokenA, + // TokenB, + // amountsBuy, + // SwapSide.BUY, + // blockNumber, + // pools, + // ); + // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + // expect(poolPrices).not.toBeNull(); + // checkPoolPrices(poolPrices!, amountsBuy, SwapSide.BUY, dexKey); + + // // Check if onchain pricing equals to calculated ones + // let falseChecksCounter = 0; + // await Promise.all( + // poolPrices!.map(async price => { + // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; + // const res = await checkOnChainPricing( + // dexHelper, + // 'quoteExactOutputSingle', + // blockNumber, + // QuoterV2, + // price.prices, + // TokenA.address, + // TokenB.address, + // fee, + // amountsBuy, + // ); + // if (res === false) falseChecksCounter++; + // }), + // ); + // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + // }); + + // it('getPoolIdentifiers and getPricesVolume SELL stable pairs', async function () { + // const TokenASymbol = 'USDT'; + // const TokenA = Tokens[network][TokenASymbol]; + + // const TokenBSymbol = 'USDC'; + // const TokenB = Tokens[network][TokenBSymbol]; + + // const amounts = [ + // 0n, + // 6000000n, + // 12000000n, + // 18000000n, + // 24000000n, + // 30000000n, + // 36000000n, + // 42000000n, + // 48000000n, + // 54000000n, + // 60000000n, + // 66000000n, + // 72000000n, + // 78000000n, + // 84000000n, + // 90000000n, + // 96000000n, + // 102000000n, + // 108000000n, + // 114000000n, + // 120000000n, + // 126000000n, + // 132000000n, + // 138000000n, + // 144000000n, + // 150000000n, + // 156000000n, + // 162000000n, + // 168000000n, + // 174000000n, + // 180000000n, + // 186000000n, + // 192000000n, + // 198000000n, + // 204000000n, + // 210000000n, + // 216000000n, + // 222000000n, + // 228000000n, + // 234000000n, + // 240000000n, + // 246000000n, + // 252000000n, + // 258000000n, + // 264000000n, + // 270000000n, + // 276000000n, + // 282000000n, + // 288000000n, + // 294000000n, + // 300000000n, + // ]; + + // const pools = await baseswapV3.getPoolIdentifiers( + // TokenA, + // TokenB, + // SwapSide.SELL, + // blockNumber, + // ); + // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + // expect(pools.length).toBeGreaterThan(0); + + // const poolPrices = await baseswapV3.getPricesVolume( + // TokenA, + // TokenB, + // amounts, + // SwapSide.SELL, + // blockNumber, + // pools, + // ); + // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + // expect(poolPrices).not.toBeNull(); + // checkPoolPrices( + // poolPrices!.filter(pp => pp.unit !== 0n), + // amounts, + // SwapSide.SELL, + // dexKey, + // ); + + // // Check if onchain pricing equals to calculated ones + // let falseChecksCounter = 0; + // await Promise.all( + // poolPrices!.map(async price => { + // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; + // const res = await checkOnChainPricing( + // dexHelper, + // 'quoteExactInputSingle', + // blockNumber, + // QuoterV2, + // price.prices, + // TokenA.address, + // TokenB.address, + // fee, + // amounts, + // ); + // if (res === false) falseChecksCounter++; + // }), + // ); + // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + // }); + + // it('getPoolIdentifiers and getPricesVolume BUY stable pairs', async function () { + // const TokenASymbol = 'DAI'; + // const TokenA = Tokens[network][TokenASymbol]; + + // const TokenBSymbol = 'USDC'; + // const TokenB = Tokens[network][TokenBSymbol]; + + // const amountsBuy = [ + // 0n, + // 6000000n, + // 12000000n, + // 18000000n, + // 24000000n, + // 30000000n, + // 36000000n, + // 42000000n, + // 48000000n, + // 54000000n, + // 60000000n, + // 66000000n, + // 72000000n, + // 78000000n, + // 84000000n, + // 90000000n, + // 96000000n, + // 102000000n, + // 108000000n, + // 114000000n, + // 120000000n, + // 126000000n, + // 132000000n, + // 138000000n, + // 144000000n, + // 150000000n, + // 156000000n, + // 162000000n, + // 168000000n, + // 174000000n, + // 180000000n, + // 186000000n, + // 192000000n, + // 198000000n, + // 204000000n, + // 210000000n, + // 216000000n, + // 222000000n, + // 228000000n, + // 234000000n, + // 240000000n, + // 246000000n, + // 252000000n, + // 258000000n, + // 264000000n, + // 270000000n, + // 276000000n, + // 282000000n, + // 288000000n, + // 294000000n, + // 300000000n, + // ]; + + // const pools = await baseswapV3.getPoolIdentifiers( + // TokenA, + // TokenB, + // SwapSide.BUY, + // blockNumber, + // ); + // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + // expect(pools.length).toBeGreaterThan(0); + + // const poolPrices = await baseswapV3.getPricesVolume( + // TokenA, + // TokenB, + // amountsBuy, + // SwapSide.BUY, + // blockNumber, + // pools, + // ); + // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + // expect(poolPrices).not.toBeNull(); + // checkPoolPrices( + // poolPrices!.filter(pp => pp.unit !== 0n), + // amountsBuy, + // SwapSide.BUY, + // dexKey, + // ); + + // // Check if onchain pricing equals to calculated ones + // let falseChecksCounter = 0; + // await Promise.all( + // poolPrices!.map(async price => { + // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; + // const res = await checkOnChainPricing( + // dexHelper, + // 'quoteExactOutputSingle', + // blockNumber, + // QuoterV2, + // price.prices, + // TokenA.address, + // TokenB.address, + // fee, + // amountsBuy, + // ); + // if (res === false) falseChecksCounter++; + // }), + // ); + // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + // }); + + // it('getTopPoolsForToken', async function () { + // const poolLiquidity = await baseswapV3Mainnet.getTopPoolsForToken( + // Tokens[Network.BASE]['USDC'].address, + // 10, + // ); + // console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + // if (!baseswapV3.hasConstantPriceLargeAmounts) { + // checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); + // } + // }); +}); diff --git a/src/dex/baseswap/baseswap-v3-pool.ts b/src/dex/baseswap-v3/baseswap-v3-pool.ts similarity index 100% rename from src/dex/baseswap/baseswap-v3-pool.ts rename to src/dex/baseswap-v3/baseswap-v3-pool.ts diff --git a/src/dex/baseswap-v3/baseswap-v3.test.ts b/src/dex/baseswap-v3/baseswap-v3.test.ts new file mode 100644 index 000000000..8147683c2 --- /dev/null +++ b/src/dex/baseswap-v3/baseswap-v3.test.ts @@ -0,0 +1,472 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { Interface, Result } from '@ethersproject/abi'; +import { DummyDexHelper, IDexHelper } from '../../dex-helper/index'; +import { Network, SwapSide } from '../../constants'; +import { BI_POWS } from '../../bigint-constants'; +import { BaseswapV3 } from './baseswap-v3'; +import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; +import { Tokens } from '../../../tests/constants-e2e'; +import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; +import { Address } from '@paraswap/core'; + +const network = Network.BASE; +const TokenASymbol = 'USDC'; +const TokenA = Tokens[network][TokenASymbol]; + +const QuoterV2 = '0x4fDBD73aD4B1DDde594BF05497C15f76308eFfb9'; + +const TokenBSymbol = 'WETH'; +const TokenB = Tokens[network][TokenBSymbol]; + +const amounts = [ + 0n, + 10_000n * BI_POWS[6], + 20_000n * BI_POWS[6], + 30_000n * BI_POWS[6], +]; + +const amountsBuy = [0n, 1n * BI_POWS[18], 2n * BI_POWS[18], 3n * BI_POWS[18]]; + +const quoterIface = new Interface(UniswapV3QuoterV2ABI); + +function getReaderCalldata( + exchangeAddress: string, + readerIface: Interface, + amounts: bigint[], + funcName: string, + tokenIn: Address, + tokenOut: Address, + fee: bigint, +) { + return amounts.map(amount => ({ + target: exchangeAddress, + callData: readerIface.encodeFunctionData(funcName, [ + [tokenIn, tokenOut, amount.toString(), fee.toString(), 0], + ]), + })); +} + +function decodeReaderResult( + results: Result, + readerIface: Interface, + funcName: string, +) { + return results.map(result => { + const parsed = readerIface.decodeFunctionResult(funcName, result); + return BigInt(parsed[0]._hex); + }); +} + +async function checkOnChainPricing( + dexHelper: IDexHelper, + funcName: string, + blockNumber: number, + exchangeAddress: string, + prices: bigint[], + tokenIn: Address, + tokenOut: Address, + fee: bigint, + _amounts: bigint[], +) { + // const exchangeAddress = '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'; + const readerIface = quoterIface; + + const sum = prices.reduce((acc, curr) => (acc += curr), 0n); + + if (sum === 0n) { + console.log( + `Prices were not calculated for tokenIn=${tokenIn}, tokenOut=${tokenOut}, fee=${fee.toString()}. Most likely price impact is too big for requested amount`, + ); + return false; + } + + const readerCallData = getReaderCalldata( + exchangeAddress, + readerIface, + _amounts.slice(1), + funcName, + tokenIn, + tokenOut, + fee, + ); + + let readerResult; + try { + readerResult = ( + await dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blockNumber) + ).returnData; + } catch (e) { + console.log( + `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, + e, + ); + return false; + } + + const expectedPrices = [0n].concat( + decodeReaderResult(readerResult, readerIface, funcName), + ); + + console.log('EXPECTED PRICES: ', expectedPrices); + + let firstZeroIndex = prices.slice(1).indexOf(0n); + + // we skipped first, so add +1 on result + firstZeroIndex = firstZeroIndex === -1 ? prices.length : firstZeroIndex; + + // Compare only the ones for which we were able to calculate prices + expect(prices.slice(0, firstZeroIndex)).toEqual( + expectedPrices.slice(0, firstZeroIndex), + ); + return true; +} + +describe('BaseswapV3', function () { + const dexHelper = new DummyDexHelper(network); + const dexKey = 'BaseswapV3'; + + let blockNumber: number; + let baseswapV3: BaseswapV3; + let baseswapV3Mainnet: BaseswapV3; + + beforeEach(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + baseswapV3 = new BaseswapV3(network, dexKey, dexHelper); + baseswapV3Mainnet = new BaseswapV3( + Network.BASE, + dexKey, + new DummyDexHelper(Network.BASE), + ); + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + const pools = await baseswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await baseswapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + 'quoteExactInputSingle', + blockNumber, + QuoterV2, + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + // it('getPoolIdentifiers and getPricesVolume BUY', async function () { + // const pools = await baseswapV3.getPoolIdentifiers( + // TokenA, + // TokenB, + // SwapSide.BUY, + // blockNumber, + // ); + // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + // expect(pools.length).toBeGreaterThan(0); + + // const poolPrices = await baseswapV3.getPricesVolume( + // TokenA, + // TokenB, + // amountsBuy, + // SwapSide.BUY, + // blockNumber, + // pools, + // ); + // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + // expect(poolPrices).not.toBeNull(); + // checkPoolPrices(poolPrices!, amountsBuy, SwapSide.BUY, dexKey); + + // // Check if onchain pricing equals to calculated ones + // let falseChecksCounter = 0; + // await Promise.all( + // poolPrices!.map(async price => { + // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; + // const res = await checkOnChainPricing( + // dexHelper, + // 'quoteExactOutputSingle', + // blockNumber, + // QuoterV2, + // price.prices, + // TokenA.address, + // TokenB.address, + // fee, + // amountsBuy, + // ); + // if (res === false) falseChecksCounter++; + // }), + // ); + // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + // }); + + // it('getPoolIdentifiers and getPricesVolume SELL stable pairs', async function () { + // const TokenASymbol = 'USDT'; + // const TokenA = Tokens[network][TokenASymbol]; + + // const TokenBSymbol = 'USDC'; + // const TokenB = Tokens[network][TokenBSymbol]; + + // const amounts = [ + // 0n, + // 6000000n, + // 12000000n, + // 18000000n, + // 24000000n, + // 30000000n, + // 36000000n, + // 42000000n, + // 48000000n, + // 54000000n, + // 60000000n, + // 66000000n, + // 72000000n, + // 78000000n, + // 84000000n, + // 90000000n, + // 96000000n, + // 102000000n, + // 108000000n, + // 114000000n, + // 120000000n, + // 126000000n, + // 132000000n, + // 138000000n, + // 144000000n, + // 150000000n, + // 156000000n, + // 162000000n, + // 168000000n, + // 174000000n, + // 180000000n, + // 186000000n, + // 192000000n, + // 198000000n, + // 204000000n, + // 210000000n, + // 216000000n, + // 222000000n, + // 228000000n, + // 234000000n, + // 240000000n, + // 246000000n, + // 252000000n, + // 258000000n, + // 264000000n, + // 270000000n, + // 276000000n, + // 282000000n, + // 288000000n, + // 294000000n, + // 300000000n, + // ]; + + // const pools = await baseswapV3.getPoolIdentifiers( + // TokenA, + // TokenB, + // SwapSide.SELL, + // blockNumber, + // ); + // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + // expect(pools.length).toBeGreaterThan(0); + + // const poolPrices = await baseswapV3.getPricesVolume( + // TokenA, + // TokenB, + // amounts, + // SwapSide.SELL, + // blockNumber, + // pools, + // ); + // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + // expect(poolPrices).not.toBeNull(); + // checkPoolPrices( + // poolPrices!.filter(pp => pp.unit !== 0n), + // amounts, + // SwapSide.SELL, + // dexKey, + // ); + + // // Check if onchain pricing equals to calculated ones + // let falseChecksCounter = 0; + // await Promise.all( + // poolPrices!.map(async price => { + // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; + // const res = await checkOnChainPricing( + // dexHelper, + // 'quoteExactInputSingle', + // blockNumber, + // QuoterV2, + // price.prices, + // TokenA.address, + // TokenB.address, + // fee, + // amounts, + // ); + // if (res === false) falseChecksCounter++; + // }), + // ); + // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + // }); + + // it('getPoolIdentifiers and getPricesVolume BUY stable pairs', async function () { + // const TokenASymbol = 'DAI'; + // const TokenA = Tokens[network][TokenASymbol]; + + // const TokenBSymbol = 'USDC'; + // const TokenB = Tokens[network][TokenBSymbol]; + + // const amountsBuy = [ + // 0n, + // 6000000n, + // 12000000n, + // 18000000n, + // 24000000n, + // 30000000n, + // 36000000n, + // 42000000n, + // 48000000n, + // 54000000n, + // 60000000n, + // 66000000n, + // 72000000n, + // 78000000n, + // 84000000n, + // 90000000n, + // 96000000n, + // 102000000n, + // 108000000n, + // 114000000n, + // 120000000n, + // 126000000n, + // 132000000n, + // 138000000n, + // 144000000n, + // 150000000n, + // 156000000n, + // 162000000n, + // 168000000n, + // 174000000n, + // 180000000n, + // 186000000n, + // 192000000n, + // 198000000n, + // 204000000n, + // 210000000n, + // 216000000n, + // 222000000n, + // 228000000n, + // 234000000n, + // 240000000n, + // 246000000n, + // 252000000n, + // 258000000n, + // 264000000n, + // 270000000n, + // 276000000n, + // 282000000n, + // 288000000n, + // 294000000n, + // 300000000n, + // ]; + + // const pools = await baseswapV3.getPoolIdentifiers( + // TokenA, + // TokenB, + // SwapSide.BUY, + // blockNumber, + // ); + // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + // expect(pools.length).toBeGreaterThan(0); + + // const poolPrices = await baseswapV3.getPricesVolume( + // TokenA, + // TokenB, + // amountsBuy, + // SwapSide.BUY, + // blockNumber, + // pools, + // ); + // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + // expect(poolPrices).not.toBeNull(); + // checkPoolPrices( + // poolPrices!.filter(pp => pp.unit !== 0n), + // amountsBuy, + // SwapSide.BUY, + // dexKey, + // ); + + // // Check if onchain pricing equals to calculated ones + // let falseChecksCounter = 0; + // await Promise.all( + // poolPrices!.map(async price => { + // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; + // const res = await checkOnChainPricing( + // dexHelper, + // 'quoteExactOutputSingle', + // blockNumber, + // QuoterV2, + // price.prices, + // TokenA.address, + // TokenB.address, + // fee, + // amountsBuy, + // ); + // if (res === false) falseChecksCounter++; + // }), + // ); + // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + // }); + + // it('getTopPoolsForToken', async function () { + // const poolLiquidity = await baseswapV3Mainnet.getTopPoolsForToken( + // Tokens[Network.BASE]['USDC'].address, + // 10, + // ); + // console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + // if (!baseswapV3.hasConstantPriceLargeAmounts) { + // checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); + // } + // }); +}); diff --git a/src/dex/baseswap/baseswap-v3.ts b/src/dex/baseswap-v3/baseswap-v3.ts similarity index 97% rename from src/dex/baseswap/baseswap-v3.ts rename to src/dex/baseswap-v3/baseswap-v3.ts index de4da625b..b5cad4b15 100644 --- a/src/dex/baseswap/baseswap-v3.ts +++ b/src/dex/baseswap-v3/baseswap-v3.ts @@ -98,12 +98,12 @@ export class BaseswapV3 getDexKeysWithNetwork( _.pick(BaseswapV3Config, [ 'BaseswapV3', - 'UniswapV3', - 'SushiSwapV3', - 'QuickSwapV3.1', - 'RamsesV2', - 'ChronosV3', - 'Retro', + // 'UniswapV3', + // 'SushiSwapV3', + // 'QuickSwapV3.1', + // 'RamsesV2', + // 'ChronosV3', + // 'Retro', ]), ); @@ -291,10 +291,12 @@ export class BaseswapV3 } this.logger.trace(`starting to listen to new pool: ${key}`); + const poolImplementation = this.config.eventPoolImplementation !== undefined ? this.config.eventPoolImplementation : BaseswapV3EventPool; + pool = pool || new poolImplementation( @@ -1015,31 +1017,31 @@ export class BaseswapV3 const res = await this._querySubgraph( `query ($token: Bytes!, $count: Int) { - pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token}) { - id - token0 { - id - decimals - } - token1 { - id - decimals - } - totalValueLockedUSD - } - pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token}) { - id - token0 { - id - decimals - } - token1 { - id - decimals - } - totalValueLockedUSD - } - }`, + pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + }`, { token: _tokenAddress, count: limit, diff --git a/src/dex/baseswap/config.ts b/src/dex/baseswap-v3/config.ts similarity index 100% rename from src/dex/baseswap/config.ts rename to src/dex/baseswap-v3/config.ts diff --git a/src/dex/baseswap/constants.ts b/src/dex/baseswap-v3/constants.ts similarity index 100% rename from src/dex/baseswap/constants.ts rename to src/dex/baseswap-v3/constants.ts diff --git a/src/dex/baseswap/contract-math/BitMath.ts b/src/dex/baseswap-v3/contract-math/BitMath.ts similarity index 100% rename from src/dex/baseswap/contract-math/BitMath.ts rename to src/dex/baseswap-v3/contract-math/BitMath.ts diff --git a/src/dex/baseswap/contract-math/FixedPoint128.ts b/src/dex/baseswap-v3/contract-math/FixedPoint128.ts similarity index 100% rename from src/dex/baseswap/contract-math/FixedPoint128.ts rename to src/dex/baseswap-v3/contract-math/FixedPoint128.ts diff --git a/src/dex/baseswap/contract-math/FixedPoint96.ts b/src/dex/baseswap-v3/contract-math/FixedPoint96.ts similarity index 100% rename from src/dex/baseswap/contract-math/FixedPoint96.ts rename to src/dex/baseswap-v3/contract-math/FixedPoint96.ts diff --git a/src/dex/baseswap/contract-math/FullMath.ts b/src/dex/baseswap-v3/contract-math/FullMath.ts similarity index 100% rename from src/dex/baseswap/contract-math/FullMath.ts rename to src/dex/baseswap-v3/contract-math/FullMath.ts diff --git a/src/dex/baseswap/contract-math/LiquidityMath.ts b/src/dex/baseswap-v3/contract-math/LiquidityMath.ts similarity index 100% rename from src/dex/baseswap/contract-math/LiquidityMath.ts rename to src/dex/baseswap-v3/contract-math/LiquidityMath.ts diff --git a/src/dex/baseswap/contract-math/Oracle.ts b/src/dex/baseswap-v3/contract-math/Oracle.ts similarity index 100% rename from src/dex/baseswap/contract-math/Oracle.ts rename to src/dex/baseswap-v3/contract-math/Oracle.ts diff --git a/src/dex/baseswap/contract-math/SqrtPriceMath.ts b/src/dex/baseswap-v3/contract-math/SqrtPriceMath.ts similarity index 100% rename from src/dex/baseswap/contract-math/SqrtPriceMath.ts rename to src/dex/baseswap-v3/contract-math/SqrtPriceMath.ts diff --git a/src/dex/baseswap/contract-math/SwapMath.ts b/src/dex/baseswap-v3/contract-math/SwapMath.ts similarity index 100% rename from src/dex/baseswap/contract-math/SwapMath.ts rename to src/dex/baseswap-v3/contract-math/SwapMath.ts diff --git a/src/dex/baseswap/contract-math/Tick.ts b/src/dex/baseswap-v3/contract-math/Tick.ts similarity index 100% rename from src/dex/baseswap/contract-math/Tick.ts rename to src/dex/baseswap-v3/contract-math/Tick.ts diff --git a/src/dex/baseswap/contract-math/TickBitMap.ts b/src/dex/baseswap-v3/contract-math/TickBitMap.ts similarity index 100% rename from src/dex/baseswap/contract-math/TickBitMap.ts rename to src/dex/baseswap-v3/contract-math/TickBitMap.ts diff --git a/src/dex/baseswap/contract-math/TickMath.ts b/src/dex/baseswap-v3/contract-math/TickMath.ts similarity index 100% rename from src/dex/baseswap/contract-math/TickMath.ts rename to src/dex/baseswap-v3/contract-math/TickMath.ts diff --git a/src/dex/baseswap/contract-math/UnsafeMath.ts b/src/dex/baseswap-v3/contract-math/UnsafeMath.ts similarity index 100% rename from src/dex/baseswap/contract-math/UnsafeMath.ts rename to src/dex/baseswap-v3/contract-math/UnsafeMath.ts diff --git a/src/dex/baseswap/contract-math/uniswap-v3-math.ts b/src/dex/baseswap-v3/contract-math/uniswap-v3-math.ts similarity index 100% rename from src/dex/baseswap/contract-math/uniswap-v3-math.ts rename to src/dex/baseswap-v3/contract-math/uniswap-v3-math.ts diff --git a/src/dex/baseswap/contract-math/utils.ts b/src/dex/baseswap-v3/contract-math/utils.ts similarity index 100% rename from src/dex/baseswap/contract-math/utils.ts rename to src/dex/baseswap-v3/contract-math/utils.ts diff --git a/src/dex/baseswap/types.ts b/src/dex/baseswap-v3/types.ts similarity index 100% rename from src/dex/baseswap/types.ts rename to src/dex/baseswap-v3/types.ts diff --git a/src/dex/baseswap/utils.ts b/src/dex/baseswap-v3/utils.ts similarity index 100% rename from src/dex/baseswap/utils.ts rename to src/dex/baseswap-v3/utils.ts diff --git a/src/dex/index.ts b/src/dex/index.ts index 25fffcde3..2d6cd349c 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -76,7 +76,7 @@ import { PancakeswapV3 } from './pancakeswap-v3/pancakeswap-v3'; import { Algebra } from './algebra/algebra'; import { QuickPerps } from './quick-perps/quick-perps'; import { NomiswapV2 } from './uniswap-v2/nomiswap-v2'; -import { BaseswapV3 } from './baseswap/baseswap-v3'; +import { BaseswapV3 } from './baseswap-v3/baseswap-v3'; const LegacyDexes = [ CurveV2, From 1fcb1458beb1fdf25912a025118bcba332d5df3d Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 27 Oct 2023 21:00:34 +0300 Subject: [PATCH 550/833] fix: update adapter addresses --- src/config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index c1dc8c86a..21d2fd5b1 100644 --- a/src/config.ts +++ b/src/config.ts @@ -281,8 +281,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], adapterAddresses: { ArbitrumAdapter01: '0xD8134ACfc9c71Ab51452b5bA23A31354F4739032', - ArbitrumAdapter02: '0x3a1F07fA88D6D88bbE5Bab462E52A8CD002810d3', - ArbitrumBuyAdapter: '0x34bDD625C494496d78A792fEB37741E3bc90d4eA', + ArbitrumAdapter02: '0x248009f6F78b5AcD5EA2fc86d56b77A7AeEe2eFc', + ArbitrumBuyAdapter: '0xEECA9223063bD13e8ca77ed9e39a07f2BD1923E6', }, uniswapV2ExchangeRouterAddress: '0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC', From 3e45a449473d987665330b016d8f795442b98fb1 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 28 Oct 2023 00:32:54 +0200 Subject: [PATCH 551/833] balancer-v1: disable AMPL pool due to wrong weights --- src/dex/balancer-v1/balancer-v1.ts | 13 ++++++++++++- tests/constants-e2e.ts | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/dex/balancer-v1/balancer-v1.ts b/src/dex/balancer-v1/balancer-v1.ts index cfdc4d67b..7b5b87491 100644 --- a/src/dex/balancer-v1/balancer-v1.ts +++ b/src/dex/balancer-v1/balancer-v1.ts @@ -39,6 +39,10 @@ import { generatePoolStates } from './utils'; import BalancerV1ExchangeProxyABI from '../../abi/BalancerV1ExchangeProxy.json'; import BalancerCustomMulticallABI from '../../abi/BalancerCustomMulticall.json'; +const BLACKLISTED_POOLS = new Set([ + '0x7860e28ebfb8ae052bfe279c07ac5d94c9cd2937', +]); + export class BalancerV1 extends SimpleExchange implements IDex @@ -82,11 +86,18 @@ export class BalancerV1 // for pricing requests. It is optional for a DEX to // implement this function async initializePricing(_blockNumber: number) { - this.poolsInfo = await this.dexHelper.httpRequest.get( + const _poolsInfo = await this.dexHelper.httpRequest.get( this.config.poolsURL, POOLS_FETCH_TIMEOUT, ); + this.poolInfosByToken = {}; + if (!_poolsInfo) return; + this.poolsInfo = { + ..._poolsInfo, + pools: _poolsInfo.pools.filter(p => !BLACKLISTED_POOLS.has(p.id)), + }; + for (const poolInfo of this.poolsInfo.pools) { for (const tokenAddress of poolInfo.tokensList) { if (!this.poolInfosByToken[tokenAddress]) { diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index d96223d69..579c16bd1 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -27,6 +27,10 @@ export const Tokens: { address: '0x8f8221aFbB33998d8584A2B05749bA73c37a938a', decimals: 18, }, + AMPL: { + address: '0xd46ba6d942050d489dbd938a2c909a5d5039a161', + decimals: 9, + }, USDC: { address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', decimals: 6, @@ -958,6 +962,7 @@ export const Holders: { [Network.MAINNET]: { ETH: '0x176F3DAb24a159341c0509bB36B833E7fdd0a132', USDC: '0x79E2Ba942B0e8fDB6ff3d406e930289d10B49ADe', + AMPL: '0x223592a191ECfC7FDC38a9256c3BD96E771539A9', WBTC: '0x1cb17a66dc606a52785f69f08f4256526abd4943', sBTC: '0xA2e3475D13776C6E42ff37B47286827d959B2195', BADGER: '0x34e2741a3f8483dbe5231f61c005110ff4b9f50a', From eb7a5b5eaef910ca8f3bdecd8fa6fd05571d65cb Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 28 Oct 2023 00:36:10 +0200 Subject: [PATCH 552/833] 2.42.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2b0a2bd4b..20f7c86c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.1", + "version": "2.42.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 5e59e15daf0a36f4df0382529c29ef7f0cadbe1e Mon Sep 17 00:00:00 2001 From: Koala <142200506+koala0814@users.noreply.github.com> Date: Mon, 30 Oct 2023 17:00:57 +0800 Subject: [PATCH 553/833] implement wombat pool based on StatefulRpcPoller --- src/abi/wombat/pool.json | 13 + src/dex/wombat/config.ts | 2 + src/dex/wombat/types.ts | 8 + src/dex/wombat/utils.ts | 9 + src/dex/wombat/wombat-bmw.ts | 112 ++-- src/dex/wombat/wombat-events.test.ts | 125 ----- src/dex/wombat/wombat-integration.test.ts | 4 +- src/dex/wombat/wombat-pool.ts | 589 ++++++---------------- src/dex/wombat/wombat.ts | 169 ++++--- 9 files changed, 369 insertions(+), 662 deletions(-) delete mode 100644 src/dex/wombat/wombat-events.test.ts diff --git a/src/abi/wombat/pool.json b/src/abi/wombat/pool.json index 398362857..33cfc0f48 100644 --- a/src/abi/wombat/pool.json +++ b/src/abi/wombat/pool.json @@ -1347,5 +1347,18 @@ ], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [], + "name": "creditForTokensHaircut", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" } ] diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts index dcd25c8d7..cd54fbf15 100644 --- a/src/dex/wombat/config.ts +++ b/src/dex/wombat/config.ts @@ -24,3 +24,5 @@ export const Adapters: Record = { ], }, }; + +export const LIQUIDITY_THRESHOLD_IN_USD = 100; diff --git a/src/dex/wombat/types.ts b/src/dex/wombat/types.ts index b552627ee..5fa11b25f 100644 --- a/src/dex/wombat/types.ts +++ b/src/dex/wombat/types.ts @@ -17,6 +17,7 @@ export type PoolState = { }; export type AssetState = { + address: Address; paused: boolean; cash: bigint; liability: bigint; @@ -44,3 +45,10 @@ export type DexParams = { // DexParams is set of parameters that can be used to initiate a DEX fork. bmwAddress: Address; }; + +export type MulticallResultOutputs = + | boolean + | bigint + | Address + | number + | undefined; diff --git a/src/dex/wombat/utils.ts b/src/dex/wombat/utils.ts index cab8abba5..cae5701a3 100644 --- a/src/dex/wombat/utils.ts +++ b/src/dex/wombat/utils.ts @@ -1,4 +1,7 @@ import { BI_POWS } from '../../bigint-constants'; +import { MultiResult } from '../../lib/multi-wrapper'; +import { BytesLike } from 'ethers/lib/utils'; +import { generalDecoder } from '../../lib/decoders'; export const WAD = BI_POWS[18]; @@ -51,3 +54,9 @@ export function sqrt(y: bigint, guess: bigint): bigint { return z; } + +export const uint120ToBigInt = ( + result: MultiResult | BytesLike, +): bigint => { + return generalDecoder(result, ['uint120'], 0n, value => value[0].toBigInt()); +}; diff --git a/src/dex/wombat/wombat-bmw.ts b/src/dex/wombat/wombat-bmw.ts index 844069805..0985fd299 100644 --- a/src/dex/wombat/wombat-bmw.ts +++ b/src/dex/wombat/wombat-bmw.ts @@ -1,7 +1,7 @@ import { Interface } from '@ethersproject/abi'; import { BytesLike } from 'ethers'; import { LogDescription } from 'ethers/lib/utils'; -import Web3EthContract, { Contract } from 'web3-eth-contract'; +import { Contract } from 'web3-eth-contract'; import { DeepReadonly } from 'ts-essentials'; import { Address, Log, Logger, MultiCallInput } from '../../types'; import { catchParseLogError } from '../../utils'; @@ -10,10 +10,12 @@ import { IDexHelper } from '../../dex-helper'; import { BmwState } from './types'; import BmwABI from '../../abi/wombat/bmw.json'; import AssetABI from '../../abi/wombat/asset.json'; +import PoolABI from '../../abi/wombat/pool.json'; export class WombatBmw extends StatefulEventSubscriber { static readonly bmwInterface = new Interface(BmwABI); static readonly assetInterface = new Interface(AssetABI); + static readonly poolInterface = new Interface(PoolABI); private readonly logDecoder: (log: Log) => any; private bmwContract: Contract; @@ -32,10 +34,11 @@ export class WombatBmw extends StatefulEventSubscriber { protected dexHelper: IDexHelper, logger: Logger, protected bmwAddress: Address, - protected onPoolAdded: ( + protected onAssetAdded: ( pool: Address, + asset2TokenMap: Map, blockNumber: number, - ) => Promise, + ) => void, ) { super( `${dexKey} ${name}`, @@ -71,7 +74,7 @@ export class WombatBmw extends StatefulEventSubscriber { try { const event = this.logDecoder(log); if (event.name in this.handlers) { - await this.handlers[event.name](event, state, log); + return await this.handlers[event.name](event, state, log); } } catch (e) { catchParseLogError(e, this.logger); @@ -107,16 +110,24 @@ export class WombatBmw extends StatefulEventSubscriber { .call({}, blockNumber) ).returnData; - const lpTokens = returnData.map( - (data: BytesLike) => - WombatBmw.bmwInterface.decodeFunctionResult('poolInfo', data)[0], + const lpTokens = returnData.map((data: BytesLike) => + WombatBmw.bmwInterface + .decodeFunctionResult('poolInfo', data)[0] + .toLowerCase(), ); - // 2. get all pools and underlying tokens - inputs = lpTokens.map((lpToken: string) => ({ - target: lpToken, - callData: WombatBmw.assetInterface.encodeFunctionData('pool'), - })); + inputs = []; + for (const lpToken of lpTokens) { + inputs.push({ + target: lpToken, + callData: + WombatBmw.assetInterface.encodeFunctionData('underlyingToken'), + }); + inputs.push({ + target: lpToken, + callData: WombatBmw.assetInterface.encodeFunctionData('pool'), + }); + } returnData = ( await this.dexHelper.multiContract.methods @@ -124,20 +135,43 @@ export class WombatBmw extends StatefulEventSubscriber { .call({}, blockNumber) ).returnData; - const pools = returnData - .map( - (data: BytesLike) => - WombatBmw.assetInterface.decodeFunctionResult('pool', data)[0], - ) - .map((pool: string) => pool.toLowerCase()); + const pool2AssetInfo = new Map>(); + let i = 0; + for (const lpToken of lpTokens) { + const underlyingToken = WombatBmw.assetInterface + .decodeFunctionResult('underlyingToken', returnData[i++])[0] + .toLowerCase(); + const pool = WombatBmw.assetInterface + .decodeFunctionResult('pool', returnData[i++])[0] + .toLowerCase(); + + if (!pool2AssetInfo.has(pool)) { + pool2AssetInfo.set(pool, new Map()); + } + pool2AssetInfo.get(pool)!.set(lpToken, underlyingToken); + } - const promises = []; - for (const pool of pools) { - if (!bmwState.pools.includes(pool)) { + inputs = []; + pool2AssetInfo.forEach((asset2TokenMap, pool) => { + inputs.push({ + target: pool, + callData: WombatBmw.poolInterface.encodeFunctionData( + 'creditForTokensHaircut', + ), + }); + }); + + returnData = await this.dexHelper.multiContract.methods + .tryAggregate(false, inputs) + .call({}, blockNumber); + i = 0; + pool2AssetInfo.forEach((asset2TokenMap, pool) => { + // don't add cross-chain pools + if (!returnData[i++].success) { bmwState.pools.push(pool); - promises.push(this.onPoolAdded(pool, blockNumber)); + this.onAssetAdded(pool, asset2TokenMap, blockNumber); } - } + }); return bmwState; } @@ -147,17 +181,37 @@ export class WombatBmw extends StatefulEventSubscriber { state: DeepReadonly, log: Readonly, ): Promise | null> { - const lpToken = event.args.lpToken.toString(); - const data = await this.dexHelper.web3Provider.eth.call({ - to: lpToken, - data: WombatBmw.assetInterface.encodeFunctionData('pool'), + const lpToken = event.args.lpToken.toString().toLowerCase(); + let multiCallInputs: MultiCallInput[] = []; + + multiCallInputs.push({ + target: lpToken, + callData: WombatBmw.assetInterface.encodeFunctionData('pool'), + }); + multiCallInputs.push({ + target: lpToken, + callData: WombatBmw.assetInterface.encodeFunctionData('underlyingToken'), }); + + const returnData = ( + await this.dexHelper.multiContract.methods + .aggregate(multiCallInputs) + .call({}, log.blockNumber) + ).returnData; + const pool = WombatBmw.assetInterface - .decodeFunctionResult('pool', data)[0] + .decodeFunctionResult('pool', returnData[0])[0] + .toLowerCase(); + const underlyingToken = WombatBmw.assetInterface + .decodeFunctionResult('underlyingToken', returnData[1])[0] .toLowerCase(); + this.onAssetAdded( + pool, + new Map().set(lpToken, underlyingToken), + log.blockNumber, + ); if (!state.pools.includes(pool)) { - await this.onPoolAdded(pool, log.blockNumber); return { pools: [...state.pools, pool], }; diff --git a/src/dex/wombat/wombat-events.test.ts b/src/dex/wombat/wombat-events.test.ts deleted file mode 100644 index ae297ded9..000000000 --- a/src/dex/wombat/wombat-events.test.ts +++ /dev/null @@ -1,125 +0,0 @@ -import dotenv from 'dotenv'; -dotenv.config(); - -import { DeepReadonly } from 'ts-essentials'; -import { WombatEventPool } from './wombat-pool'; -import { Network } from '../../constants'; -import { Address } from '../../types'; -import { DummyDexHelper } from '../../dex-helper'; -import { testEventSubscriber } from '../../../tests/utils-events'; -import { BmwState, PoolState } from './types'; -import { WombatConfig } from './config'; -import { Wombat } from './wombat'; -import { WombatBmw } from './wombat-bmw'; -/* - README - ====== - - This test script adds unit tests for Wombat event based - system. This is done by fetching the state on-chain before the - event block, manually pushing the block logs to the event-subscriber, - comparing the local state with on-chain state. - - Most of the logic for testing is abstracted by `testEventSubscriber`. - You need to do two things to make the tests work: - - 1. Fetch the block numbers where certain events were released. You - can modify the `./scripts/fetch-event-blocknumber.ts` to get the - block numbers for different events. Make sure to get sufficient - number of blockNumbers to cover all possible cases for the event - mutations. - - 2. Complete the implementation for fetchPoolState function. The - function should fetch the on-chain state of the event subscriber - using just the blocknumber. - - The template tests only include the test for a single event - subscriber. There can be cases where multiple event subscribers - exist for a single DEX. In such cases additional tests should be - added. - - You can run this individual test script by running: - `npx jest src/dex//-events.test.ts` - - (This comment should be removed from the final implementation) -*/ - -// npx jest src/dex/wombat/wombat-events.test.ts -jest.setTimeout(100 * 1000); - -async function fetchPoolState( - wombatPool: WombatEventPool, - blockNumber: number, -): Promise> { - return await wombatPool.generateState(blockNumber); -} -async function fetchBmwState( - wombatBmw: WombatBmw, - blockNumber: number, -): Promise> { - return await wombatBmw.generateState(blockNumber); -} -// eventName -> blockNumbers -type EventMappings = Record; - -describe('Wombat EventPool BSC', function () { - const dexKey = 'Wombat'; - const network = Network.BSC; - const dexHelper = new DummyDexHelper(network); - const logger = dexHelper.getLogger(dexKey); - let wombatPool: WombatEventPool; - const bmwAddress = WombatConfig.Wombat[Network.BSC].bmwAddress; - const eventsToTest: Record = { - [bmwAddress]: { - Add: [24685640, 24685642, 24685644, 24685646, 24685647, 24685649], - }, - }; - - const wombat = new Wombat(network, dexKey, dexHelper); - - for (const [poolAddress, events] of Object.entries(eventsToTest)) { - describe(`Events for ${poolAddress}`, () => { - for (const [eventName, blockNumbers] of Object.entries(events)) { - describe(`${eventName}`, () => { - for (const blockNumber of blockNumbers) { - it(`State after ${blockNumber}`, async function () { - // let cfgInfo = getSavedConfig( - // blockNumber, - // dexKey, - // ); - // - // cfgInfo = undefined; - // if (!cfgInfo) { - // const dex = new Wombat(network, dexKey, dexHelper); - // cfgInfo = await dex.generateConfigInfo(blockNumber); - // saveConfig(blockNumber, dexKey, cfgInfo); - // } - - // wombatPool = new WombatEventPool( - // dexKey, - // 'Main Pool', - // network, - // dexHelper, - // logger, - // poolAddress.toLowerCase(), - // ); - - await testEventSubscriber( - wombat.bmw, - wombat.bmw.addressesSubscribed, - (_blockNumber: number) => - fetchBmwState(wombat.bmw, _blockNumber), - blockNumber, - `${dexKey}_${bmwAddress}`, - dexHelper.provider, - ); - }); - // }); - } - }); - } - // ); - }); - } - // ); -}); diff --git a/src/dex/wombat/wombat-integration.test.ts b/src/dex/wombat/wombat-integration.test.ts index 2a78e7ac2..64b1443aa 100644 --- a/src/dex/wombat/wombat-integration.test.ts +++ b/src/dex/wombat/wombat-integration.test.ts @@ -231,7 +231,7 @@ describe('Wombat', function () { destTokenSymbol, SwapSide.SELL, amountsForSell, - 'quotePotentialSwap', // TODO: Put here proper function name to check pricing + 'quotePotentialSwap', ); }); @@ -245,7 +245,7 @@ describe('Wombat', function () { destTokenSymbol, SwapSide.BUY, amountsForBuy, - 'quotePotentialSwap', // TODO: Put here proper function name to check pricing + 'quotePotentialSwap', ); }); diff --git a/src/dex/wombat/wombat-pool.ts b/src/dex/wombat/wombat-pool.ts index aacc24d21..5514e0743 100644 --- a/src/dex/wombat/wombat-pool.ts +++ b/src/dex/wombat/wombat-pool.ts @@ -1,190 +1,152 @@ import { Interface } from '@ethersproject/abi'; -import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; -import { - Address, - Log, - Logger, - MultiCallInput, - MultiCallOutput, -} from '../../types'; -import { catchParseLogError } from '../../utils'; -import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { Address } from '@paraswap/core'; +import _ from 'lodash'; + +import { MultiCallParams, MultiResult } from '../../lib/multi-wrapper'; import { IDexHelper } from '../../dex-helper'; -import { AssetState, PoolState } from './types'; +import { StatefulRpcPoller } from '../../lib/stateful-rpc-poller/stateful-rpc-poller'; +import { StatePollingManager } from '../../lib/stateful-rpc-poller/state-polling-manager'; +import { ObjWithUpdateInfo } from '../../lib/stateful-rpc-poller/types'; +import { pollingManagerCbExtractor } from '../../lib/stateful-rpc-poller/utils'; +import { + addressArrayDecode, + booleanDecode, + uint256ToBigInt, + uint8ToNumber, +} from '../../lib/decoders'; import PoolABI from '../../abi/wombat/pool.json'; import AssetABI from '../../abi/wombat/asset.json'; +import { uint120ToBigInt } from './utils'; +import { AssetState, MulticallResultOutputs, PoolState } from './types'; -export class WombatEventPool extends StatefulEventSubscriber { +export class WombatPool extends StatefulRpcPoller< + PoolState, + MulticallResultOutputs +> { static readonly poolInterface = new Interface(PoolABI); static readonly assetInterface = new Interface(AssetABI); - private readonly logDecoder: (log: Log) => any; - private handlers: { - [event: string]: ( - event: any, - state: DeepReadonly, - log: Readonly, - ) => AsyncOrSync | null>; - } = {}; - - blankState: PoolState = { - asset: {}, - underlyingAddresses: [], - params: { - paused: false, - ampFactor: 0n, - haircutRate: 0n, - startCovRatio: 0n, - endCovRatio: 0n, - }, - }; - constructor( dexKey: string, - name: string, - protected network: number, - protected dexHelper: IDexHelper, - logger: Logger, + poolIdentifier: string, + dexHelper: IDexHelper, protected poolAddress: Address, + protected asset2TokenMap: Map, ) { - super( - `${dexKey} ${name}`, - `${dexKey}-${network} ${name}`, - dexHelper, - logger, + const callbacks = pollingManagerCbExtractor( + StatePollingManager.getInstance(dexHelper), ); - this.logDecoder = (log: Log) => WombatEventPool.poolInterface.parseLog(log); - this.addressesSubscribed = [this.poolAddress]; - - // users-actions handlers - this.handlers['Deposit'] = this.handleDeposit.bind(this); - this.handlers['Withdraw'] = this.handleWithdraw.bind(this); - this.handlers['Swap'] = this.handleSwap.bind(this); - - // admin-actions handlers - this.handlers['SetAmpFactor'] = this.handleSetAmpFactor.bind(this); - this.handlers['SetHaircutRate'] = this.handleSetHaircutRate.bind(this); - - this.handlers['AssetAdded'] = this.handleAssetAdded.bind(this); - this.handlers['AssetRemoved'] = this.handleAssetRemoved.bind(this); + super(dexKey, poolIdentifier, dexHelper, 0, 0, false, callbacks); } - /** - * The function is called every time any of the subscribed - * addresses release log. The function accepts the current - * state, updates the state according to the log, and returns - * the updated state. - * @param state - Current state of event subscriber - * @param log - Log released by one of the subscribed addresses - * @returns Updates state of the event subscriber after the log - */ - protected async processLog( - state: DeepReadonly, - log: Readonly, - ): Promise | null> { - try { - const event = this.logDecoder(log); - if (event.name in this.handlers) { - return await this.handlers[event.name](event, state, log); - } - } catch (e) { - catchParseLogError(e, this.logger); - } + protected _getFetchStateMultiCalls(): MultiCallParams[] { + const params: MultiCallParams[] = []; - return null; - } - - /** - * The function generates state using on-chain calls. This - * function is called to regenerate state if the event based - * system fails to fetch events and the local state is no - * more correct. - * @param blockNumber - Blocknumber for which the state should - * should be generated - * @returns state of the event subscriber at blocknumber - */ - async generateState(blockNumber: number): Promise> { - let multiCallInputs: MultiCallInput[] = []; - // 1 A. pool params - // paused - multiCallInputs.push({ + params.push({ target: this.poolAddress, - callData: WombatEventPool.poolInterface.encodeFunctionData('paused'), + callData: WombatPool.poolInterface.encodeFunctionData('paused'), + decodeFunction: booleanDecode, }); - // ampFactor - multiCallInputs.push({ + params.push({ target: this.poolAddress, - callData: WombatEventPool.poolInterface.encodeFunctionData('ampFactor'), + callData: WombatPool.poolInterface.encodeFunctionData('ampFactor'), + decodeFunction: uint256ToBigInt, }); - // haircutRate - multiCallInputs.push({ + params.push({ target: this.poolAddress, - callData: WombatEventPool.poolInterface.encodeFunctionData('haircutRate'), + callData: WombatPool.poolInterface.encodeFunctionData('haircutRate'), + decodeFunction: uint256ToBigInt, }); - // startCovRatio - multiCallInputs.push({ + params.push({ target: this.poolAddress, - callData: - WombatEventPool.poolInterface.encodeFunctionData('startCovRatio'), + callData: WombatPool.poolInterface.encodeFunctionData('startCovRatio'), + decodeFunction: uint256ToBigInt, }); - // endCovRatio - multiCallInputs.push({ + params.push({ target: this.poolAddress, - callData: WombatEventPool.poolInterface.encodeFunctionData('endCovRatio'), + callData: WombatPool.poolInterface.encodeFunctionData('endCovRatio'), + decodeFunction: uint256ToBigInt, }); - // tokens - multiCallInputs.push({ + params.push({ target: this.poolAddress, - callData: WombatEventPool.poolInterface.encodeFunctionData('getTokens'), + callData: WombatPool.poolInterface.encodeFunctionData('getTokens'), + decodeFunction: addressArrayDecode, }); - // 2. Decode MultiCallOutput - let returnData: MultiCallOutput[] = []; - if (multiCallInputs.length) { - returnData = ( - await this.dexHelper.multiContract.methods - .aggregate(multiCallInputs) - .call({}, blockNumber) - ).returnData; - } + this.asset2TokenMap.forEach((token, asset) => { + params.push({ + target: this.poolAddress, + callData: WombatPool.poolInterface.encodeFunctionData('isPaused', [ + token, + ]), + decodeFunction: booleanDecode, + }); + params.push({ + target: asset, + callData: WombatPool.assetInterface.encodeFunctionData('cash'), + decodeFunction: uint120ToBigInt, + }); + params.push({ + target: asset, + callData: WombatPool.assetInterface.encodeFunctionData('liability'), + decodeFunction: uint120ToBigInt, + }); + params.push({ + target: asset, + callData: WombatPool.assetInterface.encodeFunctionData( + 'underlyingTokenDecimals', + ), + decodeFunction: uint8ToNumber, + }); + params.push({ + target: asset, + callData: + WombatPool.assetInterface.encodeFunctionData('getRelativePrice'), + decodeFunction: uint256ToBigInt, + }); + }); - let i = 0; - // 2 A. decode pool params - const paused = Boolean( - WombatEventPool.poolInterface.decodeFunctionResult( - 'paused', - returnData[i++], - )[0], - ); - const ampFactor = BigInt( - WombatEventPool.poolInterface.decodeFunctionResult( - 'ampFactor', - returnData[i++], - )[0], - ); - const haircutRate = BigInt( - WombatEventPool.poolInterface.decodeFunctionResult( - 'haircutRate', - returnData[i++], - )[0], - ); - const startCovRatio = BigInt( - WombatEventPool.poolInterface.decodeFunctionResult( - 'startCovRatio', - returnData[i++], - )[0], - ); - const endCovRatio = BigInt( - WombatEventPool.poolInterface.decodeFunctionResult( - 'endCovRatio', - returnData[i++], - )[0], - ); + return params; + } + + protected _parseStateFromMultiResults( + multiOutputs: MulticallResultOutputs[], + ): PoolState { + const [ + paused, + ampFactor, + haircutRate, + startCovRatio, + endCovRatio, + tokens, + ...remained + ] = multiOutputs as [ + boolean, + bigint, + bigint, + bigint, + bigint, + Address[], + ...MulticallResultOutputs[], + ]; - const tokens = WombatEventPool.poolInterface - .decodeFunctionResult('getTokens', returnData[i++])[0] - .map((tokenAddress: Address) => tokenAddress.toLowerCase()); + const assetTokenArray = Array.from(this.asset2TokenMap.entries()); + const token2AssetStates = new Map(); + _.chunk(remained, 5).forEach((chunk, i) => { + const [paused, cash, liability, underlyingTokenDecimals, relativePrice] = + chunk as [boolean, bigint, bigint, number, bigint | undefined]; + + const [asset, token] = assetTokenArray[i]; + token2AssetStates.set(token, { + address: asset, + paused, + cash, + liability, + underlyingTokenDecimals, + relativePrice, + }); + }); const poolState: PoolState = { params: { @@ -198,295 +160,72 @@ export class WombatEventPool extends StatefulEventSubscriber { asset: {}, }; - // 1 B. asset state: cash and liability - multiCallInputs = tokens.map((tokenAddress: Address) => ({ - target: this.poolAddress, - callData: WombatEventPool.poolInterface.encodeFunctionData( - 'addressOfAsset', - [tokenAddress], - ), - })); - - // 2. Decode MultiCallOutput - returnData = ( - await this.dexHelper.multiContract.methods - .aggregate(multiCallInputs) - .call({}, blockNumber) - ).returnData; - - const assets: Address[] = returnData.map(data => { - return WombatEventPool.poolInterface.decodeFunctionResult( - 'addressOfAsset', - data, - )[0]; - }); - - const assetState = await this.getAssetState( - this.poolAddress, - assets, - tokens, - blockNumber, - ); const isMainPool = - assetState.filter(asset => asset.relativePrice === undefined).length > 0; - for (let j = 0; j < tokens.length; j++) { + Array.from(token2AssetStates.values()).filter( + assetState => assetState.relativePrice === undefined, + ).length > 0; + for (const token of poolState.underlyingAddresses) { + if (!token2AssetStates.has(token)) { + // this happens when asset has been added to pool but is not added to BMW yet + continue; + } + poolState.asset[token] = token2AssetStates.get(token)!; if (isMainPool) { - assetState[j].relativePrice = undefined; + poolState.asset[token].relativePrice = undefined; } - poolState.asset[tokens[j]] = assetState[j]; } return poolState; } - handleDeposit( - event: any, - state: DeepReadonly, - _log: Readonly, - ): DeepReadonly | null { - const amountAdded = BigInt(event.args.amount.toString()); - const tokenAddress = event.args.token.toString(); - - return { - ...state, - asset: { - ...state.asset, - [tokenAddress]: { - cash: state.asset[tokenAddress].cash + amountAdded, - liability: state.asset[tokenAddress].liability + amountAdded, - }, - }, - }; - } - - handleWithdraw( - event: any, - state: DeepReadonly, - _log: Readonly, - ): DeepReadonly | null { - const amountWithdrew = BigInt(event.args.amount.toString()); - const tokenAddress = event.args.token.toString(); - - return { - ...state, - asset: { - ...state.asset, - [tokenAddress]: { - cash: state.asset[tokenAddress].cash - amountWithdrew, - liability: state.asset[tokenAddress].liability - amountWithdrew, - }, - }, - }; - } - - handleSwap( - event: any, - state: DeepReadonly, - _log: Readonly, - ): DeepReadonly | null { - const fromTokenAddress = event.args.fromToken.toString(); - const fromAmount = BigInt(event.args.fromAmount.toString()); - const toTokenAddress = event.args.toToken.toString(); - const toAmount = BigInt(event.args.toAmount.toString()); - - return { - ...state, - asset: { - ...state.asset, - [fromTokenAddress]: { - cash: state.asset[fromTokenAddress].cash + fromAmount, - }, - [toTokenAddress]: { - cash: state.asset[toTokenAddress].cash - toAmount, - }, - }, - }; - } - - handleSetAmpFactor( - event: any, - state: DeepReadonly, - _log: Readonly, - ): DeepReadonly | null { - const ampFactor = BigInt(event.args.value.toString()); - - return { - ...state, - params: { - ...state.params, - ampFactor, - }, - }; - } - - handleSetHaircutRate( - event: any, - state: DeepReadonly, - _log: Readonly, - ): DeepReadonly | null { - const haircutRate = BigInt(event.args.value.toString()); - - return { - ...state, - params: { - ...state.params, - haircutRate, - }, - }; - } - - async handleAssetAdded( - event: any, - state: DeepReadonly, - log: Readonly, - ): Promise | null> { - const token: Address = event.args.token.toString().toLowerCase(); - const asset: Address = event.args.asset.toString().toLowerCase(); - if (state.underlyingAddresses.includes(token)) { - return null; + public async fetchLatestStateFromRpc(): Promise | null> { + const multiCalls = this.getFetchStateWithBlockInfoMultiCalls(); + try { + const lastUpdatedAtMs = Date.now(); + const aggregatedResults = (await this.dexHelper.multiWrapper.tryAggregate< + number | MulticallResultOutputs + >( + false, + multiCalls as MultiCallParams[], + )) as [MultiResult, ...MultiResult[]]; + + return this.parseStateFromMultiResultsWithBlockInfo( + aggregatedResults, + lastUpdatedAtMs, + ); + } catch (e) { + this._logMessageWithSuppression('ERROR_FETCHING_STATE_FROM_RPC', e); } - const assetState = await this.getAssetState( - this.poolAddress, - [asset], - [token], - log.blockNumber, - ); - const poolState = { - ...state, - underlyingAddresses: [...state.underlyingAddresses, token], - asset: { - ...state.asset, - [token]: assetState[0], - }, - }; - - const isMainPool = - Object.values(poolState.asset).filter( - asset => asset.relativePrice === undefined, - ).length > 0; - if (isMainPool) { - for (const underlyingAddress of poolState.underlyingAddresses) { - poolState.asset[underlyingAddress] = { - ...poolState.asset[underlyingAddress], - relativePrice: undefined, - }; - } - } - return poolState; + return null; } - async handleAssetRemoved( - event: any, - state: DeepReadonly, - _log: Readonly, - ): Promise | null> { - const token = event.args.token.toString(); - if (!state.underlyingAddresses.includes(token)) { - return null; - } + public parseStateFromMultiResultsWithBlockInfo( + multiOutputs: [ + MultiResult, + ...MultiResult[], + ], + lastUpdatedAtMs: number, + ): ObjWithUpdateInfo { + const [blockNumber, ...outputsForAbstract] = multiOutputs.map((m, i) => { + return m.returnData; + }) as [number, ...MulticallResultOutputs[]]; return { - ...state, - underlyingAddresses: state.underlyingAddresses.filter( - underlyingAddress => underlyingAddress !== token, - ), - asset: { - ...state.asset, - [token]: undefined, - }, + value: this._parseStateFromMultiResults(outputsForAbstract), + blockNumber, + lastUpdatedAtMs, }; } - private async getAssetState( - pool: Address, - assets: Address[], - tokens: Address[], - blockNumber: number, - ): Promise { - const assetStates: AssetState[] = []; - const multiCallInputs: MultiCallInput[] = []; - - const methods = [ - 'cash', - 'liability', - 'underlyingTokenDecimals', - 'getRelativePrice', - ]; - - for (let i = 0; i < assets.length; i++) { - const asset = assets[i]; - const token = tokens[i]; - - multiCallInputs.push({ - target: pool, - callData: WombatEventPool.poolInterface.encodeFunctionData('isPaused', [ - token, - ]), - }); - - for (const method of methods) { - multiCallInputs.push({ - target: asset, - callData: WombatEventPool.assetInterface.encodeFunctionData(method), - }); - } - } - - const returnData = await this.dexHelper.multiContract.methods - .tryAggregate(false, multiCallInputs) - .call({}, blockNumber); - - for ( - let i = 0; - i < assets.length * (methods.length + 1); - i += methods.length + 1 - ) { - const paused = returnData[i].success - ? Boolean( - WombatEventPool.poolInterface.decodeFunctionResult( - 'isPaused', - returnData[i].returnData, - )[0], - ) - : false; - const cash = BigInt( - WombatEventPool.assetInterface.decodeFunctionResult( - methods[0], - returnData[i + 1].returnData, - )[0], - ); - const liability = BigInt( - WombatEventPool.assetInterface.decodeFunctionResult( - methods[1], - returnData[i + 2].returnData, - )[0], - ); - const underlyingTokenDecimals = - WombatEventPool.assetInterface.decodeFunctionResult( - methods[2], - returnData[i + 3].returnData, - )[0]; - - let relativePrice: bigint | undefined; - if (returnData[i + 4].success) { - relativePrice = BigInt( - WombatEventPool.assetInterface.decodeFunctionResult( - methods[3], - returnData[i + 4].returnData, - )[0], - ); + public addAssets(asset2TokenMap: Map) { + for (const [asset, token] of asset2TokenMap) { + if (this.asset2TokenMap.has(asset)) { + continue; } - assetStates.push({ - paused, - cash, - liability, - underlyingTokenDecimals, - relativePrice, - }); + this.asset2TokenMap.set(asset, token); + this._cachedMultiCallData = undefined; } - - return assetStates; } } diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index cfad02f9d..a16cf8c78 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -1,5 +1,6 @@ import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; import { Interface } from '@ethersproject/abi'; +import { SwapSide } from '@paraswap/core'; import { AdapterExchangeParam, @@ -21,28 +22,25 @@ import { getLocalDeadlineAsFriendlyPlaceholder, SimpleExchange, } from '../simple-exchange'; -import { Adapters, WombatConfig } from './config'; -import { WombatEventPool } from './wombat-pool'; +import { Adapters, LIQUIDITY_THRESHOLD_IN_USD, WombatConfig } from './config'; import PoolABI from '../../abi/wombat/pool.json'; import AssetABI from '../../abi/wombat/asset.json'; -import BmwABI from '../../abi/wombat/bmw.json'; import ERC20ABI from '../../abi/erc20.json'; -import { SwapSide } from '@paraswap/core'; import { WombatQuoter } from './wombat-quoter'; import { WombatBmw } from './wombat-bmw'; import { fromWad } from './utils'; +import { WombatPool } from './wombat-pool'; export class Wombat extends SimpleExchange implements IDex { // contract interfaces static readonly erc20Interface = new Interface(ERC20ABI); static readonly poolInterface = new Interface(PoolABI); static readonly assetInterface = new Interface(AssetABI); - static readonly bmwInterface = new Interface(BmwABI); protected config: DexParams; protected poolLiquidityUSD?: { [poolAddress: string]: number }; public bmw: WombatBmw; - public eventPools: { [poolAddress: string]: WombatEventPool } = {}; + public pools: { [poolAddress: string]: WombatPool } = {}; readonly hasConstantPriceLargeAmounts = false; readonly needWrapNative = true; @@ -72,12 +70,14 @@ export class Wombat extends SimpleExchange implements IDex { dexHelper, this.logger, this.config.bmwAddress, - this.onPoolAdded.bind(this), + this.onAssetAdded.bind(this), ); } async init(blockNumber: number) { - await this.bmw.initialize(blockNumber); + if (!this.bmw.isInitialized) { + await this.bmw.initialize(blockNumber); + } } // Initialize pricing is called once in the start of @@ -92,18 +92,21 @@ export class Wombat extends SimpleExchange implements IDex { } } - onPoolAdded = async (pool: Address, blockNumber: number): Promise => { - if (!this.eventPools[pool]) { - this.eventPools[pool] = new WombatEventPool( + onAssetAdded = ( + pool: Address, + asset2TokenMap: Map, + blockNumber: number, + ): void => { + if (!this.pools[pool]) { + this.pools[pool] = new WombatPool( this.dexKey, - pool, - this.network, + this.getPoolIdentifier(pool), this.dexHelper, - this.logger, pool, + asset2TokenMap, ); - - await this.eventPools[pool].initialize(blockNumber); + } else { + this.pools[pool].addAssets(asset2TokenMap); } }; @@ -123,11 +126,13 @@ export class Wombat extends SimpleExchange implements IDex { side: SwapSide, blockNumber: number, ): Promise { + await this.updatePoolState(); return ( await this.findPools( srcToken.address.toLowerCase(), destToken.address.toLowerCase(), blockNumber, + LIQUIDITY_THRESHOLD_IN_USD, ) ).map(p => this.getPoolIdentifier(p)); } @@ -148,59 +153,50 @@ export class Wombat extends SimpleExchange implements IDex { blockNumber: number, limitPools?: string[], ): Promise> { - if (!this.eventPools) { - this.logger.error( - `Missing event pools for ${this.dexKey} in getPricesVolume`, - ); + if (!this.pools) { + this.logger.error(`Missing pools for ${this.dexKey} in getPricesVolume`); return null; } const srcTokenAddress = srcToken.address.toLowerCase(); const destTokenAddress = destToken.address.toLowerCase(); if (srcTokenAddress === destTokenAddress) return null; - const pools = await this.findPools( - srcTokenAddress, - destTokenAddress, - blockNumber, - ); - return await Promise.all( - pools - .filter( - poolAddress => - !limitPools || - limitPools.includes(this.getPoolIdentifier(poolAddress)), - ) - .map(poolAddress => - (async () => { - let state = this.eventPools![poolAddress].getState(blockNumber); - if (!state) { - state = await this.eventPools![poolAddress].generateState( - blockNumber, - ); - this.eventPools![poolAddress].setState(state, blockNumber); - } - const [unit, ...prices] = this.computePrices( - srcTokenAddress, - destTokenAddress, - [getBigIntPow(srcToken.decimals), ...amounts], - side, - state, - ); - return { - prices, - unit, - data: { - exchange: poolAddress, - }, - poolAddresses: [poolAddress], - exchange: this.dexKey, - /** @todo specify gas cost */ - gasCost: 260 * 1000, - poolIdentifier: this.getPoolIdentifier(poolAddress), - }; - })(), - ), + const pools = ( + await this.findPools(srcTokenAddress, destTokenAddress, blockNumber) + ).filter( + poolAddress => + !limitPools || limitPools.includes(this.getPoolIdentifier(poolAddress)), ); + + const promises = []; + for (const poolAddress of pools) { + let state = await this.pools![poolAddress].getState(blockNumber); + if (!state) { + this.logger.error(`State is null in getPricesVolume`); + continue; + } + const [unit, ...prices] = this.computePrices( + srcTokenAddress, + destTokenAddress, + [getBigIntPow(srcToken.decimals), ...amounts], + side, + state.value, + ); + promises.push({ + prices, + unit, + data: { + exchange: poolAddress, + }, + poolAddresses: [poolAddress], + exchange: this.dexKey, + /** @todo specify gas cost */ + gasCost: 260 * 1000, + poolIdentifier: this.getPoolIdentifier(poolAddress), + }); + } + + return await Promise.all(promises); } // take PoolState to compute price @@ -226,22 +222,24 @@ export class Wombat extends SimpleExchange implements IDex { srcTokenAddress: Address, destTokenAddress: Address, blockNumber: number, + liquidityThresholdInUSD = 0, ): Promise { const pools: Address[] = []; - for (const [poolAddress, eventPool] of Object.entries(this.eventPools)) { - let state = eventPool.getState(blockNumber); - if (!state) { - state = await eventPool.generateState(blockNumber); - this.eventPools![poolAddress].setState(state, blockNumber); + for (const [poolAddress, pool] of Object.entries(this.pools)) { + let stateOj = await pool.getState(blockNumber); + if (!stateOj) { + this.logger.error(`State is null in findPools`); + continue; } + const state = stateOj.value; if ( state && !state.params.paused && state.asset[srcTokenAddress] && - state.asset[srcTokenAddress].liability > 0 && state.asset[destTokenAddress] && - state.asset[destTokenAddress].liability > 0 + (liquidityThresholdInUSD === 0 || + this.poolLiquidityUSD![poolAddress] > liquidityThresholdInUSD) ) { pools.push(poolAddress); } @@ -331,14 +329,21 @@ export class Wombat extends SimpleExchange implements IDex { const poolLiquidityUSD: { [poolAddress: string]: number } = {}; const usdPromises = []; const poolStates: { [poolAddress: string]: DeepReadonly } = {}; - for (const [poolAddress, eventPool] of Object.entries(this.eventPools)) { - let state = eventPool.getState(blockNumber); + const poolStateObjs = await Promise.all( + Object.values(this.pools).map(pool => pool.getState(blockNumber)), + ); + + for (const [poolAddress, pool] of Object.entries(this.pools)) { + const index = Object.keys(this.pools).indexOf(poolAddress); + let state = poolStateObjs[index]; if (!state) { - state = await eventPool.generateState(blockNumber); - eventPool.setState(state, blockNumber); + this.logger.error(`State of ${poolAddress} is null in updatePoolState`); + continue; } - poolStates[poolAddress] = state; - for (const [tokenAddress, assetState] of Object.entries(state.asset)) { + poolStates[poolAddress] = state.value; + for (const [tokenAddress, assetState] of Object.entries( + state.value.asset, + )) { usdPromises.push( this.dexHelper.getTokenUSDPrice( { @@ -376,17 +381,19 @@ export class Wombat extends SimpleExchange implements IDex { tokenAddress = tokenAddress.toLowerCase(); const pools: string[] = []; const poolStates: { [poolAddress: string]: DeepReadonly } = {}; - for (const [poolAddress, eventPool] of Object.entries(this.eventPools)) { - let state = eventPool.getState(blockNumber); + for (const [poolAddress, eventPool] of Object.entries(this.pools)) { + let state = await eventPool.getState(blockNumber); if (!state) { - state = await eventPool.generateState(blockNumber); - eventPool.setState(state, blockNumber); + this.logger.error( + `State of ${poolAddress} is null in getTopPoolsForToken`, + ); + continue; } if ( - state.underlyingAddresses.includes(tokenAddress) && + state.value.underlyingAddresses.includes(tokenAddress) && this.poolLiquidityUSD![poolAddress] ) { - poolStates[poolAddress] = state; + poolStates[poolAddress] = state.value; pools.push(poolAddress); } } From 76564c1a13711061895cbe081edb33e3b9b90393 Mon Sep 17 00:00:00 2001 From: Koala <142200506+koala0814@users.noreply.github.com> Date: Mon, 30 Oct 2023 17:33:53 +0800 Subject: [PATCH 554/833] add cross chain pool --- src/dex/wombat/wombat-bmw.ts | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/src/dex/wombat/wombat-bmw.ts b/src/dex/wombat/wombat-bmw.ts index 0985fd299..9bc13cf28 100644 --- a/src/dex/wombat/wombat-bmw.ts +++ b/src/dex/wombat/wombat-bmw.ts @@ -151,26 +151,9 @@ export class WombatBmw extends StatefulEventSubscriber { pool2AssetInfo.get(pool)!.set(lpToken, underlyingToken); } - inputs = []; - pool2AssetInfo.forEach((asset2TokenMap, pool) => { - inputs.push({ - target: pool, - callData: WombatBmw.poolInterface.encodeFunctionData( - 'creditForTokensHaircut', - ), - }); - }); - - returnData = await this.dexHelper.multiContract.methods - .tryAggregate(false, inputs) - .call({}, blockNumber); - i = 0; pool2AssetInfo.forEach((asset2TokenMap, pool) => { - // don't add cross-chain pools - if (!returnData[i++].success) { - bmwState.pools.push(pool); - this.onAssetAdded(pool, asset2TokenMap, blockNumber); - } + bmwState.pools.push(pool); + this.onAssetAdded(pool, asset2TokenMap, blockNumber); }); return bmwState; From 11d0a3183843c09a8438c59dbfd3db791897398e Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 30 Oct 2023 16:48:12 +0200 Subject: [PATCH 555/833] fix: add arbitrum integration tests --- src/dex/wombat/wombat-integration.test.ts | 125 +++++++++++++++++----- 1 file changed, 97 insertions(+), 28 deletions(-) diff --git a/src/dex/wombat/wombat-integration.test.ts b/src/dex/wombat/wombat-integration.test.ts index 64b1443aa..16b3e7459 100644 --- a/src/dex/wombat/wombat-integration.test.ts +++ b/src/dex/wombat/wombat-integration.test.ts @@ -16,21 +16,6 @@ import { Tokens } from '../../../tests/constants-e2e'; import { Token } from '../../types'; import { Address } from '@paraswap/core'; -/* - README - ====== - - This test script adds tests for Wombat general integration - with the DEX interface. The test cases below are example tests. - It is recommended to add tests which cover Wombat specific - logic. - - You can run this individual test script by running: - `npx jest src/dex//-integration.test.ts` - - (This comment should be removed from the final implementation) -*/ - function getReaderCalldata( exchangeAddress: string, readerIface: Interface, @@ -39,19 +24,13 @@ function getReaderCalldata( toToken: Token, amounts: bigint[], funcName: string, - // TODO: Put here additional arguments you need ) { return amounts.map(amount => ({ target: exchangeAddress, callData: readerIface.encodeFunctionData( funcName, side == SwapSide.SELL - ? [ - // TODO: Put here additional arguments to encode them - fromToken.address, - toToken.address, - amount, - ] + ? [fromToken.address, toToken.address, amount] : [toToken.address, fromToken.address, -amount], ), })); @@ -62,7 +41,6 @@ function decodeReaderResult( readerIface: Interface, funcName: string, ) { - // TODO: Adapt this function for your needs return results.map(result => { const parsed = readerIface.decodeFunctionResult(funcName, result); return BigInt(parsed[0]._hex); @@ -82,9 +60,6 @@ async function checkOnChainPricing( ) { const exchangeAddress = pool; // TODO: Put here the real exchange address - // TODO: Replace dummy interface with the real one - // Normally you can get it from wombat.Iface or from eventPool. - // It depends on your implementation const readerIface = Wombat.poolInterface; const readerCallData = getReaderCalldata( @@ -180,8 +155,102 @@ describe('Wombat', function () { const tokens = Tokens[network]; - // TODO: Put here token Symbol to check against - // Don't forget to update relevant tokens in constant-e2e.ts + const srcTokenSymbol = 'USDC'; + const destTokenSymbol = 'USDT'; + + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals], + 2n * BI_POWS[tokens[destTokenSymbol].decimals], + 3n * BI_POWS[tokens[destTokenSymbol].decimals], + 4n * BI_POWS[tokens[destTokenSymbol].decimals], + 5n * BI_POWS[tokens[destTokenSymbol].decimals], + 6n * BI_POWS[tokens[destTokenSymbol].decimals], + 7n * BI_POWS[tokens[destTokenSymbol].decimals], + 8n * BI_POWS[tokens[destTokenSymbol].decimals], + 9n * BI_POWS[tokens[destTokenSymbol].decimals], + 10n * BI_POWS[tokens[destTokenSymbol].decimals], + ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + wombat = new Wombat(network, dexKey, dexHelper); + if (wombat.initializePricing) { + await wombat.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + wombat, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + 'quotePotentialSwap', + ); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + wombat, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + 'quotePotentialSwap', + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newWombat = new Wombat(network, dexKey, dexHelper); + if (newWombat.updatePoolState) { + await newWombat.updatePoolState(); + } + const poolLiquidity = await newWombat.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newWombat.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); + }); + + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + const srcTokenSymbol = 'USDC'; const destTokenSymbol = 'USDT'; From 5d24aa1df8b8adb54f695281c8af88659e1cc2e2 Mon Sep 17 00:00:00 2001 From: 0xshoehazer <0xshoehazer@gmail.com> Date: Mon, 30 Oct 2023 10:54:14 -0400 Subject: [PATCH 556/833] integration test run --- src/dex/baseswap-v3/baseswap-v3-e2e.test.ts | 80 +-- .../baseswap-v3/baseswap-v3-events.test.ts | 0 .../baseswap-v3-integration.test.ts | 624 +++++++++--------- src/dex/baseswap-v3/baseswap-v3.test.ts | 472 ------------- src/dex/baseswap-v3/baseswap-v3.ts | 26 +- src/dex/baseswap-v3/config.ts | 12 +- 6 files changed, 366 insertions(+), 848 deletions(-) create mode 100644 src/dex/baseswap-v3/baseswap-v3-events.test.ts delete mode 100644 src/dex/baseswap-v3/baseswap-v3.test.ts diff --git a/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts b/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts index 52f1de51b..a0bac1b5a 100644 --- a/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts +++ b/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts @@ -114,7 +114,7 @@ import { generateConfig } from '../../config'; describe('BasewapV3 E2E', () => { describe('BasewapV3', () => { - const dexKey = 'basewapV3'; + const dexKey = 'BasewapV3'; describe('BaseswapV3 Base', () => { const network = Network.BASE; @@ -161,45 +161,45 @@ describe('BasewapV3 E2E', () => { provider, ); }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenBSymbol} -> ${tokenASymbol}`, async () => { - await testE2E( - tokens[tokenBSymbol], - tokens[tokenASymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenBAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); + // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + // await testE2E( + // tokens[tokenASymbol], + // tokens[nativeTokenSymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${network} ${side} ${contractMethod} ${tokenBSymbol} -> ${tokenASymbol}`, async () => { + // await testE2E( + // tokens[tokenBSymbol], + // tokens[tokenASymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenBAmount : tokenAAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); + // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + // await testE2E( + // tokens[tokenASymbol], + // tokens[tokenBSymbol], + // holders[tokenASymbol], + // side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + // side, + // dexKey, + // contractMethod, + // network, + // provider, + // ); + // }); }); }), ); diff --git a/src/dex/baseswap-v3/baseswap-v3-events.test.ts b/src/dex/baseswap-v3/baseswap-v3-events.test.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/dex/baseswap-v3/baseswap-v3-integration.test.ts b/src/dex/baseswap-v3/baseswap-v3-integration.test.ts index 058b71d2f..201d997cd 100644 --- a/src/dex/baseswap-v3/baseswap-v3-integration.test.ts +++ b/src/dex/baseswap-v3/baseswap-v3-integration.test.ts @@ -155,318 +155,318 @@ describe('BaseswapV3', function () { expect(pools.length).toBeGreaterThan(0); - // const poolPrices = await baseswapV3.getPricesVolume( - // TokenA, - // TokenB, - // amounts, - // SwapSide.SELL, - // blockNumber, - // pools, - // ); - // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - // expect(poolPrices).not.toBeNull(); - // checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); - - // let falseChecksCounter = 0; - // await Promise.all( - // poolPrices!.map(async price => { - // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; - // const res = await checkOnChainPricing( - // dexHelper, - // 'quoteExactInputSingle', - // blockNumber, - // QuoterV2, - // price.prices, - // TokenA.address, - // TokenB.address, - // fee, - // amounts, - // ); - // if (res === false) falseChecksCounter++; - // }), - // ); - - // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + const poolPrices = await baseswapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + 'quoteExactInputSingle', + blockNumber, + QuoterV2, + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + const pools = await baseswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await baseswapV3.getPricesVolume( + TokenA, + TokenB, + amountsBuy, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amountsBuy, SwapSide.BUY, dexKey); + + // Check if onchain pricing equals to calculated ones + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + 'quoteExactOutputSingle', + blockNumber, + QuoterV2, + price.prices, + TokenA.address, + TokenB.address, + fee, + amountsBuy, + ); + if (res === false) falseChecksCounter++; + }), + ); + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); }); - // it('getPoolIdentifiers and getPricesVolume BUY', async function () { - // const pools = await baseswapV3.getPoolIdentifiers( - // TokenA, - // TokenB, - // SwapSide.BUY, - // blockNumber, - // ); - // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - // expect(pools.length).toBeGreaterThan(0); - - // const poolPrices = await baseswapV3.getPricesVolume( - // TokenA, - // TokenB, - // amountsBuy, - // SwapSide.BUY, - // blockNumber, - // pools, - // ); - // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - // expect(poolPrices).not.toBeNull(); - // checkPoolPrices(poolPrices!, amountsBuy, SwapSide.BUY, dexKey); - - // // Check if onchain pricing equals to calculated ones - // let falseChecksCounter = 0; - // await Promise.all( - // poolPrices!.map(async price => { - // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; - // const res = await checkOnChainPricing( - // dexHelper, - // 'quoteExactOutputSingle', - // blockNumber, - // QuoterV2, - // price.prices, - // TokenA.address, - // TokenB.address, - // fee, - // amountsBuy, - // ); - // if (res === false) falseChecksCounter++; - // }), - // ); - // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - // }); - - // it('getPoolIdentifiers and getPricesVolume SELL stable pairs', async function () { - // const TokenASymbol = 'USDT'; - // const TokenA = Tokens[network][TokenASymbol]; - - // const TokenBSymbol = 'USDC'; - // const TokenB = Tokens[network][TokenBSymbol]; - - // const amounts = [ - // 0n, - // 6000000n, - // 12000000n, - // 18000000n, - // 24000000n, - // 30000000n, - // 36000000n, - // 42000000n, - // 48000000n, - // 54000000n, - // 60000000n, - // 66000000n, - // 72000000n, - // 78000000n, - // 84000000n, - // 90000000n, - // 96000000n, - // 102000000n, - // 108000000n, - // 114000000n, - // 120000000n, - // 126000000n, - // 132000000n, - // 138000000n, - // 144000000n, - // 150000000n, - // 156000000n, - // 162000000n, - // 168000000n, - // 174000000n, - // 180000000n, - // 186000000n, - // 192000000n, - // 198000000n, - // 204000000n, - // 210000000n, - // 216000000n, - // 222000000n, - // 228000000n, - // 234000000n, - // 240000000n, - // 246000000n, - // 252000000n, - // 258000000n, - // 264000000n, - // 270000000n, - // 276000000n, - // 282000000n, - // 288000000n, - // 294000000n, - // 300000000n, - // ]; - - // const pools = await baseswapV3.getPoolIdentifiers( - // TokenA, - // TokenB, - // SwapSide.SELL, - // blockNumber, - // ); - // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - // expect(pools.length).toBeGreaterThan(0); - - // const poolPrices = await baseswapV3.getPricesVolume( - // TokenA, - // TokenB, - // amounts, - // SwapSide.SELL, - // blockNumber, - // pools, - // ); - // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - // expect(poolPrices).not.toBeNull(); - // checkPoolPrices( - // poolPrices!.filter(pp => pp.unit !== 0n), - // amounts, - // SwapSide.SELL, - // dexKey, - // ); - - // // Check if onchain pricing equals to calculated ones - // let falseChecksCounter = 0; - // await Promise.all( - // poolPrices!.map(async price => { - // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; - // const res = await checkOnChainPricing( - // dexHelper, - // 'quoteExactInputSingle', - // blockNumber, - // QuoterV2, - // price.prices, - // TokenA.address, - // TokenB.address, - // fee, - // amounts, - // ); - // if (res === false) falseChecksCounter++; - // }), - // ); - // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - // }); - - // it('getPoolIdentifiers and getPricesVolume BUY stable pairs', async function () { - // const TokenASymbol = 'DAI'; - // const TokenA = Tokens[network][TokenASymbol]; - - // const TokenBSymbol = 'USDC'; - // const TokenB = Tokens[network][TokenBSymbol]; - - // const amountsBuy = [ - // 0n, - // 6000000n, - // 12000000n, - // 18000000n, - // 24000000n, - // 30000000n, - // 36000000n, - // 42000000n, - // 48000000n, - // 54000000n, - // 60000000n, - // 66000000n, - // 72000000n, - // 78000000n, - // 84000000n, - // 90000000n, - // 96000000n, - // 102000000n, - // 108000000n, - // 114000000n, - // 120000000n, - // 126000000n, - // 132000000n, - // 138000000n, - // 144000000n, - // 150000000n, - // 156000000n, - // 162000000n, - // 168000000n, - // 174000000n, - // 180000000n, - // 186000000n, - // 192000000n, - // 198000000n, - // 204000000n, - // 210000000n, - // 216000000n, - // 222000000n, - // 228000000n, - // 234000000n, - // 240000000n, - // 246000000n, - // 252000000n, - // 258000000n, - // 264000000n, - // 270000000n, - // 276000000n, - // 282000000n, - // 288000000n, - // 294000000n, - // 300000000n, - // ]; - - // const pools = await baseswapV3.getPoolIdentifiers( - // TokenA, - // TokenB, - // SwapSide.BUY, - // blockNumber, - // ); - // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - // expect(pools.length).toBeGreaterThan(0); - - // const poolPrices = await baseswapV3.getPricesVolume( - // TokenA, - // TokenB, - // amountsBuy, - // SwapSide.BUY, - // blockNumber, - // pools, - // ); - // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - // expect(poolPrices).not.toBeNull(); - // checkPoolPrices( - // poolPrices!.filter(pp => pp.unit !== 0n), - // amountsBuy, - // SwapSide.BUY, - // dexKey, - // ); - - // // Check if onchain pricing equals to calculated ones - // let falseChecksCounter = 0; - // await Promise.all( - // poolPrices!.map(async price => { - // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; - // const res = await checkOnChainPricing( - // dexHelper, - // 'quoteExactOutputSingle', - // blockNumber, - // QuoterV2, - // price.prices, - // TokenA.address, - // TokenB.address, - // fee, - // amountsBuy, - // ); - // if (res === false) falseChecksCounter++; - // }), - // ); - // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - // }); - - // it('getTopPoolsForToken', async function () { - // const poolLiquidity = await baseswapV3Mainnet.getTopPoolsForToken( - // Tokens[Network.BASE]['USDC'].address, - // 10, - // ); - // console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); - - // if (!baseswapV3.hasConstantPriceLargeAmounts) { - // checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); - // } - // }); + it('getPoolIdentifiers and getPricesVolume SELL stable pairs', async function () { + const TokenASymbol = 'USDbC'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDC'; + const TokenB = Tokens[network][TokenBSymbol]; + + const amounts = [ + 0n, + 6000000n, + 12000000n, + 18000000n, + 24000000n, + 30000000n, + 36000000n, + 42000000n, + 48000000n, + 54000000n, + 60000000n, + 66000000n, + 72000000n, + 78000000n, + 84000000n, + 90000000n, + 96000000n, + 102000000n, + 108000000n, + 114000000n, + 120000000n, + 126000000n, + 132000000n, + 138000000n, + 144000000n, + 150000000n, + 156000000n, + 162000000n, + 168000000n, + 174000000n, + 180000000n, + 186000000n, + 192000000n, + 198000000n, + 204000000n, + 210000000n, + 216000000n, + 222000000n, + 228000000n, + 234000000n, + 240000000n, + 246000000n, + 252000000n, + 258000000n, + 264000000n, + 270000000n, + 276000000n, + 282000000n, + 288000000n, + 294000000n, + 300000000n, + ]; + + const pools = await baseswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await baseswapV3.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices( + poolPrices!.filter(pp => pp.unit !== 0n), + amounts, + SwapSide.SELL, + dexKey, + ); + + // Check if onchain pricing equals to calculated ones + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + 'quoteExactInputSingle', + blockNumber, + QuoterV2, + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume BUY stable pairs', async function () { + const TokenASymbol = 'DAI'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDC'; + const TokenB = Tokens[network][TokenBSymbol]; + + const amountsBuy = [ + 0n, + 6000000n, + 12000000n, + 18000000n, + 24000000n, + 30000000n, + 36000000n, + 42000000n, + 48000000n, + 54000000n, + 60000000n, + 66000000n, + 72000000n, + 78000000n, + 84000000n, + 90000000n, + 96000000n, + 102000000n, + 108000000n, + 114000000n, + 120000000n, + 126000000n, + 132000000n, + 138000000n, + 144000000n, + 150000000n, + 156000000n, + 162000000n, + 168000000n, + 174000000n, + 180000000n, + 186000000n, + 192000000n, + 198000000n, + 204000000n, + 210000000n, + 216000000n, + 222000000n, + 228000000n, + 234000000n, + 240000000n, + 246000000n, + 252000000n, + 258000000n, + 264000000n, + 270000000n, + 276000000n, + 282000000n, + 288000000n, + 294000000n, + 300000000n, + ]; + + const pools = await baseswapV3.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await baseswapV3.getPricesVolume( + TokenA, + TokenB, + amountsBuy, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices( + poolPrices!.filter(pp => pp.unit !== 0n), + amountsBuy, + SwapSide.BUY, + dexKey, + ); + + // Check if onchain pricing equals to calculated ones + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + 'quoteExactOutputSingle', + blockNumber, + QuoterV2, + price.prices, + TokenA.address, + TokenB.address, + fee, + amountsBuy, + ); + if (res === false) falseChecksCounter++; + }), + ); + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getTopPoolsForToken', async function () { + const poolLiquidity = await baseswapV3Mainnet.getTopPoolsForToken( + Tokens[Network.BASE]['USDC'].address, + 10, + ); + console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + if (!baseswapV3.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); + } + }); }); diff --git a/src/dex/baseswap-v3/baseswap-v3.test.ts b/src/dex/baseswap-v3/baseswap-v3.test.ts deleted file mode 100644 index 8147683c2..000000000 --- a/src/dex/baseswap-v3/baseswap-v3.test.ts +++ /dev/null @@ -1,472 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); - -import { Interface, Result } from '@ethersproject/abi'; -import { DummyDexHelper, IDexHelper } from '../../dex-helper/index'; -import { Network, SwapSide } from '../../constants'; -import { BI_POWS } from '../../bigint-constants'; -import { BaseswapV3 } from './baseswap-v3'; -import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; -import { Tokens } from '../../../tests/constants-e2e'; -import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; -import { Address } from '@paraswap/core'; - -const network = Network.BASE; -const TokenASymbol = 'USDC'; -const TokenA = Tokens[network][TokenASymbol]; - -const QuoterV2 = '0x4fDBD73aD4B1DDde594BF05497C15f76308eFfb9'; - -const TokenBSymbol = 'WETH'; -const TokenB = Tokens[network][TokenBSymbol]; - -const amounts = [ - 0n, - 10_000n * BI_POWS[6], - 20_000n * BI_POWS[6], - 30_000n * BI_POWS[6], -]; - -const amountsBuy = [0n, 1n * BI_POWS[18], 2n * BI_POWS[18], 3n * BI_POWS[18]]; - -const quoterIface = new Interface(UniswapV3QuoterV2ABI); - -function getReaderCalldata( - exchangeAddress: string, - readerIface: Interface, - amounts: bigint[], - funcName: string, - tokenIn: Address, - tokenOut: Address, - fee: bigint, -) { - return amounts.map(amount => ({ - target: exchangeAddress, - callData: readerIface.encodeFunctionData(funcName, [ - [tokenIn, tokenOut, amount.toString(), fee.toString(), 0], - ]), - })); -} - -function decodeReaderResult( - results: Result, - readerIface: Interface, - funcName: string, -) { - return results.map(result => { - const parsed = readerIface.decodeFunctionResult(funcName, result); - return BigInt(parsed[0]._hex); - }); -} - -async function checkOnChainPricing( - dexHelper: IDexHelper, - funcName: string, - blockNumber: number, - exchangeAddress: string, - prices: bigint[], - tokenIn: Address, - tokenOut: Address, - fee: bigint, - _amounts: bigint[], -) { - // const exchangeAddress = '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'; - const readerIface = quoterIface; - - const sum = prices.reduce((acc, curr) => (acc += curr), 0n); - - if (sum === 0n) { - console.log( - `Prices were not calculated for tokenIn=${tokenIn}, tokenOut=${tokenOut}, fee=${fee.toString()}. Most likely price impact is too big for requested amount`, - ); - return false; - } - - const readerCallData = getReaderCalldata( - exchangeAddress, - readerIface, - _amounts.slice(1), - funcName, - tokenIn, - tokenOut, - fee, - ); - - let readerResult; - try { - readerResult = ( - await dexHelper.multiContract.methods - .aggregate(readerCallData) - .call({}, blockNumber) - ).returnData; - } catch (e) { - console.log( - `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, - e, - ); - return false; - } - - const expectedPrices = [0n].concat( - decodeReaderResult(readerResult, readerIface, funcName), - ); - - console.log('EXPECTED PRICES: ', expectedPrices); - - let firstZeroIndex = prices.slice(1).indexOf(0n); - - // we skipped first, so add +1 on result - firstZeroIndex = firstZeroIndex === -1 ? prices.length : firstZeroIndex; - - // Compare only the ones for which we were able to calculate prices - expect(prices.slice(0, firstZeroIndex)).toEqual( - expectedPrices.slice(0, firstZeroIndex), - ); - return true; -} - -describe('BaseswapV3', function () { - const dexHelper = new DummyDexHelper(network); - const dexKey = 'BaseswapV3'; - - let blockNumber: number; - let baseswapV3: BaseswapV3; - let baseswapV3Mainnet: BaseswapV3; - - beforeEach(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - baseswapV3 = new BaseswapV3(network, dexKey, dexHelper); - baseswapV3Mainnet = new BaseswapV3( - Network.BASE, - dexKey, - new DummyDexHelper(Network.BASE), - ); - }); - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - const pools = await baseswapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.SELL, - blockNumber, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await baseswapV3.getPricesVolume( - TokenA, - TokenB, - amounts, - SwapSide.SELL, - blockNumber, - pools, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); - - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - dexHelper, - 'quoteExactInputSingle', - blockNumber, - QuoterV2, - price.prices, - TokenA.address, - TokenB.address, - fee, - amounts, - ); - if (res === false) falseChecksCounter++; - }), - ); - - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - // it('getPoolIdentifiers and getPricesVolume BUY', async function () { - // const pools = await baseswapV3.getPoolIdentifiers( - // TokenA, - // TokenB, - // SwapSide.BUY, - // blockNumber, - // ); - // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - // expect(pools.length).toBeGreaterThan(0); - - // const poolPrices = await baseswapV3.getPricesVolume( - // TokenA, - // TokenB, - // amountsBuy, - // SwapSide.BUY, - // blockNumber, - // pools, - // ); - // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - // expect(poolPrices).not.toBeNull(); - // checkPoolPrices(poolPrices!, amountsBuy, SwapSide.BUY, dexKey); - - // // Check if onchain pricing equals to calculated ones - // let falseChecksCounter = 0; - // await Promise.all( - // poolPrices!.map(async price => { - // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; - // const res = await checkOnChainPricing( - // dexHelper, - // 'quoteExactOutputSingle', - // blockNumber, - // QuoterV2, - // price.prices, - // TokenA.address, - // TokenB.address, - // fee, - // amountsBuy, - // ); - // if (res === false) falseChecksCounter++; - // }), - // ); - // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - // }); - - // it('getPoolIdentifiers and getPricesVolume SELL stable pairs', async function () { - // const TokenASymbol = 'USDT'; - // const TokenA = Tokens[network][TokenASymbol]; - - // const TokenBSymbol = 'USDC'; - // const TokenB = Tokens[network][TokenBSymbol]; - - // const amounts = [ - // 0n, - // 6000000n, - // 12000000n, - // 18000000n, - // 24000000n, - // 30000000n, - // 36000000n, - // 42000000n, - // 48000000n, - // 54000000n, - // 60000000n, - // 66000000n, - // 72000000n, - // 78000000n, - // 84000000n, - // 90000000n, - // 96000000n, - // 102000000n, - // 108000000n, - // 114000000n, - // 120000000n, - // 126000000n, - // 132000000n, - // 138000000n, - // 144000000n, - // 150000000n, - // 156000000n, - // 162000000n, - // 168000000n, - // 174000000n, - // 180000000n, - // 186000000n, - // 192000000n, - // 198000000n, - // 204000000n, - // 210000000n, - // 216000000n, - // 222000000n, - // 228000000n, - // 234000000n, - // 240000000n, - // 246000000n, - // 252000000n, - // 258000000n, - // 264000000n, - // 270000000n, - // 276000000n, - // 282000000n, - // 288000000n, - // 294000000n, - // 300000000n, - // ]; - - // const pools = await baseswapV3.getPoolIdentifiers( - // TokenA, - // TokenB, - // SwapSide.SELL, - // blockNumber, - // ); - // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - // expect(pools.length).toBeGreaterThan(0); - - // const poolPrices = await baseswapV3.getPricesVolume( - // TokenA, - // TokenB, - // amounts, - // SwapSide.SELL, - // blockNumber, - // pools, - // ); - // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - // expect(poolPrices).not.toBeNull(); - // checkPoolPrices( - // poolPrices!.filter(pp => pp.unit !== 0n), - // amounts, - // SwapSide.SELL, - // dexKey, - // ); - - // // Check if onchain pricing equals to calculated ones - // let falseChecksCounter = 0; - // await Promise.all( - // poolPrices!.map(async price => { - // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; - // const res = await checkOnChainPricing( - // dexHelper, - // 'quoteExactInputSingle', - // blockNumber, - // QuoterV2, - // price.prices, - // TokenA.address, - // TokenB.address, - // fee, - // amounts, - // ); - // if (res === false) falseChecksCounter++; - // }), - // ); - // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - // }); - - // it('getPoolIdentifiers and getPricesVolume BUY stable pairs', async function () { - // const TokenASymbol = 'DAI'; - // const TokenA = Tokens[network][TokenASymbol]; - - // const TokenBSymbol = 'USDC'; - // const TokenB = Tokens[network][TokenBSymbol]; - - // const amountsBuy = [ - // 0n, - // 6000000n, - // 12000000n, - // 18000000n, - // 24000000n, - // 30000000n, - // 36000000n, - // 42000000n, - // 48000000n, - // 54000000n, - // 60000000n, - // 66000000n, - // 72000000n, - // 78000000n, - // 84000000n, - // 90000000n, - // 96000000n, - // 102000000n, - // 108000000n, - // 114000000n, - // 120000000n, - // 126000000n, - // 132000000n, - // 138000000n, - // 144000000n, - // 150000000n, - // 156000000n, - // 162000000n, - // 168000000n, - // 174000000n, - // 180000000n, - // 186000000n, - // 192000000n, - // 198000000n, - // 204000000n, - // 210000000n, - // 216000000n, - // 222000000n, - // 228000000n, - // 234000000n, - // 240000000n, - // 246000000n, - // 252000000n, - // 258000000n, - // 264000000n, - // 270000000n, - // 276000000n, - // 282000000n, - // 288000000n, - // 294000000n, - // 300000000n, - // ]; - - // const pools = await baseswapV3.getPoolIdentifiers( - // TokenA, - // TokenB, - // SwapSide.BUY, - // blockNumber, - // ); - // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - // expect(pools.length).toBeGreaterThan(0); - - // const poolPrices = await baseswapV3.getPricesVolume( - // TokenA, - // TokenB, - // amountsBuy, - // SwapSide.BUY, - // blockNumber, - // pools, - // ); - // console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - // expect(poolPrices).not.toBeNull(); - // checkPoolPrices( - // poolPrices!.filter(pp => pp.unit !== 0n), - // amountsBuy, - // SwapSide.BUY, - // dexKey, - // ); - - // // Check if onchain pricing equals to calculated ones - // let falseChecksCounter = 0; - // await Promise.all( - // poolPrices!.map(async price => { - // const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; - // const res = await checkOnChainPricing( - // dexHelper, - // 'quoteExactOutputSingle', - // blockNumber, - // QuoterV2, - // price.prices, - // TokenA.address, - // TokenB.address, - // fee, - // amountsBuy, - // ); - // if (res === false) falseChecksCounter++; - // }), - // ); - // expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - // }); - - // it('getTopPoolsForToken', async function () { - // const poolLiquidity = await baseswapV3Mainnet.getTopPoolsForToken( - // Tokens[Network.BASE]['USDC'].address, - // 10, - // ); - // console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); - - // if (!baseswapV3.hasConstantPriceLargeAmounts) { - // checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); - // } - // }); -}); diff --git a/src/dex/baseswap-v3/baseswap-v3.ts b/src/dex/baseswap-v3/baseswap-v3.ts index b5cad4b15..e4c9e06a1 100644 --- a/src/dex/baseswap-v3/baseswap-v3.ts +++ b/src/dex/baseswap-v3/baseswap-v3.ts @@ -75,9 +75,9 @@ type PoolPairsInfo = { fee: string; }; -const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 3 * 24 * 60 * 60 * 1000; // 3 days -const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 24 * 60 * 60 * 1000; // Once in a day -const UNISWAPV3_QUOTE_GASLIMIT = 200_000; +const BASESWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 3 * 24 * 60 * 60 * 1000; // 3 days +const BASESWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 24 * 60 * 60 * 1000; // Once in a day +const BASESWAPV3_QUOTE_GASLIMIT = 200_000; export class BaseswapV3 extends SimpleExchange @@ -95,17 +95,7 @@ export class BaseswapV3 intervalTask?: NodeJS.Timeout; public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork( - _.pick(BaseswapV3Config, [ - 'BaseswapV3', - // 'UniswapV3', - // 'SushiSwapV3', - // 'QuickSwapV3.1', - // 'RamsesV2', - // 'ChronosV3', - // 'Retro', - ]), - ); + getDexKeysWithNetwork(_.pick(BaseswapV3Config, ['BaseswapV3'])); logger: Logger; @@ -187,7 +177,7 @@ export class BaseswapV3 if (!this.dexHelper.config.isSlave) { const cleanExpiredNotExistingPoolsKeys = async () => { const maxTimestamp = - Date.now() - UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS; + Date.now() - BASESWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS; await this.dexHelper.cache.zremrangebyscore( this.notExistingPoolSetKey, 0, @@ -197,7 +187,7 @@ export class BaseswapV3 this.intervalTask = setInterval( cleanExpiredNotExistingPoolsKeys.bind(this), - UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS, + BASESWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS, ); } } @@ -488,7 +478,7 @@ export class BaseswapV3 const calldata = pools.map(pool => _amounts.map(_amount => ({ target: this.config.quoter, - gasLimit: UNISWAPV3_QUOTE_GASLIMIT, + gasLimit: BASESWAPV3_QUOTE_GASLIMIT, callData: side === SwapSide.SELL ? this.quoterIface.encodeFunctionData('quoteExactInputSingle', [ @@ -559,7 +549,7 @@ export class BaseswapV3 pool.feeCode, ), exchange: this.dexKey, - gasCost: prices.map(p => (p === 0n ? 0 : UNISWAPV3_QUOTE_GASLIMIT)), + gasCost: prices.map(p => (p === 0n ? 0 : BASESWAPV3_QUOTE_GASLIMIT)), poolAddresses: [pool.poolAddress], }; }); diff --git a/src/dex/baseswap-v3/config.ts b/src/dex/baseswap-v3/config.ts index 8e0ed8cbd..af233efdc 100644 --- a/src/dex/baseswap-v3/config.ts +++ b/src/dex/baseswap-v3/config.ts @@ -17,12 +17,12 @@ export const PoolsToPreload: DexConfigMap< BaseswapV3: { [Network.BASE]: [ { - token0: ''.toLowerCase(), - token1: ''.toLowerCase(), + token0: '0x4200000000000000000000000000000000000006'.toLowerCase(), + token1: '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA'.toLowerCase(), // USDbC }, { - token0: ''.toLowerCase(), - token1: ''.toLowerCase(), + token0: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'.toLowerCase(), // USDC + token1: '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA'.toLowerCase(), // USDbC }, ], }, @@ -47,7 +47,7 @@ export const BaseswapV3Config: DexConfigMap = { export const Adapters: Record = { [Network.BASE]: { - [SwapSide.SELL]: [{ name: 'Adapter01', index: 6 }], - [SwapSide.BUY]: [{ name: 'BuyAdapter', index: 2 }], + [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 1 }], + [SwapSide.BUY]: [{ name: 'BaseBuyAdapter', index: 1 }], }, }; From f8eeec433d555fdba68ea84d6044392d932e82ad Mon Sep 17 00:00:00 2001 From: 0xshoehazer <0xshoehazer@gmail.com> Date: Mon, 30 Oct 2023 11:30:57 -0400 Subject: [PATCH 557/833] event tests passing --- .../baseswap-v3/baseswap-v3-events.test.ts | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/src/dex/baseswap-v3/baseswap-v3-events.test.ts b/src/dex/baseswap-v3/baseswap-v3-events.test.ts index e69de29bb..22ddd2d00 100644 --- a/src/dex/baseswap-v3/baseswap-v3-events.test.ts +++ b/src/dex/baseswap-v3/baseswap-v3-events.test.ts @@ -0,0 +1,141 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import _ from 'lodash'; +import { BaseswapV3EventPool } from './baseswap-v3-pool'; +import { BaseswapV3Config } from './config'; +import { Network } from '../../constants'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { testEventSubscriber } from '../../../tests/utils-events'; +import { PoolState } from './types'; +import { Interface } from '@ethersproject/abi'; +import ERC20ABI from '../../abi/erc20.json'; +import StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; +import { AbiItem } from 'web3-utils'; + +jest.setTimeout(300 * 1000); +const dexKey = 'BaseswapV3'; +const network = Network.BASE; +const config = BaseswapV3Config[dexKey][network]; + +async function fetchPoolStateFromContract( + baseswapV3Pool: BaseswapV3EventPool, + blockNumber: number, + poolAddress: string, +): Promise { + const message = `BaseswapV3: ${poolAddress} blockNumber ${blockNumber}`; + console.log(`Fetching state ${message}`); + // Be careful to not request state prior to contract deployment + // Otherwise need to use manual state sourcing from multicall + // We had that mechanism, but removed it with this commit + // You can restore it, but better just to find block after state multicall + // deployment + const state = baseswapV3Pool.generateState(blockNumber); + console.log(`Done ${message}`); + return state; +} + +describe('BaseswapV3 Event', function () { + const poolAddress = '0xEf3C164b0feE8Eb073513E88EcEa280A58cC9945'; + const poolFeeCode = 450n; + const token0 = '0x4200000000000000000000000000000000000006'; + const token1 = '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA'; // USDbC + + const blockNumbers: { [eventName: string]: number[] } = { + ['Swap']: [ + 5574195, 5574217, 5574296, 5574296, 5574369, 5574404, 5574489, 5574522, + 5574566, 5574579, 5574587, 5574588, 5574611, 5574657, 5574712, 5574737, + 5574761, 5574806, 5574851, 5574896, 5574918, 5574982, 5575086, 5575110, + 5575308, 5575378, 5575490, 5575668, + ], + ['Burn']: [ + 5575845, 5609704, 5609704, 5612315, 5612770, 5616727, 5617522, 5617821, + 5620232, 5622253, + ], + // topic0 - 0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde + ['Mint']: [ + 5594704, 5595166, 5606630, 5609854, 5612343, 5612386, 5612959, 5613707, + 5619196, 5620167, 5622035, 5622391, 5644261, 5645562, 5647711, 5649108, + 5649161, 5649377, 5651799, 5652903, + ], + // topic0 - 0x973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b133 + ['SetFeeProtocol']: [], + // topic0 - 0xac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a + // There are some events on blockNumbers: 13125816, 12733621, 12591465 + // But stateMulticall is not deployed at that time. So I just remove that check + // I think it is not important actually + ['IncreaseObservationCardinalityNext']: [], + ['Collect']: [ + 5575845, 5609704, 5612315, 5612770, 5616727, 5617522, 5617821, 5620232, + 5622253, 5642348, 5643915, 5645799, 5646074, 5647176, 5650388, 5650466, + 5653068, 5655334, 5655462, 5656401, 5657882, 5658500, 5659898, 5663603, + 5663999, 5664004, 5670005, 5671343, 5673141, + ], + ['Flash']: [], + }; + + describe('BaseswapV3EventPool', () => { + Object.keys(blockNumbers).forEach((event: string) => { + blockNumbers[event].forEach((blockNumber: number) => { + it(`${event}:${blockNumber} - should return correct state`, async function () { + const dexHelper = new DummyDexHelper(network); + // await dexHelper.init(); + + const logger = dexHelper.getLogger(dexKey); + + // readonly dexHelper: IDexHelper, + // parentName: string, + // readonly stateMultiContract: Contract, + // readonly decodeStateMultiCallResultWithRelativeBitmaps: + // | DecodeStateMultiCallFunc + // | undefined, + // readonly erc20Interface: Interface, + // protected readonly factoryAddress: Address, + // public feeCode: bigint, + // token0: Address, + // token1: Address, + // logger: Logger, + // mapKey: string = '', + // readonly poolInitCodeHash: string, + + const uniswapV3Pool = new BaseswapV3EventPool( + dexHelper, + dexKey, + new dexHelper.web3Provider.eth.Contract( + StateMulticallABI as AbiItem[], + config.stateMulticall, + ), + undefined, + new Interface(ERC20ABI), + config.factory, + poolFeeCode, + token0, + token1, + logger, + undefined, + config.initHash, + ); + + // It is done in generateState. But here have to make it manually + uniswapV3Pool.poolAddress = poolAddress.toLowerCase(); + uniswapV3Pool.addressesSubscribed[0] = poolAddress; + + await testEventSubscriber( + uniswapV3Pool, + uniswapV3Pool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolStateFromContract( + uniswapV3Pool, + _blockNumber, + poolAddress, + ), + blockNumber, + `${dexKey}_${poolAddress}`, + dexHelper.provider, + ); + }); + }); + }); + }); +}); From 538aa76a73c68da28fa80f0630289c9ab7dc713b Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 31 Oct 2023 11:27:07 +0200 Subject: [PATCH 558/833] fix: add e2e tests --- src/dex/wombat/config.ts | 11 ++- src/dex/wombat/types.ts | 1 + src/dex/wombat/wombat-e2e.test.ts | 132 +++++++++++++++++++++--------- src/dex/wombat/wombat.ts | 2 + 4 files changed, 108 insertions(+), 38 deletions(-) diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts index cd54fbf15..0a8bce995 100644 --- a/src/dex/wombat/config.ts +++ b/src/dex/wombat/config.ts @@ -6,6 +6,7 @@ export const WombatConfig: DexConfigMap = { Wombat: { [Network.BSC]: { bmwAddress: '0x489833311676B566f888119c29bd997Dc6C95830', + // routerAddress: '0x19609B03C976CCA288fbDae5c21d4290e9a4aDD7', }, [Network.ARBITRUM]: { bmwAddress: '0x62A83C6791A3d7950D823BB71a38e47252b6b6F4', @@ -19,7 +20,15 @@ export const Adapters: Record = { { name: 'BscAdapter01', /** @todo check index number */ - index: 12, + // index: 12, + // uniswapv2 forks + index: 3, + }, + ], + [SwapSide.BUY]: [ + { + name: 'BscBuyAdapter', + index: 1, }, ], }, diff --git a/src/dex/wombat/types.ts b/src/dex/wombat/types.ts index 5fa11b25f..3bac57e66 100644 --- a/src/dex/wombat/types.ts +++ b/src/dex/wombat/types.ts @@ -44,6 +44,7 @@ export type WombatData = { export type DexParams = { // DexParams is set of parameters that can be used to initiate a DEX fork. bmwAddress: Address; + // routerAddress?: Address; }; export type MulticallResultOutputs = diff --git a/src/dex/wombat/wombat-e2e.test.ts b/src/dex/wombat/wombat-e2e.test.ts index 02fe27be6..1b7a94478 100644 --- a/src/dex/wombat/wombat-e2e.test.ts +++ b/src/dex/wombat/wombat-e2e.test.ts @@ -19,6 +19,7 @@ import { generateConfig } from '../../config'; // tokenAAmount: string, // tokenBAmount: string, // nativeTokenAmount: string, +// slippage?: number | undefined, // ) { // const provider = new StaticJsonRpcProvider( // generateConfig(network).privateHttpProvider, @@ -27,7 +28,7 @@ import { generateConfig } from '../../config'; // const tokens = Tokens[network]; // const holders = Holders[network]; // const nativeTokenSymbol = NativeTokenSymbols[network]; -// + // const sideToContractMethods = new Map([ // [ // SwapSide.SELL, @@ -37,8 +38,72 @@ import { generateConfig } from '../../config'; // // ContractMethod.megaSwap, // ], // ], +// [SwapSide.BUY, [ContractMethod.simpleBuy /* ContractMethod.buy */]], // ]); -// + +// describe(`${network}`, () => { +// sideToContractMethods.forEach((contractMethods, side) => +// describe(`${side}`, () => { +// 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, +// 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, +// 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, +// network, +// provider, +// undefined, +// undefined, +// undefined, +// slippage, +// ); +// }); +// }); +// }); +// }), +// ); +// }); +// } + // describe(`${network}`, () => { // sideToContractMethods.forEach((contractMethods, side) => // describe(`${side}`, () => { @@ -107,46 +172,39 @@ describe('Wombat E2E', () => { SwapSide.SELL, [ ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - ], - ], - [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - // ContractMethod.buy, + ContractMethod.multiSwap, + ContractMethod.megaSwap, ], ], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], ]); - const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ [ - [ - { - name: 'USDC', - sellAmount: '100000000000000000000', - buyAmount: '100000000000000000000', - }, - { - name: 'USDT', - sellAmount: '100000000000000000000', - buyAmount: '100000000000000000000', - }, - ], - [ - { - name: 'BNB', - sellAmount: '1000000000000000000', - buyAmount: '1000000000', - }, - { - name: 'BNBx', - sellAmount: '1000000000', - buyAmount: '1000000000000000000', - }, - ], - ]; + { + name: 'USDC', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + { + name: 'USDT', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + ], + // [ + // { + // name: 'BNB', + // sellAmount: '1000000000000000000', + // buyAmount: '1000000000', + // }, + // { + // name: 'BNBx', + // sellAmount: '1000000000', + // buyAmount: '1000000000000000000', + // }, + // ], + ]; sideToContractMethods.forEach((contractMethods, side) => describe(`${side}`, () => { diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index a16cf8c78..3d8ab613e 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -30,8 +30,10 @@ import { WombatQuoter } from './wombat-quoter'; import { WombatBmw } from './wombat-bmw'; import { fromWad } from './utils'; import { WombatPool } from './wombat-pool'; +import { UniswapV2 } from '../uniswap-v2/uniswap-v2'; export class Wombat extends SimpleExchange implements IDex { + // export class Wombat implements IDex { // contract interfaces static readonly erc20Interface = new Interface(ERC20ABI); static readonly poolInterface = new Interface(PoolABI); From b9be3bd863c11f6cc63f2c5a8fcf22e0472fb319 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 1 Nov 2023 12:46:36 +0200 Subject: [PATCH 559/833] 2.42.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 20f7c86c1..fd06e4ee3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.2", + "version": "2.42.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From bd5a8c9c4616a079faf796ae08b7a7ece64eac84 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Wed, 1 Nov 2023 16:32:26 +0200 Subject: [PATCH 560/833] Revert "balancer-v1: disable AMPL pool due to wrong weights" This reverts commit 3e45a449473d987665330b016d8f795442b98fb1. --- src/dex/balancer-v1/balancer-v1.ts | 13 +------------ tests/constants-e2e.ts | 5 ----- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/src/dex/balancer-v1/balancer-v1.ts b/src/dex/balancer-v1/balancer-v1.ts index 7b5b87491..cfdc4d67b 100644 --- a/src/dex/balancer-v1/balancer-v1.ts +++ b/src/dex/balancer-v1/balancer-v1.ts @@ -39,10 +39,6 @@ import { generatePoolStates } from './utils'; import BalancerV1ExchangeProxyABI from '../../abi/BalancerV1ExchangeProxy.json'; import BalancerCustomMulticallABI from '../../abi/BalancerCustomMulticall.json'; -const BLACKLISTED_POOLS = new Set([ - '0x7860e28ebfb8ae052bfe279c07ac5d94c9cd2937', -]); - export class BalancerV1 extends SimpleExchange implements IDex @@ -86,18 +82,11 @@ export class BalancerV1 // for pricing requests. It is optional for a DEX to // implement this function async initializePricing(_blockNumber: number) { - const _poolsInfo = await this.dexHelper.httpRequest.get( + this.poolsInfo = await this.dexHelper.httpRequest.get( this.config.poolsURL, POOLS_FETCH_TIMEOUT, ); - this.poolInfosByToken = {}; - if (!_poolsInfo) return; - this.poolsInfo = { - ..._poolsInfo, - pools: _poolsInfo.pools.filter(p => !BLACKLISTED_POOLS.has(p.id)), - }; - for (const poolInfo of this.poolsInfo.pools) { for (const tokenAddress of poolInfo.tokensList) { if (!this.poolInfosByToken[tokenAddress]) { diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 579c16bd1..d96223d69 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -27,10 +27,6 @@ export const Tokens: { address: '0x8f8221aFbB33998d8584A2B05749bA73c37a938a', decimals: 18, }, - AMPL: { - address: '0xd46ba6d942050d489dbd938a2c909a5d5039a161', - decimals: 9, - }, USDC: { address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', decimals: 6, @@ -962,7 +958,6 @@ export const Holders: { [Network.MAINNET]: { ETH: '0x176F3DAb24a159341c0509bB36B833E7fdd0a132', USDC: '0x79E2Ba942B0e8fDB6ff3d406e930289d10B49ADe', - AMPL: '0x223592a191ECfC7FDC38a9256c3BD96E771539A9', WBTC: '0x1cb17a66dc606a52785f69f08f4256526abd4943', sBTC: '0xA2e3475D13776C6E42ff37B47286827d959B2195', BADGER: '0x34e2741a3f8483dbe5231f61c005110ff4b9f50a', From 8a807049c89d7b52fa5843fab72043f83d5166be Mon Sep 17 00:00:00 2001 From: 0xshoehazer <0xshoehazer@gmail.com> Date: Wed, 1 Nov 2023 11:21:16 -0400 Subject: [PATCH 561/833] e2e test --- src/dex/baseswap-v3/baseswap-v3-e2e.test.ts | 342 +++++++++--------- .../baseswap-v3/baseswap-v3-events.test.ts | 12 +- 2 files changed, 172 insertions(+), 182 deletions(-) diff --git a/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts b/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts index a0bac1b5a..f80696b46 100644 --- a/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts +++ b/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts @@ -11,144 +11,42 @@ import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; -// function testForNetwork( -// network: Network, -// dexKey: string, -// tokenASymbol: string, -// tokenBSymbol: string, -// tokenAAmount: string, -// tokenBAmount: string, -// nativeTokenAmount: string, -// slippage?: number | undefined, -// ) { -// const provider = new StaticJsonRpcProvider( -// generateConfig(network).privateHttpProvider, -// network, -// ); -// const tokens = Tokens[network]; -// const holders = Holders[network]; -// const nativeTokenSymbol = NativeTokenSymbols[network]; +function testForNetwork( + network: Network, + dexKey: string, + tokenASymbol: string, + tokenBSymbol: string, + tokenAAmount: string, + tokenBAmount: string, + nativeTokenAmount: string, + slippage?: number | undefined, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + const nativeTokenSymbol = NativeTokenSymbols[network]; -// const sideToContractMethods = new Map([ -// [ -// SwapSide.SELL, -// [ -// ContractMethod.simpleSwap, -// ContractMethod.multiSwap, -// ContractMethod.megaSwap, -// // ContractMethod.directUniV3Swap, -// ], -// ], -// [ -// SwapSide.BUY, -// [ -// ContractMethod.simpleBuy, -// ContractMethod.buy, -// // ContractMethod.directUniV3Buy, -// ], -// ], -// ]); + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); -// describe(`${network}`, () => { -// sideToContractMethods.forEach((contractMethods, side) => -// describe(`${side}`, () => { -// 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, -// 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, -// 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, -// network, -// provider, -// undefined, -// undefined, -// undefined, -// slippage, -// ); -// }); -// }); -// }); -// }), -// ); -// }); -// } - -describe('BasewapV3 E2E', () => { - describe('BasewapV3', () => { - const dexKey = 'BasewapV3'; - - describe('BaseswapV3 Base', () => { - const network = Network.BASE; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const tokenASymbol: string = 'USDbC'; - const tokenBSymbol: string = 'WETH'; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const tokenAAmount: string = '1000000000'; // 1000 - const tokenBAmount: string = '1000000000000000000'; // 1 - const nativeTokenAmount = '1000000000000000000'; - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ], - ], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - ]); - - sideToContractMethods.forEach((contractMethods, side) => + describe(`${network}`, () => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { contractMethods.forEach((contractMethod: ContractMethod) => { describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + it(`${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { await testE2E( tokens[nativeTokenSymbol], tokens[tokenASymbol], @@ -159,50 +57,142 @@ describe('BasewapV3 E2E', () => { contractMethod, 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, + network, + provider, + undefined, + undefined, + undefined, + slippage, ); }); - // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { - // await testE2E( - // tokens[tokenASymbol], - // tokens[nativeTokenSymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${network} ${side} ${contractMethod} ${tokenBSymbol} -> ${tokenASymbol}`, async () => { - // await testE2E( - // tokens[tokenBSymbol], - // tokens[tokenASymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenBAmount : tokenAAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); - // it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - // await testE2E( - // tokens[tokenASymbol], - // tokens[tokenBSymbol], - // holders[tokenASymbol], - // side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - // side, - // dexKey, - // contractMethod, - // network, - // provider, - // ); - // }); + 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, + slippage, + ); + }); + }); + }); + }), + ); + }); +} + +describe('BasewapV3 E2E', () => { + const dexKey = 'BasewapV3'; + describe('BasewapV3 Base', () => { + const network = Network.BASE; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ], + ], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + ]); + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ + [ + { + name: NativeTokenSymbols[network], + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + { + name: 'USDbC', + sellAmount: '100000000', + buyAmount: '100000000', + }, + ], + [ + { + name: 'USDC', + sellAmount: '100000000', + buyAmount: '100000000', + }, + { + name: 'USDbC', + sellAmount: '100000000', + buyAmount: '100000000', + }, + ], + ]; + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); }); - }), - ); - }); + }); + }), + ); }); }); diff --git a/src/dex/baseswap-v3/baseswap-v3-events.test.ts b/src/dex/baseswap-v3/baseswap-v3-events.test.ts index 22ddd2d00..cd16e354b 100644 --- a/src/dex/baseswap-v3/baseswap-v3-events.test.ts +++ b/src/dex/baseswap-v3/baseswap-v3-events.test.ts @@ -99,7 +99,7 @@ describe('BaseswapV3 Event', function () { // mapKey: string = '', // readonly poolInitCodeHash: string, - const uniswapV3Pool = new BaseswapV3EventPool( + const baseswapV3Pool = new BaseswapV3EventPool( dexHelper, dexKey, new dexHelper.web3Provider.eth.Contract( @@ -118,15 +118,15 @@ describe('BaseswapV3 Event', function () { ); // It is done in generateState. But here have to make it manually - uniswapV3Pool.poolAddress = poolAddress.toLowerCase(); - uniswapV3Pool.addressesSubscribed[0] = poolAddress; + baseswapV3Pool.poolAddress = poolAddress.toLowerCase(); + baseswapV3Pool.addressesSubscribed[0] = poolAddress; await testEventSubscriber( - uniswapV3Pool, - uniswapV3Pool.addressesSubscribed, + baseswapV3Pool, + baseswapV3Pool.addressesSubscribed, (_blockNumber: number) => fetchPoolStateFromContract( - uniswapV3Pool, + baseswapV3Pool, _blockNumber, poolAddress, ), From f79c2b5aa80653bc2d8bdc1ec7d5a7cac5fbc0c2 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Wed, 1 Nov 2023 19:46:17 +0200 Subject: [PATCH 562/833] feat: replace fleek with subgraph for BalancerV1 --- src/dex/balancer-v1/balancer-v1.ts | 38 ++++++++++++++++++++++++++---- src/dex/balancer-v1/config.ts | 3 ++- tests/constants-e2e.ts | 7 +++++- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/dex/balancer-v1/balancer-v1.ts b/src/dex/balancer-v1/balancer-v1.ts index cfdc4d67b..1469735c9 100644 --- a/src/dex/balancer-v1/balancer-v1.ts +++ b/src/dex/balancer-v1/balancer-v1.ts @@ -28,17 +28,36 @@ import { } from './types'; import { SimpleExchange } from '../simple-exchange'; import { + MIN_USD_LIQUIDITY_TO_FETCH, BalancerV1Config, Adapters, - POOLS_FETCH_TIMEOUT, MAX_POOLS_FOR_PRICING, BALANCER_SWAP_GAS_COST, + MAX_POOL_CNT, } from './config'; import { BalancerV1EventPool } from './balancer-v1-pool'; import { generatePoolStates } from './utils'; import BalancerV1ExchangeProxyABI from '../../abi/BalancerV1ExchangeProxy.json'; import BalancerCustomMulticallABI from '../../abi/BalancerCustomMulticall.json'; +const fetchAllPoolsQuery = `query { + pools(first: ${MAX_POOL_CNT.toString()} + orderBy: liquidity + orderDirection: desc + where: {liquidity_gt: ${MIN_USD_LIQUIDITY_TO_FETCH.toString()}}) { + id + swapFee + totalWeight + tokensList + tokens { + address + balance + decimals + denormWeight + } + } + }`; + export class BalancerV1 extends SimpleExchange implements IDex @@ -82,10 +101,21 @@ export class BalancerV1 // for pricing requests. It is optional for a DEX to // implement this function async initializePricing(_blockNumber: number) { - this.poolsInfo = await this.dexHelper.httpRequest.get( - this.config.poolsURL, - POOLS_FETCH_TIMEOUT, + const { data } = await this.dexHelper.httpRequest.post<{ + data: { pools: PoolInfo[] }; + }>( + this.config.subgraphURL, + { query: fetchAllPoolsQuery }, + SUBGRAPH_TIMEOUT, ); + + if (!(data && data.pools)) + throw new Error( + `Error ${this.dexKey} Subgraph: couldn't fetch the pools from the subgraph`, + ); + + this.poolsInfo = data; + this.poolInfosByToken = {}; for (const poolInfo of this.poolsInfo.pools) { for (const tokenAddress of poolInfo.tokensList) { diff --git a/src/dex/balancer-v1/config.ts b/src/dex/balancer-v1/config.ts index a1ea4e29d..0ec496a67 100644 --- a/src/dex/balancer-v1/config.ts +++ b/src/dex/balancer-v1/config.ts @@ -2,7 +2,8 @@ import { DexParams } from './types'; import { DexConfigMap, AdapterMappings } from '../../types'; import { Network, SwapSide } from '../../constants'; -export const POOLS_FETCH_TIMEOUT = 10000; +export const MAX_POOL_CNT = 1000; +export const MIN_USD_LIQUIDITY_TO_FETCH = 100; export const BALANCES_MULTICALL_POOLS_LIMIT = 200; export const MAX_POOLS_FOR_PRICING = 5; export const BALANCER_SWAP_GAS_COST = 120 * 1000; diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index d96223d69..215760ca3 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -27,6 +27,10 @@ export const Tokens: { address: '0x8f8221aFbB33998d8584A2B05749bA73c37a938a', decimals: 18, }, + AMPL: { + address: '0xd46ba6d942050d489dbd938a2c909a5d5039a161', + decimals: 9, + }, USDC: { address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', decimals: 6, @@ -957,7 +961,8 @@ export const Holders: { } = { [Network.MAINNET]: { ETH: '0x176F3DAb24a159341c0509bB36B833E7fdd0a132', - USDC: '0x79E2Ba942B0e8fDB6ff3d406e930289d10B49ADe', + USDC: '0x7713974908be4bed47172370115e8b1219f4a5f0', + AMPL: '0x223592a191ECfC7FDC38a9256c3BD96E771539A9', WBTC: '0x1cb17a66dc606a52785f69f08f4256526abd4943', sBTC: '0xA2e3475D13776C6E42ff37B47286827d959B2195', BADGER: '0x34e2741a3f8483dbe5231f61c005110ff4b9f50a', From 06733e32289c4bdd431fc0deb545ef67c0388170 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Wed, 1 Nov 2023 19:50:16 +0200 Subject: [PATCH 563/833] 2.42.4-balancer-v1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fd06e4ee3..3ac77d96f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.3", + "version": "2.42.4-balancer-v1.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 2d80f6c957a2b84e8b66ea5f8ace26b102819030 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 2 Nov 2023 16:53:58 +0200 Subject: [PATCH 564/833] fix: typo --- src/dex/baseswap-v3/baseswap-v3-e2e.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts b/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts index f80696b46..4cd753327 100644 --- a/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts +++ b/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts @@ -104,9 +104,9 @@ function testForNetwork( }); } -describe('BasewapV3 E2E', () => { - const dexKey = 'BasewapV3'; - describe('BasewapV3 Base', () => { +describe('BaseswapV3 E2E', () => { + const dexKey = 'BaseswapV3'; + describe('BaseswapV3 Base', () => { const network = Network.BASE; const tokens = Tokens[network]; const holders = Holders[network]; From 7659d26201810fb08f67f7c4dc88bedb5b9acfdb Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Thu, 2 Nov 2023 17:09:47 +0200 Subject: [PATCH 565/833] 2.42.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ac77d96f..b065131b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.4-balancer-v1.0", + "version": "2.42.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From d09739c35eb0c770c505068f7b5f0c5fdd2ad2cb Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 2 Nov 2023 17:26:29 +0200 Subject: [PATCH 566/833] fix: refactor e2e tests --- src/dex/baseswap-v3/baseswap-v3-e2e.test.ts | 97 +++------------------ 1 file changed, 14 insertions(+), 83 deletions(-) diff --git a/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts b/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts index 4cd753327..4ba0e41f0 100644 --- a/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts +++ b/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts @@ -106,93 +106,24 @@ function testForNetwork( describe('BaseswapV3 E2E', () => { const dexKey = 'BaseswapV3'; - describe('BaseswapV3 Base', () => { + describe('Base', () => { const network = Network.BASE; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ], - ], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - ]); + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDbC'; - const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ - [ - { - name: NativeTokenSymbols[network], - sellAmount: '100000000000000000000', - buyAmount: '100000000000000000000', - }, - { - name: 'USDbC', - sellAmount: '100000000', - buyAmount: '100000000', - }, - ], - [ - { - name: 'USDC', - sellAmount: '100000000', - buyAmount: '100000000', - }, - { - name: 'USDbC', - sellAmount: '100000000', - buyAmount: '100000000', - }, - ], - ]; + const tokenAAmount: string = '1000000'; + const tokenBAmount: string = '1000000'; + const nativeTokenAmount = '1000000000000000000'; - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - contractMethods.forEach((contractMethod: ContractMethod) => { - pairs.forEach(pair => { - describe(`${contractMethod}`, () => { - it(`${pair[0].name} -> ${pair[1].name}`, async () => { - await testE2E( - tokens[pair[0].name], - tokens[pair[1].name], - holders[pair[0].name], - side === SwapSide.SELL - ? pair[0].sellAmount - : pair[0].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${pair[1].name} -> ${pair[0].name}`, async () => { - await testE2E( - tokens[pair[1].name], - tokens[pair[0].name], - holders[pair[1].name], - side === SwapSide.SELL - ? pair[1].sellAmount - : pair[1].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }); - }); - }), + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, ); }); }); From 673d90f03d9c111c988665364258e52ea020d282 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 2 Nov 2023 17:36:44 +0200 Subject: [PATCH 567/833] 2.42.4-baseswap --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b065131b4..bbeab622d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.4", + "version": "2.42.4-baseswap", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From fe485c1f2e7033cae7c8817a3a34ce6f59a07499 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 2 Nov 2023 18:51:43 +0200 Subject: [PATCH 568/833] fix: move implementation & tests to univ3 --- src/dex/baseswap-v3/baseswap-v3-e2e.test.ts | 129 -- .../baseswap-v3/baseswap-v3-events.test.ts | 141 -- src/dex/baseswap-v3/baseswap-v3-factory.ts | 73 - .../baseswap-v3-integration.test.ts | 472 ------- src/dex/baseswap-v3/baseswap-v3-pool.ts | 519 ------- src/dex/baseswap-v3/baseswap-v3.ts | 1243 ----------------- src/dex/baseswap-v3/config.ts | 53 - src/dex/baseswap-v3/constants.ts | 41 - src/dex/baseswap-v3/contract-math/BitMath.ts | 90 -- .../contract-math/FixedPoint128.ts | 3 - .../baseswap-v3/contract-math/FixedPoint96.ts | 4 - src/dex/baseswap-v3/contract-math/FullMath.ts | 30 - .../contract-math/LiquidityMath.ts | 17 - src/dex/baseswap-v3/contract-math/Oracle.ts | 226 --- .../contract-math/SqrtPriceMath.ts | 226 --- src/dex/baseswap-v3/contract-math/SwapMath.ts | 139 -- src/dex/baseswap-v3/contract-math/Tick.ts | 82 -- .../baseswap-v3/contract-math/TickBitMap.ts | 123 -- src/dex/baseswap-v3/contract-math/TickMath.ts | 211 --- .../baseswap-v3/contract-math/UnsafeMath.ts | 5 - .../contract-math/uniswap-v3-math.ts | 666 --------- src/dex/baseswap-v3/contract-math/utils.ts | 55 - src/dex/baseswap-v3/types.ts | 191 --- src/dex/baseswap-v3/utils.ts | 83 -- src/dex/index.ts | 2 - src/dex/uniswap-v3/config.ts | 14 + src/dex/uniswap-v3/uniswap-v3-e2e.test.ts | 24 + .../uniswap-v3/uniswap-v3-integration.test.ts | 375 +++++ 28 files changed, 413 insertions(+), 4824 deletions(-) delete mode 100644 src/dex/baseswap-v3/baseswap-v3-e2e.test.ts delete mode 100644 src/dex/baseswap-v3/baseswap-v3-events.test.ts delete mode 100644 src/dex/baseswap-v3/baseswap-v3-factory.ts delete mode 100644 src/dex/baseswap-v3/baseswap-v3-integration.test.ts delete mode 100644 src/dex/baseswap-v3/baseswap-v3-pool.ts delete mode 100644 src/dex/baseswap-v3/baseswap-v3.ts delete mode 100644 src/dex/baseswap-v3/config.ts delete mode 100644 src/dex/baseswap-v3/constants.ts delete mode 100644 src/dex/baseswap-v3/contract-math/BitMath.ts delete mode 100644 src/dex/baseswap-v3/contract-math/FixedPoint128.ts delete mode 100644 src/dex/baseswap-v3/contract-math/FixedPoint96.ts delete mode 100644 src/dex/baseswap-v3/contract-math/FullMath.ts delete mode 100644 src/dex/baseswap-v3/contract-math/LiquidityMath.ts delete mode 100644 src/dex/baseswap-v3/contract-math/Oracle.ts delete mode 100644 src/dex/baseswap-v3/contract-math/SqrtPriceMath.ts delete mode 100644 src/dex/baseswap-v3/contract-math/SwapMath.ts delete mode 100644 src/dex/baseswap-v3/contract-math/Tick.ts delete mode 100644 src/dex/baseswap-v3/contract-math/TickBitMap.ts delete mode 100644 src/dex/baseswap-v3/contract-math/TickMath.ts delete mode 100644 src/dex/baseswap-v3/contract-math/UnsafeMath.ts delete mode 100644 src/dex/baseswap-v3/contract-math/uniswap-v3-math.ts delete mode 100644 src/dex/baseswap-v3/contract-math/utils.ts delete mode 100644 src/dex/baseswap-v3/types.ts delete mode 100644 src/dex/baseswap-v3/utils.ts diff --git a/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts b/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts deleted file mode 100644 index 4ba0e41f0..000000000 --- a/src/dex/baseswap-v3/baseswap-v3-e2e.test.ts +++ /dev/null @@ -1,129 +0,0 @@ -import dotenv from 'dotenv'; -dotenv.config(); - -import { testE2E } from '../../../tests/utils-e2e'; -import { - Tokens, - Holders, - NativeTokenSymbols, -} from '../../../tests/constants-e2e'; -import { Network, ContractMethod, SwapSide } from '../../constants'; -import { StaticJsonRpcProvider } from '@ethersproject/providers'; -import { generateConfig } from '../../config'; - -function testForNetwork( - network: Network, - dexKey: string, - tokenASymbol: string, - tokenBSymbol: string, - tokenAAmount: string, - tokenBAmount: string, - nativeTokenAmount: string, - slippage?: number | undefined, -) { - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - const tokens = Tokens[network]; - const holders = Holders[network]; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, - ], - ], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - ]); - - describe(`${network}`, () => { - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - 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, - 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, - 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, - network, - provider, - undefined, - undefined, - undefined, - slippage, - ); - }); - }); - }); - }), - ); - }); -} - -describe('BaseswapV3 E2E', () => { - const dexKey = 'BaseswapV3'; - describe('Base', () => { - const network = Network.BASE; - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDbC'; - - const tokenAAmount: string = '1000000'; - const tokenBAmount: string = '1000000'; - const nativeTokenAmount = '1000000000000000000'; - - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); -}); diff --git a/src/dex/baseswap-v3/baseswap-v3-events.test.ts b/src/dex/baseswap-v3/baseswap-v3-events.test.ts deleted file mode 100644 index cd16e354b..000000000 --- a/src/dex/baseswap-v3/baseswap-v3-events.test.ts +++ /dev/null @@ -1,141 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); - -import _ from 'lodash'; -import { BaseswapV3EventPool } from './baseswap-v3-pool'; -import { BaseswapV3Config } from './config'; -import { Network } from '../../constants'; -import { DummyDexHelper } from '../../dex-helper/index'; -import { testEventSubscriber } from '../../../tests/utils-events'; -import { PoolState } from './types'; -import { Interface } from '@ethersproject/abi'; -import ERC20ABI from '../../abi/erc20.json'; -import StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; -import { AbiItem } from 'web3-utils'; - -jest.setTimeout(300 * 1000); -const dexKey = 'BaseswapV3'; -const network = Network.BASE; -const config = BaseswapV3Config[dexKey][network]; - -async function fetchPoolStateFromContract( - baseswapV3Pool: BaseswapV3EventPool, - blockNumber: number, - poolAddress: string, -): Promise { - const message = `BaseswapV3: ${poolAddress} blockNumber ${blockNumber}`; - console.log(`Fetching state ${message}`); - // Be careful to not request state prior to contract deployment - // Otherwise need to use manual state sourcing from multicall - // We had that mechanism, but removed it with this commit - // You can restore it, but better just to find block after state multicall - // deployment - const state = baseswapV3Pool.generateState(blockNumber); - console.log(`Done ${message}`); - return state; -} - -describe('BaseswapV3 Event', function () { - const poolAddress = '0xEf3C164b0feE8Eb073513E88EcEa280A58cC9945'; - const poolFeeCode = 450n; - const token0 = '0x4200000000000000000000000000000000000006'; - const token1 = '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA'; // USDbC - - const blockNumbers: { [eventName: string]: number[] } = { - ['Swap']: [ - 5574195, 5574217, 5574296, 5574296, 5574369, 5574404, 5574489, 5574522, - 5574566, 5574579, 5574587, 5574588, 5574611, 5574657, 5574712, 5574737, - 5574761, 5574806, 5574851, 5574896, 5574918, 5574982, 5575086, 5575110, - 5575308, 5575378, 5575490, 5575668, - ], - ['Burn']: [ - 5575845, 5609704, 5609704, 5612315, 5612770, 5616727, 5617522, 5617821, - 5620232, 5622253, - ], - // topic0 - 0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde - ['Mint']: [ - 5594704, 5595166, 5606630, 5609854, 5612343, 5612386, 5612959, 5613707, - 5619196, 5620167, 5622035, 5622391, 5644261, 5645562, 5647711, 5649108, - 5649161, 5649377, 5651799, 5652903, - ], - // topic0 - 0x973d8d92bb299f4af6ce49b52a8adb85ae46b9f214c4c4fc06ac77401237b133 - ['SetFeeProtocol']: [], - // topic0 - 0xac49e518f90a358f652e4400164f05a5d8f7e35e7747279bc3a93dbf584e125a - // There are some events on blockNumbers: 13125816, 12733621, 12591465 - // But stateMulticall is not deployed at that time. So I just remove that check - // I think it is not important actually - ['IncreaseObservationCardinalityNext']: [], - ['Collect']: [ - 5575845, 5609704, 5612315, 5612770, 5616727, 5617522, 5617821, 5620232, - 5622253, 5642348, 5643915, 5645799, 5646074, 5647176, 5650388, 5650466, - 5653068, 5655334, 5655462, 5656401, 5657882, 5658500, 5659898, 5663603, - 5663999, 5664004, 5670005, 5671343, 5673141, - ], - ['Flash']: [], - }; - - describe('BaseswapV3EventPool', () => { - Object.keys(blockNumbers).forEach((event: string) => { - blockNumbers[event].forEach((blockNumber: number) => { - it(`${event}:${blockNumber} - should return correct state`, async function () { - const dexHelper = new DummyDexHelper(network); - // await dexHelper.init(); - - const logger = dexHelper.getLogger(dexKey); - - // readonly dexHelper: IDexHelper, - // parentName: string, - // readonly stateMultiContract: Contract, - // readonly decodeStateMultiCallResultWithRelativeBitmaps: - // | DecodeStateMultiCallFunc - // | undefined, - // readonly erc20Interface: Interface, - // protected readonly factoryAddress: Address, - // public feeCode: bigint, - // token0: Address, - // token1: Address, - // logger: Logger, - // mapKey: string = '', - // readonly poolInitCodeHash: string, - - const baseswapV3Pool = new BaseswapV3EventPool( - dexHelper, - dexKey, - new dexHelper.web3Provider.eth.Contract( - StateMulticallABI as AbiItem[], - config.stateMulticall, - ), - undefined, - new Interface(ERC20ABI), - config.factory, - poolFeeCode, - token0, - token1, - logger, - undefined, - config.initHash, - ); - - // It is done in generateState. But here have to make it manually - baseswapV3Pool.poolAddress = poolAddress.toLowerCase(); - baseswapV3Pool.addressesSubscribed[0] = poolAddress; - - await testEventSubscriber( - baseswapV3Pool, - baseswapV3Pool.addressesSubscribed, - (_blockNumber: number) => - fetchPoolStateFromContract( - baseswapV3Pool, - _blockNumber, - poolAddress, - ), - blockNumber, - `${dexKey}_${poolAddress}`, - dexHelper.provider, - ); - }); - }); - }); - }); -}); diff --git a/src/dex/baseswap-v3/baseswap-v3-factory.ts b/src/dex/baseswap-v3/baseswap-v3-factory.ts deleted file mode 100644 index 93b79f3a5..000000000 --- a/src/dex/baseswap-v3/baseswap-v3-factory.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Interface } from '@ethersproject/abi'; -import { DeepReadonly } from 'ts-essentials'; -import FactoryABI from '../../abi/uniswap-v3/UniswapV3Factory.abi.json'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; -import { Address, Log, Logger } from '../../types'; -import { LogDescription } from 'ethers/lib/utils'; -import { FactoryState } from './types'; - -export type OnPoolCreatedCallback = ({ - token0, - token1, - fee, -}: { - token0: string; - token1: string; - fee: bigint; -}) => Promise; - -/* - * "Stateless" event subscriber in order to capture "PoolCreated" event on new pools created. - * State is present, but it's a placeholder to actually make the events reach handlers (if there's no previous state - `processBlockLogs` is not called) - */ -export class BaseswapV3Factory extends StatefulEventSubscriber { - handlers: { - [event: string]: (event: any) => Promise; - } = {}; - - logDecoder: (log: Log) => any; - - public readonly factoryIface = new Interface(FactoryABI); - - constructor( - readonly dexHelper: IDexHelper, - parentName: string, - protected readonly factoryAddress: Address, - logger: Logger, - protected readonly onPoolCreated: OnPoolCreatedCallback, - mapKey: string = '', - ) { - super(parentName, `${parentName} Factory`, dexHelper, logger, true, mapKey); - - this.addressesSubscribed = [factoryAddress]; - - this.logDecoder = (log: Log) => this.factoryIface.parseLog(log); - - this.handlers['PoolCreated'] = this.handleNewPool.bind(this); - } - - generateState(): FactoryState { - return {}; - } - - protected async processLog( - _: DeepReadonly, - log: Readonly, - ): Promise { - const event = this.logDecoder(log); - if (event.name in this.handlers) { - await this.handlers[event.name](event); - } - - return {}; - } - - async handleNewPool(event: LogDescription) { - const token0 = event.args.token0.toLowerCase(); - const token1 = event.args.token1.toLowerCase(); - const fee = event.args.fee; - - await this.onPoolCreated({ token0, token1, fee }); - } -} diff --git a/src/dex/baseswap-v3/baseswap-v3-integration.test.ts b/src/dex/baseswap-v3/baseswap-v3-integration.test.ts deleted file mode 100644 index 201d997cd..000000000 --- a/src/dex/baseswap-v3/baseswap-v3-integration.test.ts +++ /dev/null @@ -1,472 +0,0 @@ -/* eslint-disable no-console */ -import dotenv from 'dotenv'; -dotenv.config(); - -import { Interface, Result } from '@ethersproject/abi'; -import { DummyDexHelper, IDexHelper } from '../../dex-helper/index'; -import { Network, SwapSide } from '../../constants'; -import { BI_POWS } from '../../bigint-constants'; -import { BaseswapV3 } from './baseswap-v3'; -import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; -import { Tokens } from '../../../tests/constants-e2e'; -import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; -import { Address } from '@paraswap/core'; - -const network = Network.BASE; -const TokenASymbol = 'USDC'; -const TokenA = Tokens[network][TokenASymbol]; - -const QuoterV2 = '0x4fDBD73aD4B1DDde594BF05497C15f76308eFfb9'; - -const TokenBSymbol = 'WETH'; -const TokenB = Tokens[network][TokenBSymbol]; - -const amounts = [ - 0n, - 10_000n * BI_POWS[6], - 20_000n * BI_POWS[6], - 30_000n * BI_POWS[6], -]; - -const amountsBuy = [0n, 1n * BI_POWS[18], 2n * BI_POWS[18], 3n * BI_POWS[18]]; - -const quoterIface = new Interface(UniswapV3QuoterV2ABI); - -function getReaderCalldata( - exchangeAddress: string, - readerIface: Interface, - amounts: bigint[], - funcName: string, - tokenIn: Address, - tokenOut: Address, - fee: bigint, -) { - return amounts.map(amount => ({ - target: exchangeAddress, - callData: readerIface.encodeFunctionData(funcName, [ - [tokenIn, tokenOut, amount.toString(), fee.toString(), 0], - ]), - })); -} - -function decodeReaderResult( - results: Result, - readerIface: Interface, - funcName: string, -) { - return results.map(result => { - const parsed = readerIface.decodeFunctionResult(funcName, result); - return BigInt(parsed[0]._hex); - }); -} - -async function checkOnChainPricing( - dexHelper: IDexHelper, - funcName: string, - blockNumber: number, - exchangeAddress: string, - prices: bigint[], - tokenIn: Address, - tokenOut: Address, - fee: bigint, - _amounts: bigint[], -) { - // const exchangeAddress = '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'; - const readerIface = quoterIface; - - const sum = prices.reduce((acc, curr) => (acc += curr), 0n); - - if (sum === 0n) { - console.log( - `Prices were not calculated for tokenIn=${tokenIn}, tokenOut=${tokenOut}, fee=${fee.toString()}. Most likely price impact is too big for requested amount`, - ); - return false; - } - - const readerCallData = getReaderCalldata( - exchangeAddress, - readerIface, - _amounts.slice(1), - funcName, - tokenIn, - tokenOut, - fee, - ); - - let readerResult; - try { - readerResult = ( - await dexHelper.multiContract.methods - .aggregate(readerCallData) - .call({}, blockNumber) - ).returnData; - } catch (e) { - console.log( - `Can not fetch on-chain pricing for fee ${fee}. It happens for low liquidity pools`, - e, - ); - return false; - } - - const expectedPrices = [0n].concat( - decodeReaderResult(readerResult, readerIface, funcName), - ); - - console.log('EXPECTED PRICES: ', expectedPrices); - - let firstZeroIndex = prices.slice(1).indexOf(0n); - - // we skipped first, so add +1 on result - firstZeroIndex = firstZeroIndex === -1 ? prices.length : firstZeroIndex; - - // Compare only the ones for which we were able to calculate prices - expect(prices.slice(0, firstZeroIndex)).toEqual( - expectedPrices.slice(0, firstZeroIndex), - ); - return true; -} - -describe('BaseswapV3', function () { - const dexHelper = new DummyDexHelper(network); - const dexKey = 'BaseswapV3'; - - let blockNumber: number; - let baseswapV3: BaseswapV3; - let baseswapV3Mainnet: BaseswapV3; - - beforeEach(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - baseswapV3 = new BaseswapV3(network, dexKey, dexHelper); - baseswapV3Mainnet = new BaseswapV3( - Network.BASE, - dexKey, - new DummyDexHelper(Network.BASE), - ); - }); - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - const pools = await baseswapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.SELL, - blockNumber, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await baseswapV3.getPricesVolume( - TokenA, - TokenB, - amounts, - SwapSide.SELL, - blockNumber, - pools, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); - - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - dexHelper, - 'quoteExactInputSingle', - blockNumber, - QuoterV2, - price.prices, - TokenA.address, - TokenB.address, - fee, - amounts, - ); - if (res === false) falseChecksCounter++; - }), - ); - - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - const pools = await baseswapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.BUY, - blockNumber, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await baseswapV3.getPricesVolume( - TokenA, - TokenB, - amountsBuy, - SwapSide.BUY, - blockNumber, - pools, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices(poolPrices!, amountsBuy, SwapSide.BUY, dexKey); - - // Check if onchain pricing equals to calculated ones - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - dexHelper, - 'quoteExactOutputSingle', - blockNumber, - QuoterV2, - price.prices, - TokenA.address, - TokenB.address, - fee, - amountsBuy, - ); - if (res === false) falseChecksCounter++; - }), - ); - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - it('getPoolIdentifiers and getPricesVolume SELL stable pairs', async function () { - const TokenASymbol = 'USDbC'; - const TokenA = Tokens[network][TokenASymbol]; - - const TokenBSymbol = 'USDC'; - const TokenB = Tokens[network][TokenBSymbol]; - - const amounts = [ - 0n, - 6000000n, - 12000000n, - 18000000n, - 24000000n, - 30000000n, - 36000000n, - 42000000n, - 48000000n, - 54000000n, - 60000000n, - 66000000n, - 72000000n, - 78000000n, - 84000000n, - 90000000n, - 96000000n, - 102000000n, - 108000000n, - 114000000n, - 120000000n, - 126000000n, - 132000000n, - 138000000n, - 144000000n, - 150000000n, - 156000000n, - 162000000n, - 168000000n, - 174000000n, - 180000000n, - 186000000n, - 192000000n, - 198000000n, - 204000000n, - 210000000n, - 216000000n, - 222000000n, - 228000000n, - 234000000n, - 240000000n, - 246000000n, - 252000000n, - 258000000n, - 264000000n, - 270000000n, - 276000000n, - 282000000n, - 288000000n, - 294000000n, - 300000000n, - ]; - - const pools = await baseswapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.SELL, - blockNumber, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await baseswapV3.getPricesVolume( - TokenA, - TokenB, - amounts, - SwapSide.SELL, - blockNumber, - pools, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices( - poolPrices!.filter(pp => pp.unit !== 0n), - amounts, - SwapSide.SELL, - dexKey, - ); - - // Check if onchain pricing equals to calculated ones - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - dexHelper, - 'quoteExactInputSingle', - blockNumber, - QuoterV2, - price.prices, - TokenA.address, - TokenB.address, - fee, - amounts, - ); - if (res === false) falseChecksCounter++; - }), - ); - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - it('getPoolIdentifiers and getPricesVolume BUY stable pairs', async function () { - const TokenASymbol = 'DAI'; - const TokenA = Tokens[network][TokenASymbol]; - - const TokenBSymbol = 'USDC'; - const TokenB = Tokens[network][TokenBSymbol]; - - const amountsBuy = [ - 0n, - 6000000n, - 12000000n, - 18000000n, - 24000000n, - 30000000n, - 36000000n, - 42000000n, - 48000000n, - 54000000n, - 60000000n, - 66000000n, - 72000000n, - 78000000n, - 84000000n, - 90000000n, - 96000000n, - 102000000n, - 108000000n, - 114000000n, - 120000000n, - 126000000n, - 132000000n, - 138000000n, - 144000000n, - 150000000n, - 156000000n, - 162000000n, - 168000000n, - 174000000n, - 180000000n, - 186000000n, - 192000000n, - 198000000n, - 204000000n, - 210000000n, - 216000000n, - 222000000n, - 228000000n, - 234000000n, - 240000000n, - 246000000n, - 252000000n, - 258000000n, - 264000000n, - 270000000n, - 276000000n, - 282000000n, - 288000000n, - 294000000n, - 300000000n, - ]; - - const pools = await baseswapV3.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.BUY, - blockNumber, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await baseswapV3.getPricesVolume( - TokenA, - TokenB, - amountsBuy, - SwapSide.BUY, - blockNumber, - pools, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - expect(poolPrices).not.toBeNull(); - checkPoolPrices( - poolPrices!.filter(pp => pp.unit !== 0n), - amountsBuy, - SwapSide.BUY, - dexKey, - ); - - // Check if onchain pricing equals to calculated ones - let falseChecksCounter = 0; - await Promise.all( - poolPrices!.map(async price => { - const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; - const res = await checkOnChainPricing( - dexHelper, - 'quoteExactOutputSingle', - blockNumber, - QuoterV2, - price.prices, - TokenA.address, - TokenB.address, - fee, - amountsBuy, - ); - if (res === false) falseChecksCounter++; - }), - ); - expect(falseChecksCounter).toBeLessThan(poolPrices!.length); - }); - - it('getTopPoolsForToken', async function () { - const poolLiquidity = await baseswapV3Mainnet.getTopPoolsForToken( - Tokens[Network.BASE]['USDC'].address, - 10, - ); - console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); - - if (!baseswapV3.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); - } - }); -}); diff --git a/src/dex/baseswap-v3/baseswap-v3-pool.ts b/src/dex/baseswap-v3/baseswap-v3-pool.ts deleted file mode 100644 index ee4966ee2..000000000 --- a/src/dex/baseswap-v3/baseswap-v3-pool.ts +++ /dev/null @@ -1,519 +0,0 @@ -import _ from 'lodash'; -import { Contract } from 'web3-eth-contract'; -import { Interface } from '@ethersproject/abi'; -import { ethers } from 'ethers'; -import { assert, DeepReadonly } from 'ts-essentials'; -import { Log, Logger, BlockHeader, Address } from '../../types'; -import { - InitializeStateOptions, - StatefulEventSubscriber, -} from '../../stateful-event-subscriber'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { - PoolState, - DecodedStateMultiCallResultWithRelativeBitmaps, - DecodeStateMultiCallFunc, -} from './types'; -import UniswapV3PoolABI from '../../abi/uniswap-v3/UniswapV3Pool.abi.json'; -import { bigIntify, catchParseLogError, isSampled } from '../../utils'; -import { uniswapV3Math } from './contract-math/uniswap-v3-math'; -import { MultiCallParams } from '../../lib/multi-wrapper'; -import { - OUT_OF_RANGE_ERROR_POSTFIX, - TICK_BITMAP_BUFFER, - TICK_BITMAP_TO_USE, -} from './constants'; -import { TickBitMap } from './contract-math/TickBitMap'; -import { uint256ToBigInt } from '../../lib/decoders'; -import { decodeStateMultiCallResultWithRelativeBitmaps } from './utils'; -import { _reduceTickBitmap, _reduceTicks } from './contract-math/utils'; - -export class BaseswapV3EventPool extends StatefulEventSubscriber { - handlers: { - [event: string]: ( - event: any, - pool: PoolState, - log: Log, - blockHeader: Readonly, - ) => PoolState; - } = {}; - - logDecoder: (log: Log) => any; - - readonly token0: Address; - - readonly token1: Address; - - private _poolAddress?: Address; - - protected _stateRequestCallData?: MultiCallParams< - bigint | DecodedStateMultiCallResultWithRelativeBitmaps - >[]; - - public readonly poolIface = new Interface(UniswapV3PoolABI); - - public initFailed = false; - public initRetryAttemptCount = 0; - - public feeCodeAsString; - - constructor( - readonly dexHelper: IDexHelper, - parentName: string, - readonly stateMultiContract: Contract, - readonly decodeStateMultiCallResultWithRelativeBitmaps: - | DecodeStateMultiCallFunc - | undefined, - readonly erc20Interface: Interface, - protected readonly factoryAddress: Address, - public feeCode: bigint, - token0: Address, - token1: Address, - logger: Logger, - mapKey: string = '', - readonly poolInitCodeHash: string, - ) { - super( - parentName, - `${token0}_${token1}_${feeCode}`, - dexHelper, - logger, - true, - mapKey, - ); - this.feeCodeAsString = feeCode.toString(); - this.token0 = token0.toLowerCase(); - this.token1 = token1.toLowerCase(); - this.logDecoder = (log: Log) => this.poolIface.parseLog(log); - this.addressesSubscribed = new Array
(1); - - // Add handlers - this.handlers['Swap'] = this.handleSwapEvent.bind(this); - this.handlers['Burn'] = this.handleBurnEvent.bind(this); - this.handlers['Mint'] = this.handleMintEvent.bind(this); - this.handlers['SetFeeProtocol'] = this.handleSetFeeProtocolEvent.bind(this); - this.handlers['IncreaseObservationCardinalityNext'] = - this.handleIncreaseObservationCardinalityNextEvent.bind(this); - - // Wen need them to keep balance of the pool up to date - this.handlers['Collect'] = this.handleCollectEvent.bind(this); - // Almost the same as Collect, but for pool owners - this.handlers['CollectProtocol'] = this.handleCollectEvent.bind(this); - this.handlers['Flash'] = this.handleFlashEvent.bind(this); - } - - get poolAddress() { - if (this._poolAddress === undefined) { - this._poolAddress = this._computePoolAddress( - this.token0, - this.token1, - this.feeCode, - ); - } - return this._poolAddress; - } - - set poolAddress(address: Address) { - this._poolAddress = address.toLowerCase(); - } - - async initialize( - blockNumber: number, - options?: InitializeStateOptions, - ) { - await super.initialize(blockNumber, options); - } - - protected async processBlockLogs( - state: DeepReadonly, - logs: Readonly[], - blockHeader: Readonly, - ): Promise | null> { - const newState = await super.processBlockLogs(state, logs, blockHeader); - if (newState && !newState.isValid) { - return await this.generateState(blockHeader.number); - } - return newState; - } - - protected processLog( - state: DeepReadonly, - log: Readonly, - blockHeader: Readonly, - ): DeepReadonly | null { - try { - const event = this.logDecoder(log); - - const uniswapV3EventLoggingSampleRate = - this.dexHelper.config.data.uniswapV3EventLoggingSampleRate; - if ( - !this.dexHelper.config.isSlave && - uniswapV3EventLoggingSampleRate && - isSampled(uniswapV3EventLoggingSampleRate) - ) { - this.logger.info( - `event=${event.name} - block=${ - blockHeader.number - }. Log sampled at rate ${uniswapV3EventLoggingSampleRate * 100}%`, - ); - } - - if (event.name in this.handlers) { - // Because we have observations in array which is mutable by nature, there is a - // ts compile error: https://stackoverflow.com/questions/53412934/disable-allowing-assigning-readonly-types-to-non-readonly-types - // And there is no good workaround, so turn off the type checker for this line - const _state = _.cloneDeep(state) as PoolState; - try { - return this.handlers[event.name](event, _state, log, blockHeader); - } catch (e) { - if ( - e instanceof Error && - e.message.endsWith(OUT_OF_RANGE_ERROR_POSTFIX) - ) { - this.logger.warn( - `${this.parentName}: Pool ${this.poolAddress} on ${ - this.dexHelper.config.data.network - } is out of TickBitmap requested range. Re-query the state. ${JSON.stringify( - event, - )}`, - e, - ); - } else { - this.logger.error( - `${this.parentName}: Pool ${this.poolAddress}, ` + - `network=${this.dexHelper.config.data.network}: Unexpected ` + - `error while handling event on blockNumber=${blockHeader.number}, ` + - `blockHash=${blockHeader.hash} and parentHash=${ - blockHeader.parentHash - } for UniswapV3, ${JSON.stringify(event)}`, - e, - ); - } - _state.isValid = false; - return _state; - } - } - } catch (e) { - catchParseLogError(e, this.logger); - } - return null; // ignore unrecognized event - } - - protected _getStateRequestCallData() { - if (!this._stateRequestCallData) { - const callData: MultiCallParams< - bigint | DecodedStateMultiCallResultWithRelativeBitmaps - >[] = [ - { - target: this.token0, - callData: this.erc20Interface.encodeFunctionData('balanceOf', [ - this.poolAddress, - ]), - decodeFunction: uint256ToBigInt, - }, - { - target: this.token1, - callData: this.erc20Interface.encodeFunctionData('balanceOf', [ - this.poolAddress, - ]), - decodeFunction: uint256ToBigInt, - }, - { - target: this.stateMultiContract.options.address, - callData: this.stateMultiContract.methods - .getFullStateWithRelativeBitmaps( - this.factoryAddress, - this.token0, - this.token1, - this.feeCode, - this.getBitmapRangeToRequest(), - this.getBitmapRangeToRequest(), - ) - .encodeABI(), - decodeFunction: - this.decodeStateMultiCallResultWithRelativeBitmaps !== undefined - ? this.decodeStateMultiCallResultWithRelativeBitmaps - : decodeStateMultiCallResultWithRelativeBitmaps, - }, - ]; - - this._stateRequestCallData = callData; - } - return this._stateRequestCallData; - } - - getBitmapRangeToRequest() { - return TICK_BITMAP_TO_USE + TICK_BITMAP_BUFFER; - } - - async generateState(blockNumber: number): Promise> { - const callData = this._getStateRequestCallData(); - - const [resBalance0, resBalance1, resState] = - await this.dexHelper.multiWrapper.tryAggregate< - bigint | DecodedStateMultiCallResultWithRelativeBitmaps - >( - false, - callData, - blockNumber, - this.dexHelper.multiWrapper.defaultBatchSize, - false, - ); - - // Quite ugly solution, but this is the one that fits to current flow. - // I think UniswapV3 callbacks subscriptions are complexified for no reason. - // Need to be revisited later - assert(resState.success, 'Pool does not exist'); - - const [balance0, balance1, _state] = [ - resBalance0.returnData, - resBalance1.returnData, - resState.returnData, - ] as [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmaps]; - - const tickBitmap = {}; - const ticks = {}; - - _reduceTickBitmap(tickBitmap, _state.tickBitmap); - _reduceTicks(ticks, _state.ticks); - - const observations = { - [_state.slot0.observationIndex]: { - blockTimestamp: bigIntify(_state.observation.blockTimestamp), - tickCumulative: bigIntify(_state.observation.tickCumulative), - secondsPerLiquidityCumulativeX128: bigIntify( - _state.observation.secondsPerLiquidityCumulativeX128, - ), - initialized: _state.observation.initialized, - }, - }; - - const currentTick = bigIntify(_state.slot0.tick); - const tickSpacing = bigIntify(_state.tickSpacing); - - const startTickBitmap = TickBitMap.position(currentTick / tickSpacing)[0]; - const requestedRange = this.getBitmapRangeToRequest(); - - return { - pool: _state.pool, - blockTimestamp: bigIntify(_state.blockTimestamp), - slot0: { - sqrtPriceX96: bigIntify(_state.slot0.sqrtPriceX96), - tick: currentTick, - observationIndex: +_state.slot0.observationIndex, - observationCardinality: +_state.slot0.observationCardinality, - observationCardinalityNext: +_state.slot0.observationCardinalityNext, - feeProtocol: bigIntify(_state.slot0.feeProtocol), - }, - liquidity: bigIntify(_state.liquidity), - fee: this.feeCode, - tickSpacing, - maxLiquidityPerTick: bigIntify(_state.maxLiquidityPerTick), - tickBitmap, - ticks, - observations, - isValid: true, - startTickBitmap, - lowestKnownTick: - (BigInt.asIntN(24, startTickBitmap - requestedRange) << 8n) * - tickSpacing, - highestKnownTick: - ((BigInt.asIntN(24, startTickBitmap + requestedRange) << 8n) + - BigInt.asIntN(24, 255n)) * - tickSpacing, - balance0, - balance1, - }; - } - - handleSwapEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - const newSqrtPriceX96 = bigIntify(event.args.sqrtPriceX96); - const amount0 = bigIntify(event.args.amount0); - const amount1 = bigIntify(event.args.amount1); - const newTick = bigIntify(event.args.tick); - const newLiquidity = bigIntify(event.args.liquidity); - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - - if (amount0 <= 0n && amount1 <= 0n) { - this.logger.error( - `${this.parentName}: amount0 <= 0n && amount1 <= 0n for ` + - `${this.poolAddress} and ${blockHeader.number}. Check why it happened`, - ); - pool.isValid = false; - return pool; - } else { - const zeroForOne = amount0 > 0n; - - uniswapV3Math.swapFromEvent( - pool, - newSqrtPriceX96, - newTick, - newLiquidity, - zeroForOne, - ); - - if (zeroForOne) { - if (amount1 < 0n) { - pool.balance1 -= BigInt.asUintN(256, -amount1); - } else { - this.logger.error( - `In swapEvent for pool ${pool.pool} received incorrect values ${zeroForOne} and ${amount1}`, - ); - pool.isValid = false; - } - // This is not correct fully, because pool may get more tokens then it needs, but - // it is not accounted in internal state, it should be good enough - pool.balance0 += BigInt.asUintN(256, amount0); - } else { - if (amount0 < 0n) { - pool.balance0 -= BigInt.asUintN(256, -amount0); - } else { - this.logger.error( - `In swapEvent for pool ${pool.pool} received incorrect values ${zeroForOne} and ${amount0}`, - ); - pool.isValid = false; - } - pool.balance1 += BigInt.asUintN(256, amount1); - } - - return pool; - } - } - - handleBurnEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - const amount = bigIntify(event.args.amount); - const tickLower = bigIntify(event.args.tickLower); - const tickUpper = bigIntify(event.args.tickUpper); - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - - uniswapV3Math._modifyPosition(pool, { - tickLower, - tickUpper, - liquidityDelta: -BigInt.asIntN(128, BigInt.asIntN(256, amount)), - }); - - // From this transaction I conclude that there is no balance change from - // Burn event: https://dashboard.tenderly.co/tx/mainnet/0xfccf5341147ac3ad0e66452273d12dfc3219e81f8fb369a6cdecfb24b9b9d078/logs - // And it aligns with UniswapV3 doc: - // https://github.com/Uniswap/v3-core/blob/05c10bf6d547d6121622ac51c457f93775e1df09/contracts/interfaces/pool/IUniswapV3PoolActions.sol#L59 - // It just updates positions and tokensOwed which may be requested calling collect - // So, we don't need to update pool.balances0 and pool.balances1 here - - return pool; - } - - handleMintEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - const amount = bigIntify(event.args.amount); - const tickLower = bigIntify(event.args.tickLower); - const tickUpper = bigIntify(event.args.tickUpper); - const amount0 = bigIntify(event.args.amount0); - const amount1 = bigIntify(event.args.amount1); - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - - uniswapV3Math._modifyPosition(pool, { - tickLower, - tickUpper, - liquidityDelta: amount, - }); - - pool.balance0 += amount0; - pool.balance1 += amount1; - - return pool; - } - - handleSetFeeProtocolEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - const feeProtocol0 = bigIntify(event.args.feeProtocol0New); - const feeProtocol1 = bigIntify(event.args.feeProtocol1New); - pool.slot0.feeProtocol = feeProtocol0 + (feeProtocol1 << 4n); - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - - return pool; - } - - handleCollectEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - const amount0 = bigIntify(event.args.amount0); - const amount1 = bigIntify(event.args.amount1); - pool.balance0 -= amount0; - pool.balance1 -= amount1; - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - - return pool; - } - - handleFlashEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - const paid0 = bigIntify(event.args.paid0); - const paid1 = bigIntify(event.args.paid1); - pool.balance0 += paid0; - pool.balance1 += paid1; - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - - return pool; - } - - handleIncreaseObservationCardinalityNextEvent( - event: any, - pool: PoolState, - log: Log, - blockHeader: BlockHeader, - ) { - pool.slot0.observationCardinalityNext = parseInt( - event.args.observationCardinalityNextNew, - 10, - ); - pool.blockTimestamp = bigIntify(blockHeader.timestamp); - return pool; - } - - private _computePoolAddress( - token0: Address, - token1: Address, - fee: bigint, - ): Address { - // https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/PoolAddress.sol - if (token0 > token1) [token0, token1] = [token1, token0]; - - const encodedKey = ethers.utils.keccak256( - ethers.utils.defaultAbiCoder.encode( - ['address', 'address', 'uint24'], - [token0, token1, BigInt.asUintN(24, fee)], - ), - ); - - return ethers.utils.getCreate2Address( - this.factoryAddress, - encodedKey, - this.poolInitCodeHash, - ); - } -} diff --git a/src/dex/baseswap-v3/baseswap-v3.ts b/src/dex/baseswap-v3/baseswap-v3.ts deleted file mode 100644 index e4c9e06a1..000000000 --- a/src/dex/baseswap-v3/baseswap-v3.ts +++ /dev/null @@ -1,1243 +0,0 @@ -import { defaultAbiCoder, Interface } from '@ethersproject/abi'; -import _ from 'lodash'; -import { pack } from '@ethersproject/solidity'; -import { - AdapterExchangeParam, - Address, - ExchangePrices, - ExchangeTxInfo, - Logger, - NumberAsString, - PoolLiquidity, - PoolPrices, - PreprocessTransactionOptions, - SimpleExchangeParam, - Token, - TxInfo, -} from '../../types'; -import { CACHE_PREFIX, Network, SwapSide } from '../../constants'; -import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { - getBigIntPow, - getDexKeysWithNetwork, - interpolate, - isTruthy, - uuidToBytes16, -} from '../../utils'; -import { IDex } from '../idex'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { - DexParams, - OutputResult, - PoolState, - UniswapV3Data, - UniswapV3Functions, - UniswapV3Param, - UniswapV3SimpleSwapParams, -} from './types'; -import { - getLocalDeadlineAsFriendlyPlaceholder, - SimpleExchange, -} from '../simple-exchange'; -import { Adapters, PoolsToPreload, BaseswapV3Config } from './config'; -import { BaseswapV3EventPool } from './baseswap-v3-pool'; -import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; -import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; -import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; -import DirectSwapABI from '../../abi/DirectSwap.json'; -import UniswapV3StateMulticallABI from '../../abi/uniswap-v3/UniswapV3StateMulticall.abi.json'; -import { - DirectMethods, - UNISWAPV3_EFFICIENCY_FACTOR, - UNISWAPV3_POOL_SEARCH_OVERHEAD, - UNISWAPV3_TICK_BASE_OVERHEAD, - UNISWAPV3_TICK_GAS_COST, -} from './constants'; -import { assert, DeepReadonly } from 'ts-essentials'; -import { uniswapV3Math } from './contract-math/uniswap-v3-math'; -import { Contract } from 'web3-eth-contract'; -import { AbiItem } from 'web3-utils'; -import { BalanceRequest, getBalances } from '../../lib/tokens/balancer-fetcher'; -import { - AssetType, - DEFAULT_ID_ERC20, - DEFAULT_ID_ERC20_AS_STRING, -} from '../../lib/tokens/types'; -import { OptimalSwapExchange } from '@paraswap/core'; -import { - OnPoolCreatedCallback, - BaseswapV3Factory, -} from './baseswap-v3-factory'; - -type PoolPairsInfo = { - token0: Address; - token1: Address; - fee: string; -}; - -const BASESWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 3 * 24 * 60 * 60 * 1000; // 3 days -const BASESWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 24 * 60 * 60 * 1000; // Once in a day -const BASESWAPV3_QUOTE_GASLIMIT = 200_000; - -export class BaseswapV3 - extends SimpleExchange - implements IDex -{ - private readonly factory: BaseswapV3Factory; - readonly isFeeOnTransferSupported: boolean = false; - readonly eventPools: Record = {}; - - readonly hasConstantPriceLargeAmounts = false; - readonly needWrapNative = true; - - readonly directSwapIface = new Interface(DirectSwapABI); - - intervalTask?: NodeJS.Timeout; - - public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(_.pick(BaseswapV3Config, ['BaseswapV3'])); - - logger: Logger; - - private uniswapMulti: Contract; - private stateMultiContract: Contract; - - private notExistingPoolSetKey: string; - - constructor( - protected network: Network, - dexKey: string, - protected dexHelper: IDexHelper, - protected adapters = Adapters[network] || {}, - readonly routerIface = new Interface(UniswapV3RouterABI), - readonly quoterIface = new Interface(UniswapV3QuoterV2ABI), - protected config = BaseswapV3Config[dexKey][network], - protected poolsToPreload = PoolsToPreload[dexKey]?.[network] || [], - ) { - super(dexHelper, dexKey); - this.logger = dexHelper.getLogger(dexKey + '-' + network); - this.uniswapMulti = new this.dexHelper.web3Provider.eth.Contract( - UniswapV3MultiABI as AbiItem[], - this.config.uniswapMulticall, - ); - this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( - this.config.stateMultiCallAbi !== undefined - ? this.config.stateMultiCallAbi - : (UniswapV3StateMulticallABI as AbiItem[]), - this.config.stateMulticall, - ); - - // To receive revert reasons - this.dexHelper.web3Provider.eth.handleRevert = false; - - // Normalize once all config addresses and use across all scenarios - this.config = this._toLowerForAllConfigAddresses(); - - this.notExistingPoolSetKey = - `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); - - this.factory = new BaseswapV3Factory( - dexHelper, - dexKey, - this.config.factory, - this.logger, - this.onPoolCreatedDeleteFromNonExistingSet, - ); - } - - get supportedFees() { - return this.config.supportedFees; - } - - getAdapters(side: SwapSide): { name: string; index: number }[] | null { - return this.adapters[side] ? this.adapters[side] : null; - } - - getPoolIdentifier(srcAddress: Address, destAddress: Address, fee: bigint) { - const tokenAddresses = this._sortTokens(srcAddress, destAddress).join('_'); - return `${this.dexKey}_${tokenAddresses}_${fee}`; - } - - async initializePricing(blockNumber: number) { - // Init listening to new pools creation - await this.factory.initialize(blockNumber); - - // This is only for testing, because cold pool fetching is goes out of - // FETCH_POOL_INDENTIFIER_TIMEOUT range - await Promise.all( - this.poolsToPreload.map(async pool => - Promise.all( - this.config.supportedFees.map(async fee => - this.getPool(pool.token0, pool.token1, fee, blockNumber), - ), - ), - ), - ); - - if (!this.dexHelper.config.isSlave) { - const cleanExpiredNotExistingPoolsKeys = async () => { - const maxTimestamp = - Date.now() - BASESWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS; - await this.dexHelper.cache.zremrangebyscore( - this.notExistingPoolSetKey, - 0, - maxTimestamp, - ); - }; - - this.intervalTask = setInterval( - cleanExpiredNotExistingPoolsKeys.bind(this), - BASESWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS, - ); - } - } - - /* - * When a non existing pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls - * Once the pool is created, it gets immediately flagged - */ - onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ - token0, - token1, - fee, - }) => { - const logPrefix = '[UniswapV3.onPoolCreatedDeleteFromNonExistingSet]'; - const [_token0, _token1] = this._sortTokens(token0, token1); - const poolKey = `${_token0}_${_token1}_${fee}`; - - // consider doing it only from master pool for less calls to distant cache - - // delete entry locally to let local instance discover the pool - delete this.eventPools[this.getPoolIdentifier(_token0, _token1, fee)]; - - try { - this.logger.info( - `${logPrefix} delete pool from not existing set: ${poolKey}`, - ); - // delete pool record from set - await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); - } catch (error) { - this.logger.error( - `${logPrefix} failed to delete pool from set: ${poolKey}`, - error, - ); - } - }; - - async getPool( - srcAddress: Address, - destAddress: Address, - fee: bigint, - blockNumber: number, - ): Promise { - let pool = this.eventPools[ - this.getPoolIdentifier(srcAddress, destAddress, fee) - ] as BaseswapV3EventPool | null | undefined; - - if (pool === null) return null; - - if (pool) { - if (!pool.initFailed) { - return pool; - } else { - // if init failed then prefer to early return pool with empty state to fallback to rpc call - if ( - ++pool.initRetryAttemptCount % this.config.initRetryFrequency !== - 0 - ) { - return pool; - } - // else pursue with re-try initialization - } - } - - const [token0, token1] = this._sortTokens(srcAddress, destAddress); - - const key = `${token0}_${token1}_${fee}`.toLowerCase(); - - if (!pool) { - const notExistingPoolScore = await this.dexHelper.cache.zscore( - this.notExistingPoolSetKey, - key, - ); - - const poolDoesNotExist = notExistingPoolScore !== null; - - if (poolDoesNotExist) { - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - null; - return null; - } - - await this.dexHelper.cache.hset( - this.dexmapKey, - key, - JSON.stringify({ - token0, - token1, - fee: fee.toString(), - }), - ); - } - - this.logger.trace(`starting to listen to new pool: ${key}`); - - const poolImplementation = - this.config.eventPoolImplementation !== undefined - ? this.config.eventPoolImplementation - : BaseswapV3EventPool; - - pool = - pool || - new poolImplementation( - this.dexHelper, - this.dexKey, - this.stateMultiContract, - this.config.decodeStateMultiCallResultWithRelativeBitmaps, - this.erc20Interface, - this.config.factory, - fee, - token0, - token1, - this.logger, - this.cacheStateKey, - this.config.initHash, - ); - - try { - await pool.initialize(blockNumber, { - initCallback: (state: DeepReadonly) => { - //really hacky, we need to push poolAddress so that we subscribeToLogs in StatefulEventSubscriber - pool!.addressesSubscribed[0] = state.pool; - pool!.poolAddress = state.pool; - pool!.initFailed = false; - pool!.initRetryAttemptCount = 0; - }, - }); - } catch (e) { - if (e instanceof Error && e.message.endsWith('Pool does not exist')) { - // no need to await we want the set to have the pool key but it's not blocking - this.dexHelper.cache.zadd( - this.notExistingPoolSetKey, - [Date.now(), key], - 'NX', - ); - - // Pool does not exist for this feeCode, so we can set it to null - // to prevent more requests for this pool - pool = null; - this.logger.trace( - `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} not found`, - e, - ); - } else { - // on unknown error mark as failed and increase retryCount for retry init strategy - // note: state would be null by default which allows to fallback - this.logger.warn( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress}, fee=${fee} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, - e, - ); - pool.initFailed = true; - } - } - - if (pool !== null) { - const allEventPools = Object.values(this.eventPools); - this.logger.info( - `starting to listen to new non-null pool: ${key}. Already following ${allEventPools - // Not that I like this reduce, but since it is done only on initialization, expect this to be ok - .reduce( - (acc, curr) => (curr !== null ? ++acc : acc), - 0, - )} non-null pools or ${allEventPools.length} total pools`, - ); - } - - this.eventPools[this.getPoolIdentifier(srcAddress, destAddress, fee)] = - pool; - return pool; - } - - async addMasterPool(poolKey: string, blockNumber: number): Promise { - const _pairs = await this.dexHelper.cache.hget(this.dexmapKey, poolKey); - if (!_pairs) { - this.logger.warn( - `did not find poolConfig in for key ${this.dexmapKey} ${poolKey}`, - ); - return false; - } - - const poolInfo: PoolPairsInfo = JSON.parse(_pairs); - - const pool = await this.getPool( - poolInfo.token0, - poolInfo.token1, - BigInt(poolInfo.fee), - blockNumber, - ); - - if (!pool) { - return false; - } - - return true; - } - - async getPoolIdentifiers( - srcToken: Token, - destToken: Token, - side: SwapSide, - blockNumber: number, - ): Promise { - const _srcToken = this.dexHelper.config.wrapETH(srcToken); - const _destToken = this.dexHelper.config.wrapETH(destToken); - - const [_srcAddress, _destAddress] = this._getLoweredAddresses( - _srcToken, - _destToken, - ); - - if (_srcAddress === _destAddress) return []; - - const pools = ( - await Promise.all( - this.supportedFees.map(async fee => - this.getPool(_srcAddress, _destAddress, fee, blockNumber), - ), - ) - ).filter(pool => pool); - - if (pools.length === 0) return []; - - return pools.map(pool => - this.getPoolIdentifier(_srcAddress, _destAddress, pool!.feeCode), - ); - } - - async getPricingFromRpc( - from: Token, - to: Token, - amounts: bigint[], - side: SwapSide, - pools: BaseswapV3EventPool[], - states: PoolState[], - ): Promise | null> { - if (pools.length === 0) { - return null; - } - this.logger.warn(`fallback to rpc for ${pools.length} pool(s)`); - - const requests = pools.map( - pool => ({ - owner: pool.poolAddress, - asset: side == SwapSide.SELL ? from.address : to.address, - assetType: AssetType.ERC20, - ids: [ - { - id: DEFAULT_ID_ERC20, - spenders: [], - }, - ], - }), - [], - ); - - const balances = await getBalances(this.dexHelper.multiWrapper, requests); - - pools = pools.filter((pool, index) => { - const balance = balances[index].amounts[DEFAULT_ID_ERC20_AS_STRING]; - if (balance >= amounts[amounts.length - 1]) { - return true; - } - this.logger.warn( - `[${this.network}][${pool.parentName}] have no balance ${pool.poolAddress} ${from.address} ${to.address}. (Balance: ${balance})`, - ); - return false; - }); - - pools.forEach(pool => { - this.logger.warn( - `[${this.network}][${pool.parentName}] fallback to rpc for ${pool.name}`, - ); - }); - - const unitVolume = getBigIntPow( - (side === SwapSide.SELL ? from : to).decimals, - ); - - const chunks = amounts.length - 1; - - const _width = Math.floor(chunks / this.config.chunksCount); - - const _amounts = [unitVolume].concat( - Array.from(Array(this.config.chunksCount).keys()).map( - i => amounts[(i + 1) * _width], - ), - ); - - const calldata = pools.map(pool => - _amounts.map(_amount => ({ - target: this.config.quoter, - gasLimit: BASESWAPV3_QUOTE_GASLIMIT, - callData: - side === SwapSide.SELL - ? this.quoterIface.encodeFunctionData('quoteExactInputSingle', [ - [ - from.address, - to.address, - _amount.toString(), - pool.feeCodeAsString, - 0, //sqrtPriceLimitX96 - ], - ]) - : this.quoterIface.encodeFunctionData('quoteExactOutputSingle', [ - [ - from.address, - to.address, - _amount.toString(), - pool.feeCodeAsString, - 0, //sqrtPriceLimitX96 - ], - ]), - })), - ); - - const data = await this.uniswapMulti.methods - .multicall(calldata.flat()) - .call(); - - const decode = (j: number): bigint => { - if (!data.returnData[j].success) { - return 0n; - } - const decoded = defaultAbiCoder.decode( - ['uint256'], - data.returnData[j].returnData, - ); - return BigInt(decoded[0].toString()); - }; - - let i = 0; - const result = pools.map((pool, index) => { - const _rates = _amounts.map(() => decode(i++)); - const unit: bigint = _rates[0]; - - const prices = interpolate( - _amounts.slice(1), - _rates.slice(1), - amounts, - side, - ); - - return { - prices, - unit, - data: { - path: [ - { - tokenIn: from.address, - tokenOut: to.address, - fee: pool.feeCodeAsString, - currentFee: states[index].fee.toString(), - }, - ], - exchange: pool.poolAddress, - }, - poolIdentifier: this.getPoolIdentifier( - pool.token0, - pool.token1, - pool.feeCode, - ), - exchange: this.dexKey, - gasCost: prices.map(p => (p === 0n ? 0 : BASESWAPV3_QUOTE_GASLIMIT)), - poolAddresses: [pool.poolAddress], - }; - }); - - return result; - } - - async getPricesVolume( - srcToken: Token, - destToken: Token, - amounts: bigint[], - side: SwapSide, - blockNumber: number, - limitPools?: string[], - ): Promise> { - try { - const _srcToken = this.dexHelper.config.wrapETH(srcToken); - const _destToken = this.dexHelper.config.wrapETH(destToken); - - const [_srcAddress, _destAddress] = this._getLoweredAddresses( - _srcToken, - _destToken, - ); - - if (_srcAddress === _destAddress) return null; - - let selectedPools: BaseswapV3EventPool[] = []; - - if (!limitPools) { - selectedPools = ( - await Promise.all( - this.supportedFees.map(async fee => { - const locallyFoundPool = - this.eventPools[ - this.getPoolIdentifier(_srcAddress, _destAddress, fee) - ]; - if (locallyFoundPool) return locallyFoundPool; - - const newlyFetchedPool = await this.getPool( - _srcAddress, - _destAddress, - fee, - blockNumber, - ); - return newlyFetchedPool; - }), - ) - ).filter(isTruthy); - } else { - const pairIdentifierWithoutFee = this.getPoolIdentifier( - _srcAddress, - _destAddress, - 0n, - // Trim from 0 fee postfix, so it become comparable - ).slice(0, -1); - - const poolIdentifiers = limitPools.filter(identifier => - identifier.startsWith(pairIdentifierWithoutFee), - ); - - selectedPools = ( - await Promise.all( - poolIdentifiers.map(async identifier => { - let locallyFoundPool = this.eventPools[identifier]; - if (locallyFoundPool) return locallyFoundPool; - - const [, srcAddress, destAddress, fee] = identifier.split('_'); - const newlyFetchedPool = await this.getPool( - srcAddress, - destAddress, - BigInt(fee), - blockNumber, - ); - return newlyFetchedPool; - }), - ) - ).filter(isTruthy); - } - - if (selectedPools.length === 0) return null; - - const poolsToUse = selectedPools.reduce( - (acc, pool) => { - let state = pool.getState(blockNumber); - if (state === null) { - this.logger.trace( - `${this.dexKey}: State === null. Fallback to rpc ${pool.name}`, - ); - acc.poolWithoutState.push(pool); - } else { - acc.poolWithState.push(pool); - } - return acc; - }, - { - poolWithState: [] as BaseswapV3EventPool[], - poolWithoutState: [] as BaseswapV3EventPool[], - }, - ); - - const states = poolsToUse.poolWithState.map( - p => p.getState(blockNumber)!, - ); - - const rpcResultsPromise = this.getPricingFromRpc( - _srcToken, - _destToken, - amounts, - side, - this.network === Network.ZKEVM ? [] : poolsToUse.poolWithoutState, - this.network === Network.ZKEVM ? [] : states, - ); - - const unitAmount = getBigIntPow( - side == SwapSide.SELL ? _srcToken.decimals : _destToken.decimals, - ); - - const _amounts = [...amounts.slice(1)]; - - const [token0] = this._sortTokens(_srcAddress, _destAddress); - - const zeroForOne = token0 === _srcAddress ? true : false; - - const result = await Promise.all( - poolsToUse.poolWithState.map(async (pool, i) => { - const state = states[i]; - - if (state.liquidity <= 0n) { - if (state.liquidity < 0) { - this.logger.error( - `${this.dexKey}-${this.network}: ${pool.poolAddress} pool has negative liquidity: ${state.liquidity}. Find with key: ${pool.mapKey}`, - ); - } - this.logger.trace(`pool have 0 liquidity`); - return null; - } - - const balanceDestToken = - _destAddress === pool.token0 ? state.balance0 : state.balance1; - - const unitResult = this._getOutputs( - state, - [unitAmount], - zeroForOne, - side, - balanceDestToken, - ); - const pricesResult = this._getOutputs( - state, - _amounts, - zeroForOne, - side, - balanceDestToken, - ); - - if (!unitResult || !pricesResult) { - this.logger.debug('Prices or unit is not calculated'); - return null; - } - - const prices = [0n, ...pricesResult.outputs]; - const gasCost = [ - 0, - ...pricesResult.outputs.map((p, index) => { - if (p == 0n) { - return 0; - } else { - return ( - UNISWAPV3_POOL_SEARCH_OVERHEAD + - UNISWAPV3_TICK_BASE_OVERHEAD + - pricesResult.tickCounts[index] * UNISWAPV3_TICK_GAS_COST - ); - } - }), - ]; - return { - unit: unitResult.outputs[0], - prices, - data: { - path: [ - { - tokenIn: _srcAddress, - tokenOut: _destAddress, - fee: pool.feeCode.toString(), - currentFee: state.fee.toString(), - }, - ], - }, - poolIdentifier: this.getPoolIdentifier( - pool.token0, - pool.token1, - pool.feeCode, - ), - exchange: this.dexKey, - gasCost: gasCost, - poolAddresses: [pool.poolAddress], - }; - }), - ); - const rpcResults = await rpcResultsPromise; - - const notNullResult = result.filter( - res => res !== null, - ) as ExchangePrices; - - if (rpcResults) { - rpcResults.forEach(r => { - if (r) { - notNullResult.push(r); - } - }); - } - - return notNullResult; - } catch (e) { - this.logger.error( - `Error_getPricesVolume ${srcToken.symbol || srcToken.address}, ${ - destToken.symbol || destToken.address - }, ${side}:`, - e, - ); - return null; - } - } - - getAdapterParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, - data: UniswapV3Data, - side: SwapSide, - ): AdapterExchangeParam { - const { path: rawPath } = data; - const path = this._encodePath(rawPath, side); - - const payload = this.abiCoder.encodeParameter( - { - ParentStruct: { - path: 'bytes', - deadline: 'uint256', - }, - }, - { - path, - deadline: getLocalDeadlineAsFriendlyPlaceholder(), // FIXME: more gas efficient to pass block.timestamp in adapter - }, - ); - - return { - targetExchange: this.config.router, - payload, - networkFee: '0', - }; - } - - getCalldataGasCost(poolPrices: PoolPrices): number | number[] { - const gasCost = - CALLDATA_GAS_COST.DEX_OVERHEAD + - CALLDATA_GAS_COST.LENGTH_SMALL + - // ParentStruct header - CALLDATA_GAS_COST.OFFSET_SMALL + - // ParentStruct -> path header - CALLDATA_GAS_COST.OFFSET_SMALL + - // ParentStruct -> deadline - CALLDATA_GAS_COST.TIMESTAMP + - // ParentStruct -> path (20+3+20 = 43 = 32+11 bytes) - CALLDATA_GAS_COST.LENGTH_SMALL + - CALLDATA_GAS_COST.FULL_WORD + - CALLDATA_GAS_COST.wordNonZeroBytes(11); - const arr = new Array(poolPrices.prices.length); - poolPrices.prices.forEach((p, index) => { - if (p == 0n) { - arr[index] = 0; - } else { - arr[index] = gasCost; - } - }); - return arr; - } - - getTokenFromAddress(address: Address): Token { - // In this Dex decimals are not used - return { address, decimals: 0 }; - } - - async preProcessTransaction( - optimalSwapExchange: OptimalSwapExchange, - srcToken: Token, - _0: Token, - _1: SwapSide, - options: PreprocessTransactionOptions, - ): Promise<[OptimalSwapExchange, ExchangeTxInfo]> { - if (!options.isDirectMethod) { - return [ - optimalSwapExchange, - { - deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), - }, - ]; - } - - assert( - optimalSwapExchange.data !== undefined, - `preProcessTransaction: data field is missing`, - ); - - let isApproved: boolean | undefined; - - try { - this.erc20Contract.options.address = - this.dexHelper.config.wrapETH(srcToken).address; - const allowance = await this.erc20Contract.methods - .allowance(this.augustusAddress, this.config.router) - .call(undefined, 'latest'); - isApproved = - BigInt(allowance.toString()) >= BigInt(optimalSwapExchange.srcAmount); - } catch (e) { - this.logger.error( - `preProcessTransaction failed to retrieve allowance info: `, - e, - ); - } - - return [ - { - ...optimalSwapExchange, - data: { - ...optimalSwapExchange.data, - isApproved, - }, - }, - { - deadline: BigInt(getLocalDeadlineAsFriendlyPlaceholder()), - }, - ]; - } - - getDirectParam( - srcToken: Address, - destToken: Address, - srcAmount: NumberAsString, - destAmount: NumberAsString, - expectedAmount: NumberAsString, - data: UniswapV3Data, - side: SwapSide, - permit: string, - uuid: string, - feePercent: NumberAsString, - deadline: NumberAsString, - partner: string, - beneficiary: string, - contractMethod?: string, - ): TxInfo { - if ( - contractMethod !== DirectMethods.directSell && - contractMethod !== DirectMethods.directBuy - ) { - throw new Error(`Invalid contract method ${contractMethod}`); - } - - let isApproved: boolean = !!data.isApproved; - if (data.isApproved === undefined) { - this.logger.warn(`isApproved is undefined, defaulting to false`); - } - - const path = this._encodePath(data.path, side); - - const swapParams: UniswapV3Param = [ - srcToken, - destToken, - this.config.router, - srcAmount, - destAmount, - expectedAmount, - feePercent, - deadline, - partner, - isApproved, - beneficiary, - path, - permit, - uuidToBytes16(uuid), - ]; - - const encoder = (...params: UniswapV3Param) => { - return this.directSwapIface.encodeFunctionData( - side === SwapSide.SELL - ? DirectMethods.directSell - : DirectMethods.directBuy, - [params], - ); - }; - - return { - params: swapParams, - encoder, - networkFee: '0', - }; - } - - static getDirectFunctionName(): string[] { - return [DirectMethods.directSell, DirectMethods.directBuy]; - } - - async getSimpleParam( - srcToken: string, - destToken: string, - srcAmount: string, - destAmount: string, - data: UniswapV3Data, - side: SwapSide, - ): Promise { - const swapFunction = - side === SwapSide.SELL - ? UniswapV3Functions.exactInput - : UniswapV3Functions.exactOutput; - - const path = this._encodePath(data.path, side); - const swapFunctionParams: UniswapV3SimpleSwapParams = - side === SwapSide.SELL - ? { - recipient: this.augustusAddress, - deadline: getLocalDeadlineAsFriendlyPlaceholder(), - amountIn: srcAmount, - amountOutMinimum: destAmount, - path, - } - : { - recipient: this.augustusAddress, - deadline: getLocalDeadlineAsFriendlyPlaceholder(), - amountOut: destAmount, - amountInMaximum: srcAmount, - path, - }; - const swapData = this.routerIface.encodeFunctionData(swapFunction, [ - swapFunctionParams, - ]); - - return this.buildSimpleParamWithoutWETHConversion( - srcToken, - srcAmount, - destToken, - destAmount, - swapData, - this.config.router, - ); - } - - async getTopPoolsForToken( - tokenAddress: Address, - limit: number, - ): Promise { - const _tokenAddress = tokenAddress.toLowerCase(); - - const res = await this._querySubgraph( - `query ($token: Bytes!, $count: Int) { - pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token}) { - id - token0 { - id - decimals - } - token1 { - id - decimals - } - totalValueLockedUSD - } - pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token}) { - id - token0 { - id - decimals - } - token1 { - id - decimals - } - totalValueLockedUSD - } - }`, - { - token: _tokenAddress, - count: limit, - }, - ); - - if (!(res && res.pools0 && res.pools1)) { - this.logger.error( - `Error_${this.dexKey}_Subgraph: couldn't fetch the pools from the subgraph`, - ); - return []; - } - - const pools0 = _.map(res.pools0, pool => ({ - exchange: this.dexKey, - address: pool.id.toLowerCase(), - connectorTokens: [ - { - address: pool.token1.id.toLowerCase(), - decimals: parseInt(pool.token1.decimals), - }, - ], - liquidityUSD: - parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, - })); - - const pools1 = _.map(res.pools1, pool => ({ - exchange: this.dexKey, - address: pool.id.toLowerCase(), - connectorTokens: [ - { - address: pool.token0.id.toLowerCase(), - decimals: parseInt(pool.token0.decimals), - }, - ], - liquidityUSD: - parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, - })); - - const pools = _.slice( - _.sortBy(_.concat(pools0, pools1), [pool => -1 * pool.liquidityUSD]), - 0, - limit, - ); - return pools; - } - - private async _getPoolsFromIdentifiers( - poolIdentifiers: string[], - blockNumber: number, - ): Promise { - const pools = await Promise.all( - poolIdentifiers.map(async identifier => { - const [, srcAddress, destAddress, fee] = identifier.split('_'); - return this.getPool(srcAddress, destAddress, BigInt(fee), blockNumber); - }), - ); - return pools.filter(pool => pool) as BaseswapV3EventPool[]; - } - - private _getLoweredAddresses(srcToken: Token, destToken: Token) { - return [srcToken.address.toLowerCase(), destToken.address.toLowerCase()]; - } - - private _sortTokens(srcAddress: Address, destAddress: Address) { - return [srcAddress, destAddress].sort((a, b) => (a < b ? -1 : 1)); - } - - private _toLowerForAllConfigAddresses() { - // If new config property will be added, the TS will throw compile error - const newConfig: DexParams = { - router: this.config.router.toLowerCase(), - quoter: this.config.quoter.toLowerCase(), - factory: this.config.factory.toLowerCase(), - supportedFees: this.config.supportedFees, - stateMulticall: this.config.stateMulticall.toLowerCase(), - chunksCount: this.config.chunksCount, - initRetryFrequency: this.config.initRetryFrequency, - uniswapMulticall: this.config.uniswapMulticall, - deployer: this.config.deployer?.toLowerCase(), - initHash: this.config.initHash, - subgraphURL: this.config.subgraphURL, - stateMultiCallAbi: this.config.stateMultiCallAbi, - eventPoolImplementation: this.config.eventPoolImplementation, - decodeStateMultiCallResultWithRelativeBitmaps: - this.config.decodeStateMultiCallResultWithRelativeBitmaps, - }; - return newConfig; - } - - private _getOutputs( - state: DeepReadonly, - amounts: bigint[], - zeroForOne: boolean, - side: SwapSide, - destTokenBalance: bigint, - ): OutputResult | null { - try { - const outputsResult = uniswapV3Math.queryOutputs( - state, - amounts, - zeroForOne, - side, - ); - - if (side === SwapSide.SELL) { - if (outputsResult.outputs[0] > destTokenBalance) { - return null; - } - - for (let i = 0; i < outputsResult.outputs.length; i++) { - if (outputsResult.outputs[i] > destTokenBalance) { - outputsResult.outputs[i] = 0n; - outputsResult.tickCounts[i] = 0; - } - } - } else { - if (amounts[0] > destTokenBalance) { - return null; - } - - // This may be improved by first checking outputs and requesting outputs - // only for amounts that makes more sense, but I don't think this is really - // important now - for (let i = 0; i < amounts.length; i++) { - if (amounts[i] > destTokenBalance) { - outputsResult.outputs[i] = 0n; - outputsResult.tickCounts[i] = 0; - } - } - } - - return outputsResult; - } catch (e) { - this.logger.debug( - `${this.dexKey}: received error in _getOutputs while calculating outputs`, - e, - ); - return null; - } - } - - private async _querySubgraph( - query: string, - variables: Object, - timeout = 30000, - ) { - try { - const res = await this.dexHelper.httpRequest.post( - this.config.subgraphURL, - { query, variables }, - undefined, - { timeout: timeout }, - ); - return res.data; - } catch (e) { - this.logger.error(`${this.dexKey}: can not query subgraph: `, e); - return {}; - } - } - - private _encodePath( - path: { - tokenIn: Address; - tokenOut: Address; - fee: NumberAsString; - }[], - side: SwapSide, - ): string { - if (path.length === 0) { - this.logger.error( - `${this.dexKey}: Received invalid path=${path} for side=${side} to encode`, - ); - return '0x'; - } - - const { _path, types } = path.reduce( - ( - { _path, types }: { _path: string[]; types: string[] }, - curr, - index, - ): { _path: string[]; types: string[] } => { - if (index === 0) { - return { - types: ['address', 'uint24', 'address'], - _path: [curr.tokenIn, curr.fee, curr.tokenOut], - }; - } else { - return { - types: [...types, 'uint24', 'address'], - _path: [..._path, curr.fee, curr.tokenOut], - }; - } - }, - { _path: [], types: [] }, - ); - - return side === SwapSide.BUY - ? pack(types.reverse(), _path.reverse()) - : pack(types, _path); - } - - releaseResources() { - if (this.intervalTask !== undefined) { - clearInterval(this.intervalTask); - this.intervalTask = undefined; - } - } -} diff --git a/src/dex/baseswap-v3/config.ts b/src/dex/baseswap-v3/config.ts deleted file mode 100644 index af233efdc..000000000 --- a/src/dex/baseswap-v3/config.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { DexParams } from './types'; -import { DexConfigMap, AdapterMappings } from '../../types'; -import { Network, SwapSide } from '../../constants'; -import { Address } from '../../types'; -// import RamsesV2StateMulticallABI from '../../abi/RamsesV2StateMulticall.abi.json'; -// import { AbiItem } from 'web3-utils'; -// import { decodeStateMultiCallResultWithRelativeBitmaps } from './forks/ramses-v2/utils'; -// import { RamsesV2EventPool } from './forks/ramses-v2/ramses-v2-pool'; - -const SUPPORTED_FEES = [10000n, 2500n, 450n, 80n]; - -// Pools that will be initialized on app startup -// They are added for testing -export const PoolsToPreload: DexConfigMap< - { token0: Address; token1: Address }[] -> = { - BaseswapV3: { - [Network.BASE]: [ - { - token0: '0x4200000000000000000000000000000000000006'.toLowerCase(), - token1: '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA'.toLowerCase(), // USDbC - }, - { - token0: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'.toLowerCase(), // USDC - token1: '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA'.toLowerCase(), // USDbC - }, - ], - }, -}; - -export const BaseswapV3Config: DexConfigMap = { - BaseswapV3: { - [Network.BASE]: { - factory: '0x38015D05f4fEC8AFe15D7cc0386a126574e8077B', - quoter: '0x4fDBD73aD4B1DDde594BF05497C15f76308eFfb9', - router: '0x1B8eea9315bE495187D873DA7773a874545D9D48', - supportedFees: SUPPORTED_FEES, - stateMulticall: '0x7160f736c52e1e78e92FD4eE4D73e21A7Cf4F950', - uniswapMulticall: '0x091e99cb1C49331a94dD62755D168E941AbD0693', - chunksCount: 10, - initRetryFrequency: 10, - initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - subgraphURL: 'https://api.thegraph.com/subgraphs/name/baseswapfi/v3-base', - }, - }, -}; - -export const Adapters: Record = { - [Network.BASE]: { - [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 1 }], - [SwapSide.BUY]: [{ name: 'BaseBuyAdapter', index: 1 }], - }, -}; diff --git a/src/dex/baseswap-v3/constants.ts b/src/dex/baseswap-v3/constants.ts deleted file mode 100644 index 5baae88e6..000000000 --- a/src/dex/baseswap-v3/constants.ts +++ /dev/null @@ -1,41 +0,0 @@ -export const UNISWAPV3_TICK_GAS_COST = 24_000; // Ceiled -export const UNISWAPV3_TICK_BASE_OVERHEAD = 75_000; -export const UNISWAPV3_POOL_SEARCH_OVERHEAD = 10_000; - -// This is used for price calculation. If out of scope, return 0n -export const TICK_BITMAP_TO_USE = 4n; - -// This is used to check if the state is still valid. -export const TICK_BITMAP_BUFFER = 8n; - -export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 128; - -export const UNISWAPV3_SUBGRAPH_URL = - 'https://api.thegraph.com/subgraphs/name/baseswapfi/v3-base'; - -export const UNISWAPV3_EFFICIENCY_FACTOR = 3; - -export const ZERO_TICK_INFO = { - liquidityGross: 0n, - liquidityNet: 0n, - tickCumulativeOutside: 0n, - secondsPerLiquidityOutsideX128: 0n, - secondsOutside: 0n, - initialized: false, -}; - -export const ZERO_ORACLE_OBSERVATION = { - blockTimestamp: 0n, - tickCumulative: 0n, - secondsPerLiquidityCumulativeX128: 0n, - initialized: false, -}; - -export const OUT_OF_RANGE_ERROR_POSTFIX = `INVALID_TICK_BIT_MAP_RANGES`; - -export const DEFAULT_POOL_INIT_CODE_HASH = `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`; - -export enum DirectMethods { - directSell = 'directUniV3Swap', - directBuy = 'directUniV3Buy', -} diff --git a/src/dex/baseswap-v3/contract-math/BitMath.ts b/src/dex/baseswap-v3/contract-math/BitMath.ts deleted file mode 100644 index d7a2e6d9a..000000000 --- a/src/dex/baseswap-v3/contract-math/BitMath.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { - BI_MAX_UINT128, - BI_MAX_UINT16, - BI_MAX_UINT32, - BI_MAX_UINT64, - BI_MAX_UINT8, -} from '../../../bigint-constants'; -import { _require } from '../../../utils'; - -export class BitMath { - static mostSignificantBit(x: bigint): bigint { - _require(x > 0, '', { x }, 'x > 0'); - let r = 0n; - - if (x >= 0x100000000000000000000000000000000n) { - x >>= 128n; - r += 128n; - } - if (x >= 0x10000000000000000n) { - x >>= 64n; - r += 64n; - } - if (x >= 0x100000000n) { - x >>= 32n; - r += 32n; - } - if (x >= 0x10000n) { - x >>= 16n; - r += 16n; - } - if (x >= 0x100n) { - x >>= 8n; - r += 8n; - } - if (x >= 0x10n) { - x >>= 4n; - r += 4n; - } - if (x >= 0x4n) { - x >>= 2n; - r += 2n; - } - if (x >= 0x2n) r += 1n; - - return r; - } - - static leastSignificantBit(x: bigint): bigint { - _require(x > 0, '', { x }, 'x > 0'); - - let r = 255n; - if ((x & BI_MAX_UINT128) > 0n) { - r -= 128n; - } else { - x >>= 128n; - } - if ((x & BI_MAX_UINT64) > 0n) { - r -= 64n; - } else { - x >>= 64n; - } - if ((x & BI_MAX_UINT32) > 0n) { - r -= 32n; - } else { - x >>= 32n; - } - if ((x & BI_MAX_UINT16) > 0n) { - r -= 16n; - } else { - x >>= 16n; - } - if ((x & BI_MAX_UINT8) > 0n) { - r -= 8n; - } else { - x >>= 8n; - } - if ((x & 0xfn) > 0n) { - r -= 4n; - } else { - x >>= 4n; - } - if ((x & 0x3n) > 0n) { - r -= 2n; - } else { - x >>= 2n; - } - if ((x & 0x1n) > 0n) r -= 1n; - return r; - } -} diff --git a/src/dex/baseswap-v3/contract-math/FixedPoint128.ts b/src/dex/baseswap-v3/contract-math/FixedPoint128.ts deleted file mode 100644 index 2058307bd..000000000 --- a/src/dex/baseswap-v3/contract-math/FixedPoint128.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class FixedPoint128 { - static readonly Q128 = 0x100000000000000000000000000000000n; -} diff --git a/src/dex/baseswap-v3/contract-math/FixedPoint96.ts b/src/dex/baseswap-v3/contract-math/FixedPoint96.ts deleted file mode 100644 index 1a551dcb9..000000000 --- a/src/dex/baseswap-v3/contract-math/FixedPoint96.ts +++ /dev/null @@ -1,4 +0,0 @@ -export class FixedPoint96 { - static readonly RESOLUTION = 96n; - static readonly Q96 = 0x1000000000000000000000000n; -} diff --git a/src/dex/baseswap-v3/contract-math/FullMath.ts b/src/dex/baseswap-v3/contract-math/FullMath.ts deleted file mode 100644 index 7c6a3bdc3..000000000 --- a/src/dex/baseswap-v3/contract-math/FullMath.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { BI_MAX_UINT256 } from '../../../bigint-constants'; -import { _require } from '../../../utils'; - -export class FullMath { - static mulDiv(a: bigint, b: bigint, denominator: bigint) { - const result = (a * b) / denominator; - - _require( - result <= BI_MAX_UINT256, - '', - { result, BI_MAX_UINT: BI_MAX_UINT256 }, - 'result <= BI_MAX_UINT', - ); - - return result; - } - - static mulDivRoundingUp(a: bigint, b: bigint, denominator: bigint) { - const result = (a * b + denominator - 1n) / denominator; - - _require( - result <= BI_MAX_UINT256, - '', - { result, BI_MAX_UINT: BI_MAX_UINT256 }, - 'result <= BI_MAX_UINT', - ); - - return result; - } -} diff --git a/src/dex/baseswap-v3/contract-math/LiquidityMath.ts b/src/dex/baseswap-v3/contract-math/LiquidityMath.ts deleted file mode 100644 index a495e55cc..000000000 --- a/src/dex/baseswap-v3/contract-math/LiquidityMath.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { _require } from '../../../utils'; - -export class LiquidityMath { - static addDelta(x: bigint, y: bigint): bigint { - let z; - if (y < 0) { - const _y = BigInt.asUintN(128, -y); - z = x - _y; - _require(z < x, 'LS', { z, x, y, _y }, 'z < x'); - } else { - const _y = BigInt.asUintN(128, y); - z = x + _y; - _require(z >= x, 'LA', { z, x, y, _y }, 'z >= x'); - } - return z; - } -} diff --git a/src/dex/baseswap-v3/contract-math/Oracle.ts b/src/dex/baseswap-v3/contract-math/Oracle.ts deleted file mode 100644 index 19b1918d1..000000000 --- a/src/dex/baseswap-v3/contract-math/Oracle.ts +++ /dev/null @@ -1,226 +0,0 @@ -import { - OracleObservation, - OracleObservationCandidates, - PoolState, -} from '../types'; -import { _require } from '../../../utils'; -import { DeepReadonly } from 'ts-essentials'; -import { ZERO_ORACLE_OBSERVATION } from '../constants'; - -function replaceUndefinedObservationWithZero(state: PoolState, index: number) { - if (state.observations[index] === undefined) { - state.observations[index] = { ...ZERO_ORACLE_OBSERVATION }; - } -} - -export class Oracle { - static transform( - state: DeepReadonly, - last: OracleObservation, - blockTimestamp: bigint, - tick: bigint, - liquidity: bigint, - ): OracleObservation { - const delta = blockTimestamp - last.blockTimestamp; - return { - blockTimestamp: state.blockTimestamp, - tickCumulative: last.tickCumulative + BigInt.asIntN(56, tick) * delta, - secondsPerLiquidityCumulativeX128: - last.secondsPerLiquidityCumulativeX128 + - (BigInt.asUintN(160, delta) << 128n) / - (liquidity > 0n ? liquidity : 1n), - initialized: true, - }; - } - - static write( - state: PoolState, - index: number, - blockTimestamp: bigint, - tick: bigint, - liquidity: bigint, - cardinality: number, - cardinalityNext: number, - ): [number, number] { - const last = state.observations[index]; - - if (last.blockTimestamp == state.blockTimestamp) - return [index, cardinality]; - - let indexUpdated = 0; - let cardinalityUpdated = 0; - - if (cardinalityNext > cardinality && index == cardinality - 1) { - cardinalityUpdated = cardinalityNext; - } else { - cardinalityUpdated = cardinality; - } - - indexUpdated = (index + 1) % cardinalityUpdated; - - state.observations[indexUpdated] = Oracle.transform( - state, - last, - blockTimestamp, - tick, - liquidity, - ); - if (indexUpdated !== index) { - delete state.observations[index]; - } - return [indexUpdated, cardinalityUpdated]; - } - - static lte(time: bigint, a: bigint, b: bigint): boolean { - if (a <= time && b <= time) return a <= b; - - const aAdjusted = a > time ? a : a + 2n ** 32n; - const bAdjusted = b > time ? b : b + 2n ** 32n; - return aAdjusted <= bAdjusted; - } - - static binarySearch( - state: DeepReadonly, - time: bigint, - target: bigint, - index: number, - cardinality: number, - ): OracleObservationCandidates { - let l = (index + 1) % cardinality; - let r = l + cardinality - 1; - let i; - - let beforeOrAt; - let atOrAfter; - while (true) { - i = (l + r) / 2; - - beforeOrAt = state.observations[i % cardinality]; - - // we've landed on an uninitialized tick, keep searching higher (more recently) - if (!beforeOrAt.initialized) { - l = i + 1; - continue; - } - - atOrAfter = state.observations[(i + 1) % cardinality]; - - const targetAtOrAfter = Oracle.lte( - time, - beforeOrAt.blockTimestamp, - target, - ); - - // check if we've found the answer! - if (targetAtOrAfter && Oracle.lte(time, target, atOrAfter.blockTimestamp)) - break; - - if (!targetAtOrAfter) r = i - 1; - else l = i + 1; - } - return { beforeOrAt, atOrAfter }; - } - - static getSurroundingObservations( - state: DeepReadonly, - time: bigint, - target: bigint, - tick: bigint, - index: number, - liquidity: bigint, - cardinality: number, - ): OracleObservationCandidates { - let beforeOrAt = state.observations[index]; - - if (Oracle.lte(time, beforeOrAt.blockTimestamp, target)) { - if (beforeOrAt.blockTimestamp === target) { - return { beforeOrAt, atOrAfter: beforeOrAt }; - } else { - return { - beforeOrAt, - atOrAfter: Oracle.transform( - state, - beforeOrAt, - target, - tick, - liquidity, - ), - }; - } - } - - beforeOrAt = state.observations[(index + 1) % cardinality]; - if (!beforeOrAt.initialized) beforeOrAt = state.observations[0]; - - _require( - Oracle.lte(time, beforeOrAt.blockTimestamp, target), - 'OLD', - { time, beforeOrAtBlockTimestamp: beforeOrAt.blockTimestamp, target }, - 'Oracle.lte(time, beforeOrAt.blockTimestamp, target)', - ); - - return Oracle.binarySearch(state, time, target, index, cardinality); - } - - static observeSingle( - state: DeepReadonly, - time: bigint, - secondsAgo: bigint, - tick: bigint, - index: number, - liquidity: bigint, - cardinality: number, - ): [bigint, bigint] { - if (secondsAgo == 0n) { - let last = state.observations[index]; - if (last.blockTimestamp != time) - last = Oracle.transform(state, last, time, tick, liquidity); - return [last.tickCumulative, last.secondsPerLiquidityCumulativeX128]; - } - - const target = time - secondsAgo; - - const { beforeOrAt, atOrAfter } = Oracle.getSurroundingObservations( - state, - time, - target, - tick, - index, - liquidity, - cardinality, - ); - - if (target === beforeOrAt.blockTimestamp) { - return [ - beforeOrAt.tickCumulative, - beforeOrAt.secondsPerLiquidityCumulativeX128, - ]; - } else if (target === atOrAfter.blockTimestamp) { - return [ - atOrAfter.tickCumulative, - atOrAfter.secondsPerLiquidityCumulativeX128, - ]; - } else { - const observationTimeDelta = - atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp; - const targetDelta = target - beforeOrAt.blockTimestamp; - return [ - beforeOrAt.tickCumulative + - ((atOrAfter.tickCumulative - beforeOrAt.tickCumulative) / - observationTimeDelta) * - targetDelta, - beforeOrAt.secondsPerLiquidityCumulativeX128 + - BigInt.asUintN( - 160, - (BigInt.asUintN( - 256, - atOrAfter.secondsPerLiquidityCumulativeX128 - - beforeOrAt.secondsPerLiquidityCumulativeX128, - ) * - targetDelta) / - observationTimeDelta, - ), - ]; - } - } -} diff --git a/src/dex/baseswap-v3/contract-math/SqrtPriceMath.ts b/src/dex/baseswap-v3/contract-math/SqrtPriceMath.ts deleted file mode 100644 index 31b801d73..000000000 --- a/src/dex/baseswap-v3/contract-math/SqrtPriceMath.ts +++ /dev/null @@ -1,226 +0,0 @@ -import { BI_MAX_UINT160 } from '../../../bigint-constants'; -import { FixedPoint96 } from './FixedPoint96'; -import { FullMath } from './FullMath'; -import { UnsafeMath } from './UnsafeMath'; -import { _require } from '../../../utils'; - -export class SqrtPriceMath { - static getNextSqrtPriceFromAmount0RoundingUp( - sqrtPX96: bigint, - liquidity: bigint, - amount: bigint, - add: boolean, - ): bigint { - if (amount === 0n) return sqrtPX96; - const numerator1 = - BigInt.asUintN(256, liquidity) << FixedPoint96.RESOLUTION; - - const product = amount * sqrtPX96; - if (add) { - if (product / amount === sqrtPX96) { - const denominator = numerator1 + product; - if (denominator >= numerator1) { - return BigInt.asUintN( - 160, - FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator), - ); - } - } - return BigInt.asUintN( - 160, - UnsafeMath.divRoundingUp(numerator1, numerator1 / sqrtPX96 + amount), - ); - } else { - _require( - product / amount === sqrtPX96 && numerator1 > product, - '', - { product, amount, sqrtPX96, numerator1 }, - 'product / amount === sqrtPX96 && numerator1 > product', - ); - const denominator = numerator1 - product; - return BigInt.asUintN( - 160, - FullMath.mulDivRoundingUp(numerator1, sqrtPX96, denominator), - ); - } - } - - static getNextSqrtPriceFromAmount1RoundingDown( - sqrtPX96: bigint, - liquidity: bigint, - amount: bigint, - add: boolean, - ): bigint { - if (add) { - const quotient = - amount <= BI_MAX_UINT160 - ? (amount << FixedPoint96.RESOLUTION) / liquidity - : FullMath.mulDiv(amount, FixedPoint96.Q96, liquidity); - return BigInt.asUintN(160, BigInt.asUintN(256, sqrtPX96) + quotient); - } else { - const quotient = - amount <= BI_MAX_UINT160 - ? UnsafeMath.divRoundingUp( - amount << FixedPoint96.RESOLUTION, - liquidity, - ) - : FullMath.mulDivRoundingUp(amount, FixedPoint96.Q96, liquidity); - - _require( - sqrtPX96 > quotient, - '', - { sqrtPX96, quotient }, - 'sqrtPX96 > quotient', - ); - return BigInt.asUintN(160, sqrtPX96 - quotient); - } - } - - static getNextSqrtPriceFromInput( - sqrtPX96: bigint, - liquidity: bigint, - amountIn: bigint, - zeroForOne: boolean, - ): bigint { - _require(sqrtPX96 > 0n, '', { sqrtPX96 }, 'sqrtPX96 > 0n'); - _require(liquidity > 0n, '', { liquidity }, 'liquidity > 0n'); - - return zeroForOne - ? SqrtPriceMath.getNextSqrtPriceFromAmount0RoundingUp( - sqrtPX96, - liquidity, - amountIn, - true, - ) - : SqrtPriceMath.getNextSqrtPriceFromAmount1RoundingDown( - sqrtPX96, - liquidity, - amountIn, - true, - ); - } - - static getNextSqrtPriceFromOutput( - sqrtPX96: bigint, - liquidity: bigint, - amountOut: bigint, - zeroForOne: boolean, - ): bigint { - _require(sqrtPX96 > 0n, '', { sqrtPX96 }, 'sqrtPX96 > 0n'); - _require(liquidity > 0n, '', { liquidity }, 'liquidity > 0n'); - - return zeroForOne - ? SqrtPriceMath.getNextSqrtPriceFromAmount1RoundingDown( - sqrtPX96, - liquidity, - amountOut, - false, - ) - : SqrtPriceMath.getNextSqrtPriceFromAmount0RoundingUp( - sqrtPX96, - liquidity, - amountOut, - false, - ); - } - - static getAmount0Delta( - sqrtRatioAX96: bigint, - sqrtRatioBX96: bigint, - liquidity: bigint, - roundUp: boolean, - ) { - if (sqrtRatioAX96 > sqrtRatioBX96) { - [sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]; - } - - const numerator1 = - BigInt.asUintN(256, liquidity) << FixedPoint96.RESOLUTION; - const numerator2 = sqrtRatioBX96 - sqrtRatioAX96; - - _require(sqrtRatioAX96 > 0, '', { sqrtRatioAX96 }, 'sqrtRatioAX96 > 0'); - - return roundUp - ? UnsafeMath.divRoundingUp( - FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioBX96), - sqrtRatioAX96, - ) - : FullMath.mulDiv(numerator1, numerator2, sqrtRatioBX96) / sqrtRatioAX96; - } - - static getAmount1Delta( - sqrtRatioAX96: bigint, - sqrtRatioBX96: bigint, - liquidity: bigint, - roundUp: boolean, - ) { - if (sqrtRatioAX96 > sqrtRatioBX96) - [sqrtRatioAX96, sqrtRatioBX96] = [sqrtRatioBX96, sqrtRatioAX96]; - - return roundUp - ? FullMath.mulDivRoundingUp( - liquidity, - sqrtRatioBX96 - sqrtRatioAX96, - FixedPoint96.Q96, - ) - : FullMath.mulDiv( - liquidity, - sqrtRatioBX96 - sqrtRatioAX96, - FixedPoint96.Q96, - ); - } - - // Overloaded with different argument numbers - static _getAmount0DeltaO( - sqrtRatioAX96: bigint, - sqrtRatioBX96: bigint, - liquidity: bigint, - ) { - return liquidity < 0 - ? -BigInt.asIntN( - 256, - SqrtPriceMath.getAmount0Delta( - sqrtRatioAX96, - sqrtRatioBX96, - BigInt.asUintN(128, -liquidity), - false, - ), - ) - : BigInt.asIntN( - 256, - SqrtPriceMath.getAmount0Delta( - sqrtRatioAX96, - sqrtRatioBX96, - BigInt.asUintN(128, liquidity), - true, - ), - ); - } - - // Overloaded with different argument numbers - static _getAmount1DeltaO( - sqrtRatioAX96: bigint, - sqrtRatioBX96: bigint, - liquidity: bigint, - ) { - return liquidity < 0 - ? -BigInt.asIntN( - 256, - SqrtPriceMath.getAmount1Delta( - sqrtRatioAX96, - sqrtRatioBX96, - BigInt.asUintN(128, -liquidity), - false, - ), - ) - : BigInt.asIntN( - 256, - SqrtPriceMath.getAmount1Delta( - sqrtRatioAX96, - sqrtRatioBX96, - BigInt.asUintN(128, liquidity), - true, - ), - ); - } -} diff --git a/src/dex/baseswap-v3/contract-math/SwapMath.ts b/src/dex/baseswap-v3/contract-math/SwapMath.ts deleted file mode 100644 index 3f19cf8cb..000000000 --- a/src/dex/baseswap-v3/contract-math/SwapMath.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { BI_POWS } from '../../../bigint-constants'; -import { FullMath } from './FullMath'; -import { SqrtPriceMath } from './SqrtPriceMath'; - -export class SwapMath { - static computeSwapStep( - sqrtRatioCurrentX96: bigint, - sqrtRatioTargetX96: bigint, - liquidity: bigint, - amountRemaining: bigint, - feePips: bigint, - ): { - sqrtRatioNextX96: bigint; - amountIn: bigint; - amountOut: bigint; - feeAmount: bigint; - } { - const zeroForOne = sqrtRatioCurrentX96 >= sqrtRatioTargetX96; - const exactIn = amountRemaining >= 0n; - - let sqrtRatioNextX96 = 0n; - let amountIn = 0n; - let amountOut = 0n; - let feeAmount = 0n; - - if (exactIn) { - const amountRemainingLessFee = FullMath.mulDiv( - BigInt.asUintN(256, amountRemaining), - BI_POWS[6] - feePips, - BI_POWS[6], - ); - amountIn = zeroForOne - ? SqrtPriceMath.getAmount0Delta( - sqrtRatioTargetX96, - sqrtRatioCurrentX96, - liquidity, - true, - ) - : SqrtPriceMath.getAmount1Delta( - sqrtRatioCurrentX96, - sqrtRatioTargetX96, - liquidity, - true, - ); - if (amountRemainingLessFee >= amountIn) - sqrtRatioNextX96 = sqrtRatioTargetX96; - else - sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromInput( - sqrtRatioCurrentX96, - liquidity, - amountRemainingLessFee, - zeroForOne, - ); - } else { - amountOut = zeroForOne - ? SqrtPriceMath.getAmount1Delta( - sqrtRatioTargetX96, - sqrtRatioCurrentX96, - liquidity, - false, - ) - : SqrtPriceMath.getAmount0Delta( - sqrtRatioCurrentX96, - sqrtRatioTargetX96, - liquidity, - false, - ); - if (BigInt.asUintN(256, -amountRemaining) >= amountOut) - sqrtRatioNextX96 = sqrtRatioTargetX96; - else - sqrtRatioNextX96 = SqrtPriceMath.getNextSqrtPriceFromOutput( - sqrtRatioCurrentX96, - liquidity, - BigInt.asUintN(256, -amountRemaining), - zeroForOne, - ); - } - - const max = sqrtRatioTargetX96 == sqrtRatioNextX96; - - if (zeroForOne) { - amountIn = - max && exactIn - ? amountIn - : SqrtPriceMath.getAmount0Delta( - sqrtRatioNextX96, - sqrtRatioCurrentX96, - liquidity, - true, - ); - amountOut = - max && !exactIn - ? amountOut - : SqrtPriceMath.getAmount1Delta( - sqrtRatioNextX96, - sqrtRatioCurrentX96, - liquidity, - false, - ); - } else { - amountIn = - max && exactIn - ? amountIn - : SqrtPriceMath.getAmount1Delta( - sqrtRatioCurrentX96, - sqrtRatioNextX96, - liquidity, - true, - ); - amountOut = - max && !exactIn - ? amountOut - : SqrtPriceMath.getAmount0Delta( - sqrtRatioCurrentX96, - sqrtRatioNextX96, - liquidity, - false, - ); - } - - // cap the output amount to not exceed the remaining output amount - if (!exactIn && amountOut > BigInt.asUintN(256, -amountRemaining)) { - amountOut = BigInt.asUintN(256, -amountRemaining); - } - - if (exactIn && sqrtRatioNextX96 != sqrtRatioTargetX96) { - // we didn't reach the target, so take the remainder of the maximum input as fee - feeAmount = BigInt.asUintN(256, amountRemaining) - amountIn; - } else { - feeAmount = FullMath.mulDivRoundingUp( - amountIn, - feePips, - BI_POWS[6] - feePips, - ); - } - - return { sqrtRatioNextX96, amountIn, amountOut, feeAmount }; - } -} diff --git a/src/dex/baseswap-v3/contract-math/Tick.ts b/src/dex/baseswap-v3/contract-math/Tick.ts deleted file mode 100644 index ab2e3c48b..000000000 --- a/src/dex/baseswap-v3/contract-math/Tick.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { PoolState, TickInfo } from '../types'; -import { LiquidityMath } from './LiquidityMath'; -import { _require } from '../../../utils'; -import { NumberAsString } from '@paraswap/core'; -import { ZERO_TICK_INFO } from '../constants'; - -export class Tick { - static update( - state: Pick, - tick: bigint, - tickCurrent: bigint, - liquidityDelta: bigint, - secondsPerLiquidityCumulativeX128: bigint, - tickCumulative: bigint, - time: bigint, - upper: boolean, - maxLiquidity: bigint, - ): boolean { - let info = state.ticks[Number(tick)]; - - if (info === undefined) { - info = { ...ZERO_TICK_INFO }; - state.ticks[Number(tick)] = info; - } - - const liquidityGrossBefore = info.liquidityGross; - const liquidityGrossAfter = LiquidityMath.addDelta( - liquidityGrossBefore, - liquidityDelta, - ); - - _require( - liquidityGrossAfter <= maxLiquidity, - 'LO', - { liquidityGrossAfter, maxLiquidity }, - 'liquidityGrossAfter <= maxLiquidity', - ); - - const flipped = (liquidityGrossAfter == 0n) != (liquidityGrossBefore == 0n); - - if (liquidityGrossBefore == 0n) { - if (tick <= tickCurrent) { - info.secondsPerLiquidityOutsideX128 = secondsPerLiquidityCumulativeX128; - info.tickCumulativeOutside = tickCumulative; - info.secondsOutside = time; - } - info.initialized = true; - } - - info.liquidityGross = liquidityGrossAfter; - - info.liquidityNet = upper - ? BigInt.asIntN( - 128, - BigInt.asIntN(256, info.liquidityNet) - liquidityDelta, - ) - : BigInt.asIntN( - 128, - BigInt.asIntN(256, info.liquidityNet) + liquidityDelta, - ); - return flipped; - } - - static clear(state: Pick, tick: bigint) { - delete state.ticks[Number(tick)]; - } - - static cross( - ticks: Record, - tick: bigint, - secondsPerLiquidityCumulativeX128: bigint, - tickCumulative: bigint, - time: bigint, - ): bigint { - const info = ticks[Number(tick)]; - info.secondsPerLiquidityOutsideX128 = - secondsPerLiquidityCumulativeX128 - info.secondsPerLiquidityOutsideX128; - info.tickCumulativeOutside = tickCumulative - info.tickCumulativeOutside; - info.secondsOutside = time - info.secondsOutside; - return info.liquidityNet; - } -} diff --git a/src/dex/baseswap-v3/contract-math/TickBitMap.ts b/src/dex/baseswap-v3/contract-math/TickBitMap.ts deleted file mode 100644 index 405cfa70e..000000000 --- a/src/dex/baseswap-v3/contract-math/TickBitMap.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { BI_MAX_UINT8 } from '../../../bigint-constants'; -import { PoolState } from '../types'; -import { BitMath } from './BitMath'; -import { _require } from '../../../utils'; -import { DeepReadonly } from 'ts-essentials'; -import { - OUT_OF_RANGE_ERROR_POSTFIX, - TICK_BITMAP_BUFFER, - TICK_BITMAP_TO_USE, -} from '../constants'; - -function isWordPosOut( - wordPos: bigint, - startTickBitmap: bigint, - // For pricing we use wider range to check price impact. If function called from event - // it must always be within buffer - isPriceQuery: boolean, -) { - let lowerTickBitmapLimit; - let upperTickBitmapLimit; - - if (isPriceQuery) { - lowerTickBitmapLimit = - startTickBitmap - (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE); - upperTickBitmapLimit = - startTickBitmap + (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE); - } else { - lowerTickBitmapLimit = startTickBitmap - TICK_BITMAP_BUFFER; - upperTickBitmapLimit = startTickBitmap + TICK_BITMAP_BUFFER; - } - - _require( - wordPos >= lowerTickBitmapLimit && wordPos <= upperTickBitmapLimit, - `wordPos is out of safe state tickBitmap request range: ${OUT_OF_RANGE_ERROR_POSTFIX}`, - { wordPos }, - `wordPos >= LOWER_TICK_REQUEST_LIMIT && wordPos <= UPPER_TICK_REQUEST_LIMIT`, - ); -} - -export class TickBitMap { - static position(tick: bigint): [bigint, bigint] { - return [BigInt.asIntN(16, tick >> 8n), BigInt.asUintN(8, tick % 256n)]; - } - - static flipTick( - state: Pick, - tick: bigint, - tickSpacing: bigint, - ) { - _require( - tick % tickSpacing === 0n, - '', - { tick, tickSpacing }, - 'tick % tickSpacing == 0n,', - ); - const [wordPos, bitPos] = TickBitMap.position(tick / tickSpacing); - const mask = 1n << bitPos; - - // flipTick is used only in _updatePosition which is always state changing event - // Therefore it is never used in price query - isWordPosOut(wordPos, state.startTickBitmap, false); - - const stringWordPos = wordPos.toString(); - if (state.tickBitmap[stringWordPos] === undefined) { - state.tickBitmap[stringWordPos] = 0n; - } - - state.tickBitmap[stringWordPos] ^= mask; - } - - static nextInitializedTickWithinOneWord( - state: DeepReadonly>, - tick: bigint, - tickSpacing: bigint, - lte: boolean, - isPriceQuery: boolean, - ): [bigint, boolean] { - let compressed = tick / tickSpacing; - if (tick < 0n && tick % tickSpacing != 0n) compressed--; - - let next = 0n; - let initialized = false; - - if (lte) { - const [wordPos, bitPos] = TickBitMap.position(compressed); - const mask = (1n << bitPos) - 1n + (1n << bitPos); - - isWordPosOut(wordPos, state.startTickBitmap, isPriceQuery); - let tickBitmapValue = state.tickBitmap[wordPos.toString()]; - tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; - - const masked = tickBitmapValue & mask; - - initialized = masked != 0n; - next = initialized - ? (compressed - - BigInt.asIntN(24, bitPos - BitMath.mostSignificantBit(masked))) * - tickSpacing - : (compressed - BigInt.asIntN(24, bitPos)) * tickSpacing; - } else { - // start from the word of the next tick, since the current tick state doesn't matter - const [wordPos, bitPos] = TickBitMap.position(compressed + 1n); - const mask = ~((1n << bitPos) - 1n); - - isWordPosOut(wordPos, state.startTickBitmap, isPriceQuery); - let tickBitmapValue = state.tickBitmap[wordPos.toString()]; - tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; - - const masked = tickBitmapValue & mask; - - initialized = masked != 0n; - next = initialized - ? (compressed + - 1n + - BigInt.asIntN(24, BitMath.leastSignificantBit(masked) - bitPos)) * - tickSpacing - : (compressed + 1n + BigInt.asIntN(24, BI_MAX_UINT8 - bitPos)) * - tickSpacing; - } - - return [next, initialized]; - } -} diff --git a/src/dex/baseswap-v3/contract-math/TickMath.ts b/src/dex/baseswap-v3/contract-math/TickMath.ts deleted file mode 100644 index 5515ce15c..000000000 --- a/src/dex/baseswap-v3/contract-math/TickMath.ts +++ /dev/null @@ -1,211 +0,0 @@ -import { gt } from 'lodash'; -import { BI_MAX_UINT256 } from '../../../bigint-constants'; -import { _gt } from './utils'; -import { _require } from '../../../utils'; - -export class TickMath { - static readonly MIN_TICK = -887272n; - static readonly MAX_TICK = -TickMath.MIN_TICK; - static readonly MIN_SQRT_RATIO = 4295128739n; - static readonly MAX_SQRT_RATIO = - 1461446703485210103287273052203988822378723970342n; - - static getSqrtRatioAtTick(tick: bigint): bigint { - const absTick = - tick < 0n - ? BigInt.asUintN(256, -BigInt.asIntN(256, tick)) - : BigInt.asUintN(256, BigInt.asIntN(256, tick)); - _require( - absTick <= BigInt.asUintN(256, TickMath.MAX_TICK), - 'T', - { absTick }, - 'absTick <= BigInt.asUintN(256, TickMath.MAX_TICK)', - ); - - let ratio = - (absTick & 0x1n) !== 0n - ? 0xfffcb933bd6fad37aa2d162d1a594001n - : 0x100000000000000000000000000000000n; - if ((absTick & 0x2n) !== 0n) - ratio = (ratio * 0xfff97272373d413259a46990580e213an) >> 128n; - if ((absTick & 0x4n) !== 0n) - ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdccn) >> 128n; - if ((absTick & 0x8n) !== 0n) - ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0n) >> 128n; - if ((absTick & 0x10n) !== 0n) - ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644n) >> 128n; - if ((absTick & 0x20n) !== 0n) - ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0n) >> 128n; - if ((absTick & 0x40n) !== 0n) - ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861n) >> 128n; - if ((absTick & 0x80n) !== 0n) - ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053n) >> 128n; - if ((absTick & 0x100n) !== 0n) - ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4n) >> 128n; - if ((absTick & 0x200n) !== 0n) - ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54n) >> 128n; - if ((absTick & 0x400n) !== 0n) - ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3n) >> 128n; - if ((absTick & 0x800n) !== 0n) - ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9n) >> 128n; - if ((absTick & 0x1000n) !== 0n) - ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825n) >> 128n; - if ((absTick & 0x2000n) !== 0n) - ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5n) >> 128n; - if ((absTick & 0x4000n) !== 0n) - ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7n) >> 128n; - if ((absTick & 0x8000n) !== 0n) - ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6n) >> 128n; - if ((absTick & 0x10000n) !== 0n) - ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9n) >> 128n; - if ((absTick & 0x20000n) !== 0n) - ratio = (ratio * 0x5d6af8dedb81196699c329225ee604n) >> 128n; - if ((absTick & 0x40000n) !== 0n) - ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98n) >> 128n; - if ((absTick & 0x80000n) !== 0n) - ratio = (ratio * 0x48a170391f7dc42444e8fa2n) >> 128n; - - if (tick > 0) ratio = BI_MAX_UINT256 / ratio; - return BigInt.asUintN( - 160, - (ratio >> 32n) + (ratio % (1n << 32n) == 0n ? 0n : 1n), - ); - } - - static getTickAtSqrtRatio(sqrtPriceX96: bigint): bigint { - _require( - sqrtPriceX96 >= TickMath.MIN_SQRT_RATIO && - sqrtPriceX96 < TickMath.MAX_SQRT_RATIO, - 'R', - { sqrtPriceX96 }, - 'sqrtPriceX96 >= TickMath.MIN_SQRT_RATIO && sqrtPriceX96 < TickMath.MAX_SQRT_RATIO', - ); - - let ratio = BigInt.asUintN(256, sqrtPriceX96) << 32n; - - let r = ratio; - let msb = 0n; - - let f = _gt(r, 0xffffffffffffffffffffffffffffffffn) << 7n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0xffffffffffffffffn) << 6n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0xffffffffn) << 5n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0xffffn) << 4n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0xffn) << 3n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0xfn) << 2n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0x3n) << 1n; - msb = msb | f; - r = r >> f; - - f = _gt(r, 0x1n); - msb = msb | f; - - if (msb >= 128n) r = ratio >> (msb - 127n); - else r = ratio << (127n - msb); - - let log_2 = (BigInt.asIntN(256, msb) - 128n) << 64n; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 63n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 62n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 61n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 60n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 59n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 58n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 57n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 56n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 55n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 54n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 53n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 52n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 51n); - r = r >> f; - - r = (r * r) >> 127n; - f = r >> 128n; - log_2 = log_2 | (f << 50n); - - const log_sqrt10001 = log_2 * 255738958999603826347141n; // 128.128 number - - const tickLow = BigInt.asIntN( - 24, - (log_sqrt10001 - 3402992956809132418596140100660247210n) >> 128n, - ); - const tickHi = BigInt.asIntN( - 24, - (log_sqrt10001 + 291339464771989622907027621153398088495n) >> 128n, - ); - - return tickLow === tickHi - ? tickLow - : TickMath.getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 - ? tickHi - : tickLow; - } -} diff --git a/src/dex/baseswap-v3/contract-math/UnsafeMath.ts b/src/dex/baseswap-v3/contract-math/UnsafeMath.ts deleted file mode 100644 index aebd7c579..000000000 --- a/src/dex/baseswap-v3/contract-math/UnsafeMath.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class UnsafeMath { - static divRoundingUp(x: bigint, y: bigint) { - return (x + y - 1n) / y; - } -} diff --git a/src/dex/baseswap-v3/contract-math/uniswap-v3-math.ts b/src/dex/baseswap-v3/contract-math/uniswap-v3-math.ts deleted file mode 100644 index d18881006..000000000 --- a/src/dex/baseswap-v3/contract-math/uniswap-v3-math.ts +++ /dev/null @@ -1,666 +0,0 @@ -import _ from 'lodash'; -import { OutputResult, PoolState, Slot0, TickInfo } from '../types'; -import { LiquidityMath } from './LiquidityMath'; -import { Oracle } from './Oracle'; -import { SqrtPriceMath } from './SqrtPriceMath'; -import { SwapMath } from './SwapMath'; -import { Tick } from './Tick'; -import { TickBitMap } from './TickBitMap'; -import { TickMath } from './TickMath'; -import { _require } from '../../../utils'; -import { DeepReadonly } from 'ts-essentials'; -import { NumberAsString, SwapSide } from '@paraswap/core'; -import { BI_MAX_INT } from '../../../bigint-constants'; -import { - MAX_PRICING_COMPUTATION_STEPS_ALLOWED, - OUT_OF_RANGE_ERROR_POSTFIX, -} from '../constants'; - -type ModifyPositionParams = { - tickLower: bigint; - tickUpper: bigint; - liquidityDelta: bigint; -}; - -export type PriceComputationState = { - amountSpecifiedRemaining: bigint; - amountCalculated: bigint; - sqrtPriceX96: bigint; - tick: bigint; - protocolFee: bigint; - liquidity: bigint; - isFirstCycleState: boolean; -}; - -export type PriceComputationCache = { - liquidityStart: bigint; - blockTimestamp: bigint; - feeProtocol: bigint; - secondsPerLiquidityCumulativeX128: bigint; - tickCumulative: bigint; - computedLatestObservation: boolean; - tickCount: number; -}; - -export function _updatePriceComputationObjects< - T extends PriceComputationState | PriceComputationCache, ->(toUpdate: T, updateBy: T) { - for (const k of Object.keys(updateBy) as (keyof T)[]) { - toUpdate[k] = updateBy[k]; - } -} - -function _priceComputationCycles( - poolState: DeepReadonly, - ticksCopy: Record, - slot0Start: Slot0, - state: PriceComputationState, - cache: PriceComputationCache, - sqrtPriceLimitX96: bigint, - zeroForOne: boolean, - exactInput: boolean, -): [ - // result - PriceComputationState, - // Latest calculated full cycle state we can use for bigger amounts - { - latestFullCycleState: PriceComputationState; - latestFullCycleCache: PriceComputationCache; - }, -] { - const latestFullCycleState: PriceComputationState = { ...state }; - - if (cache.tickCount == 0) { - cache.tickCount = 1; - } - const latestFullCycleCache: PriceComputationCache = { ...cache }; - - // We save tick before any change. Later we use this to restore - // state before last step - let lastTicksCopy: { index: number; tick: TickInfo } | undefined; - - let i = 0; - for ( - ; - state.amountSpecifiedRemaining !== 0n && - state.sqrtPriceX96 !== sqrtPriceLimitX96; - ++i - ) { - if ( - latestFullCycleCache.tickCount + i > - MAX_PRICING_COMPUTATION_STEPS_ALLOWED - ) { - state.amountSpecifiedRemaining = 0n; - state.amountCalculated = 0n; - break; - } - - const step = { - sqrtPriceStartX96: 0n, - tickNext: 0n, - initialized: false, - sqrtPriceNextX96: 0n, - amountIn: 0n, - amountOut: 0n, - feeAmount: 0n, - }; - - step.sqrtPriceStartX96 = state.sqrtPriceX96; - - try { - [step.tickNext, step.initialized] = - TickBitMap.nextInitializedTickWithinOneWord( - poolState, - state.tick, - poolState.tickSpacing, - zeroForOne, - true, - ); - } catch (e) { - if ( - e instanceof Error && - e.message.endsWith(OUT_OF_RANGE_ERROR_POSTFIX) - ) { - state.amountSpecifiedRemaining = 0n; - state.amountCalculated = 0n; - break; - } - throw e; - } - - if (step.tickNext < TickMath.MIN_TICK) { - step.tickNext = TickMath.MIN_TICK; - } else if (step.tickNext > TickMath.MAX_TICK) { - step.tickNext = TickMath.MAX_TICK; - } - - step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext); - - const swapStepResult = SwapMath.computeSwapStep( - state.sqrtPriceX96, - ( - zeroForOne - ? step.sqrtPriceNextX96 < sqrtPriceLimitX96 - : step.sqrtPriceNextX96 > sqrtPriceLimitX96 - ) - ? sqrtPriceLimitX96 - : step.sqrtPriceNextX96, - state.liquidity, - state.amountSpecifiedRemaining, - poolState.fee, - ); - - state.sqrtPriceX96 = swapStepResult.sqrtRatioNextX96; - step.amountIn = swapStepResult.amountIn; - step.amountOut = swapStepResult.amountOut; - step.feeAmount = swapStepResult.feeAmount; - - if (exactInput) { - state.amountSpecifiedRemaining -= step.amountIn + step.feeAmount; - state.amountCalculated = state.amountCalculated - step.amountOut; - } else { - state.amountSpecifiedRemaining += step.amountOut; - state.amountCalculated = - state.amountCalculated + step.amountIn + step.feeAmount; - } - - if (cache.feeProtocol > 0n) { - const delta = step.feeAmount / cache.feeProtocol; - step.feeAmount -= delta; - state.protocolFee += delta; - } - - if (state.sqrtPriceX96 === step.sqrtPriceNextX96) { - if (step.initialized) { - if (!cache.computedLatestObservation) { - [cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128] = - Oracle.observeSingle( - poolState, - cache.blockTimestamp, - 0n, - slot0Start.tick, - slot0Start.observationIndex, - cache.liquidityStart, - slot0Start.observationCardinality, - ); - cache.computedLatestObservation = true; - } - - if (state.amountSpecifiedRemaining === 0n) { - const castTickNext = Number(step.tickNext); - lastTicksCopy = { - index: castTickNext, - tick: { ...ticksCopy[castTickNext] }, - }; - } - - let liquidityNet = Tick.cross( - ticksCopy, - step.tickNext, - cache.secondsPerLiquidityCumulativeX128, - cache.tickCumulative, - cache.blockTimestamp, - ); - if (zeroForOne) liquidityNet = -liquidityNet; - - state.liquidity = LiquidityMath.addDelta(state.liquidity, liquidityNet); - } - - state.tick = zeroForOne ? step.tickNext - 1n : step.tickNext; - } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) { - state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96); - } - - if (state.amountSpecifiedRemaining !== 0n) { - _updatePriceComputationObjects(latestFullCycleState, state); - _updatePriceComputationObjects(latestFullCycleCache, cache); - // If it last cycle, check if ticks were changed and then restore previous state - // for next calculations - } else if (lastTicksCopy !== undefined) { - ticksCopy[lastTicksCopy.index] = lastTicksCopy.tick; - } - } - - if (i > 1) { - latestFullCycleCache.tickCount += i - 1; - } - - if (state.amountSpecifiedRemaining !== 0n) { - state.amountSpecifiedRemaining = 0n; - state.amountCalculated = 0n; - } - - return [state, { latestFullCycleState, latestFullCycleCache }]; -} - -class UniswapV3Math { - queryOutputs( - poolState: DeepReadonly, - // Amounts must increase - amounts: bigint[], - zeroForOne: boolean, - side: SwapSide, - ): OutputResult { - const slot0Start = poolState.slot0; - - const isSell = side === SwapSide.SELL; - - // While calculating, ticks are changing, so to not change the actual state, - // we use copy - const ticksCopy = _.cloneDeep(poolState.ticks); - - const sqrtPriceLimitX96 = zeroForOne - ? TickMath.MIN_SQRT_RATIO + 1n - : TickMath.MAX_SQRT_RATIO - 1n; - - const cache: PriceComputationCache = { - liquidityStart: poolState.liquidity, - blockTimestamp: this._blockTimestamp(poolState), - feeProtocol: zeroForOne - ? slot0Start.feeProtocol % 16n - : slot0Start.feeProtocol >> 4n, - secondsPerLiquidityCumulativeX128: 0n, - tickCumulative: 0n, - computedLatestObservation: false, - tickCount: 0, - }; - - const state: PriceComputationState = { - // Will be overwritten later - amountSpecifiedRemaining: 0n, - amountCalculated: 0n, - sqrtPriceX96: slot0Start.sqrtPriceX96, - tick: slot0Start.tick, - protocolFee: 0n, - liquidity: cache.liquidityStart, - isFirstCycleState: true, - }; - - let isOutOfRange = false; - let previousAmount = 0n; - - const outputs = new Array(amounts.length); - const tickCounts = new Array(amounts.length); - for (const [i, amount] of amounts.entries()) { - if (amount === 0n) { - outputs[i] = 0n; - tickCounts[i] = 0; - continue; - } - - const amountSpecified = isSell - ? BigInt.asIntN(256, amount) - : -BigInt.asIntN(256, amount); - - if (state.isFirstCycleState) { - // Set first non zero amount - state.amountSpecifiedRemaining = amountSpecified; - state.isFirstCycleState = false; - } else { - state.amountSpecifiedRemaining = - amountSpecified - (previousAmount - state.amountSpecifiedRemaining); - } - - const exactInput = amountSpecified > 0n; - - _require( - zeroForOne - ? sqrtPriceLimitX96 < slot0Start.sqrtPriceX96 && - sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO - : sqrtPriceLimitX96 > slot0Start.sqrtPriceX96 && - sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO, - 'SPL', - { zeroForOne, sqrtPriceLimitX96, slot0Start }, - 'zeroForOne ? sqrtPriceLimitX96 < slot0Start.sqrtPriceX96 && sqrtPriceLimitX96 > TickMath.MIN_SQRT_RATIO : sqrtPriceLimitX96 > slot0Start.sqrtPriceX96 && sqrtPriceLimitX96 < TickMath.MAX_SQRT_RATIO', - ); - - if (!isOutOfRange) { - const [finalState, { latestFullCycleState, latestFullCycleCache }] = - _priceComputationCycles( - poolState, - ticksCopy, - slot0Start, - state, - cache, - sqrtPriceLimitX96, - zeroForOne, - exactInput, - ); - if ( - finalState.amountSpecifiedRemaining === 0n && - finalState.amountCalculated === 0n - ) { - isOutOfRange = true; - outputs[i] = 0n; - tickCounts[i] = 0; - continue; - } - - // We use it on next step to correct state.amountSpecifiedRemaining - previousAmount = amountSpecified; - - // First extract calculated values - const [amount0, amount1] = - zeroForOne === exactInput - ? [ - amountSpecified - finalState.amountSpecifiedRemaining, - finalState.amountCalculated, - ] - : [ - finalState.amountCalculated, - amountSpecified - finalState.amountSpecifiedRemaining, - ]; - - // Update for next amount - _updatePriceComputationObjects(state, latestFullCycleState); - _updatePriceComputationObjects(cache, latestFullCycleCache); - - if (isSell) { - outputs[i] = BigInt.asUintN(256, -(zeroForOne ? amount1 : amount0)); - tickCounts[i] = latestFullCycleCache.tickCount; - continue; - } else { - outputs[i] = zeroForOne - ? BigInt.asUintN(256, amount0) - : BigInt.asUintN(256, amount1); - tickCounts[i] = latestFullCycleCache.tickCount; - continue; - } - } else { - outputs[i] = 0n; - tickCounts[i] = 0; - } - } - - return { - outputs, - tickCounts, - }; - } - - swapFromEvent( - poolState: PoolState, - newSqrtPriceX96: bigint, - newTick: bigint, - newLiquidity: bigint, - zeroForOne: boolean, - ): void { - const slot0Start = poolState.slot0; - - const cache = { - liquidityStart: poolState.liquidity, - blockTimestamp: this._blockTimestamp(poolState), - feeProtocol: 0n, - secondsPerLiquidityCumulativeX128: 0n, - tickCumulative: 0n, - computedLatestObservation: false, - }; - - const state = { - // Because I don't have the exact amount user used, set this number to MAX_NUMBER to proceed - // with calculations. I think it is not a problem since in loop I don't rely on this value - amountSpecifiedRemaining: BI_MAX_INT, - amountCalculated: 0n, - sqrtPriceX96: slot0Start.sqrtPriceX96, - tick: slot0Start.tick, - protocolFee: 0n, - liquidity: cache.liquidityStart, - }; - - // Because I didn't have all variables, adapted loop stop with state.tick !== newTick - // condition. This cycle need only to calculate Tick.cross() function values - // It means that we are interested in cycling only if state.tick !== newTick - // When they become equivalent, we proceed with state updating part as normal - // And if assumptions regarding this cycle are correct, we don't need to process - // the last cycle when state.tick === newTick - while (state.tick !== newTick && state.sqrtPriceX96 !== newSqrtPriceX96) { - const step = { - sqrtPriceStartX96: 0n, - tickNext: 0n, - initialized: false, - sqrtPriceNextX96: 0n, - amountIn: 0n, - amountOut: 0n, - feeAmount: 0n, - }; - - step.sqrtPriceStartX96 = state.sqrtPriceX96; - - [step.tickNext, step.initialized] = - TickBitMap.nextInitializedTickWithinOneWord( - poolState, - state.tick, - poolState.tickSpacing, - zeroForOne, - false, - ); - - if (step.tickNext < TickMath.MIN_TICK) { - step.tickNext = TickMath.MIN_TICK; - } else if (step.tickNext > TickMath.MAX_TICK) { - step.tickNext = TickMath.MAX_TICK; - } - - step.sqrtPriceNextX96 = TickMath.getSqrtRatioAtTick(step.tickNext); - - const swapStepResult = SwapMath.computeSwapStep( - state.sqrtPriceX96, - ( - zeroForOne - ? step.sqrtPriceNextX96 < newSqrtPriceX96 - : step.sqrtPriceNextX96 > newSqrtPriceX96 - ) - ? newSqrtPriceX96 - : step.sqrtPriceNextX96, - state.liquidity, - state.amountSpecifiedRemaining, - poolState.fee, - ); - - state.sqrtPriceX96 = swapStepResult.sqrtRatioNextX96; - - if (state.sqrtPriceX96 == step.sqrtPriceNextX96) { - if (step.initialized) { - if (!cache.computedLatestObservation) { - [cache.tickCumulative, cache.secondsPerLiquidityCumulativeX128] = - Oracle.observeSingle( - poolState, - cache.blockTimestamp, - 0n, - slot0Start.tick, - slot0Start.observationIndex, - cache.liquidityStart, - slot0Start.observationCardinality, - ); - cache.computedLatestObservation = true; - } - - let liquidityNet = Tick.cross( - poolState.ticks, - step.tickNext, - cache.secondsPerLiquidityCumulativeX128, - cache.tickCumulative, - cache.blockTimestamp, - ); - - if (zeroForOne) liquidityNet = -liquidityNet; - - state.liquidity = LiquidityMath.addDelta( - state.liquidity, - liquidityNet, - ); - } - - state.tick = zeroForOne ? step.tickNext - 1n : step.tickNext; - } else if (state.sqrtPriceX96 != step.sqrtPriceStartX96) { - state.tick = TickMath.getTickAtSqrtRatio(state.sqrtPriceX96); - } - } - - if (slot0Start.tick !== newTick) { - const [observationIndex, observationCardinality] = Oracle.write( - poolState, - slot0Start.observationIndex, - this._blockTimestamp(poolState), - slot0Start.tick, - poolState.liquidity, - slot0Start.observationCardinality, - slot0Start.observationCardinalityNext, - ); - - [ - poolState.slot0.sqrtPriceX96, - poolState.slot0.tick, - poolState.slot0.observationIndex, - poolState.slot0.observationCardinality, - ] = [newSqrtPriceX96, newTick, observationIndex, observationCardinality]; - } else { - poolState.slot0.sqrtPriceX96 = newSqrtPriceX96; - } - - if (poolState.liquidity !== newLiquidity) - poolState.liquidity = newLiquidity; - } - - _modifyPosition( - state: PoolState, - params: ModifyPositionParams, - ): [bigint, bigint] { - const _slot0 = state.slot0; - - this._updatePosition( - state, - params.tickLower, - params.tickUpper, - params.liquidityDelta, - _slot0.tick, - ); - - let amount0 = 0n; - let amount1 = 0n; - if (params.liquidityDelta !== 0n) { - if (_slot0.tick < params.tickLower) { - amount0 = SqrtPriceMath._getAmount0DeltaO( - TickMath.getSqrtRatioAtTick(params.tickLower), - TickMath.getSqrtRatioAtTick(params.tickUpper), - params.liquidityDelta, - ); - } else if (_slot0.tick < params.tickUpper) { - const liquidityBefore = state.liquidity; - - [state.slot0.observationIndex, state.slot0.observationCardinality] = - Oracle.write( - state, - _slot0.observationIndex, - this._blockTimestamp(state), - _slot0.tick, - liquidityBefore, - _slot0.observationCardinality, - _slot0.observationCardinalityNext, - ); - - amount0 = SqrtPriceMath._getAmount0DeltaO( - _slot0.sqrtPriceX96, - TickMath.getSqrtRatioAtTick(params.tickUpper), - params.liquidityDelta, - ); - amount1 = SqrtPriceMath._getAmount1DeltaO( - TickMath.getSqrtRatioAtTick(params.tickLower), - _slot0.sqrtPriceX96, - params.liquidityDelta, - ); - - state.liquidity = LiquidityMath.addDelta( - liquidityBefore, - params.liquidityDelta, - ); - } else { - amount1 = SqrtPriceMath._getAmount1DeltaO( - TickMath.getSqrtRatioAtTick(params.tickLower), - TickMath.getSqrtRatioAtTick(params.tickUpper), - params.liquidityDelta, - ); - } - } - return [amount0, amount1]; - } - - private _isTickToProcess(state: PoolState, tick: bigint): boolean { - return tick >= state.lowestKnownTick && tick <= state.highestKnownTick; - } - - private _updatePosition( - state: PoolState, - tickLower: bigint, - tickUpper: bigint, - liquidityDelta: bigint, - tick: bigint, - ): void { - // if we need to update the ticks, do it - let flippedLower = false; - let flippedUpper = false; - if (liquidityDelta !== 0n) { - const time = this._blockTimestamp(state); - const [tickCumulative, secondsPerLiquidityCumulativeX128] = - Oracle.observeSingle( - state, - time, - 0n, - state.slot0.tick, - state.slot0.observationIndex, - state.liquidity, - state.slot0.observationCardinality, - ); - - if (this._isTickToProcess(state, tickLower)) { - flippedLower = Tick.update( - state, - tickLower, - tick, - liquidityDelta, - secondsPerLiquidityCumulativeX128, - tickCumulative, - time, - false, - state.maxLiquidityPerTick, - ); - } - if (this._isTickToProcess(state, tickUpper)) { - flippedUpper = Tick.update( - state, - tickUpper, - tick, - liquidityDelta, - secondsPerLiquidityCumulativeX128, - tickCumulative, - time, - true, - state.maxLiquidityPerTick, - ); - } - - if (flippedLower) { - TickBitMap.flipTick(state, tickLower, state.tickSpacing); - } - if (flippedUpper) { - TickBitMap.flipTick(state, tickUpper, state.tickSpacing); - } - } - - // clear any tick data that is no longer needed - if (liquidityDelta < 0n) { - if (flippedLower) { - Tick.clear(state, tickLower); - } - if (flippedUpper) { - Tick.clear(state, tickUpper); - } - } - } - - private _blockTimestamp(state: DeepReadonly) { - return BigInt.asUintN(32, state.blockTimestamp); - } -} - -export const uniswapV3Math = new UniswapV3Math(); diff --git a/src/dex/baseswap-v3/contract-math/utils.ts b/src/dex/baseswap-v3/contract-math/utils.ts deleted file mode 100644 index 65d97736d..000000000 --- a/src/dex/baseswap-v3/contract-math/utils.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { NumberAsString } from '@paraswap/core'; -import { - TickBitMapMappingsWithBigNumber, - TickInfo, - TickInfoMappingsWithBigNumber, -} from '../types'; -import { bigIntify } from '../../../utils'; - -export function _mulmod(x: bigint, y: bigint, m: bigint): bigint { - return m === 0n ? 0n : (x * y) % m; -} - -export function _lt(x: bigint, y: bigint) { - return x < y ? 1n : 0n; -} - -export function _gt(x: bigint, y: bigint) { - return x > y ? 1n : 0n; -} - -export function _reduceTickBitmap( - tickBitmap: Record, - tickBitmapToReduce: TickBitMapMappingsWithBigNumber[], -) { - return tickBitmapToReduce.reduce>( - (acc, curr) => { - const { index, value } = curr; - acc[index] = bigIntify(value); - return acc; - }, - tickBitmap, - ); -} - -export function _reduceTicks( - ticks: Record, - ticksToReduce: TickInfoMappingsWithBigNumber[], -) { - return ticksToReduce.reduce>((acc, curr) => { - const { index, value } = curr; - if (value.initialized) { - acc[index] = { - liquidityGross: bigIntify(value.liquidityGross), - liquidityNet: bigIntify(value.liquidityNet), - tickCumulativeOutside: bigIntify(value.tickCumulativeOutside), - secondsPerLiquidityOutsideX128: bigIntify( - value.secondsPerLiquidityOutsideX128, - ), - secondsOutside: bigIntify(value.secondsOutside), - initialized: value.initialized, - }; - } - return acc; - }, ticks); -} diff --git a/src/dex/baseswap-v3/types.ts b/src/dex/baseswap-v3/types.ts deleted file mode 100644 index cebc762b8..000000000 --- a/src/dex/baseswap-v3/types.ts +++ /dev/null @@ -1,191 +0,0 @@ -import { BigNumber, BytesLike } from 'ethers'; -import { NumberAsString } from '../../types'; -import { Address } from '../../types'; -import { AbiItem } from 'web3-utils'; -import { MultiResult } from '../../lib/multi-wrapper'; -import { BaseswapV3EventPool } from './baseswap-v3-pool'; - -export type OracleObservation = { - blockTimestamp: bigint; - tickCumulative: bigint; - secondsPerLiquidityCumulativeX128: bigint; - initialized: boolean; -}; - -export type OracleObservationCandidates = { - beforeOrAt: OracleObservation; - atOrAfter: OracleObservation; -}; - -export type TickInfo = { - liquidityGross: bigint; - liquidityNet: bigint; - tickCumulativeOutside: bigint; - secondsPerLiquidityOutsideX128: bigint; - secondsOutside: bigint; - initialized: boolean; -}; - -export type Slot0 = { - sqrtPriceX96: bigint; - tick: bigint; - observationIndex: number; - observationCardinality: number; - observationCardinalityNext: number; - feeProtocol: bigint; -}; - -export type PoolState = { - pool: string; - blockTimestamp: bigint; - tickSpacing: bigint; - fee: bigint; - slot0: Slot0; - liquidity: bigint; - maxLiquidityPerTick: bigint; - tickBitmap: Record; - ticks: Record; - observations: Record; - isValid: boolean; - startTickBitmap: bigint; - lowestKnownTick: bigint; - highestKnownTick: bigint; - balance0: bigint; - balance1: bigint; -}; - -export type FactoryState = Record; - -export type UniswapV3Data = { - path: { - tokenIn: Address; - tokenOut: Address; - fee: NumberAsString; - currentFee?: NumberAsString; - }[]; - isApproved?: boolean; -}; - -export type DecodeStateMultiCallFunc = ( - result: MultiResult | BytesLike, -) => DecodedStateMultiCallResultWithRelativeBitmaps; - -export type DexParams = { - router: Address; - quoter: Address; - factory: Address; - stateMulticall: Address; - uniswapMulticall: Address; - supportedFees: bigint[]; - chunksCount: number; - initRetryFrequency: number; - deployer?: Address; - subgraphURL: string; - initHash: string; - stateMultiCallAbi?: AbiItem[]; - eventPoolImplementation?: typeof BaseswapV3EventPool; - decodeStateMultiCallResultWithRelativeBitmaps?: DecodeStateMultiCallFunc; -}; - -export type UniswapV3SimpleSwapSellParam = { - path: string; - recipient: Address; - deadline: string; - amountIn: NumberAsString; - amountOutMinimum: NumberAsString; -}; - -export type UniswapV3SimpleSwapBuyParam = { - path: string; - recipient: Address; - deadline: string; - amountOut: NumberAsString; - amountInMaximum: NumberAsString; -}; - -export type UniswapV3SimpleSwapParams = - | UniswapV3SimpleSwapSellParam - | UniswapV3SimpleSwapBuyParam; - -export type UniswapV3Param = [ - fromToken: Address, - toToken: Address, - exchange: Address, - fromAmount: NumberAsString, - toAmount: NumberAsString, - expectedAmount: NumberAsString, - feePercent: NumberAsString, - deadline: NumberAsString, - partner: Address, - isApproved: boolean, - beneficiary: Address, - path: string, - permit: string, - uuid: string, -]; - -export enum UniswapV3Functions { - exactInput = 'exactInput', - exactOutput = 'exactOutput', -} - -export type TickInfoMappings = { - index: number; - value: TickInfo; -}; - -export type TickBitMapMappings = { - index: number; - value: bigint; -}; - -export type OutputResult = { - outputs: bigint[]; - tickCounts: number[]; -}; - -// Just rewrote every type with BigNumber basically - -export type TickBitMapMappingsWithBigNumber = { - index: number; - value: BigNumber; -}; - -export type TickInfoWithBigNumber = { - initialized: boolean; - liquidityGross: BigNumber; - liquidityNet: BigNumber; - secondsOutside: number; - secondsPerLiquidityOutsideX128: BigNumber; - tickCumulativeOutside: BigNumber; -}; - -export type TickInfoMappingsWithBigNumber = { - index: number; - value: TickInfoWithBigNumber; -}; - -export type DecodedStateMultiCallResultWithRelativeBitmaps = { - pool: Address; - blockTimestamp: BigNumber; - slot0: { - feeProtocol: number; - observationCardinality: number; - observationCardinalityNext: number; - observationIndex: number; - sqrtPriceX96: BigNumber; - tick: number; - unlocked: boolean; - }; - liquidity: BigNumber; - tickSpacing: number; - maxLiquidityPerTick: BigNumber; - observation: { - blockTimestamp: number; - initialized: boolean; - secondsPerLiquidityCumulativeX128: BigNumber; - tickCumulative: BigNumber; - }; - tickBitmap: TickBitMapMappingsWithBigNumber[]; - ticks: TickInfoMappingsWithBigNumber[]; -}; diff --git a/src/dex/baseswap-v3/utils.ts b/src/dex/baseswap-v3/utils.ts deleted file mode 100644 index afd953e07..000000000 --- a/src/dex/baseswap-v3/utils.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { BytesLike, ethers } from 'ethers'; -import { assert } from 'ts-essentials'; -import { extractSuccessAndValue } from '../../lib/decoders'; -import { MultiResult } from '../../lib/multi-wrapper'; -import { DexConfigMap } from '../../types'; -import { - DexParams, - DecodedStateMultiCallResultWithRelativeBitmaps, -} from './types'; - -export function getUniswapV3DexKey(UniswapV3Config: DexConfigMap) { - const UniswapV3Keys = Object.keys(UniswapV3Config); - if (UniswapV3Keys.length !== 1) { - throw new Error( - `UniswapV3 key in UniswapV3Config is not unique. Update relevant places (optimizer) or fix config issue. Received: ${JSON.stringify( - UniswapV3Config, - (_0, value) => (typeof value === 'bigint' ? value.toString() : value), - )}`, - ); - } - - return UniswapV3Keys[0].toLowerCase(); -} - -export function decodeStateMultiCallResultWithRelativeBitmaps( - result: MultiResult | BytesLike, -): DecodedStateMultiCallResultWithRelativeBitmaps { - const [isSuccess, toDecode] = extractSuccessAndValue(result); - - assert( - isSuccess && toDecode !== '0x', - `decodeStateMultiCallResultWithRelativeBitmaps failed to get decodable result: ${result}`, - ); - - const decoded = ethers.utils.defaultAbiCoder.decode( - [ - // I don't want to pass here any interface, so I just use it in ethers format - ` - tuple( - address pool, - uint256 blockTimestamp, - tuple( - uint160 sqrtPriceX96, - int24 tick, - uint16 observationIndex, - uint16 observationCardinality, - uint16 observationCardinalityNext, - uint8 feeProtocol, - bool unlocked, - ) slot0, - uint128 liquidity, - int24 tickSpacing, - uint128 maxLiquidityPerTick, - tuple( - uint32 blockTimestamp, - int56 tickCumulative, - uint160 secondsPerLiquidityCumulativeX128, - bool initialized, - ) observation, - tuple( - int16 index, - uint256 value, - )[] tickBitmap, - tuple( - int24 index, - tuple( - uint128 liquidityGross, - int128 liquidityNet, - int56 tickCumulativeOutside, - uint160 secondsPerLiquidityOutsideX128, - uint32 secondsOutside, - bool initialized, - ) value, - )[] ticks - ) - `, - ], - toDecode, - )[0]; - // This conversion is not precise, because when we decode, we have more values - // But I typed only the ones that are used later - return decoded as DecodedStateMultiCallResultWithRelativeBitmaps; -} diff --git a/src/dex/index.ts b/src/dex/index.ts index 046a8d869..a4f58e878 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -80,7 +80,6 @@ import { Algebra } from './algebra/algebra'; import { QuickPerps } from './quick-perps/quick-perps'; import { NomiswapV2 } from './uniswap-v2/nomiswap-v2'; import { Dexalot } from './dexalot/dexalot'; -import { BaseswapV3 } from './baseswap-v3/baseswap-v3'; const LegacyDexes = [ CurveV2, @@ -158,7 +157,6 @@ const Dexes = [ SwaapV2, QuickPerps, NomiswapV2, - BaseswapV3, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< diff --git a/src/dex/uniswap-v3/config.ts b/src/dex/uniswap-v3/config.ts index e260b7f42..12920b5f6 100644 --- a/src/dex/uniswap-v3/config.ts +++ b/src/dex/uniswap-v3/config.ts @@ -289,6 +289,20 @@ export const UniswapV3Config: DexConfigMap = { subgraphURL: 'https://api.thegraph.com/subgraphs/name/ruvlol/univ3-test', }, }, + BaseswapV3: { + [Network.BASE]: { + factory: '0x38015D05f4fEC8AFe15D7cc0386a126574e8077B', + quoter: '0x4fDBD73aD4B1DDde594BF05497C15f76308eFfb9', + router: '0x1B8eea9315bE495187D873DA7773a874545D9D48', + supportedFees: [10000n, 2500n, 450n, 80n], + stateMulticall: '0x7160f736c52e1e78e92FD4eE4D73e21A7Cf4F950', + uniswapMulticall: '0x091e99cb1C49331a94dD62755D168E941AbD0693', + chunksCount: 10, + initRetryFrequency: 10, + initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, + subgraphURL: 'https://api.thegraph.com/subgraphs/name/baseswapfi/v3-base', + }, + }, }; export const Adapters: Record = { diff --git a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts index 02c0062bf..1c30feb42 100644 --- a/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-e2e.test.ts @@ -1135,4 +1135,28 @@ describe('UniswapV3 E2E', () => { ); }); }); + + describe('BaseswapV3 E2E', () => { + const dexKey = 'BaseswapV3'; + describe('Base', () => { + const network = Network.BASE; + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDbC'; + + const tokenAAmount: string = '1000000'; + const tokenBAmount: string = '1000000'; + const nativeTokenAmount = '1000000000000000000'; + + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + }); }); diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index 75a27e43d..5e58e1a98 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -11,6 +11,7 @@ import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; import { Address } from '@paraswap/core'; +import { BaseswapV3 } from '../baseswap-v3/baseswap-v3'; const network = Network.POLYGON; const TokenASymbol = 'USDC'; @@ -1239,3 +1240,377 @@ describe('Retro', () => { }); }); }); + +describe('BaseswapV3', function () { + const dexKey = 'BaseswapV3'; + + describe('Base', function () { + const network = Network.BASE; + const dexHelper = new DummyDexHelper(network); + + let blockNumber: number; + let retro: UniswapV3; + + const TokenASymbol = 'USDC'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'WETH'; + const TokenB = Tokens[network][TokenBSymbol]; + + const QuoterV2 = '0x4fDBD73aD4B1DDde594BF05497C15f76308eFfb9'; + + beforeEach(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + retro = new UniswapV3(network, dexKey, dexHelper); + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + const pools = await retro.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await retro.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = retro.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + retro, + 'quoteExactInputSingle', + blockNumber, + QuoterV2, + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + const pools = await retro.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await retro.getPricesVolume( + TokenA, + TokenB, + amountsBuy, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices(poolPrices!, amountsBuy, SwapSide.BUY, dexKey); + + // Check if onchain pricing equals to calculated ones + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = retro.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + retro, + 'quoteExactOutputSingle', + blockNumber, + QuoterV2, + price.prices, + TokenA.address, + TokenB.address, + fee, + amountsBuy, + ); + if (res === false) falseChecksCounter++; + }), + ); + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume SELL stable pairs', async function () { + const TokenASymbol = 'USDbC'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDC'; + const TokenB = Tokens[network][TokenBSymbol]; + + const amounts = [ + 0n, + 6000000n, + 12000000n, + 18000000n, + 24000000n, + 30000000n, + 36000000n, + 42000000n, + 48000000n, + 54000000n, + 60000000n, + 66000000n, + 72000000n, + 78000000n, + 84000000n, + 90000000n, + 96000000n, + 102000000n, + 108000000n, + 114000000n, + 120000000n, + 126000000n, + 132000000n, + 138000000n, + 144000000n, + 150000000n, + 156000000n, + 162000000n, + 168000000n, + 174000000n, + 180000000n, + 186000000n, + 192000000n, + 198000000n, + 204000000n, + 210000000n, + 216000000n, + 222000000n, + 228000000n, + 234000000n, + 240000000n, + 246000000n, + 252000000n, + 258000000n, + 264000000n, + 270000000n, + 276000000n, + 282000000n, + 288000000n, + 294000000n, + 300000000n, + ]; + + const pools = await retro.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await retro.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices( + poolPrices!.filter(pp => pp.unit !== 0n), + amounts, + SwapSide.SELL, + dexKey, + ); + + // Check if onchain pricing equals to calculated ones + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = retro.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + retro, + 'quoteExactInputSingle', + blockNumber, + QuoterV2, + price.prices, + TokenA.address, + TokenB.address, + fee, + amounts, + ); + if (res === false) falseChecksCounter++; + }), + ); + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getPoolIdentifiers and getPricesVolume BUY stable pairs', async function () { + const TokenASymbol = 'DAI'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'USDC'; + const TokenB = Tokens[network][TokenBSymbol]; + + const amountsBuy = [ + 0n, + 6000000n, + 12000000n, + 18000000n, + 24000000n, + 30000000n, + 36000000n, + 42000000n, + 48000000n, + 54000000n, + 60000000n, + 66000000n, + 72000000n, + 78000000n, + 84000000n, + 90000000n, + 96000000n, + 102000000n, + 108000000n, + 114000000n, + 120000000n, + 126000000n, + 132000000n, + 138000000n, + 144000000n, + 150000000n, + 156000000n, + 162000000n, + 168000000n, + 174000000n, + 180000000n, + 186000000n, + 192000000n, + 198000000n, + 204000000n, + 210000000n, + 216000000n, + 222000000n, + 228000000n, + 234000000n, + 240000000n, + 246000000n, + 252000000n, + 258000000n, + 264000000n, + 270000000n, + 276000000n, + 282000000n, + 288000000n, + 294000000n, + 300000000n, + ]; + + const pools = await retro.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.BUY, + blockNumber, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, + pools, + ); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await retro.getPricesVolume( + TokenA, + TokenB, + amountsBuy, + SwapSide.BUY, + blockNumber, + pools, + ); + console.log( + `${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, + poolPrices, + ); + + expect(poolPrices).not.toBeNull(); + checkPoolPrices( + poolPrices!.filter(pp => pp.unit !== 0n), + amountsBuy, + SwapSide.BUY, + dexKey, + ); + + // Check if onchain pricing equals to calculated ones + let falseChecksCounter = 0; + await Promise.all( + poolPrices!.map(async price => { + const fee = retro.eventPools[price.poolIdentifier!]!.feeCode; + const res = await checkOnChainPricing( + dexHelper, + retro, + 'quoteExactOutputSingle', + blockNumber, + QuoterV2, + price.prices, + TokenA.address, + TokenB.address, + fee, + amountsBuy, + ); + if (res === false) falseChecksCounter++; + }), + ); + expect(falseChecksCounter).toBeLessThan(poolPrices!.length); + }); + + it('getTopPoolsForToken', async function () { + const poolLiquidity = await retro.getTopPoolsForToken(TokenB.address, 10); + console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); + + checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); + }); + }); +}); From c3ed3dee6b7a05dffd31e3d1b18073e7bb08c310 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 2 Nov 2023 18:52:53 +0200 Subject: [PATCH 569/833] 2.42.4-baseswap.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bbeab622d..bbf46b504 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.4-baseswap", + "version": "2.42.4-baseswap.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 6a78c38fa8d9cce645f489655a48f8859c101a26 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 3 Nov 2023 11:44:21 +0200 Subject: [PATCH 570/833] fix: update dex-key list --- src/dex/uniswap-v3/uniswap-v3.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 2ab48c822..5e14c10c8 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -100,6 +100,7 @@ export class UniswapV3 'RamsesV2', 'ChronosV3', 'Retro', + 'BaseswapV3', ]), ); From 0d1082cc6eb254ccba9033c1668d58c0ffa5733c Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 3 Nov 2023 11:47:36 +0200 Subject: [PATCH 571/833] 2.42.4-baseswap.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bbf46b504..de027f995 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.4-baseswap.2", + "version": "2.42.4-baseswap.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 238e5acae2706bf595cea5ca1cebb8cfc82e5062 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 3 Nov 2023 12:29:07 +0200 Subject: [PATCH 572/833] fix: typo --- src/dex/uniswap-v3/uniswap-v3-integration.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index 5e58e1a98..44f7b9a52 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -11,7 +11,6 @@ import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; import { Address } from '@paraswap/core'; -import { BaseswapV3 } from '../baseswap-v3/baseswap-v3'; const network = Network.POLYGON; const TokenASymbol = 'USDC'; From e9c9e28caa087ebca47143f6908e3d732ff0a1f2 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 3 Nov 2023 12:40:26 +0200 Subject: [PATCH 573/833] fix: rename dex in tests --- .../uniswap-v3/uniswap-v3-integration.test.ts | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index 44f7b9a52..4261ccf8b 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -1248,7 +1248,7 @@ describe('BaseswapV3', function () { const dexHelper = new DummyDexHelper(network); let blockNumber: number; - let retro: UniswapV3; + let baseswapV3: UniswapV3; const TokenASymbol = 'USDC'; const TokenA = Tokens[network][TokenASymbol]; @@ -1260,11 +1260,11 @@ describe('BaseswapV3', function () { beforeEach(async () => { blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - retro = new UniswapV3(network, dexKey, dexHelper); + baseswapV3 = new UniswapV3(network, dexKey, dexHelper); }); it('getPoolIdentifiers and getPricesVolume SELL', async function () { - const pools = await retro.getPoolIdentifiers( + const pools = await baseswapV3.getPoolIdentifiers( TokenA, TokenB, SwapSide.SELL, @@ -1277,7 +1277,7 @@ describe('BaseswapV3', function () { expect(pools.length).toBeGreaterThan(0); - const poolPrices = await retro.getPricesVolume( + const poolPrices = await baseswapV3.getPricesVolume( TokenA, TokenB, amounts, @@ -1296,10 +1296,10 @@ describe('BaseswapV3', function () { let falseChecksCounter = 0; await Promise.all( poolPrices!.map(async price => { - const fee = retro.eventPools[price.poolIdentifier!]!.feeCode; + const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; const res = await checkOnChainPricing( dexHelper, - retro, + baseswapV3, 'quoteExactInputSingle', blockNumber, QuoterV2, @@ -1317,7 +1317,7 @@ describe('BaseswapV3', function () { }); it('getPoolIdentifiers and getPricesVolume BUY', async function () { - const pools = await retro.getPoolIdentifiers( + const pools = await baseswapV3.getPoolIdentifiers( TokenA, TokenB, SwapSide.BUY, @@ -1330,7 +1330,7 @@ describe('BaseswapV3', function () { expect(pools.length).toBeGreaterThan(0); - const poolPrices = await retro.getPricesVolume( + const poolPrices = await baseswapV3.getPricesVolume( TokenA, TokenB, amountsBuy, @@ -1350,10 +1350,10 @@ describe('BaseswapV3', function () { let falseChecksCounter = 0; await Promise.all( poolPrices!.map(async price => { - const fee = retro.eventPools[price.poolIdentifier!]!.feeCode; + const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; const res = await checkOnChainPricing( dexHelper, - retro, + baseswapV3, 'quoteExactOutputSingle', blockNumber, QuoterV2, @@ -1430,7 +1430,7 @@ describe('BaseswapV3', function () { 300000000n, ]; - const pools = await retro.getPoolIdentifiers( + const pools = await baseswapV3.getPoolIdentifiers( TokenA, TokenB, SwapSide.SELL, @@ -1443,7 +1443,7 @@ describe('BaseswapV3', function () { expect(pools.length).toBeGreaterThan(0); - const poolPrices = await retro.getPricesVolume( + const poolPrices = await baseswapV3.getPricesVolume( TokenA, TokenB, amounts, @@ -1468,10 +1468,10 @@ describe('BaseswapV3', function () { let falseChecksCounter = 0; await Promise.all( poolPrices!.map(async price => { - const fee = retro.eventPools[price.poolIdentifier!]!.feeCode; + const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; const res = await checkOnChainPricing( dexHelper, - retro, + baseswapV3, 'quoteExactInputSingle', blockNumber, QuoterV2, @@ -1548,7 +1548,7 @@ describe('BaseswapV3', function () { 300000000n, ]; - const pools = await retro.getPoolIdentifiers( + const pools = await baseswapV3.getPoolIdentifiers( TokenA, TokenB, SwapSide.BUY, @@ -1561,7 +1561,7 @@ describe('BaseswapV3', function () { expect(pools.length).toBeGreaterThan(0); - const poolPrices = await retro.getPricesVolume( + const poolPrices = await baseswapV3.getPricesVolume( TokenA, TokenB, amountsBuy, @@ -1586,10 +1586,10 @@ describe('BaseswapV3', function () { let falseChecksCounter = 0; await Promise.all( poolPrices!.map(async price => { - const fee = retro.eventPools[price.poolIdentifier!]!.feeCode; + const fee = baseswapV3.eventPools[price.poolIdentifier!]!.feeCode; const res = await checkOnChainPricing( dexHelper, - retro, + baseswapV3, 'quoteExactOutputSingle', blockNumber, QuoterV2, @@ -1606,7 +1606,10 @@ describe('BaseswapV3', function () { }); it('getTopPoolsForToken', async function () { - const poolLiquidity = await retro.getTopPoolsForToken(TokenB.address, 10); + const poolLiquidity = await baseswapV3.getTopPoolsForToken( + TokenB.address, + 10, + ); console.log(`${TokenASymbol} Top Pools:`, poolLiquidity); checkPoolsLiquidity(poolLiquidity, TokenB.address, dexKey); From be3cb2a81f378bfd04a635455b0155e0ecd4c872 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 30 Oct 2023 16:48:12 +0200 Subject: [PATCH 574/833] fix: add arbitrum integration tests --- src/dex/wombat/wombat-integration.test.ts | 125 +++++++++++++++++----- 1 file changed, 97 insertions(+), 28 deletions(-) diff --git a/src/dex/wombat/wombat-integration.test.ts b/src/dex/wombat/wombat-integration.test.ts index 64b1443aa..16b3e7459 100644 --- a/src/dex/wombat/wombat-integration.test.ts +++ b/src/dex/wombat/wombat-integration.test.ts @@ -16,21 +16,6 @@ import { Tokens } from '../../../tests/constants-e2e'; import { Token } from '../../types'; import { Address } from '@paraswap/core'; -/* - README - ====== - - This test script adds tests for Wombat general integration - with the DEX interface. The test cases below are example tests. - It is recommended to add tests which cover Wombat specific - logic. - - You can run this individual test script by running: - `npx jest src/dex//-integration.test.ts` - - (This comment should be removed from the final implementation) -*/ - function getReaderCalldata( exchangeAddress: string, readerIface: Interface, @@ -39,19 +24,13 @@ function getReaderCalldata( toToken: Token, amounts: bigint[], funcName: string, - // TODO: Put here additional arguments you need ) { return amounts.map(amount => ({ target: exchangeAddress, callData: readerIface.encodeFunctionData( funcName, side == SwapSide.SELL - ? [ - // TODO: Put here additional arguments to encode them - fromToken.address, - toToken.address, - amount, - ] + ? [fromToken.address, toToken.address, amount] : [toToken.address, fromToken.address, -amount], ), })); @@ -62,7 +41,6 @@ function decodeReaderResult( readerIface: Interface, funcName: string, ) { - // TODO: Adapt this function for your needs return results.map(result => { const parsed = readerIface.decodeFunctionResult(funcName, result); return BigInt(parsed[0]._hex); @@ -82,9 +60,6 @@ async function checkOnChainPricing( ) { const exchangeAddress = pool; // TODO: Put here the real exchange address - // TODO: Replace dummy interface with the real one - // Normally you can get it from wombat.Iface or from eventPool. - // It depends on your implementation const readerIface = Wombat.poolInterface; const readerCallData = getReaderCalldata( @@ -180,8 +155,102 @@ describe('Wombat', function () { const tokens = Tokens[network]; - // TODO: Put here token Symbol to check against - // Don't forget to update relevant tokens in constant-e2e.ts + const srcTokenSymbol = 'USDC'; + const destTokenSymbol = 'USDT'; + + const amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + const amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals], + 2n * BI_POWS[tokens[destTokenSymbol].decimals], + 3n * BI_POWS[tokens[destTokenSymbol].decimals], + 4n * BI_POWS[tokens[destTokenSymbol].decimals], + 5n * BI_POWS[tokens[destTokenSymbol].decimals], + 6n * BI_POWS[tokens[destTokenSymbol].decimals], + 7n * BI_POWS[tokens[destTokenSymbol].decimals], + 8n * BI_POWS[tokens[destTokenSymbol].decimals], + 9n * BI_POWS[tokens[destTokenSymbol].decimals], + 10n * BI_POWS[tokens[destTokenSymbol].decimals], + ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + wombat = new Wombat(network, dexKey, dexHelper); + if (wombat.initializePricing) { + await wombat.initializePricing(blockNumber); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + await testPricingOnNetwork( + wombat, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + 'quotePotentialSwap', + ); + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + await testPricingOnNetwork( + wombat, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + 'quotePotentialSwap', + ); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + const newWombat = new Wombat(network, dexKey, dexHelper); + if (newWombat.updatePoolState) { + await newWombat.updatePoolState(); + } + const poolLiquidity = await newWombat.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!newWombat.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); + }); + + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + const srcTokenSymbol = 'USDC'; const destTokenSymbol = 'USDT'; From 0e81d78c5508f9169270454bb09dfb2f01897d79 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 31 Oct 2023 11:27:07 +0200 Subject: [PATCH 575/833] fix: add e2e tests --- src/dex/wombat/config.ts | 11 ++- src/dex/wombat/types.ts | 1 + src/dex/wombat/wombat-e2e.test.ts | 132 +++++++++++++++++++++--------- src/dex/wombat/wombat.ts | 2 + 4 files changed, 108 insertions(+), 38 deletions(-) diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts index cd54fbf15..0a8bce995 100644 --- a/src/dex/wombat/config.ts +++ b/src/dex/wombat/config.ts @@ -6,6 +6,7 @@ export const WombatConfig: DexConfigMap = { Wombat: { [Network.BSC]: { bmwAddress: '0x489833311676B566f888119c29bd997Dc6C95830', + // routerAddress: '0x19609B03C976CCA288fbDae5c21d4290e9a4aDD7', }, [Network.ARBITRUM]: { bmwAddress: '0x62A83C6791A3d7950D823BB71a38e47252b6b6F4', @@ -19,7 +20,15 @@ export const Adapters: Record = { { name: 'BscAdapter01', /** @todo check index number */ - index: 12, + // index: 12, + // uniswapv2 forks + index: 3, + }, + ], + [SwapSide.BUY]: [ + { + name: 'BscBuyAdapter', + index: 1, }, ], }, diff --git a/src/dex/wombat/types.ts b/src/dex/wombat/types.ts index 5fa11b25f..3bac57e66 100644 --- a/src/dex/wombat/types.ts +++ b/src/dex/wombat/types.ts @@ -44,6 +44,7 @@ export type WombatData = { export type DexParams = { // DexParams is set of parameters that can be used to initiate a DEX fork. bmwAddress: Address; + // routerAddress?: Address; }; export type MulticallResultOutputs = diff --git a/src/dex/wombat/wombat-e2e.test.ts b/src/dex/wombat/wombat-e2e.test.ts index 02fe27be6..1b7a94478 100644 --- a/src/dex/wombat/wombat-e2e.test.ts +++ b/src/dex/wombat/wombat-e2e.test.ts @@ -19,6 +19,7 @@ import { generateConfig } from '../../config'; // tokenAAmount: string, // tokenBAmount: string, // nativeTokenAmount: string, +// slippage?: number | undefined, // ) { // const provider = new StaticJsonRpcProvider( // generateConfig(network).privateHttpProvider, @@ -27,7 +28,7 @@ import { generateConfig } from '../../config'; // const tokens = Tokens[network]; // const holders = Holders[network]; // const nativeTokenSymbol = NativeTokenSymbols[network]; -// + // const sideToContractMethods = new Map([ // [ // SwapSide.SELL, @@ -37,8 +38,72 @@ import { generateConfig } from '../../config'; // // ContractMethod.megaSwap, // ], // ], +// [SwapSide.BUY, [ContractMethod.simpleBuy /* ContractMethod.buy */]], // ]); -// + +// describe(`${network}`, () => { +// sideToContractMethods.forEach((contractMethods, side) => +// describe(`${side}`, () => { +// 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, +// 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, +// 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, +// network, +// provider, +// undefined, +// undefined, +// undefined, +// slippage, +// ); +// }); +// }); +// }); +// }), +// ); +// }); +// } + // describe(`${network}`, () => { // sideToContractMethods.forEach((contractMethods, side) => // describe(`${side}`, () => { @@ -107,46 +172,39 @@ describe('Wombat E2E', () => { SwapSide.SELL, [ ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - ], - ], - [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - // ContractMethod.buy, + ContractMethod.multiSwap, + ContractMethod.megaSwap, ], ], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], ]); - const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ [ - [ - { - name: 'USDC', - sellAmount: '100000000000000000000', - buyAmount: '100000000000000000000', - }, - { - name: 'USDT', - sellAmount: '100000000000000000000', - buyAmount: '100000000000000000000', - }, - ], - [ - { - name: 'BNB', - sellAmount: '1000000000000000000', - buyAmount: '1000000000', - }, - { - name: 'BNBx', - sellAmount: '1000000000', - buyAmount: '1000000000000000000', - }, - ], - ]; + { + name: 'USDC', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + { + name: 'USDT', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + ], + // [ + // { + // name: 'BNB', + // sellAmount: '1000000000000000000', + // buyAmount: '1000000000', + // }, + // { + // name: 'BNBx', + // sellAmount: '1000000000', + // buyAmount: '1000000000000000000', + // }, + // ], + ]; sideToContractMethods.forEach((contractMethods, side) => describe(`${side}`, () => { diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index a16cf8c78..3d8ab613e 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -30,8 +30,10 @@ import { WombatQuoter } from './wombat-quoter'; import { WombatBmw } from './wombat-bmw'; import { fromWad } from './utils'; import { WombatPool } from './wombat-pool'; +import { UniswapV2 } from '../uniswap-v2/uniswap-v2'; export class Wombat extends SimpleExchange implements IDex { + // export class Wombat implements IDex { // contract interfaces static readonly erc20Interface = new Interface(ERC20ABI); static readonly poolInterface = new Interface(PoolABI); From 22e531656103d255f519f16acfcb9cecd0f948c4 Mon Sep 17 00:00:00 2001 From: Koala <142200506+koala0814@users.noreply.github.com> Date: Fri, 3 Nov 2023 20:38:28 +0800 Subject: [PATCH 576/833] update pool state logs and integration tests --- src/dex/wombat/wombat-integration.test.ts | 100 +++++++++++----------- src/dex/wombat/wombat.ts | 24 ++++-- 2 files changed, 67 insertions(+), 57 deletions(-) diff --git a/src/dex/wombat/wombat-integration.test.ts b/src/dex/wombat/wombat-integration.test.ts index 16b3e7459..e7dfb3727 100644 --- a/src/dex/wombat/wombat-integration.test.ts +++ b/src/dex/wombat/wombat-integration.test.ts @@ -189,12 +189,33 @@ describe('Wombat', function () { beforeAll(async () => { blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); wombat = new Wombat(network, dexKey, dexHelper); - if (wombat.initializePricing) { - await wombat.initializePricing(blockNumber); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + if (wombat.updatePoolState) { + await wombat.updatePoolState(); + } + const poolLiquidity = await wombat.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!wombat.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); } }); it('getPoolIdentifiers and getPricesVolume SELL', async function () { + if (wombat.initializePricing) { + await wombat.initializePricing(blockNumber); + } await testPricingOnNetwork( wombat, network, @@ -209,6 +230,9 @@ describe('Wombat', function () { }); it('getPoolIdentifiers and getPricesVolume BUY', async function () { + if (wombat.initializePricing) { + await wombat.initializePricing(blockNumber); + } await testPricingOnNetwork( wombat, network, @@ -221,28 +245,6 @@ describe('Wombat', function () { 'quotePotentialSwap', ); }); - - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - const newWombat = new Wombat(network, dexKey, dexHelper); - if (newWombat.updatePoolState) { - await newWombat.updatePoolState(); - } - const poolLiquidity = await newWombat.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, - ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - - if (!newWombat.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, - dexKey, - ); - } - }); }); describe('Arbitrum', () => { @@ -285,12 +287,33 @@ describe('Wombat', function () { beforeAll(async () => { blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); wombat = new Wombat(network, dexKey, dexHelper); - if (wombat.initializePricing) { - await wombat.initializePricing(blockNumber); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + if (wombat.updatePoolState) { + await wombat.updatePoolState(); + } + const poolLiquidity = await wombat.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!wombat.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); } }); it('getPoolIdentifiers and getPricesVolume SELL', async function () { + if (wombat.initializePricing) { + await wombat.initializePricing(blockNumber); + } await testPricingOnNetwork( wombat, network, @@ -305,6 +328,9 @@ describe('Wombat', function () { }); it('getPoolIdentifiers and getPricesVolume BUY', async function () { + if (wombat.initializePricing) { + await wombat.initializePricing(blockNumber); + } await testPricingOnNetwork( wombat, network, @@ -317,27 +343,5 @@ describe('Wombat', function () { 'quotePotentialSwap', ); }); - - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - const newWombat = new Wombat(network, dexKey, dexHelper); - if (newWombat.updatePoolState) { - await newWombat.updatePoolState(); - } - const poolLiquidity = await newWombat.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, - ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - - if (!newWombat.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, - dexKey, - ); - } - }); }); }); diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 3d8ab613e..a9f487be8 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -174,7 +174,9 @@ export class Wombat extends SimpleExchange implements IDex { for (const poolAddress of pools) { let state = await this.pools![poolAddress].getState(blockNumber); if (!state) { - this.logger.error(`State is null in getPricesVolume`); + this.logger.warn( + `State of pool ${poolAddress} is null in getPricesVolume, skipping...`, + ); continue; } const [unit, ...prices] = this.computePrices( @@ -230,7 +232,9 @@ export class Wombat extends SimpleExchange implements IDex { for (const [poolAddress, pool] of Object.entries(this.pools)) { let stateOj = await pool.getState(blockNumber); if (!stateOj) { - this.logger.error(`State is null in findPools`); + this.logger.warn( + `State of pool ${poolAddress} is null in findPools, skipping...`, + ); continue; } @@ -241,7 +245,8 @@ export class Wombat extends SimpleExchange implements IDex { state.asset[srcTokenAddress] && state.asset[destTokenAddress] && (liquidityThresholdInUSD === 0 || - this.poolLiquidityUSD![poolAddress] > liquidityThresholdInUSD) + (this.poolLiquidityUSD![poolAddress] && + this.poolLiquidityUSD![poolAddress] > liquidityThresholdInUSD)) ) { pools.push(poolAddress); } @@ -332,14 +337,16 @@ export class Wombat extends SimpleExchange implements IDex { const usdPromises = []; const poolStates: { [poolAddress: string]: DeepReadonly } = {}; const poolStateObjs = await Promise.all( - Object.values(this.pools).map(pool => pool.getState(blockNumber)), + Object.values(this.pools).map(pool => pool.getState()), ); for (const [poolAddress, pool] of Object.entries(this.pools)) { const index = Object.keys(this.pools).indexOf(poolAddress); let state = poolStateObjs[index]; if (!state) { - this.logger.error(`State of ${poolAddress} is null in updatePoolState`); + this.logger.warn( + `State of ${poolAddress} is null in updatePoolState, skipping...`, + ); continue; } poolStates[poolAddress] = state.value; @@ -379,15 +386,14 @@ export class Wombat extends SimpleExchange implements IDex { limit: number, ): Promise { if (!this.poolLiquidityUSD) await this.updatePoolState(); - const blockNumber = await this.dexHelper.provider.getBlockNumber(); tokenAddress = tokenAddress.toLowerCase(); const pools: string[] = []; const poolStates: { [poolAddress: string]: DeepReadonly } = {}; for (const [poolAddress, eventPool] of Object.entries(this.pools)) { - let state = await eventPool.getState(blockNumber); + let state = await eventPool.getState(); if (!state) { - this.logger.error( - `State of ${poolAddress} is null in getTopPoolsForToken`, + this.logger.warn( + `State of ${poolAddress} is null in getTopPoolsForToken, skipping...`, ); continue; } From 01c32deed3151f53a7ed97bd7d9c87ce4238ce54 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Sat, 4 Nov 2023 19:39:15 +0200 Subject: [PATCH 577/833] fix: move impl to gmx --- src/dex/gmx/config.ts | 36 +++++++ src/dex/gmx/gmx-e2e.test.ts | 154 ++++++++++++++++++++++++++++ src/dex/morphex/morphex-e2e.test.ts | 4 +- 3 files changed, 192 insertions(+), 2 deletions(-) diff --git a/src/dex/gmx/config.ts b/src/dex/gmx/config.ts index 3822ee464..6fb792f0c 100644 --- a/src/dex/gmx/config.ts +++ b/src/dex/gmx/config.ts @@ -21,6 +21,24 @@ export const GMXConfig: DexConfigMap = { usdg: '0x45096e7aA921f27590f8F19e457794EB09678141', }, }, + Morphex: { + [Network.FANTOM]: { + vault: '0x245cD6d33578de9aF75a3C0c636c726b1A8cbdAa', + reader: '0xcA47b9b612a152ece991F31d8D3547D73BaF2Ecc', + priceFeed: '0x7a451DE877CbB6551AACa671d0458B6f9dF1e29A', + fastPriceFeed: '0x7f54C35A38D89fcf5Fe516206E6628745ed38CC7', + fastPriceEvents: '0xDc7C389be5da32e326A261dC0126feCa7AE04d79', + usdg: '0xe135c7BFfda932b5B862Da442cF4CbC4d43DC3Ad', + }, + [Network.BSC]: { + vault: '0x46940Dc651bFe3F2CC3E04cf9dC5579B50Cf0765', + reader: '0x49A97680938B4F1f73816d1B70C3Ab801FAd124B', + priceFeed: '0x0144b19D1B9338fC7C286d6767bd9b29F0347f27', + fastPriceFeed: '0x55e6e6A968e485abEC1e1d957f408586e45a4f99', + fastPriceEvents: '0x491Df61db853761d42C4F38BeD220E9D807143dE', + usdg: '0x548f93779fBC992010C07467cBaf329DD5F059B7', + }, + }, }; export const Adapters: { @@ -44,4 +62,22 @@ export const Adapters: { }, ], }, + [Network.BSC]: { + [SwapSide.SELL]: [ + { + // TODO: Update + name: 'BscAdapter01', + index: 9, + }, + ], + }, + [Network.FANTOM]: { + [SwapSide.SELL]: [ + { + // TODO: Update + name: 'FantomAdapter01', + index: 9, + }, + ], + }, }; diff --git a/src/dex/gmx/gmx-e2e.test.ts b/src/dex/gmx/gmx-e2e.test.ts index f209019cb..c982e2a0d 100644 --- a/src/dex/gmx/gmx-e2e.test.ts +++ b/src/dex/gmx/gmx-e2e.test.ts @@ -164,3 +164,157 @@ describe('GMX E2E', () => { ); }); }); + +describe('Morphex E2E', () => { + const dexKey = 'Morphex'; + + describe('Fantom', () => { + const network = Network.FANTOM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'axlUSDC'; + const tokenBSymbol: string = 'lzUSDC'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '500000000'; // 500 Axelar USDC + const tokenBAmount: string = '500000000'; // 500 Layer Zero USDC + const nativeTokenAmount = '100000000000000000000'; // 100 FTM + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + 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, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); + + describe('BSC', () => { + const network = Network.BSC; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'USDT'; + const tokenBSymbol: string = 'ETH'; + const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '2000000000000000000000'; // 2000 USDT + const tokenBAmount: string = '1000000000000000000'; // 1 ETH + const nativeTokenAmount = '1000000000000000000'; // 1 BNB + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + ], + ], + ]); + + sideToContractMethods.forEach((contractMethods, side) => + 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, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[nativeTokenSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); +}); diff --git a/src/dex/morphex/morphex-e2e.test.ts b/src/dex/morphex/morphex-e2e.test.ts index cf701af17..ab91967a7 100644 --- a/src/dex/morphex/morphex-e2e.test.ts +++ b/src/dex/morphex/morphex-e2e.test.ts @@ -14,7 +14,7 @@ import { generateConfig } from '../../config'; describe('Morphex E2E', () => { const dexKey = 'Morphex'; - describe('Morphex Fantom', () => { + describe('Fantom', () => { const network = Network.FANTOM; const tokens = Tokens[network]; const holders = Holders[network]; @@ -89,7 +89,7 @@ describe('Morphex E2E', () => { ); }); - describe('Morphex BSC', () => { + describe('BSC', () => { const network = Network.BSC; const tokens = Tokens[network]; const holders = Holders[network]; From 4e801ae4a761ef45b233b3e993e8102e3d38cd62 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Sun, 5 Nov 2023 23:05:02 +0200 Subject: [PATCH 578/833] fix: move morphex to gmx & clean --- src/config.ts | 4 +- src/dex/gmx/config.ts | 8 +- src/dex/gmx/gmx-e2e.test.ts | 19 +- src/dex/gmx/gmx-integration.test.ts | 121 +++++++++-- src/dex/index.ts | 2 - src/dex/morphex/config.ts | 47 ----- src/dex/morphex/morphex-e2e.test.ts | 166 --------------- src/dex/morphex/morphex-events.test.ts | 150 -------------- src/dex/morphex/morphex-integration.test.ts | 211 -------------------- src/dex/morphex/morphex.ts | 22 -- tests/constants-e2e.ts | 4 + 11 files changed, 127 insertions(+), 627 deletions(-) delete mode 100644 src/dex/morphex/config.ts delete mode 100644 src/dex/morphex/morphex-e2e.test.ts delete mode 100644 src/dex/morphex/morphex-events.test.ts delete mode 100644 src/dex/morphex/morphex-integration.test.ts delete mode 100644 src/dex/morphex/morphex.ts diff --git a/src/config.ts b/src/config.ts index 21d2fd5b1..6923ee077 100644 --- a/src/config.ts +++ b/src/config.ts @@ -165,7 +165,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_56`]?.split(',') || [], adapterAddresses: { BscAdapter01: '0xA31d9C571DF00e0F428B0bD24c34D103E8112222', - BscAdapter02: '0x02f2c31ebDE63E871AD0E74c01E21c819292a59D', + BscAdapter02: '0x3B9F60Bb1D8C5cfEDB9f4635678C6b97AA52d208', BscBuyAdapter: '0x301c2813e3ceb43A448a12f21551EDBcdC37F157', }, rpcPollingMaxAllowedStateDelayInBlocks: 1, @@ -252,7 +252,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_250`]?.split(',') || [], adapterAddresses: { - FantomAdapter01: '0x434C1Cca4842629230067674Dd54E21a14D9FD5D', + FantomAdapter01: '0xede616e2e3c35eeb28a1737785c5c5e8e965cd56', FantomBuyAdapter: '0xb2634B3CBc1E401AB3C2743DB44d459C5c9aA662', }, uniswapV2ExchangeRouterAddress: diff --git a/src/dex/gmx/config.ts b/src/dex/gmx/config.ts index 6fb792f0c..5b1802ea3 100644 --- a/src/dex/gmx/config.ts +++ b/src/dex/gmx/config.ts @@ -65,18 +65,16 @@ export const Adapters: { [Network.BSC]: { [SwapSide.SELL]: [ { - // TODO: Update - name: 'BscAdapter01', - index: 9, + name: 'BscAdapter02', + index: 6, }, ], }, [Network.FANTOM]: { [SwapSide.SELL]: [ { - // TODO: Update name: 'FantomAdapter01', - index: 9, + index: 12, }, ], }, diff --git a/src/dex/gmx/gmx-e2e.test.ts b/src/dex/gmx/gmx-e2e.test.ts index c982e2a0d..4a6fe096d 100644 --- a/src/dex/gmx/gmx-e2e.test.ts +++ b/src/dex/gmx/gmx-e2e.test.ts @@ -190,8 +190,8 @@ describe('Morphex E2E', () => { SwapSide.SELL, [ ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, ], ], ]); @@ -251,22 +251,21 @@ describe('Morphex E2E', () => { generateConfig(network).privateHttpProvider, network, ); - - const tokenASymbol: string = 'USDT'; - const tokenBSymbol: string = 'ETH'; + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'XRP'; const nativeTokenSymbol = NativeTokenSymbols[network]; - const tokenAAmount: string = '2000000000000000000000'; // 2000 USDT - const tokenBAmount: string = '1000000000000000000'; // 1 ETH - const nativeTokenAmount = '1000000000000000000'; // 1 BNB + const tokenAAmount: string = '100000'; + const tokenBAmount: string = '100000'; + const nativeTokenAmount = '1000000000000000000'; const sideToContractMethods = new Map([ [ SwapSide.SELL, [ ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, ], ], ]); diff --git a/src/dex/gmx/gmx-integration.test.ts b/src/dex/gmx/gmx-integration.test.ts index f8ef4f659..ef0e96e6c 100644 --- a/src/dex/gmx/gmx-integration.test.ts +++ b/src/dex/gmx/gmx-integration.test.ts @@ -15,13 +15,6 @@ import { import { Tokens } from '../../../tests/constants-e2e'; import ReaderABI from '../../abi/gmx/reader.json'; -const network = Network.AVALANCHE; -const TokenASymbol = 'USDCe'; -const TokenA = Tokens[network][TokenASymbol]; - -const TokenBSymbol = 'WAVAX'; -const TokenB = Tokens[network][TokenBSymbol]; - const amounts = [ 0n, 1000000000n, @@ -31,12 +24,116 @@ const amounts = [ 5000000000n, ]; -const dexKey = 'GMX'; -const params = GMXConfig[dexKey][network]; -const readerInterface = new Interface(ReaderABI); -const readerAddress = '0x67b789D48c926006F5132BFCe4e976F0A7A63d5D'; +describe('GMX Avalanche', function () { + const network = Network.AVALANCHE; + const TokenASymbol = 'USDCe'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'WAVAX'; + const TokenB = Tokens[network][TokenBSymbol]; + const dexKey = 'GMX'; + const params = GMXConfig[dexKey][network]; + const readerInterface = new Interface(ReaderABI); + const readerAddress = '0x67b789D48c926006F5132BFCe4e976F0A7A63d5D'; + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + const dexHelper = new DummyDexHelper(network); + const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); + const gmx = new GMX(network, dexKey, dexHelper); + + await gmx.initializePricing(blocknumber); + + const pools = await gmx.getPoolIdentifiers( + TokenA, + TokenB, + SwapSide.SELL, + blocknumber, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); + + expect(pools.length).toBeGreaterThan(0); + + const poolPrices = await gmx.getPricesVolume( + TokenA, + TokenB, + amounts, + SwapSide.SELL, + blocknumber, + pools, + ); + console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); + + expect(poolPrices).not.toBeNull(); + if (gmx.hasConstantPriceLargeAmounts) { + checkConstantPoolPrices(poolPrices!, amounts, dexKey); + } else { + checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); + } + + // Do on chain pricing based on reader to compare + const readerCallData = amounts.map(a => ({ + target: readerAddress, + callData: readerInterface.encodeFunctionData('getAmountOut', [ + params.vault, + TokenA.address, + TokenB.address, + a.toString(), + ]), + })); + + const readerResult = ( + await dexHelper.multiContract.methods + .aggregate(readerCallData) + .call({}, blocknumber) + ).returnData; + const expectedPrices = readerResult.map((p: any) => + BigInt( + readerInterface.decodeFunctionResult('getAmountOut', p)[0].toString(), + ), + ); + + expect(poolPrices![0].prices).toEqual(expectedPrices); + }); + + it('getTopPoolsForToken', async function () { + const dexHelper = new DummyDexHelper(network); + const gmx = new GMX(network, dexKey, dexHelper); + + await gmx.updatePoolState(); + const poolLiquidity = await gmx.getTopPoolsForToken(TokenA.address, 10); + console.log( + `${TokenASymbol} Top Pools:`, + JSON.stringify(poolLiquidity, null, 2), + ); + + if (!gmx.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); + } + }); +}); + +describe('Morphex BSC', function () { + const dexKey = 'Morphex'; + const network = Network.BSC; + const TokenASymbol = 'WBNB'; + const TokenA = Tokens[network][TokenASymbol]; + + const TokenBSymbol = 'XRP'; + const TokenB = Tokens[network][TokenBSymbol]; + + const amounts = [ + 0n, + 1000000000000000000n, + 2000000000000000000n, + 3000000000000000000n, + 4000000000000000000n, + 5000000000000000000n, + ]; + + const readerInterface = new Interface(ReaderABI); + const params = GMXConfig[dexKey][network]; + const readerAddress = params.reader; -describe('GMX', function () { it('getPoolIdentifiers and getPricesVolume SELL', async function () { const dexHelper = new DummyDexHelper(network); const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); diff --git a/src/dex/index.ts b/src/dex/index.ts index b6649363e..a4f58e878 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -80,7 +80,6 @@ import { Algebra } from './algebra/algebra'; import { QuickPerps } from './quick-perps/quick-perps'; import { NomiswapV2 } from './uniswap-v2/nomiswap-v2'; import { Dexalot } from './dexalot/dexalot'; -import { Morphex } from './morphex/morphex'; const LegacyDexes = [ CurveV2, @@ -158,7 +157,6 @@ const Dexes = [ SwaapV2, QuickPerps, NomiswapV2, - Morphex, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< diff --git a/src/dex/morphex/config.ts b/src/dex/morphex/config.ts deleted file mode 100644 index be57e017c..000000000 --- a/src/dex/morphex/config.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { DexParams } from '../gmx/types'; -import { DexConfigMap } from '../../types'; -import { Network, SwapSide } from '../../constants'; - -export const MorphexConfig: DexConfigMap = { - Morphex: { - [Network.FANTOM]: { - vault: '0x245cD6d33578de9aF75a3C0c636c726b1A8cbdAa', - reader: '0xcA47b9b612a152ece991F31d8D3547D73BaF2Ecc', - priceFeed: '0x7a451DE877CbB6551AACa671d0458B6f9dF1e29A', - fastPriceFeed: '0x7f54C35A38D89fcf5Fe516206E6628745ed38CC7', - fastPriceEvents: '0xDc7C389be5da32e326A261dC0126feCa7AE04d79', - usdg: '0xe135c7BFfda932b5B862Da442cF4CbC4d43DC3Ad', - }, - [Network.BSC]: { - vault: '0x46940Dc651bFe3F2CC3E04cf9dC5579B50Cf0765', - reader: '0x49A97680938B4F1f73816d1B70C3Ab801FAd124B', - priceFeed: '0x0144b19D1B9338fC7C286d6767bd9b29F0347f27', - fastPriceFeed: '0x55e6e6A968e485abEC1e1d957f408586e45a4f99', - fastPriceEvents: '0x491Df61db853761d42C4F38BeD220E9D807143dE', - usdg: '0x548f93779fBC992010C07467cBaf329DD5F059B7', - }, - }, -}; - -export const Adapters: { - [chainId: number]: { - [side: string]: { name: string; index: number }[] | null; - }; -} = { - [Network.FANTOM]: { - [SwapSide.SELL]: [ - { - name: 'FantomAdapter01', - index: 6, // TODO: there is no Morphex adapter - }, - ], - }, - [Network.BSC]: { - [SwapSide.SELL]: [ - { - name: 'BscAdapter01', - index: 6, // TODO: there is no Morphex adapter - }, - ], - }, -}; diff --git a/src/dex/morphex/morphex-e2e.test.ts b/src/dex/morphex/morphex-e2e.test.ts deleted file mode 100644 index ab91967a7..000000000 --- a/src/dex/morphex/morphex-e2e.test.ts +++ /dev/null @@ -1,166 +0,0 @@ -import dotenv from 'dotenv'; -dotenv.config(); - -import { testE2E } from '../../../tests/utils-e2e'; -import { - Tokens, - Holders, - NativeTokenSymbols, -} from '../../../tests/constants-e2e'; -import { Network, ContractMethod, SwapSide } from '../../constants'; -import { StaticJsonRpcProvider } from '@ethersproject/providers'; -import { generateConfig } from '../../config'; - -describe('Morphex E2E', () => { - const dexKey = 'Morphex'; - - describe('Fantom', () => { - const network = Network.FANTOM; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const tokenASymbol: string = 'axlUSDC'; - const tokenBSymbol: string = 'lzUSDC'; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const tokenAAmount: string = '500000000'; // 500 Axelar USDC - const tokenBAmount: string = '500000000'; // 500 Layer Zero USDC - const nativeTokenAmount = '100000000000000000000'; // 100 FTM - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - ], - ], - ]); - - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(nativeTokenSymbol + ' -> TOKEN', async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it('TOKEN -> ' + nativeTokenSymbol, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it('TOKEN -> TOKEN', async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }), - ); - }); - - describe('BSC', () => { - const network = Network.BSC; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const tokenASymbol: string = 'USDT'; - const tokenBSymbol: string = 'ETH'; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const tokenAAmount: string = '2000000000000000000000'; // 2000 USDT - const tokenBAmount: string = '1000000000000000000'; // 1 ETH - const nativeTokenAmount = '1000000000000000000'; // 1 BNB - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - ], - ], - ]); - - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(nativeTokenSymbol + ' -> TOKEN', async () => { - await testE2E( - tokens[nativeTokenSymbol], - tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it('TOKEN -> ' + nativeTokenSymbol, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it('TOKEN -> TOKEN', async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }), - ); - }); -}); diff --git a/src/dex/morphex/morphex-events.test.ts b/src/dex/morphex/morphex-events.test.ts deleted file mode 100644 index f2bf62360..000000000 --- a/src/dex/morphex/morphex-events.test.ts +++ /dev/null @@ -1,150 +0,0 @@ -import dotenv from 'dotenv'; -dotenv.config(); - -import { GMXEventPool } from '../gmx/pool'; -import { MorphexConfig } from './config'; -import { Network } from '../../constants'; -import { DummyDexHelper } from '../../dex-helper/index'; -import { testEventSubscriber } from '../../../tests/utils-events'; -import { PoolState } from '../gmx/types'; - -jest.setTimeout(50 * 1000); -const dexKey = 'Morphex'; - -async function fetchPoolState( - gmxPool: GMXEventPool, - blockNumber: number, -): Promise { - return gmxPool.generateState(blockNumber); -} - -// timestamp can't be compared exactly as the event released -// doesn't have the timestamp. It is safe to consider the -// timestamp as the blockTime as the max deviation is bounded -// on the contract -const stateWithoutTimestamp = (state: PoolState) => ({ - ...state, - secondaryPrices: { - prices: state.secondaryPrices.prices, - // timestamp (this is removed) - }, -}); - -function compareState(state: PoolState, expectedState: PoolState) { - expect(stateWithoutTimestamp(state)).toEqual( - stateWithoutTimestamp(expectedState), - ); -} - -describe('Morphex Fantom Events', function () { - const network = Network.FANTOM; - const params = MorphexConfig[dexKey][network]; - const blockNumbers: { [eventName: string]: number[] } = { - IncreaseUsdgAmount: [ - 67247602, 67247565, 67247561, 67247508, 67247393, 67247305, 67247303, - 67247302, 67247230, 67247220, 67247218, 67247216, 67247215, 67247145, - 67247059, 67247026, 67246788, 67246731, - ], - DecreaseUsdgAmount: [ - 67247778, 67247602, 67247565, 67247561, 67247508, 67247393, 67247305, - 67247303, 67247302, 67247230, 67247220, 67247218, 67247216, 67247215, - 67247145, 67247059, 67247026, 67246788, - ], - Transfer: [ - 67087282, 67087063, 67087039, 67068002, 67052880, 67052806, 67052801, - ], - PriceUpdate: [67248035, 67247977, 67247907, 67247897, 67247893], - }; - - describe('MorphexEventPool', function () { - Object.keys(blockNumbers).forEach((event: string) => { - blockNumbers[event].forEach((blockNumber: number) => { - it(`Should return the correct state after the ${blockNumber}:${event}`, async function () { - const dexHelper = new DummyDexHelper(network); - const logger = dexHelper.getLogger(dexKey); - - const config = await GMXEventPool.getConfig( - params, - blockNumber, - dexHelper.multiContract, - ); - const gmxPool = new GMXEventPool( - dexKey, - network, - dexHelper, - logger, - config, - ); - - await testEventSubscriber( - gmxPool, - gmxPool.addressesSubscribed, - (_blockNumber: number) => fetchPoolState(gmxPool, _blockNumber), - blockNumber, - `${dexKey}_${params.vault}`, - dexHelper.provider, - compareState, - ); - }); - }); - }); - }); -}); - -describe('Morphex BSC Events', function () { - const network = Network.BSC; - const params = MorphexConfig[dexKey][network]; - const blockNumbers: { [eventName: string]: number[] } = { - IncreaseUsdgAmount: [ - 31152256, 31138628, 31137790, 31137788, 31131427, 31123797, 31120641, - 31116766, 31116335, 31116205, 31115380, 31112437, 31112433, 31107317, - 31106077, 31106044, 31105166, 31104580, 31104252, 31104234, 31102490, - 31097010, - ], - DecreaseUsdgAmount: [ - 31152256, 31137790, 31137788, 31136832, 31136830, 31136827, 31136825, - 31136823, 31136820, 31136818, 31136815, 31131427, 31112437, 31112433, - 31106077, 31106044, 31105166, 31104580, 31099233, 31099169, 31098990, - 31097010, 31093513, - ], - Transfer: [ - 31138628, 31123797, 31120641, 31116766, 31116335, 31116205, 31115380, - 31107317, 31104252, 31104234, 31102490, 31099233, 31099233, 31099169, - ], - PriceUpdate: [31156757, 31156707, 31156648, 31156597, 31156526], - }; - - describe('MorphexEventPool', function () { - Object.keys(blockNumbers).forEach((event: string) => { - blockNumbers[event].forEach((blockNumber: number) => { - it(`Should return the correct state after the ${blockNumber}:${event}`, async function () { - const dexHelper = new DummyDexHelper(network); - const logger = dexHelper.getLogger(dexKey); - - const config = await GMXEventPool.getConfig( - params, - blockNumber, - dexHelper.multiContract, - ); - const gmxPool = new GMXEventPool( - dexKey, - network, - dexHelper, - logger, - config, - ); - - await testEventSubscriber( - gmxPool, - gmxPool.addressesSubscribed, - (_blockNumber: number) => fetchPoolState(gmxPool, _blockNumber), - blockNumber, - `${dexKey}_${params.vault}`, - dexHelper.provider, - compareState, - ); - }); - }); - }); - }); -}); diff --git a/src/dex/morphex/morphex-integration.test.ts b/src/dex/morphex/morphex-integration.test.ts deleted file mode 100644 index 7574e5767..000000000 --- a/src/dex/morphex/morphex-integration.test.ts +++ /dev/null @@ -1,211 +0,0 @@ -import dotenv from 'dotenv'; -dotenv.config(); - -import { Interface } from '@ethersproject/abi'; -import { DummyDexHelper } from '../../dex-helper/index'; -import { Network, SwapSide } from '../../constants'; -import { Morphex } from './morphex'; -import { MorphexConfig } from './config'; -import { - checkPoolPrices, - checkPoolsLiquidity, - checkConstantPoolPrices, -} from '../../../tests/utils'; -import { Tokens } from '../../../tests/constants-e2e'; -import ReaderABI from '../../abi/gmx/reader.json'; - -const dexKey = 'Morphex'; - -describe('Morphex Fantom', function () { - const network = Network.FANTOM; - const TokenASymbol = 'axlUSDC'; - const TokenA = Tokens[network][TokenASymbol]; - - const TokenBSymbol = 'WFTM'; - const TokenB = Tokens[network][TokenBSymbol]; - - const amounts = [ - 0n, - 1000000000n, - 2000000000n, - 3000000000n, - 4000000000n, - 5000000000n, - ]; - - const readerInterface = new Interface(ReaderABI); - const params = MorphexConfig[dexKey][network]; - const readerAddress = params.reader; - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - const dexHelper = new DummyDexHelper(network); - const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); - const gmx = new Morphex(network, dexKey, dexHelper); - - await gmx.initializePricing(blocknumber); - - const pools = await gmx.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.SELL, - blocknumber, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await gmx.getPricesVolume( - TokenA, - TokenB, - amounts, - SwapSide.SELL, - blocknumber, - pools, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - expect(poolPrices).not.toBeNull(); - if (gmx.hasConstantPriceLargeAmounts) { - checkConstantPoolPrices(poolPrices!, amounts, dexKey); - } else { - checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); - } - - // Do on chain pricing based on reader to compare - const readerCallData = amounts.map(a => ({ - target: readerAddress, - callData: readerInterface.encodeFunctionData('getAmountOut', [ - params.vault, - TokenA.address, - TokenB.address, - a.toString(), - ]), - })); - - const readerResult = ( - await dexHelper.multiContract.methods - .aggregate(readerCallData) - .call({}, blocknumber) - ).returnData; - const expectedPrices = readerResult.map((p: any) => - BigInt( - readerInterface.decodeFunctionResult('getAmountOut', p)[0].toString(), - ), - ); - - expect(poolPrices![0].prices).toEqual(expectedPrices); - }); - - it('getTopPoolsForToken', async function () { - const dexHelper = new DummyDexHelper(network); - const gmx = new Morphex(network, dexKey, dexHelper); - - await gmx.updatePoolState(); - const poolLiquidity = await gmx.getTopPoolsForToken(TokenA.address, 10); - console.log( - `${TokenASymbol} Top Pools:`, - JSON.stringify(poolLiquidity, null, 2), - ); - - if (!gmx.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); - } - }); -}); - -describe('Morphex BSC', function () { - const network = Network.BSC; - const TokenASymbol = 'ETH'; - const TokenA = Tokens[network][TokenASymbol]; - - const TokenBSymbol = 'USDT'; - const TokenB = Tokens[network][TokenBSymbol]; - - const amounts = [ - 0n, - 1000000000000000000n, - 2000000000000000000n, - 3000000000000000000n, - 4000000000000000000n, - 5000000000000000000n, - ]; - - const readerInterface = new Interface(ReaderABI); - const params = MorphexConfig[dexKey][network]; - const readerAddress = params.reader; - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - const dexHelper = new DummyDexHelper(network); - const blocknumber = await dexHelper.web3Provider.eth.getBlockNumber(); - const gmx = new Morphex(network, dexKey, dexHelper); - - await gmx.initializePricing(blocknumber); - - const pools = await gmx.getPoolIdentifiers( - TokenA, - TokenB, - SwapSide.SELL, - blocknumber, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Identifiers: `, pools); - - expect(pools.length).toBeGreaterThan(0); - - const poolPrices = await gmx.getPricesVolume( - TokenA, - TokenB, - amounts, - SwapSide.SELL, - blocknumber, - pools, - ); - console.log(`${TokenASymbol} <> ${TokenBSymbol} Pool Prices: `, poolPrices); - - expect(poolPrices).not.toBeNull(); - if (gmx.hasConstantPriceLargeAmounts) { - checkConstantPoolPrices(poolPrices!, amounts, dexKey); - } else { - checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); - } - - // Do on chain pricing based on reader to compare - const readerCallData = amounts.map(a => ({ - target: readerAddress, - callData: readerInterface.encodeFunctionData('getAmountOut', [ - params.vault, - TokenA.address, - TokenB.address, - a.toString(), - ]), - })); - - const readerResult = ( - await dexHelper.multiContract.methods - .aggregate(readerCallData) - .call({}, blocknumber) - ).returnData; - const expectedPrices = readerResult.map((p: any) => - BigInt( - readerInterface.decodeFunctionResult('getAmountOut', p)[0].toString(), - ), - ); - - expect(poolPrices![0].prices).toEqual(expectedPrices); - }); - - it('getTopPoolsForToken', async function () { - const dexHelper = new DummyDexHelper(network); - const gmx = new Morphex(network, dexKey, dexHelper); - - await gmx.updatePoolState(); - const poolLiquidity = await gmx.getTopPoolsForToken(TokenA.address, 10); - console.log( - `${TokenASymbol} Top Pools:`, - JSON.stringify(poolLiquidity, null, 2), - ); - - if (!gmx.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity(poolLiquidity, TokenA.address, dexKey); - } - }); -}); diff --git a/src/dex/morphex/morphex.ts b/src/dex/morphex/morphex.ts deleted file mode 100644 index 41596a87a..000000000 --- a/src/dex/morphex/morphex.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Network } from '../../constants'; -import { IDexHelper } from '../../dex-helper'; -import { DexParams } from '../gmx/types'; -import { Adapters, MorphexConfig } from './config'; -import { GMX } from '../gmx/gmx'; -import { getDexKeysWithNetwork } from '../../utils'; - -export class Morphex extends GMX { - public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = - getDexKeysWithNetwork(MorphexConfig); - - constructor( - protected network: Network, - dexKey: string, - protected dexHelper: IDexHelper, - protected adapters = Adapters[network], - protected params: DexParams = MorphexConfig[dexKey][network], - ) { - super(network, dexKey, dexHelper, adapters, params); - this.logger = dexHelper.getLogger(dexKey); - } -} diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 215760ca3..b5dc2c945 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -607,6 +607,10 @@ export const Tokens: { address: '0x11A38e06699b238D6D9A0C7A01f3AC63a07ad318', decimals: 18, }, + XRP: { + address: '0x1d2f0da169ceb9fc7b3144628db156f3f6c60dbe', + decimals: 18, + }, }, [Network.AVALANCHE]: { USDCe: { From 8a74592ed6998a6568b73f5052656c5d3d47d615 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 6 Nov 2023 12:51:07 +0200 Subject: [PATCH 579/833] fix: acc to review --- .../uniswap-v3/uniswap-v3-integration.test.ts | 178 +++++++----------- 1 file changed, 66 insertions(+), 112 deletions(-) diff --git a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts index 4261ccf8b..d197b4cf9 100644 --- a/src/dex/uniswap-v3/uniswap-v3-integration.test.ts +++ b/src/dex/uniswap-v3/uniswap-v3-integration.test.ts @@ -11,6 +11,7 @@ import { checkPoolPrices, checkPoolsLiquidity } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; import { Address } from '@paraswap/core'; +import { UniswapV3Config } from './config'; const network = Network.POLYGON; const TokenASymbol = 'USDC'; @@ -1256,7 +1257,61 @@ describe('BaseswapV3', function () { const TokenBSymbol = 'WETH'; const TokenB = Tokens[network][TokenBSymbol]; - const QuoterV2 = '0x4fDBD73aD4B1DDde594BF05497C15f76308eFfb9'; + const QuoterV2 = UniswapV3Config[dexKey][network].quoter; + + const amountsBuy = [ + 0n, + 6000000n, + 12000000n, + 18000000n, + 24000000n, + 30000000n, + 36000000n, + 42000000n, + 48000000n, + 54000000n, + 60000000n, + 66000000n, + 72000000n, + 78000000n, + 84000000n, + 90000000n, + 96000000n, + 102000000n, + 108000000n, + 114000000n, + 120000000n, + 126000000n, + 132000000n, + 138000000n, + 144000000n, + 150000000n, + 156000000n, + 162000000n, + 168000000n, + 174000000n, + 180000000n, + 186000000n, + 192000000n, + 198000000n, + 204000000n, + 210000000n, + 216000000n, + 222000000n, + 228000000n, + 234000000n, + 240000000n, + 246000000n, + 252000000n, + 258000000n, + 264000000n, + 270000000n, + 276000000n, + 282000000n, + 288000000n, + 294000000n, + 300000000n, + ]; beforeEach(async () => { blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); @@ -1317,6 +1372,13 @@ describe('BaseswapV3', function () { }); it('getPoolIdentifiers and getPricesVolume BUY', async function () { + const amountsBuy = [ + 0n, + 1n * BI_POWS[18], + 2n * BI_POWS[18], + 3n * BI_POWS[18], + ]; + const pools = await baseswapV3.getPoolIdentifiers( TokenA, TokenB, @@ -1376,60 +1438,6 @@ describe('BaseswapV3', function () { const TokenBSymbol = 'USDC'; const TokenB = Tokens[network][TokenBSymbol]; - const amounts = [ - 0n, - 6000000n, - 12000000n, - 18000000n, - 24000000n, - 30000000n, - 36000000n, - 42000000n, - 48000000n, - 54000000n, - 60000000n, - 66000000n, - 72000000n, - 78000000n, - 84000000n, - 90000000n, - 96000000n, - 102000000n, - 108000000n, - 114000000n, - 120000000n, - 126000000n, - 132000000n, - 138000000n, - 144000000n, - 150000000n, - 156000000n, - 162000000n, - 168000000n, - 174000000n, - 180000000n, - 186000000n, - 192000000n, - 198000000n, - 204000000n, - 210000000n, - 216000000n, - 222000000n, - 228000000n, - 234000000n, - 240000000n, - 246000000n, - 252000000n, - 258000000n, - 264000000n, - 270000000n, - 276000000n, - 282000000n, - 288000000n, - 294000000n, - 300000000n, - ]; - const pools = await baseswapV3.getPoolIdentifiers( TokenA, TokenB, @@ -1446,7 +1454,7 @@ describe('BaseswapV3', function () { const poolPrices = await baseswapV3.getPricesVolume( TokenA, TokenB, - amounts, + amountsBuy, SwapSide.SELL, blockNumber, pools, @@ -1459,7 +1467,7 @@ describe('BaseswapV3', function () { expect(poolPrices).not.toBeNull(); checkPoolPrices( poolPrices!.filter(pp => pp.unit !== 0n), - amounts, + amountsBuy, SwapSide.SELL, dexKey, ); @@ -1479,7 +1487,7 @@ describe('BaseswapV3', function () { TokenA.address, TokenB.address, fee, - amounts, + amountsBuy, ); if (res === false) falseChecksCounter++; }), @@ -1494,60 +1502,6 @@ describe('BaseswapV3', function () { const TokenBSymbol = 'USDC'; const TokenB = Tokens[network][TokenBSymbol]; - const amountsBuy = [ - 0n, - 6000000n, - 12000000n, - 18000000n, - 24000000n, - 30000000n, - 36000000n, - 42000000n, - 48000000n, - 54000000n, - 60000000n, - 66000000n, - 72000000n, - 78000000n, - 84000000n, - 90000000n, - 96000000n, - 102000000n, - 108000000n, - 114000000n, - 120000000n, - 126000000n, - 132000000n, - 138000000n, - 144000000n, - 150000000n, - 156000000n, - 162000000n, - 168000000n, - 174000000n, - 180000000n, - 186000000n, - 192000000n, - 198000000n, - 204000000n, - 210000000n, - 216000000n, - 222000000n, - 228000000n, - 234000000n, - 240000000n, - 246000000n, - 252000000n, - 258000000n, - 264000000n, - 270000000n, - 276000000n, - 282000000n, - 288000000n, - 294000000n, - 300000000n, - ]; - const pools = await baseswapV3.getPoolIdentifiers( TokenA, TokenB, From 55f6ad2488927c9bce03669b891930aeb8d6279c Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 6 Nov 2023 12:52:31 +0200 Subject: [PATCH 580/833] 2.42.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index de027f995..a9baec6e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.4-baseswap.3", + "version": "2.42.5", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 223a44d8a8b8d50f494d18484eb26215f1ca7afa Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 6 Nov 2023 16:54:19 +0200 Subject: [PATCH 581/833] fix: extend logging for pool capturing --- src/dex/algebra/algebra.ts | 10 ++++++++-- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 10 ++++++++-- src/dex/uniswap-v3/uniswap-v3.ts | 10 ++++++++-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 42ad77520..9301760fe 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -165,7 +165,7 @@ export class Algebra extends SimpleExchange implements IDex { token0, token1, }) => { - const logPrefix = '[Algebra.onPoolCreatedDeleteFromNonExistingSet]'; + const logPrefix = `[${this.dexKey}.onPoolCreatedDeleteFromNonExistingSet]`; const [_token0, _token1] = this._sortTokens(token0, token1); const poolKey = `${_token0}_${_token1}`; @@ -179,7 +179,13 @@ export class Algebra extends SimpleExchange implements IDex { `${logPrefix} delete pool from not existing set: ${poolKey}`, ); // delete pool record from set - await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); + const result = await this.dexHelper.cache.zrem( + this.notExistingPoolSetKey, + [poolKey], + ); + this.logger.info( + `${logPrefix} delete pool from not existing set: ${poolKey}, result: ${result}`, + ); } catch (error) { this.logger.error( `${logPrefix} failed to delete pool from set: ${poolKey}`, diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index be08718f7..611a39e76 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -176,7 +176,7 @@ export class PancakeswapV3 token1, fee, }) => { - const logPrefix = '[PancakeV3.onPoolCreatedDeleteFromNonExistingSet]'; + const logPrefix = `[${this.dexKey}.onPoolCreatedDeleteFromNonExistingSet]`; const [_token0, _token1] = this._sortTokens(token0, token1); const poolKey = `${_token0}_${_token1}_${fee}`; @@ -190,7 +190,13 @@ export class PancakeswapV3 `${logPrefix} delete pool from not existing set: ${poolKey}`, ); // delete pool record from set - await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); + const result = await this.dexHelper.cache.zrem( + this.notExistingPoolSetKey, + [poolKey], + ); + this.logger.info( + `${logPrefix} delete pool from not existing set: ${poolKey}, result: ${result}`, + ); } catch (error) { this.logger.error( `${logPrefix} failed to delete pool from set :${poolKey}`, diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 5e14c10c8..4f08694d7 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -208,7 +208,7 @@ export class UniswapV3 token1, fee, }) => { - const logPrefix = '[UniswapV3.onPoolCreatedDeleteFromNonExistingSet]'; + const logPrefix = `[${this.dexKey}.onPoolCreatedDeleteFromNonExistingSet]`; const [_token0, _token1] = this._sortTokens(token0, token1); const poolKey = `${_token0}_${_token1}_${fee}`; @@ -222,7 +222,13 @@ export class UniswapV3 `${logPrefix} delete pool from not existing set: ${poolKey}`, ); // delete pool record from set - await this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [poolKey]); + const result = await this.dexHelper.cache.zrem( + this.notExistingPoolSetKey, + [poolKey], + ); + this.logger.info( + `${logPrefix} delete pool from not existing set: ${poolKey}, result: ${result}`, + ); } catch (error) { this.logger.error( `${logPrefix} failed to delete pool from set: ${poolKey}`, From 6309af1685107390c51142534de7a2ec78dd6372 Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Mon, 6 Nov 2023 18:35:01 +0000 Subject: [PATCH 582/833] fix: return correct orderbook for BUY swaps --- src/dex/dexalot/dexalot.ts | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 633007272..83f1f4fcb 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -323,7 +323,7 @@ export class Dexalot extends SimpleExchange implements IDex { orderbook: string[][], baseToken: Token, quoteToken: Token, - side: ClobSide, + isInputQuote: boolean, ) { let result = []; @@ -345,7 +345,7 @@ export class Dexalot extends SimpleExchange implements IDex { .parseUnits(orderbook[mid][1], quoteToken.decimals) .toString(), ); - if (side === ClobSide.ASK) { + if (isInputQuote) { const price = BigInt( ethers.utils .parseUnits(orderbook[mid][0], baseToken.decimals) @@ -371,6 +371,8 @@ export class Dexalot extends SimpleExchange implements IDex { .toString(), ); amount = amounts[i]; + } else if (left === 0) { + price = 0n; } else if (left < orderbook.length) { const lPrice = BigInt( ethers.utils @@ -392,9 +394,8 @@ export class Dexalot extends SimpleExchange implements IDex { .parseUnits(orderbook[left][1], quoteToken.decimals) .toString(), ); - if (side === ClobSide.ASK) { - lQty = - (lQty * BigInt(10 ** (baseToken.decimals * 2))) / + if (isInputQuote) { + lQty = (lQty * BigInt(10 ** (baseToken.decimals * 2))) / (lPrice * BigInt(10 ** quoteToken.decimals)); rQty = (rQty * BigInt(10 ** (baseToken.decimals * 2))) / @@ -404,18 +405,18 @@ export class Dexalot extends SimpleExchange implements IDex { amount = amounts[i]; } - if (side === ClobSide.BID) { + if (isInputQuote) { + result.push( + (price * amount * BigInt(10 ** quoteToken.decimals)) / + BigInt(10 ** (baseToken.decimals * 2)), + ); + } else { result.push( price !== 0n // To avoid division by zero error ? (amount * BigInt(10 ** (baseToken.decimals * 2))) / (price * BigInt(10 ** quoteToken.decimals)) : 0n, ); - } else { - result.push( - (price * amount * BigInt(10 ** quoteToken.decimals)) / - BigInt(10 ** (baseToken.decimals * 2)), - ); } } return result; @@ -496,10 +497,7 @@ export class Dexalot extends SimpleExchange implements IDex { // convert from swap to clob side let orderbook = priceData.asks; let clobSide = ClobSide.BID; - if ( - (side === SwapSide.SELL && pairData.isSrcBase) || - (side === SwapSide.BUY && !pairData.isSrcBase) - ) { + if (pairData.isSrcBase) { orderbook = priceData.bids; clobSide = ClobSide.ASK; } @@ -507,12 +505,14 @@ export class Dexalot extends SimpleExchange implements IDex { throw new Error(`Empty orderbook for ${pairKey}`); } + const isInputQuote = (clobSide === ClobSide.ASK && side === SwapSide.SELL) || (clobSide === ClobSide.BID && side === SwapSide.BUY); + const prices = this.calculateOrderPrice( amounts, orderbook, baseToken, quoteToken, - clobSide, + isInputQuote ); const outDecimals = clobSide === ClobSide.BID ? baseToken.decimals : quoteToken.decimals; From b82d86b6322a4a46f3045ea093e4bd68f9b3ebe6 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 6 Nov 2023 23:18:27 +0100 Subject: [PATCH 583/833] univ3 & algebra: increase bitmap ranger by 10x and pricing cycles upper bound by 2x --- src/dex/uniswap-v3/constants.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/uniswap-v3/constants.ts b/src/dex/uniswap-v3/constants.ts index e625c3882..c1aca9e05 100644 --- a/src/dex/uniswap-v3/constants.ts +++ b/src/dex/uniswap-v3/constants.ts @@ -3,12 +3,12 @@ export const UNISWAPV3_TICK_BASE_OVERHEAD = 75_000; export const UNISWAPV3_POOL_SEARCH_OVERHEAD = 10_000; // This is used for price calculation. If out of scope, return 0n -export const TICK_BITMAP_TO_USE = 4n; +export const TICK_BITMAP_TO_USE = 40n; // This is used to check if the state is still valid. -export const TICK_BITMAP_BUFFER = 8n; +export const TICK_BITMAP_BUFFER = 80n; -export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 128; +export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 256; export const UNISWAPV3_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3'; From 40e941baec8aad4b76c3ef3c3389996c281ed045 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 6 Nov 2023 23:20:03 +0100 Subject: [PATCH 584/833] 2.42.6-univ3-algebra-state-pricing.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a9baec6e3..09e7e0cee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.5", + "version": "2.42.6-univ3-algebra-state-pricing.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 69100303699768d0ab1497b9e6c82ca7197c79d0 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 6 Nov 2023 23:46:26 +0100 Subject: [PATCH 585/833] extend params values --- src/dex/uniswap-v3/constants.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/uniswap-v3/constants.ts b/src/dex/uniswap-v3/constants.ts index c1aca9e05..32da51beb 100644 --- a/src/dex/uniswap-v3/constants.ts +++ b/src/dex/uniswap-v3/constants.ts @@ -3,12 +3,12 @@ export const UNISWAPV3_TICK_BASE_OVERHEAD = 75_000; export const UNISWAPV3_POOL_SEARCH_OVERHEAD = 10_000; // This is used for price calculation. If out of scope, return 0n -export const TICK_BITMAP_TO_USE = 40n; +export const TICK_BITMAP_TO_USE = 400n; // This is used to check if the state is still valid. -export const TICK_BITMAP_BUFFER = 80n; +export const TICK_BITMAP_BUFFER = 800n; -export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 256; +export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 4096; export const UNISWAPV3_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3'; From 6416ecbb06161d768b9c6822952a54f2dd22bb08 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 6 Nov 2023 23:48:24 +0100 Subject: [PATCH 586/833] 2.42.6-univ3-algebra-state-pricing.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 09e7e0cee..ab255aded 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.6-univ3-algebra-state-pricing.0", + "version": "2.42.6-univ3-algebra-state-pricing.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 7f71e0cf26055352d07ae206a255405d9108cddb Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 7 Nov 2023 00:40:05 +0100 Subject: [PATCH 587/833] algebra: use more computation cycles & fetch more tick bitmap --- src/dex/algebra/algebra-pool-v1_1.ts | 7 ++----- src/dex/algebra/algebra-pool-v1_9.ts | 7 ++----- src/dex/algebra/constants.ts | 7 +++++++ src/dex/algebra/lib/AlgebraMath.ts | 6 ++---- src/dex/algebra/lib/TickTable.ts | 7 ++----- src/dex/uniswap-v3/constants.ts | 6 +++--- 6 files changed, 18 insertions(+), 22 deletions(-) create mode 100644 src/dex/algebra/constants.ts diff --git a/src/dex/algebra/algebra-pool-v1_1.ts b/src/dex/algebra/algebra-pool-v1_1.ts index 41b3737b6..dc6f77843 100644 --- a/src/dex/algebra/algebra-pool-v1_1.ts +++ b/src/dex/algebra/algebra-pool-v1_1.ts @@ -20,11 +20,7 @@ import { Contract } from 'web3-eth-contract'; import AlgebraABI from '../../abi/algebra/AlgebraPool-v1_1.abi.json'; import FactoryABI from '../../abi/algebra/AlgebraFactory-v1_1.abi.json'; import { DecodedStateMultiCallResultWithRelativeBitmapsV1_1 } from './types'; -import { - OUT_OF_RANGE_ERROR_POSTFIX, - TICK_BITMAP_BUFFER, - TICK_BITMAP_TO_USE, -} from '../uniswap-v3/constants'; +import { OUT_OF_RANGE_ERROR_POSTFIX } from '../uniswap-v3/constants'; import { addressDecode, uint256ToBigInt, @@ -45,6 +41,7 @@ import { import { Constants } from './lib/Constants'; import { Network, NULL_ADDRESS } from '../../constants'; import { TickTable } from './lib/TickTable'; +import { TICK_BITMAP_BUFFER, TICK_BITMAP_TO_USE } from './constants'; const BN_ZERO = BigNumber.from(0); const MAX_BATCH_SIZE = 100; diff --git a/src/dex/algebra/algebra-pool-v1_9.ts b/src/dex/algebra/algebra-pool-v1_9.ts index f740680a9..7995b06e3 100644 --- a/src/dex/algebra/algebra-pool-v1_9.ts +++ b/src/dex/algebra/algebra-pool-v1_9.ts @@ -17,11 +17,7 @@ import { import { ethers } from 'ethers'; import { Contract } from 'web3-eth-contract'; import AlgebraV1_9ABI from '../../abi/algebra/AlgebraPool-v1_9.abi.json'; -import { - OUT_OF_RANGE_ERROR_POSTFIX, - TICK_BITMAP_BUFFER, - TICK_BITMAP_TO_USE, -} from '../uniswap-v3/constants'; +import { OUT_OF_RANGE_ERROR_POSTFIX } from '../uniswap-v3/constants'; import { uint256ToBigInt } from '../../lib/decoders'; import { MultiCallParams } from '../../lib/multi-wrapper'; import { decodeStateMultiCallResultWithRelativeBitmapsV1_9 } from './utils'; @@ -33,6 +29,7 @@ import { import { Constants } from './lib/Constants'; import { Network } from '../../constants'; import { TickTable } from './lib/TickTable'; +import { TICK_BITMAP_BUFFER, TICK_BITMAP_TO_USE } from './constants'; export class AlgebraEventPoolV1_9 extends StatefulEventSubscriber { handlers: { diff --git a/src/dex/algebra/constants.ts b/src/dex/algebra/constants.ts new file mode 100644 index 000000000..918c6a64d --- /dev/null +++ b/src/dex/algebra/constants.ts @@ -0,0 +1,7 @@ +/// THIS FILE CONTAINS OVERRIDES OF UniswapV3's constant file + +export const TICK_BITMAP_TO_USE = 400n; + +export const TICK_BITMAP_BUFFER = 800n; + +export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 4096; diff --git a/src/dex/algebra/lib/AlgebraMath.ts b/src/dex/algebra/lib/AlgebraMath.ts index af9af67d1..c6efbd6c4 100644 --- a/src/dex/algebra/lib/AlgebraMath.ts +++ b/src/dex/algebra/lib/AlgebraMath.ts @@ -16,12 +16,10 @@ import { PriceComputationState, _updatePriceComputationObjects, } from '../../uniswap-v3/contract-math/uniswap-v3-math'; -import { - MAX_PRICING_COMPUTATION_STEPS_ALLOWED, - OUT_OF_RANGE_ERROR_POSTFIX, -} from '../../uniswap-v3/constants'; +import { OUT_OF_RANGE_ERROR_POSTFIX } from '../../uniswap-v3/constants'; import { TickManager } from './TickManager'; import { TickTable } from './TickTable'; +import { MAX_PRICING_COMPUTATION_STEPS_ALLOWED } from '../constants'; type UpdatePositionCache = { price: bigint; diff --git a/src/dex/algebra/lib/TickTable.ts b/src/dex/algebra/lib/TickTable.ts index 9066c66db..edad424d6 100644 --- a/src/dex/algebra/lib/TickTable.ts +++ b/src/dex/algebra/lib/TickTable.ts @@ -1,13 +1,10 @@ import { IAlgebraPoolState } from '../types'; import { _require } from '../../../utils'; import { DeepReadonly } from 'ts-essentials'; -import { - OUT_OF_RANGE_ERROR_POSTFIX, - TICK_BITMAP_BUFFER, - TICK_BITMAP_TO_USE, -} from '../../uniswap-v3/constants'; +import { OUT_OF_RANGE_ERROR_POSTFIX } from '../../uniswap-v3/constants'; import { TickMath } from '../../uniswap-v3/contract-math/TickMath'; import { Yul } from './yul-helper'; +import { TICK_BITMAP_BUFFER, TICK_BITMAP_TO_USE } from '../constants'; function isWordPosOut( wordPos: bigint, diff --git a/src/dex/uniswap-v3/constants.ts b/src/dex/uniswap-v3/constants.ts index 32da51beb..e625c3882 100644 --- a/src/dex/uniswap-v3/constants.ts +++ b/src/dex/uniswap-v3/constants.ts @@ -3,12 +3,12 @@ export const UNISWAPV3_TICK_BASE_OVERHEAD = 75_000; export const UNISWAPV3_POOL_SEARCH_OVERHEAD = 10_000; // This is used for price calculation. If out of scope, return 0n -export const TICK_BITMAP_TO_USE = 400n; +export const TICK_BITMAP_TO_USE = 4n; // This is used to check if the state is still valid. -export const TICK_BITMAP_BUFFER = 800n; +export const TICK_BITMAP_BUFFER = 8n; -export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 4096; +export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 128; export const UNISWAPV3_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3'; From bb6b330300224cac8f4bd250b149e41912123fa5 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 7 Nov 2023 00:42:36 +0100 Subject: [PATCH 588/833] 2.42.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ab255aded..1c8a50e68 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.6-univ3-algebra-state-pricing.1", + "version": "2.42.6", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 45872743c5b082f172eb4f52c63c5946475d51c7 Mon Sep 17 00:00:00 2001 From: David Bouba Date: Tue, 7 Nov 2023 10:41:43 +0100 Subject: [PATCH 589/833] feat: differentiated 403 from 429 restrictions --- src/dex/swaap-v2/constants.ts | 4 +++- src/dex/swaap-v2/swaap-v2.ts | 17 ++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/dex/swaap-v2/constants.ts b/src/dex/swaap-v2/constants.ts index 3274d6560..bd868b440 100644 --- a/src/dex/swaap-v2/constants.ts +++ b/src/dex/swaap-v2/constants.ts @@ -22,7 +22,9 @@ export const SWAAP_RFQ_QUOTE_ENDPOINT = 'quote'; export const SWAAP_RFQ_TOKENS_ENDPOINT = 'tokens'; -export const SWAAP_BLACKLIST_TTL_S = 60 * 60 * 24; // 24 hours +export const SWAAP_403_TTL_S = 60 * 60 * 24; // 24 hours + +export const SWAAP_429_TTL_S = 60 * 60 * 1; // 1 hour export const SWAAP_RESTRICT_TTL_S = 60 * 30; // 30 minutes diff --git a/src/dex/swaap-v2/swaap-v2.ts b/src/dex/swaap-v2/swaap-v2.ts index c672da964..bf0b29451 100644 --- a/src/dex/swaap-v2/swaap-v2.ts +++ b/src/dex/swaap-v2/swaap-v2.ts @@ -41,7 +41,8 @@ import { GAS_COST_ESTIMATION, BATCH_SWAP_SELECTOR, CALLER_SLOT, - SWAAP_BLACKLIST_TTL_S, + SWAAP_403_TTL_S, + SWAAP_429_TTL_S, SWAAP_RFQ_TOKENS_ENDPOINT, SWAAP_RESTRICT_TTL_S, SWAAP_RESTRICTED_CACHE_KEY, @@ -561,11 +562,13 @@ export class SwaapV2 extends SimpleExchange implements IDex { { deadline: minDeadline }, ]; } catch (e) { - if ( - isAxiosError(e) && - (e.response?.status === 403 || e.response?.status === 429) - ) { - await this.setBlacklist(options.txOrigin); + if (isAxiosError(e) && e.response?.status === 403) { + await this.setBlacklist(options.txOrigin, SWAAP_403_TTL_S); + this.logger.warn( + `${this.dexKey}-${this.network}: Encountered blacklisted user=${options.txOrigin}. Adding to local blacklist cache`, + ); + } else if (isAxiosError(e) && e.response?.status === 429) { + await this.setBlacklist(options.txOrigin, SWAAP_429_TTL_S); this.logger.warn( `${this.dexKey}-${this.network}: Encountered restricted user=${options.txOrigin}. Adding to local blacklist cache`, ); @@ -622,7 +625,7 @@ export class SwaapV2 extends SimpleExchange implements IDex { async setBlacklist( txOrigin: Address, - ttl: number = SWAAP_BLACKLIST_TTL_S, + ttl: number = SWAAP_403_TTL_S, ): Promise { await this.dexHelper.cache.setex( this.dexKey, From 36c29defff1514461040c456fb9e06bad3b5c766 Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Tue, 7 Nov 2023 10:29:52 +0000 Subject: [PATCH 590/833] chore: update USDT holder address for avalanche --- tests/constants-e2e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 215760ca3..8f5c624ad 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1126,7 +1126,7 @@ export const Holders: { TSD: '0x691A89db352B72dDb249bFe16503494eC0D920A4', THO: '0xc40d16c47394a506d451475c8a7c46c1175c1da1', aAvaUSDT: '0x50B1Ba98Cf117c9682048D56628B294ebbAA4ec2', - USDT: '0x764fe7fb23f0f995c45faef5e32a4526f2028814', + USDT: '0x0d0707963952f2fba59dd06f2b425ace40b492fe', aAvaWAVAX: '0x1B18Df70863636AEe4BfBAb6F7C70ceBCA9bA404', oldFRAX: '0x4e3376018add04ebe4c46bf6f924ddec8c67aa7b', newFRAX: '0x4e3376018add04ebe4c46bf6f924ddec8c67aa7b', From 1bda9b5398345f3dac65aa5b5cbcfc15d246b6cd Mon Sep 17 00:00:00 2001 From: David Bouba Date: Tue, 7 Nov 2023 11:32:23 +0100 Subject: [PATCH 591/833] feat: clarified token naming convention in swaap-v2 getPoolIdentifier --- src/dex/swaap-v2/utils.ts | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/dex/swaap-v2/utils.ts b/src/dex/swaap-v2/utils.ts index 77a8a8063..20efdda83 100644 --- a/src/dex/swaap-v2/utils.ts +++ b/src/dex/swaap-v2/utils.ts @@ -3,30 +3,23 @@ import { CACHE_PREFIX, ETHER_ADDRESS, NULL_ADDRESS } from '../../constants'; export const getIdentifierPrefix = ( dexKey: string, - srcAddress: Address, - destAddress: Address, + tokenA: Address, + tokenB: Address, ) => { - return `${dexKey}_${getPairName(srcAddress, destAddress)}`.toLowerCase(); + return `${dexKey}_${getPairName(tokenA, tokenB)}`.toLowerCase(); }; -export const getPairName = (srcAddress: Address, destAddress: Address) => { - const sortedAddresses = - srcAddress < destAddress - ? [srcAddress, destAddress] - : [destAddress, srcAddress]; +export const getPairName = (tokenA: Address, tokenB: Address) => { + const sortedAddresses = tokenA < tokenB ? [tokenA, tokenB] : [tokenB, tokenA]; return `${sortedAddresses[0]}_${sortedAddresses[1]}`.toLowerCase(); }; export const getPoolIdentifier = ( dexKey: string, - srcAddress: Address, - destAddress: Address, + tokenA: Address, + tokenB: Address, ) => { - return `${getIdentifierPrefix( - dexKey, - srcAddress, - destAddress, - )}`.toLowerCase(); + return `${getIdentifierPrefix(dexKey, tokenA, tokenB)}`.toLowerCase(); }; export const normalizeTokenAddress = (address: string): string => { From 45b3b38a753b5133a9f15b228033ac64f445c1ce Mon Sep 17 00:00:00 2001 From: David Bouba Date: Tue, 7 Nov 2023 11:22:41 +0100 Subject: [PATCH 592/833] feat: updated swaap-v2 ban logic --- src/dex/swaap-v2/constants.ts | 2 +- src/dex/swaap-v2/swaap-v2.ts | 94 ++++++++++++++++++++++++----------- 2 files changed, 67 insertions(+), 29 deletions(-) diff --git a/src/dex/swaap-v2/constants.ts b/src/dex/swaap-v2/constants.ts index bd868b440..d9999451f 100644 --- a/src/dex/swaap-v2/constants.ts +++ b/src/dex/swaap-v2/constants.ts @@ -26,7 +26,7 @@ export const SWAAP_403_TTL_S = 60 * 60 * 24; // 24 hours export const SWAAP_429_TTL_S = 60 * 60 * 1; // 1 hour -export const SWAAP_RESTRICT_TTL_S = 60 * 30; // 30 minutes +export const SWAAP_POOL_RESTRICT_TTL_S = 60 * 30; // 30 minutes export const SWAAP_RESTRICTED_CACHE_KEY = 'restricted'; diff --git a/src/dex/swaap-v2/swaap-v2.ts b/src/dex/swaap-v2/swaap-v2.ts index bf0b29451..792c4bbc1 100644 --- a/src/dex/swaap-v2/swaap-v2.ts +++ b/src/dex/swaap-v2/swaap-v2.ts @@ -11,7 +11,13 @@ import { OptimalSwapExchange, PreprocessTransactionOptions, } from '../../types'; -import { SwapSide, Network, MAX_INT, MAX_UINT } from '../../constants'; +import { + SwapSide, + Network, + MAX_INT, + MAX_UINT, + CACHE_PREFIX, +} from '../../constants'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { getDexKeysWithNetwork, isAxiosError } from '../../utils'; import { IDex } from '../idex'; @@ -44,7 +50,7 @@ import { SWAAP_403_TTL_S, SWAAP_429_TTL_S, SWAAP_RFQ_TOKENS_ENDPOINT, - SWAAP_RESTRICT_TTL_S, + SWAAP_POOL_RESTRICT_TTL_S, SWAAP_RESTRICTED_CACHE_KEY, SWAAP_RFQ_API_TOKENS_POLLING_INTERVAL_MS, SWAAP_RFQ_TOKENS_CACHES_TTL_S, @@ -72,6 +78,7 @@ export class SwaapV2 extends SimpleExchange implements IDex { private rateFetcher: RateFetcher; private swaapV2AuthToken: string; private tokensMap: TokensMap = {}; + private runtimeMMsRestrictHashMapKey: string; public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork(SwaapV2Config); @@ -114,6 +121,9 @@ export class SwaapV2 extends SimpleExchange implements IDex { }, }, ); + + this.runtimeMMsRestrictHashMapKey = + `${CACHE_PREFIX}_${this.dexKey}_${this.network}_restricted_mms`.toLowerCase(); } async initializePricing(blockNumber: number): Promise { @@ -299,22 +309,22 @@ export class SwaapV2 extends SimpleExchange implements IDex { blockNumber: number, limitPools?: string[], ): Promise> { + const normalizedSrcToken = this.normalizeToken(srcToken); + const normalizedDestToken = this.normalizeToken(destToken); + + const requestedPoolIdentifier: string = getPoolIdentifier( + this.dexKey, + normalizedSrcToken.address, + normalizedDestToken.address, + ); + try { - if (await this.isRestricted()) { + if (await this.isRestrictedPool(requestedPoolIdentifier)) { return null; } this.tokensMap = (await this.getCachedTokens()) || {}; - const normalizedSrcToken = this.normalizeToken(srcToken); - const normalizedDestToken = this.normalizeToken(destToken); - - const requestedPoolIdentifier: string = getPoolIdentifier( - this.dexKey, - normalizedSrcToken.address, - normalizedDestToken.address, - ); - if (normalizedSrcToken.address === normalizedDestToken.address) { return null; } @@ -581,7 +591,12 @@ export class SwaapV2 extends SimpleExchange implements IDex { this.logger.warn( `${this.dexKey}-${this.network}: protocol is restricted`, ); - await this.restrict(); + const poolIdentifier = getPoolIdentifier( + this.dexKey, + normalizedSrcToken.address, + normalizedDestToken.address, + ); + await this.restrictPool(poolIdentifier); } } @@ -589,7 +604,20 @@ export class SwaapV2 extends SimpleExchange implements IDex { } } - async restrict(ttl: number = SWAAP_RESTRICT_TTL_S): Promise { + async restrictPool(poolIdentifier: string): Promise { + this.logger.warn( + `${this.dexKey}-${this.network}: ${poolIdentifier} was restricted for ${SWAAP_POOL_RESTRICT_TTL_S} sec. due to fails`, + ); + + // We use timestamp for creation date to later discern if it already expired or not + await this.dexHelper.cache.hset( + this.runtimeMMsRestrictHashMapKey, + poolIdentifier, + Date.now().toString(), + ); + } + + async restrict(ttl: number = SWAAP_POOL_RESTRICT_TTL_S): Promise { await this.dexHelper.cache.setex( this.dexKey, this.network, @@ -600,14 +628,18 @@ export class SwaapV2 extends SimpleExchange implements IDex { return true; } - async isRestricted(): Promise { - const result = await this.dexHelper.cache.get( - this.dexKey, - this.network, - SWAAP_RESTRICTED_CACHE_KEY, + async isRestrictedPool(poolIdentifier: string): Promise { + const expirationThreshold = Date.now() - SWAAP_POOL_RESTRICT_TTL_S * 1000; + const createdAt = await this.dexHelper.cache.hget( + this.runtimeMMsRestrictHashMapKey, + poolIdentifier, ); - - return result === 'true'; + const wasNotRestricted = createdAt == null; + if (wasNotRestricted) { + return false; + } + const restrictionExpired = +createdAt < expirationThreshold; + return !restrictionExpired; } async isBlacklisted(txOrigin: Address): Promise { @@ -869,10 +901,6 @@ export class SwaapV2 extends SimpleExchange implements IDex { tokenAddress: Address, limit: number, ): Promise { - if (await this.isRestricted()) { - return []; - } - this.tokensMap = (await this.getCachedTokens()) || {}; const normalizedTokenAddress = normalizeTokenAddress(tokenAddress); @@ -883,12 +911,22 @@ export class SwaapV2 extends SimpleExchange implements IDex { } return Object.keys(pLevels) - .filter((pair: string) => { + .filter(async (pair: string) => { const { base, quote } = pLevels[pair]; - return ( - normalizedTokenAddress === base || normalizedTokenAddress === quote + const levelDoesNotIncludeToken = + normalizedTokenAddress !== base && normalizedTokenAddress !== quote; + if (levelDoesNotIncludeToken) { + return false; + } + + const poolIdentifier: string = getPoolIdentifier( + this.dexKey, + base, + quote, ); + const isRestrictedPool = await this.isRestrictedPool(poolIdentifier); + return !isRestrictedPool; }) .map((pair: string) => { return { From f97550a9cebc40f7a680ed49d12f70e02d776279 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 7 Nov 2023 13:30:49 +0200 Subject: [PATCH 593/833] fix: extend logging --- src/dex/algebra/algebra.ts | 6 +++--- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 6 +++--- src/dex/uniswap-v3/uniswap-v3.ts | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 9301760fe..8a670fd02 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -176,7 +176,7 @@ export class Algebra extends SimpleExchange implements IDex { try { this.logger.info( - `${logPrefix} delete pool from not existing set: ${poolKey}`, + `${logPrefix} delete pool from not existing set=${this.notExistingPoolSetKey}; key=${poolKey}`, ); // delete pool record from set const result = await this.dexHelper.cache.zrem( @@ -184,11 +184,11 @@ export class Algebra extends SimpleExchange implements IDex { [poolKey], ); this.logger.info( - `${logPrefix} delete pool from not existing set: ${poolKey}, result: ${result}`, + `${logPrefix} delete pool from not existing set=${this.notExistingPoolSetKey}; key=${poolKey}; result: ${result}`, ); } catch (error) { this.logger.error( - `${logPrefix} failed to delete pool from set: ${poolKey}`, + `${logPrefix} ERROR: failed to delete pool from set: set=${this.notExistingPoolSetKey}; key=${poolKey}`, error, ); } diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 611a39e76..36b2e3d75 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -187,7 +187,7 @@ export class PancakeswapV3 try { this.logger.info( - `${logPrefix} delete pool from not existing set: ${poolKey}`, + `${logPrefix} delete pool from not existing set=${this.notExistingPoolSetKey}; key=${poolKey}`, ); // delete pool record from set const result = await this.dexHelper.cache.zrem( @@ -195,11 +195,11 @@ export class PancakeswapV3 [poolKey], ); this.logger.info( - `${logPrefix} delete pool from not existing set: ${poolKey}, result: ${result}`, + `${logPrefix} delete pool from not existing set=${this.notExistingPoolSetKey}; key=${poolKey}; result: ${result}`, ); } catch (error) { this.logger.error( - `${logPrefix} failed to delete pool from set :${poolKey}`, + `${logPrefix} ERROR: failed to delete pool from set: set=${this.notExistingPoolSetKey}; key=${poolKey}`, error, ); } diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 4f08694d7..193fc3d38 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -219,7 +219,7 @@ export class UniswapV3 try { this.logger.info( - `${logPrefix} delete pool from not existing set: ${poolKey}`, + `${logPrefix} delete pool from not existing set=${this.notExistingPoolSetKey}; key=${poolKey}`, ); // delete pool record from set const result = await this.dexHelper.cache.zrem( @@ -227,11 +227,11 @@ export class UniswapV3 [poolKey], ); this.logger.info( - `${logPrefix} delete pool from not existing set: ${poolKey}, result: ${result}`, + `${logPrefix} delete pool from not existing set=${this.notExistingPoolSetKey}; key=${poolKey}; result: ${result}`, ); } catch (error) { this.logger.error( - `${logPrefix} failed to delete pool from set: ${poolKey}`, + `${logPrefix} ERROR: failed to delete pool from set: set=${this.notExistingPoolSetKey}; key=${poolKey}`, error, ); } From be8ca9021113b07d3cd5f8079317d7210fbc0c1b Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 7 Nov 2023 16:57:25 +0200 Subject: [PATCH 594/833] fix: update fantom adapter address --- src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index 6923ee077..cd7b8aa0e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -252,7 +252,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_250`]?.split(',') || [], adapterAddresses: { - FantomAdapter01: '0xede616e2e3c35eeb28a1737785c5c5e8e965cd56', + FantomAdapter01: '0x2C091198d44Adc34831B165e390B083D66109ddA', FantomBuyAdapter: '0xb2634B3CBc1E401AB3C2743DB44d459C5c9aA662', }, uniswapV2ExchangeRouterAddress: From b36e12455517723d9ccfa628a4c2bbe72035f6bb Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 7 Nov 2023 17:35:30 +0200 Subject: [PATCH 595/833] =?UTF-8?q?feat:=20add=20ca=D1=81hing=20for=20appr?= =?UTF-8?q?ove=20rpc=20call=20on=20simple=20exchange?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dex/simple-exchange.ts | 42 +++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/dex/simple-exchange.ts b/src/dex/simple-exchange.ts index 79c1360b1..9724219b0 100644 --- a/src/dex/simple-exchange.ts +++ b/src/dex/simple-exchange.ts @@ -9,7 +9,7 @@ import augustusABI from '../abi/augustus.json'; import { isETHAddress } from '../utils'; import { MAX_UINT } from '../constants'; import Web3 from 'web3'; -import { IDexHelper } from '../dex-helper'; +import { ICache, IDexHelper } from '../dex-helper'; import { AbiItem } from 'web3-utils'; /* @@ -36,11 +36,13 @@ export class SimpleExchange { protected augustusAddress: Address; protected augustusInterface: Interface; private provider: Web3; + private cache: ICache; protected network: number; protected dexmapKey: string; readonly cacheStateKey: string; + private readonly cacheApprovesKey: string; constructor(dexHelper: IDexHelper, public dexKey: string) { this.simpleSwapHelper = new Interface(SimpleSwapHelperABI); @@ -54,12 +56,17 @@ export class SimpleExchange { this.augustusAddress = dexHelper.config.data.augustusAddress; this.augustusInterface = new Interface(augustusABI); this.provider = dexHelper.web3Provider; + this.cache = dexHelper.cache; this.dexmapKey = `${CACHE_PREFIX}_${this.network}_${this.dexKey}_poolconfigs`.toLowerCase(); this.cacheStateKey = `${CACHE_PREFIX}_${this.network}_${this.dexKey}_states`.toLowerCase(); + + // if there's anything else to cache, this name could be more abstract + this.cacheApprovesKey = + `${CACHE_PREFIX}_${this.network}_approves`.toLowerCase(); } private async hasAugustusAllowance( @@ -68,9 +75,37 @@ export class SimpleExchange { amount: string, ): Promise { if (token.toLowerCase() === ETHER_ADDRESS.toLowerCase()) return true; + // TODO: is it possible that augustus address will be changed ?? + // if so, it should be included in the cache key + const cacheKey = `${token}_${target}`; + + // as approve is given to an infinite amount, we can cache only the target and token address + const isCachedApproved = await this.cache.sismember( + this.cacheApprovesKey, + cacheKey, + ); - const allowanceData = this.erc20Interface.encodeFunctionData('allowance', [ + if (isCachedApproved) return true; + + const allowance = await this.getAllowance( this.augustusAddress, + token, + target, + ); + const isApproved = BigInt(allowance) >= BigInt(amount); + + if (isApproved) await this.cache.sadd(this.cacheApprovesKey, cacheKey); + + return isApproved; + } + + private async getAllowance( + spender: Address, + token: Address, + target: Address, + ): Promise { + const allowanceData = this.erc20Interface.encodeFunctionData('allowance', [ + spender, target, ]); @@ -83,7 +118,8 @@ export class SimpleExchange { 'allowance', allowanceRaw, ); - return BigInt(allowance.toString()) >= BigInt(amount); + + return allowance.toString(); } protected async getApproveSimpleParam( From 645876e105213931a3c826de66633296eb60cac7 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 7 Nov 2023 20:24:37 +0300 Subject: [PATCH 596/833] 2.42.7-dexalot-incorrect-buy-prices --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a9baec6e3..250caf5ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.5", + "version": "2.42.7-dexalot-incorrect-buy-prices", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 557b7f4b367b943624dd69948dc43a7813662463 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 7 Nov 2023 21:00:50 +0300 Subject: [PATCH 597/833] 2.42.7-dexalot-incorrect-buy-prices.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 250caf5ce..620f532dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.7-dexalot-incorrect-buy-prices", + "version": "2.42.7-dexalot-incorrect-buy-prices.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From c1718b9c13917b06d963a2a8fbd7a682b5165ba7 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 7 Nov 2023 21:06:45 +0300 Subject: [PATCH 598/833] 2.42.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 620f532dd..3afd1c524 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.7-dexalot-incorrect-buy-prices.2", + "version": "2.42.7", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 6f96a619b27213e247b7b20f4e0faac5bc028003 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 7 Nov 2023 20:42:57 +0200 Subject: [PATCH 599/833] fix: add arb tests & clean & add todos --- src/dex/wombat/config.ts | 22 +++++-- src/dex/wombat/wombat-e2e.test.ts | 99 +++++++++++++++++++++++++++---- 2 files changed, 107 insertions(+), 14 deletions(-) diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts index 0a8bce995..8e2cebe4c 100644 --- a/src/dex/wombat/config.ts +++ b/src/dex/wombat/config.ts @@ -6,7 +6,6 @@ export const WombatConfig: DexConfigMap = { Wombat: { [Network.BSC]: { bmwAddress: '0x489833311676B566f888119c29bd997Dc6C95830', - // routerAddress: '0x19609B03C976CCA288fbDae5c21d4290e9a4aDD7', }, [Network.ARBITRUM]: { bmwAddress: '0x62A83C6791A3d7950D823BB71a38e47252b6b6F4', @@ -18,20 +17,35 @@ export const Adapters: Record = { [Network.BSC]: { [SwapSide.SELL]: [ { + // TODO: implement name: 'BscAdapter01', - /** @todo check index number */ - // index: 12, - // uniswapv2 forks index: 3, }, ], [SwapSide.BUY]: [ { + // TODO: implement name: 'BscBuyAdapter', index: 1, }, ], }, + [Network.ARBITRUM]: { + [SwapSide.SELL]: [ + { + // TODO: implement + name: 'ArbitrumAdapter01', + index: 2, + }, + ], + [SwapSide.BUY]: [ + { + // TODO: implement + name: 'ArbitrumBuyAdapter', + index: 1, + }, + ], + }, }; export const LIQUIDITY_THRESHOLD_IN_USD = 100; diff --git a/src/dex/wombat/wombat-e2e.test.ts b/src/dex/wombat/wombat-e2e.test.ts index 1b7a94478..98edae4aa 100644 --- a/src/dex/wombat/wombat-e2e.test.ts +++ b/src/dex/wombat/wombat-e2e.test.ts @@ -155,6 +155,7 @@ import { generateConfig } from '../../config'; // }); // } +// TODO: Rewrite with testForNetwork describe('Wombat E2E', () => { const dexKey = 'Wombat'; @@ -172,24 +173,24 @@ describe('Wombat E2E', () => { SwapSide.SELL, [ ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, ], ], - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + [SwapSide.BUY, [ContractMethod.simpleBuy /* ContractMethod.buy */]], ]); const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ [ { name: 'USDC', - sellAmount: '100000000000000000000', - buyAmount: '100000000000000000000', + sellAmount: '1000000000', + buyAmount: '1000000000', }, { name: 'USDT', - sellAmount: '100000000000000000000', - buyAmount: '100000000000000000000', + sellAmount: '1000000000', + buyAmount: '1000000000', }, ], // [ @@ -248,16 +249,94 @@ describe('Wombat E2E', () => { ); }); + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + ], + ], + [SwapSide.BUY, [ContractMethod.simpleBuy /* ContractMethod.buy */]], + ]); + + const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ + [ + { + name: 'USDC', + sellAmount: '100000000', + buyAmount: '100000000', + }, + { + name: 'USDT', + sellAmount: '100000000', + buyAmount: '100000000', + }, + ], + ]; + + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL + ? pair[0].sellAmount + : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL + ? pair[1].sellAmount + : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }); + }); + }), + ); + }); + // describe('Arbitrum', () => { // const network = Network.ARBITRUM; - // + // const tokenASymbol: string = 'USDC'; // const tokenBSymbol: string = 'USDT'; - // + // const tokenAAmount: string = '100000000'; // const tokenBAmount: string = '100000000'; // const nativeTokenAmount = '1000000000000000000'; - // + // testForNetwork( // network, // dexKey, From bd9fabb3eb124f521412246565fd56ab4ba72587 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 7 Nov 2023 22:51:25 +0200 Subject: [PATCH 600/833] 2.42.8-cache-approves.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3afd1c524..d535d67a5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.7", + "version": "2.42.8-cache-approves.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From cb329a28fc44f07e78ff1f159106a904ebefa4d9 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 7 Nov 2023 22:58:38 +0200 Subject: [PATCH 601/833] chore: remove comment --- src/dex/simple-exchange.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/dex/simple-exchange.ts b/src/dex/simple-exchange.ts index 9724219b0..6a7dd302b 100644 --- a/src/dex/simple-exchange.ts +++ b/src/dex/simple-exchange.ts @@ -75,8 +75,6 @@ export class SimpleExchange { amount: string, ): Promise { if (token.toLowerCase() === ETHER_ADDRESS.toLowerCase()) return true; - // TODO: is it possible that augustus address will be changed ?? - // if so, it should be included in the cache key const cacheKey = `${token}_${target}`; // as approve is given to an infinite amount, we can cache only the target and token address From 1ef7628ed1652ad83bcfce14a3f3fc3a8bfade31 Mon Sep 17 00:00:00 2001 From: Koala <142200506+koala0814@users.noreply.github.com> Date: Wed, 8 Nov 2023 12:28:40 +0800 Subject: [PATCH 602/833] add pool state initialization and add more supported chains --- src/dex/wombat/config.ts | 12 + src/dex/wombat/wombat-bmw.ts | 8 +- src/dex/wombat/wombat-integration.test.ts | 285 ++++++++-------------- src/dex/wombat/wombat.ts | 7 +- 4 files changed, 118 insertions(+), 194 deletions(-) diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts index 8e2cebe4c..6550dea74 100644 --- a/src/dex/wombat/config.ts +++ b/src/dex/wombat/config.ts @@ -10,6 +10,18 @@ export const WombatConfig: DexConfigMap = { [Network.ARBITRUM]: { bmwAddress: '0x62A83C6791A3d7950D823BB71a38e47252b6b6F4', }, + [Network.MAINNET]: { + bmwAddress: '0xC9bFC3eFeFe4CF96877009F75a61F5c1937e5d1a', + }, + [Network.AVALANCHE]: { + bmwAddress: '0x6521a549834F5E6d253CD2e5F4fbe4048f86cd7b', + }, + [Network.BASE]: { + bmwAddress: '0x6521a549834F5E6d253CD2e5F4fbe4048f86cd7b', + }, + [Network.OPTIMISM]: { + bmwAddress: '0x82E62f4e174E3C5e1641Df670c91Ac6Ab8541518', + }, }, }; diff --git a/src/dex/wombat/wombat-bmw.ts b/src/dex/wombat/wombat-bmw.ts index 9bc13cf28..fcb41e4b9 100644 --- a/src/dex/wombat/wombat-bmw.ts +++ b/src/dex/wombat/wombat-bmw.ts @@ -38,7 +38,7 @@ export class WombatBmw extends StatefulEventSubscriber { pool: Address, asset2TokenMap: Map, blockNumber: number, - ) => void, + ) => Promise, ) { super( `${dexKey} ${name}`, @@ -151,10 +151,12 @@ export class WombatBmw extends StatefulEventSubscriber { pool2AssetInfo.get(pool)!.set(lpToken, underlyingToken); } + const promises: Promise[] = []; pool2AssetInfo.forEach((asset2TokenMap, pool) => { bmwState.pools.push(pool); - this.onAssetAdded(pool, asset2TokenMap, blockNumber); + promises.push(this.onAssetAdded(pool, asset2TokenMap, blockNumber)); }); + await Promise.all(promises); return bmwState; } @@ -189,7 +191,7 @@ export class WombatBmw extends StatefulEventSubscriber { .decodeFunctionResult('underlyingToken', returnData[1])[0] .toLowerCase(); - this.onAssetAdded( + await this.onAssetAdded( pool, new Map().set(lpToken, underlyingToken), log.blockNumber, diff --git a/src/dex/wombat/wombat-integration.test.ts b/src/dex/wombat/wombat-integration.test.ts index e7dfb3727..778669fa4 100644 --- a/src/dex/wombat/wombat-integration.test.ts +++ b/src/dex/wombat/wombat-integration.test.ts @@ -15,6 +15,7 @@ import { import { Tokens } from '../../../tests/constants-e2e'; import { Token } from '../../types'; import { Address } from '@paraswap/core'; +import { WombatConfig } from './config'; function getReaderCalldata( exchangeAddress: string, @@ -149,199 +150,109 @@ describe('Wombat', function () { let blockNumber: number; let wombat: Wombat; - describe('BSC', () => { - const network = Network.BSC; - const dexHelper = new DummyDexHelper(network); - - const tokens = Tokens[network]; - - const srcTokenSymbol = 'USDC'; - const destTokenSymbol = 'USDT'; - - const amountsForSell = [ - 0n, - 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - 10n * BI_POWS[tokens[srcTokenSymbol].decimals], - ]; - - const amountsForBuy = [ - 0n, - 1n * BI_POWS[tokens[destTokenSymbol].decimals], - 2n * BI_POWS[tokens[destTokenSymbol].decimals], - 3n * BI_POWS[tokens[destTokenSymbol].decimals], - 4n * BI_POWS[tokens[destTokenSymbol].decimals], - 5n * BI_POWS[tokens[destTokenSymbol].decimals], - 6n * BI_POWS[tokens[destTokenSymbol].decimals], - 7n * BI_POWS[tokens[destTokenSymbol].decimals], - 8n * BI_POWS[tokens[destTokenSymbol].decimals], - 9n * BI_POWS[tokens[destTokenSymbol].decimals], - 10n * BI_POWS[tokens[destTokenSymbol].decimals], - ]; - - beforeAll(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - wombat = new Wombat(network, dexKey, dexHelper); - }); - - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - if (wombat.updatePoolState) { - await wombat.updatePoolState(); + Object.keys(WombatConfig[dexKey]).forEach(key => { + describe(`network ${key}`, () => { + const network = Number(key) as Network; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + + const srcTokenSymbol = 'USDC'; + const destTokenSymbol = network == Network.BASE ? 'USDbC' : 'USDT'; + + let amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + let amountsForBuy = [ + 0n, + 1n * BI_POWS[tokens[destTokenSymbol].decimals], + 2n * BI_POWS[tokens[destTokenSymbol].decimals], + 3n * BI_POWS[tokens[destTokenSymbol].decimals], + 4n * BI_POWS[tokens[destTokenSymbol].decimals], + 5n * BI_POWS[tokens[destTokenSymbol].decimals], + 6n * BI_POWS[tokens[destTokenSymbol].decimals], + 7n * BI_POWS[tokens[destTokenSymbol].decimals], + 8n * BI_POWS[tokens[destTokenSymbol].decimals], + 9n * BI_POWS[tokens[destTokenSymbol].decimals], + 10n * BI_POWS[tokens[destTokenSymbol].decimals], + ]; + + // BASE and OPTIMISM have very low liquidity currently, so we have to use very small amounts + if (network === Network.BASE || network === Network.OPTIMISM) { + amountsForSell = amountsForSell.map(a => a / 100n); + amountsForBuy = amountsForBuy.map(a => a / 100n); } - const poolLiquidity = await wombat.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, - ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - if (!wombat.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + wombat = new Wombat(network, dexKey, dexHelper); + }); + + it('getTopPoolsForToken', async function () { + // We have to check without calling initializePricing, because + // pool-tracker is not calling that function + if (wombat.updatePoolState) { + await wombat.updatePoolState(); + } + const poolLiquidity = await wombat.getTopPoolsForToken( + tokens[srcTokenSymbol].address, + 10, + ); + console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + + if (!wombat.hasConstantPriceLargeAmounts) { + checkPoolsLiquidity( + poolLiquidity, + Tokens[network][srcTokenSymbol].address, + dexKey, + ); + } + }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + if (wombat.initializePricing) { + await wombat.initializePricing(blockNumber); + } + await testPricingOnNetwork( + wombat, + network, dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + 'quotePotentialSwap', ); - } - }); - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - if (wombat.initializePricing) { - await wombat.initializePricing(blockNumber); - } - await testPricingOnNetwork( - wombat, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.SELL, - amountsForSell, - 'quotePotentialSwap', - ); - }); - - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - if (wombat.initializePricing) { - await wombat.initializePricing(blockNumber); - } - await testPricingOnNetwork( - wombat, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.BUY, - amountsForBuy, - 'quotePotentialSwap', - ); - }); - }); - - describe('Arbitrum', () => { - const network = Network.ARBITRUM; - const dexHelper = new DummyDexHelper(network); - - const tokens = Tokens[network]; - - const srcTokenSymbol = 'USDC'; - const destTokenSymbol = 'USDT'; - - const amountsForSell = [ - 0n, - 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - 10n * BI_POWS[tokens[srcTokenSymbol].decimals], - ]; - - const amountsForBuy = [ - 0n, - 1n * BI_POWS[tokens[destTokenSymbol].decimals], - 2n * BI_POWS[tokens[destTokenSymbol].decimals], - 3n * BI_POWS[tokens[destTokenSymbol].decimals], - 4n * BI_POWS[tokens[destTokenSymbol].decimals], - 5n * BI_POWS[tokens[destTokenSymbol].decimals], - 6n * BI_POWS[tokens[destTokenSymbol].decimals], - 7n * BI_POWS[tokens[destTokenSymbol].decimals], - 8n * BI_POWS[tokens[destTokenSymbol].decimals], - 9n * BI_POWS[tokens[destTokenSymbol].decimals], - 10n * BI_POWS[tokens[destTokenSymbol].decimals], - ]; - - beforeAll(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - wombat = new Wombat(network, dexKey, dexHelper); - }); - - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - if (wombat.updatePoolState) { - await wombat.updatePoolState(); - } - const poolLiquidity = await wombat.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, - ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - - if (!wombat.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, + }); + + it('getPoolIdentifiers and getPricesVolume BUY', async function () { + if (wombat.initializePricing) { + await wombat.initializePricing(blockNumber); + } + await testPricingOnNetwork( + wombat, + network, dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.BUY, + amountsForBuy, + 'quotePotentialSwap', ); - } - }); - - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - if (wombat.initializePricing) { - await wombat.initializePricing(blockNumber); - } - await testPricingOnNetwork( - wombat, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.SELL, - amountsForSell, - 'quotePotentialSwap', - ); - }); - - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - if (wombat.initializePricing) { - await wombat.initializePricing(blockNumber); - } - await testPricingOnNetwork( - wombat, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.BUY, - amountsForBuy, - 'quotePotentialSwap', - ); + }); }); }); }); diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index a9f487be8..6f097b014 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -30,7 +30,6 @@ import { WombatQuoter } from './wombat-quoter'; import { WombatBmw } from './wombat-bmw'; import { fromWad } from './utils'; import { WombatPool } from './wombat-pool'; -import { UniswapV2 } from '../uniswap-v2/uniswap-v2'; export class Wombat extends SimpleExchange implements IDex { // export class Wombat implements IDex { @@ -94,11 +93,11 @@ export class Wombat extends SimpleExchange implements IDex { } } - onAssetAdded = ( + onAssetAdded = async ( pool: Address, asset2TokenMap: Map, blockNumber: number, - ): void => { + ): Promise => { if (!this.pools[pool]) { this.pools[pool] = new WombatPool( this.dexKey, @@ -107,6 +106,7 @@ export class Wombat extends SimpleExchange implements IDex { pool, asset2TokenMap, ); + await this.pools[pool].getState('latest', true); } else { this.pools[pool].addAssets(asset2TokenMap); } @@ -134,7 +134,6 @@ export class Wombat extends SimpleExchange implements IDex { srcToken.address.toLowerCase(), destToken.address.toLowerCase(), blockNumber, - LIQUIDITY_THRESHOLD_IN_USD, ) ).map(p => this.getPoolIdentifier(p)); } From c5100b5ecccf4168d7e8f427579f017d7c1f3461 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 8 Nov 2023 14:37:38 +0200 Subject: [PATCH 603/833] fix: update adapters addresses --- src/config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index cd7b8aa0e..0886ebf6a 100644 --- a/src/config.ts +++ b/src/config.ts @@ -165,7 +165,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_56`]?.split(',') || [], adapterAddresses: { BscAdapter01: '0xA31d9C571DF00e0F428B0bD24c34D103E8112222', - BscAdapter02: '0x3B9F60Bb1D8C5cfEDB9f4635678C6b97AA52d208', + BscAdapter02: '0xEECA9223063bD13e8ca77ed9e39a07f2BD1923E6', BscBuyAdapter: '0x301c2813e3ceb43A448a12f21551EDBcdC37F157', }, rpcPollingMaxAllowedStateDelayInBlocks: 1, @@ -252,7 +252,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_250`]?.split(',') || [], adapterAddresses: { - FantomAdapter01: '0x2C091198d44Adc34831B165e390B083D66109ddA', + FantomAdapter01: '0x654dE10890f8B2C5bF54E50Af169a7E93165C416', FantomBuyAdapter: '0xb2634B3CBc1E401AB3C2743DB44d459C5c9aA662', }, uniswapV2ExchangeRouterAddress: From 3787efdd330913748b6045bb93ad5ff58e93a0d0 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 8 Nov 2023 14:39:27 +0200 Subject: [PATCH 604/833] 2.42.7-add-morphex --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3afd1c524..5806cf88f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.7", + "version": "2.42.7-add-morphex", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From f91ee56919edb57a6781f40ebbcf18383714ecb7 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Wed, 8 Nov 2023 17:27:49 +0200 Subject: [PATCH 605/833] 2.42.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d535d67a5..26932bd4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.8-cache-approves.0", + "version": "2.42.8", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From dd24731e35fd6643043584a25ec5790ba8c14b99 Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Wed, 8 Nov 2023 17:38:03 +0000 Subject: [PATCH 606/833] feat: restrict by pool and send slippage + partner to firm quote --- src/dex/dexalot/dexalot.ts | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 83f1f4fcb..afec8c34c 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -432,10 +432,6 @@ export class Dexalot extends SimpleExchange implements IDex { transferFees?: TransferFeeParams, ): Promise> { try { - if (await this.isRestricted()) { - return null; - } - const normalizedSrcToken = this.normalizeToken(srcToken); const normalizedDestToken = this.normalizeToken(destToken); @@ -444,7 +440,7 @@ export class Dexalot extends SimpleExchange implements IDex { return null; } - const pools = limitPools + let pools = limitPools ? limitPools.filter( p => p === @@ -455,6 +451,7 @@ export class Dexalot extends SimpleExchange implements IDex { ) : await this.getPoolIdentifiers(srcToken, destToken, side, blockNumber); + pools = await Promise.all(pools.map(async (p) => !(await this.isRestrictedPool(p)))).then((res) => pools.filter((_v, i) => res[i])); if (pools.length === 0) { return null; } @@ -579,6 +576,7 @@ export class Dexalot extends SimpleExchange implements IDex { const makerToken = normalizedDestToken; const takerToken = normalizedSrcToken; + const slippageBps = side === SwapSide.SELL ? BigNumber(1).minus(options.slippageFactor).multipliedBy(10000).toFixed(0) : options.slippageFactor.minus(1).multipliedBy(10000).toFixed(0); const rfqParams = { makerAsset: ethers.utils.getAddress(makerToken.address), takerAsset: ethers.utils.getAddress(takerToken.address), @@ -588,6 +586,8 @@ export class Dexalot extends SimpleExchange implements IDex { side === SwapSide.SELL ? optimalSwapExchange.srcAmount : undefined, userAddress: options.txOrigin, chainid: this.network, + partner: options.partner, + slippage: slippageBps, }; const rfq: RFQResponse = await this.dexHelper.httpRequest.post( @@ -725,10 +725,11 @@ export class Dexalot extends SimpleExchange implements IDex { `${this.dexKey}-${this.network}: failed to build transaction on side ${side} with too strict slippage. Skipping restriction`, ); } else { + const poolIdentifiers = await this.getPoolIdentifiers(srcToken, destToken, side, 0); this.logger.warn( - `${this.dexKey}-${this.network}: protocol is restricted`, + `${this.dexKey}-${this.network}: protocol is restricted for pools ${poolIdentifiers} due to swap: ${swapIdentifier}`, ); - await this.restrict(); + await Promise.all(poolIdentifiers.map(async (p) => await this.restrictPool(p))); } } @@ -813,22 +814,26 @@ export class Dexalot extends SimpleExchange implements IDex { }; } - async restrict(ttl: number = DEXALOT_RESTRICT_TTL_S): Promise { + getRestrictedPoolKey(poolIdentifier: string): string { + return `${DEXALOT_RESTRICTED_CACHE_KEY}-${poolIdentifier}`; + } + + async restrictPool(poolIdentifier: string, ttl: number = DEXALOT_RESTRICT_TTL_S): Promise { await this.dexHelper.cache.setex( this.dexKey, this.network, - DEXALOT_RESTRICTED_CACHE_KEY, + this.getRestrictedPoolKey(poolIdentifier), ttl, 'true', ); return true; } - async isRestricted(): Promise { + async isRestrictedPool(poolIdentifier: string): Promise { const result = await this.dexHelper.cache.get( this.dexKey, this.network, - DEXALOT_RESTRICTED_CACHE_KEY, + this.getRestrictedPoolKey(poolIdentifier), ); return result === 'true'; From 1adb14c06c4df762e46c360c9515d5af87defc6d Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 9 Nov 2023 01:16:19 +0200 Subject: [PATCH 607/833] fix: remove keys from logs --- src/dex/algebra/algebra.ts | 2 +- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 2 +- src/dex/uniswap-v3/uniswap-v3.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 8a670fd02..1fe60dc7e 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -165,7 +165,7 @@ export class Algebra extends SimpleExchange implements IDex { token0, token1, }) => { - const logPrefix = `[${this.dexKey}.onPoolCreatedDeleteFromNonExistingSet]`; + const logPrefix = `[onPoolCreatedDeleteFromNonExistingSet]`; const [_token0, _token1] = this._sortTokens(token0, token1); const poolKey = `${_token0}_${_token1}`; diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 36b2e3d75..313fc4401 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -176,7 +176,7 @@ export class PancakeswapV3 token1, fee, }) => { - const logPrefix = `[${this.dexKey}.onPoolCreatedDeleteFromNonExistingSet]`; + const logPrefix = `[onPoolCreatedDeleteFromNonExistingSet]`; const [_token0, _token1] = this._sortTokens(token0, token1); const poolKey = `${_token0}_${_token1}_${fee}`; diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 193fc3d38..5fcef6dbd 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -208,7 +208,7 @@ export class UniswapV3 token1, fee, }) => { - const logPrefix = `[${this.dexKey}.onPoolCreatedDeleteFromNonExistingSet]`; + const logPrefix = `[onPoolCreatedDeleteFromNonExistingSet]`; const [_token0, _token1] = this._sortTokens(token0, token1); const poolKey = `${_token0}_${_token1}_${fee}`; From b75bae0f52c26b40fcb7a1ec64f88efd6644a0c1 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 9 Nov 2023 01:17:52 +0200 Subject: [PATCH 608/833] fix: remove keys from logs 2 --- src/dex/algebra/algebra.ts | 2 +- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 2 +- src/dex/uniswap-v3/uniswap-v3.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 1fe60dc7e..91f932de0 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -165,7 +165,7 @@ export class Algebra extends SimpleExchange implements IDex { token0, token1, }) => { - const logPrefix = `[onPoolCreatedDeleteFromNonExistingSet]`; + const logPrefix = '[onPoolCreatedDeleteFromNonExistingSet]'; const [_token0, _token1] = this._sortTokens(token0, token1); const poolKey = `${_token0}_${_token1}`; diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 313fc4401..2e0457e20 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -176,7 +176,7 @@ export class PancakeswapV3 token1, fee, }) => { - const logPrefix = `[onPoolCreatedDeleteFromNonExistingSet]`; + const logPrefix = '[onPoolCreatedDeleteFromNonExistingSet]'; const [_token0, _token1] = this._sortTokens(token0, token1); const poolKey = `${_token0}_${_token1}_${fee}`; diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 5fcef6dbd..f5429c19e 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -208,7 +208,7 @@ export class UniswapV3 token1, fee, }) => { - const logPrefix = `[onPoolCreatedDeleteFromNonExistingSet]`; + const logPrefix = '[onPoolCreatedDeleteFromNonExistingSet]'; const [_token0, _token1] = this._sortTokens(token0, token1); const poolKey = `${_token0}_${_token1}_${fee}`; From 244c24ccc81f08d75b3e69987d8accb25f2c1a37 Mon Sep 17 00:00:00 2001 From: David Bouba Date: Thu, 9 Nov 2023 18:50:20 +0100 Subject: [PATCH 609/833] feat: added swaap-v2 API notification --- src/dex/swaap-v2/constants.ts | 8 +++++ src/dex/swaap-v2/rate-fetcher.ts | 52 +++++++++++++++++++++++++++++++- src/dex/swaap-v2/swaap-v2.ts | 39 ++++++++++++++++-------- src/dex/swaap-v2/types.ts | 10 ++++++ src/dex/swaap-v2/utils.ts | 2 +- src/dex/swaap-v2/validators.ts | 6 ++++ 6 files changed, 103 insertions(+), 14 deletions(-) diff --git a/src/dex/swaap-v2/constants.ts b/src/dex/swaap-v2/constants.ts index d9999451f..c438b08c7 100644 --- a/src/dex/swaap-v2/constants.ts +++ b/src/dex/swaap-v2/constants.ts @@ -20,6 +20,8 @@ export const SWAAP_RFQ_PRICES_ENDPOINT = 'prices'; export const SWAAP_RFQ_QUOTE_ENDPOINT = 'quote'; +export const SWAAP_NOTIFY_ENDPOINT = 'notify'; + export const SWAAP_RFQ_TOKENS_ENDPOINT = 'tokens'; export const SWAAP_403_TTL_S = 60 * 60 * 24; // 24 hours @@ -42,3 +44,9 @@ export const SWAAP_ORDER_TYPE_BUY = 2; export const SWAAP_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION = new BigNumber('0.001'); + +export const SWAAP_NOTIFY_TIMEOUT_MS = 2000; + +export const SWAAP_NOTIFICATION_ORIGIN = 'paraswap'; + +export const SWAAP_BANNED_CODE = 1; diff --git a/src/dex/swaap-v2/rate-fetcher.ts b/src/dex/swaap-v2/rate-fetcher.ts index 2adc9b208..d47b30313 100644 --- a/src/dex/swaap-v2/rate-fetcher.ts +++ b/src/dex/swaap-v2/rate-fetcher.ts @@ -11,14 +11,21 @@ import { SwaapV2OrderType, SwaapV2TokensResponse, TokensMap, + SwaapV2NotificationRequest, + SwaapV2NotificationResponse, } from './types'; import { priceLevelsResponseValidator, getQuoteResponseValidator, getTokensResponseValidator, + notifyResponseValidator, } from './validators'; import { normalizeTokenAddress } from './utils'; -import { SWAAP_RFQ_QUOTE_TIMEOUT_MS } from './constants'; +import { + SWAAP_RFQ_QUOTE_TIMEOUT_MS, + SWAAP_NOTIFY_TIMEOUT_MS, + SWAAP_NOTIFICATION_ORIGIN, +} from './constants'; import { RequestConfig } from '../../dex-helper/irequest-wrapper'; export class RateFetcher { @@ -211,4 +218,47 @@ export class RateFetcher { throw e; } } + + async notify( + code: number, + message: string, + requestParameters: RequestConfig, + ): Promise { + const _payload: SwaapV2NotificationRequest = { + origin: SWAAP_NOTIFICATION_ORIGIN, + code: code, + message: message, + }; + + try { + let payload: RequestConfig = { + data: _payload, + ...requestParameters, + timeout: SWAAP_NOTIFY_TIMEOUT_MS, + }; + + this.logger.info( + 'Notify Request:', + JSON.stringify(payload).replace(/(?:\r\n|\r|\n)/g, ' '), + ); + const { data } = await this.dexHelper.httpRequest.request( + payload, + ); + this.logger.info( + 'Notify Response: ', + JSON.stringify(data).replace(/(?:\r\n|\r|\n)/g, ' '), + ); + const notifyResp = validateAndCast( + data, + notifyResponseValidator, + ); + + return { + success: notifyResp.success, + }; + } catch (e) { + this.logger.error(e); + throw e; + } + } } diff --git a/src/dex/swaap-v2/swaap-v2.ts b/src/dex/swaap-v2/swaap-v2.ts index 792c4bbc1..aa9472748 100644 --- a/src/dex/swaap-v2/swaap-v2.ts +++ b/src/dex/swaap-v2/swaap-v2.ts @@ -29,6 +29,8 @@ import { SwaapV2APIParameters, SwaapV2QuoteError, TokensMap, + SwaapV2NotificationRequest, + SwaapV2NotificationResponse, } from './types'; import { SimpleExchange } from '../simple-exchange'; import { Adapters, SwaapV2Config } from './config'; @@ -59,6 +61,8 @@ import { SWAAP_ORDER_TYPE_SELL, SWAAP_ORDER_TYPE_BUY, SWAAP_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION, + SWAAP_BANNED_CODE, + SWAAP_NOTIFY_ENDPOINT, } from './constants'; import { getPoolIdentifier, normalizeTokenAddress, getPairName } from './utils'; import { Method } from '../../dex-helper/irequest-wrapper'; @@ -596,7 +600,11 @@ export class SwaapV2 extends SimpleExchange implements IDex { normalizedSrcToken.address, normalizedDestToken.address, ); - await this.restrictPool(poolIdentifier); + var message = 'Unknown error'; + if (e instanceof Error) { + message = `${e.name}: ${e.message}`; + } + await this.restrictPool(message, poolIdentifier); } } @@ -604,7 +612,7 @@ export class SwaapV2 extends SimpleExchange implements IDex { } } - async restrictPool(poolIdentifier: string): Promise { + async restrictPool(message: string, poolIdentifier: string): Promise { this.logger.warn( `${this.dexKey}-${this.network}: ${poolIdentifier} was restricted for ${SWAAP_POOL_RESTRICT_TTL_S} sec. due to fails`, ); @@ -615,17 +623,20 @@ export class SwaapV2 extends SimpleExchange implements IDex { poolIdentifier, Date.now().toString(), ); - } - async restrict(ttl: number = SWAAP_POOL_RESTRICT_TTL_S): Promise { - await this.dexHelper.cache.setex( - this.dexKey, - this.network, - SWAAP_RESTRICTED_CACHE_KEY, - ttl, - 'true', - ); - return true; + this.rateFetcher + .notify(SWAAP_BANNED_CODE, message, this.getNotifyReqParams()) + .then((answer: SwaapV2NotificationResponse) => { + if (answer.success) { + this.logger.info(`Successfully notified Swaap API`); + } else { + this.logger.error(`Swaap API was not successfully notified`); + } + }) + .catch(e => { + // Must never happen + this.logger.error(`Swaap API notification failed: ${e}`); + }); } async isRestrictedPool(poolIdentifier: string): Promise { @@ -965,6 +976,10 @@ export class SwaapV2 extends SimpleExchange implements IDex { return this.getAPIReqParams(SWAAP_RFQ_QUOTE_ENDPOINT, 'POST'); } + getNotifyReqParams(): SwaapV2APIParameters { + return this.getAPIReqParams(SWAAP_NOTIFY_ENDPOINT, 'POST'); + } + getTokensReqParams(): SwaapV2APIParameters { return this.getAPIReqParams(SWAAP_RFQ_TOKENS_ENDPOINT, 'GET'); } diff --git a/src/dex/swaap-v2/types.ts b/src/dex/swaap-v2/types.ts index 1c7572b83..1ac7a9d9f 100644 --- a/src/dex/swaap-v2/types.ts +++ b/src/dex/swaap-v2/types.ts @@ -93,3 +93,13 @@ export type SwaapV2APIParameters = { export type TokensMap = { [address: string]: Token; }; + +export type SwaapV2NotificationRequest = { + origin: string; + code: number; + message: string; +}; + +export type SwaapV2NotificationResponse = { + success: boolean; +}; diff --git a/src/dex/swaap-v2/utils.ts b/src/dex/swaap-v2/utils.ts index 20efdda83..9790aa7d4 100644 --- a/src/dex/swaap-v2/utils.ts +++ b/src/dex/swaap-v2/utils.ts @@ -1,5 +1,5 @@ import { Address } from '../../types'; -import { CACHE_PREFIX, ETHER_ADDRESS, NULL_ADDRESS } from '../../constants'; +import { ETHER_ADDRESS, NULL_ADDRESS } from '../../constants'; export const getIdentifierPrefix = ( dexKey: string, diff --git a/src/dex/swaap-v2/validators.ts b/src/dex/swaap-v2/validators.ts index 69e239ec9..c065ed7bc 100644 --- a/src/dex/swaap-v2/validators.ts +++ b/src/dex/swaap-v2/validators.ts @@ -126,3 +126,9 @@ export const getQuoteResponseValidator = joi success: joi.boolean().required(), }) .unknown(true); + +export const notifyResponseValidator = joi + .object({ + success: joi.boolean().required(), + }) + .unknown(true); From e51b757669a774d2b2d2701e8ad1072753715b97 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 10 Nov 2023 12:02:30 +0200 Subject: [PATCH 610/833] 2.42.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 26932bd4e..1b3b06b65 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.8", + "version": "2.42.9", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 6678994c34e018e7d75eea5f34843ed52e207e69 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Fri, 10 Nov 2023 21:55:11 +0200 Subject: [PATCH 611/833] feat: add extra cache cleaning for new pools --- src/dex/algebra/algebra.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 91f932de0..b2f9e20b9 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -319,6 +319,8 @@ export class Algebra extends SimpleExchange implements IDex { if (pool !== null) { const allEventPools = Object.values(this.eventPools); + // if pool was created, delete pool record from non existing set + this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [key]); this.logger.info( `starting to listen to new non-null pool: ${key}. Already following ${allEventPools // Not that I like this reduce, but since it is done only on initialization, expect this to be ok From 504ed875082f6b3c4cdd65ac4594c93629f19165 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Fri, 10 Nov 2023 22:02:55 +0200 Subject: [PATCH 612/833] feat: add cache cleaning for uniswap-v3 & pancackeswap-v3 --- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 2 ++ src/dex/uniswap-v3/uniswap-v3.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 2e0457e20..9ee46b7cc 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -319,6 +319,8 @@ export class PancakeswapV3 if (pool !== null) { const allEventPools = Object.values(this.eventPools); + // if pool was created, delete pool record from non existing set + this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [key]); this.logger.info( `starting to listen to new non-null pool: ${key}. Already following ${allEventPools // Not that I like this reduce, but since it is done only on initialization, expect this to be ok diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index f5429c19e..4f467b6e5 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -354,6 +354,8 @@ export class UniswapV3 if (pool !== null) { const allEventPools = Object.values(this.eventPools); + // if pool was created, delete pool record from non existing set + this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [key]); this.logger.info( `starting to listen to new non-null pool: ${key}. Already following ${allEventPools // Not that I like this reduce, but since it is done only on initialization, expect this to be ok From 52b453129cad0d028a1681687a30254fbf96d283 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Fri, 10 Nov 2023 22:13:03 +0200 Subject: [PATCH 613/833] feat: add extra catch for cache cleaning --- src/dex/algebra/algebra.ts | 4 +++- src/dex/pancakeswap-v3/pancakeswap-v3.ts | 4 +++- src/dex/uniswap-v3/uniswap-v3.ts | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index b2f9e20b9..2a20eeac7 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -320,7 +320,9 @@ export class Algebra extends SimpleExchange implements IDex { if (pool !== null) { const allEventPools = Object.values(this.eventPools); // if pool was created, delete pool record from non existing set - this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [key]); + this.dexHelper.cache + .zrem(this.notExistingPoolSetKey, [key]) + .catch(() => {}); this.logger.info( `starting to listen to new non-null pool: ${key}. Already following ${allEventPools // Not that I like this reduce, but since it is done only on initialization, expect this to be ok diff --git a/src/dex/pancakeswap-v3/pancakeswap-v3.ts b/src/dex/pancakeswap-v3/pancakeswap-v3.ts index 9ee46b7cc..185a8f17b 100644 --- a/src/dex/pancakeswap-v3/pancakeswap-v3.ts +++ b/src/dex/pancakeswap-v3/pancakeswap-v3.ts @@ -320,7 +320,9 @@ export class PancakeswapV3 if (pool !== null) { const allEventPools = Object.values(this.eventPools); // if pool was created, delete pool record from non existing set - this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [key]); + this.dexHelper.cache + .zrem(this.notExistingPoolSetKey, [key]) + .catch(() => {}); this.logger.info( `starting to listen to new non-null pool: ${key}. Already following ${allEventPools // Not that I like this reduce, but since it is done only on initialization, expect this to be ok diff --git a/src/dex/uniswap-v3/uniswap-v3.ts b/src/dex/uniswap-v3/uniswap-v3.ts index 4f467b6e5..df81fa69c 100644 --- a/src/dex/uniswap-v3/uniswap-v3.ts +++ b/src/dex/uniswap-v3/uniswap-v3.ts @@ -355,7 +355,9 @@ export class UniswapV3 if (pool !== null) { const allEventPools = Object.values(this.eventPools); // if pool was created, delete pool record from non existing set - this.dexHelper.cache.zrem(this.notExistingPoolSetKey, [key]); + this.dexHelper.cache + .zrem(this.notExistingPoolSetKey, [key]) + .catch(() => {}); this.logger.info( `starting to listen to new non-null pool: ${key}. Already following ${allEventPools // Not that I like this reduce, but since it is done only on initialization, expect this to be ok From 8b3812695f7c6a91eef07637009258928e3ec900 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Fri, 10 Nov 2023 22:18:39 +0200 Subject: [PATCH 614/833] 2.42.10-cache-cleaning-bug.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b3b06b65..6e8ecfc56 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.9", + "version": "2.42.10-cache-cleaning-bug.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1bf2723ff9bd79683be51bd9a817973a5ffae7aa Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 13 Nov 2023 14:29:45 +0200 Subject: [PATCH 615/833] 2.42.9-dexalot-pool-restriction --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b3b06b65..efab7916a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.9", + "version": "2.42.9-dexalot-pool-restriction", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e84d8dcd7c0dcf33ae6807ac66ec809b0c32e501 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 13 Nov 2023 22:25:34 +0200 Subject: [PATCH 616/833] fix: styles --- src/dex/dexalot/dexalot.ts | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index afec8c34c..913548434 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -395,7 +395,8 @@ export class Dexalot extends SimpleExchange implements IDex { .toString(), ); if (isInputQuote) { - lQty = (lQty * BigInt(10 ** (baseToken.decimals * 2))) / + lQty = + (lQty * BigInt(10 ** (baseToken.decimals * 2))) / (lPrice * BigInt(10 ** quoteToken.decimals)); rQty = (rQty * BigInt(10 ** (baseToken.decimals * 2))) / @@ -451,7 +452,9 @@ export class Dexalot extends SimpleExchange implements IDex { ) : await this.getPoolIdentifiers(srcToken, destToken, side, blockNumber); - pools = await Promise.all(pools.map(async (p) => !(await this.isRestrictedPool(p)))).then((res) => pools.filter((_v, i) => res[i])); + pools = await Promise.all( + pools.map(async p => !(await this.isRestrictedPool(p))), + ).then(res => pools.filter((_v, i) => res[i])); if (pools.length === 0) { return null; } @@ -502,14 +505,16 @@ export class Dexalot extends SimpleExchange implements IDex { throw new Error(`Empty orderbook for ${pairKey}`); } - const isInputQuote = (clobSide === ClobSide.ASK && side === SwapSide.SELL) || (clobSide === ClobSide.BID && side === SwapSide.BUY); + const isInputQuote = + (clobSide === ClobSide.ASK && side === SwapSide.SELL) || + (clobSide === ClobSide.BID && side === SwapSide.BUY); const prices = this.calculateOrderPrice( amounts, orderbook, baseToken, quoteToken, - isInputQuote + isInputQuote, ); const outDecimals = clobSide === ClobSide.BID ? baseToken.decimals : quoteToken.decimals; @@ -576,7 +581,13 @@ export class Dexalot extends SimpleExchange implements IDex { const makerToken = normalizedDestToken; const takerToken = normalizedSrcToken; - const slippageBps = side === SwapSide.SELL ? BigNumber(1).minus(options.slippageFactor).multipliedBy(10000).toFixed(0) : options.slippageFactor.minus(1).multipliedBy(10000).toFixed(0); + const slippageBps = + side === SwapSide.SELL + ? BigNumber(1) + .minus(options.slippageFactor) + .multipliedBy(10000) + .toFixed(0) + : options.slippageFactor.minus(1).multipliedBy(10000).toFixed(0); const rfqParams = { makerAsset: ethers.utils.getAddress(makerToken.address), takerAsset: ethers.utils.getAddress(takerToken.address), @@ -725,11 +736,18 @@ export class Dexalot extends SimpleExchange implements IDex { `${this.dexKey}-${this.network}: failed to build transaction on side ${side} with too strict slippage. Skipping restriction`, ); } else { - const poolIdentifiers = await this.getPoolIdentifiers(srcToken, destToken, side, 0); + const poolIdentifiers = await this.getPoolIdentifiers( + srcToken, + destToken, + side, + 0, + ); this.logger.warn( `${this.dexKey}-${this.network}: protocol is restricted for pools ${poolIdentifiers} due to swap: ${swapIdentifier}`, ); - await Promise.all(poolIdentifiers.map(async (p) => await this.restrictPool(p))); + await Promise.all( + poolIdentifiers.map(async p => await this.restrictPool(p)), + ); } } @@ -818,7 +836,10 @@ export class Dexalot extends SimpleExchange implements IDex { return `${DEXALOT_RESTRICTED_CACHE_KEY}-${poolIdentifier}`; } - async restrictPool(poolIdentifier: string, ttl: number = DEXALOT_RESTRICT_TTL_S): Promise { + async restrictPool( + poolIdentifier: string, + ttl: number = DEXALOT_RESTRICT_TTL_S, + ): Promise { await this.dexHelper.cache.setex( this.dexKey, this.network, From 2a2a934727421dfceed6143b44681fd2cb3ff826 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 14 Nov 2023 15:52:31 +0200 Subject: [PATCH 617/833] feat: replace constants with relevant data from pool --- src/dex/algebra/algebra-pool-v1_9.ts | 5 ++--- src/dex/algebra/types.ts | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/dex/algebra/algebra-pool-v1_9.ts b/src/dex/algebra/algebra-pool-v1_9.ts index 7995b06e3..4758139fa 100644 --- a/src/dex/algebra/algebra-pool-v1_9.ts +++ b/src/dex/algebra/algebra-pool-v1_9.ts @@ -26,7 +26,6 @@ import { _reduceTickBitmap, _reduceTicks, } from '../uniswap-v3/contract-math/utils'; -import { Constants } from './lib/Constants'; import { Network } from '../../constants'; import { TickTable } from './lib/TickTable'; import { TICK_BITMAP_BUFFER, TICK_BITMAP_TO_USE } from './constants'; @@ -368,8 +367,8 @@ export class AlgebraEventPoolV1_9 extends StatefulEventSubscriber; // actually called tickTable in contract- ticks: Record; // although variable names are different in contracts but matches UniswapV3 TickInfo struct 1:1 isValid: boolean; From 0d1dfd3c775e66108900c1a2258c612883f179a4 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 14 Nov 2023 15:53:04 +0200 Subject: [PATCH 618/833] 2.42.10-camelotv3-tick-fix.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6e8ecfc56..a23bf9730 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.10-cache-cleaning-bug.0", + "version": "2.42.10-camelotv3-tick-fix.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 3e937bc2248b68d703d2dc3f067cb1cb96dd053b Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 14 Nov 2023 16:55:43 +0200 Subject: [PATCH 619/833] 2.42.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a23bf9730..cfca9f5fe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.10-camelotv3-tick-fix.0", + "version": "2.42.10", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 859d2eacd74654ed59d7e0ea8f13dd532f88f7cd Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 14 Nov 2023 22:57:13 +0200 Subject: [PATCH 620/833] 2.42.10-swaapv2-pool-restriction --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cfca9f5fe..a44aee1a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.10", + "version": "2.42.10-swaapv2-pool-restriction", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From c66e450929d606224cda226d1b81dcab2da78ec4 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 15 Nov 2023 01:38:53 +0100 Subject: [PATCH 621/833] mitigate missed newly created pool issue by locally checking if pool got discovered locally before --- src/dex/algebra/algebra.ts | 45 +++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 2a20eeac7..c5f095721 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -64,6 +64,8 @@ export class Algebra extends SimpleExchange implements IDex { readonly isFeeOnTransferSupported: boolean = false; protected eventPools: Record = {}; + private newlyCreatedPoolKeys: Set = new Set(); + readonly hasConstantPriceLargeAmounts = false; readonly needWrapNative = true; @@ -167,7 +169,9 @@ export class Algebra extends SimpleExchange implements IDex { }) => { const logPrefix = '[onPoolCreatedDeleteFromNonExistingSet]'; const [_token0, _token1] = this._sortTokens(token0, token1); - const poolKey = `${_token0}_${_token1}`; + const poolKey = `${_token0}_${_token1}`.toLowerCase(); + + this.newlyCreatedPoolKeys.add(poolKey); // consider doing it only from master pool for less calls to distant cache @@ -292,25 +296,36 @@ export class Algebra extends SimpleExchange implements IDex { }); } catch (e) { if (e instanceof Error && e.message.endsWith('Pool does not exist')) { - // no need to await we want the set to have the pool key but it's not blocking - this.dexHelper.cache.zadd( - this.notExistingPoolSetKey, - [Date.now(), key], - 'NX', - ); + /* + protection against 2 race conditions + 1/ if pool.initialize() promise rejects after the Pool creation event got treated + 2/ if the rpc node we hit on the http request is lagging behind the one we got event from (websocket) + */ + if (this.newlyCreatedPoolKeys.has(key)) { + this.logger.warn( + `[block=${blockNumber}][Pool=${key}] newly created pool failed to initialise`, + ); + } else { + // no need to await we want the set to have the pool key but it's not blocking + this.dexHelper.cache.zadd( + this.notExistingPoolSetKey, + [Date.now(), key], + 'NX', + ); - // Pool does not exist for this pair, so we can set it to null - // to prevent more requests for this pool - pool = null; - this.logger.trace( - `${this.dexHelper}: Pool: srcAddress=${srcAddress}, destAddress=${destAddress} not found`, - e, - ); + // Pool does not exist for this pair, so we can set it to null + // to prevent more requests for this pool + pool = null; + this.logger.info( + `[block=${blockNumber}][Pool=${key}] pool failed to initialize, probably not existing`, + e, + ); + } } else { // on unknown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( - `${this.dexKey}: Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, + `Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, e, ); pool.initFailed = true; From 05f3a4c13fa02cc7f63f23976b645eaca843ec81 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 15 Nov 2023 01:41:07 +0100 Subject: [PATCH 622/833] cleanup to prevent memory leak --- src/dex/algebra/algebra.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index c5f095721..c1d7a595b 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -294,6 +294,10 @@ export class Algebra extends SimpleExchange implements IDex { pool!.initRetryAttemptCount = 0; }, }); + + if (this.newlyCreatedPoolKeys.has(key)) { + this.newlyCreatedPoolKeys.delete(key); + } } catch (e) { if (e instanceof Error && e.message.endsWith('Pool does not exist')) { /* @@ -305,6 +309,7 @@ export class Algebra extends SimpleExchange implements IDex { this.logger.warn( `[block=${blockNumber}][Pool=${key}] newly created pool failed to initialise`, ); + this.newlyCreatedPoolKeys.delete(key); } else { // no need to await we want the set to have the pool key but it's not blocking this.dexHelper.cache.zadd( From 04aa9b213a17dc84cbb4fae70d419069da902cf6 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 15 Nov 2023 01:47:20 +0100 Subject: [PATCH 623/833] storing non exisiting pools in set forever till effective creation of pool (if happens) --- src/dex/algebra/algebra.ts | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index c1d7a595b..b99512c72 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -45,8 +45,8 @@ type PoolPairsInfo = { token1: Address; }; -const ALGEBRA_CLEAN_NOT_EXISTING_POOL_TTL_MS = 3 * 24 * 60 * 60 * 1000; // 3 days -const ALGEBRA_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 24 * 60 * 60 * 1000; // Once in a day +// const ALGEBRA_CLEAN_NOT_EXISTING_POOL_TTL_MS = 3 * 24 * 60 * 60 * 1000; // 3 days +// const ALGEBRA_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 24 * 60 * 60 * 1000; // Once in a day const ALGEBRA_EFFICIENCY_FACTOR = 3; const ALGEBRA_TICK_GAS_COST = 24_000; // Ceiled const ALGEBRA_TICK_BASE_OVERHEAD = 75_000; @@ -141,22 +141,23 @@ export class Algebra extends SimpleExchange implements IDex { // Init listening to new pools creation await this.factory.initialize(blockNumber); - if (!this.dexHelper.config.isSlave) { - const cleanExpiredNotExistingPoolsKeys = async () => { - const maxTimestamp = - Date.now() - ALGEBRA_CLEAN_NOT_EXISTING_POOL_TTL_MS; - await this.dexHelper.cache.zremrangebyscore( - this.notExistingPoolSetKey, - 0, - maxTimestamp, - ); - }; - - this.intervalTask = setInterval( - cleanExpiredNotExistingPoolsKeys.bind(this), - ALGEBRA_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS, - ); - } + //// COMMENTING DEPRECATED LOGIC: as we now invalidate pools on creation this is not needed anymore + // if (!this.dexHelper.config.isSlave) { + // const cleanExpiredNotExistingPoolsKeys = async () => { + // const maxTimestamp = + // Date.now() - ALGEBRA_CLEAN_NOT_EXISTING_POOL_TTL_MS; + // await this.dexHelper.cache.zremrangebyscore( + // this.notExistingPoolSetKey, + // 0, + // maxTimestamp, + // ); + // }; + + // this.intervalTask = setInterval( + // cleanExpiredNotExistingPoolsKeys.bind(this), + // ALGEBRA_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS, + // ); + // } } /* From 093709790bf5e59af6eb42e47297aa2b164dcd1d Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 15 Nov 2023 01:55:52 +0100 Subject: [PATCH 624/833] reduce risk of collision by only allowing leader node to mark pools as non existing in distant cache --- src/dex/algebra/algebra.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index b99512c72..f45a08be5 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -312,12 +312,15 @@ export class Algebra extends SimpleExchange implements IDex { ); this.newlyCreatedPoolKeys.delete(key); } else { - // no need to await we want the set to have the pool key but it's not blocking - this.dexHelper.cache.zadd( - this.notExistingPoolSetKey, - [Date.now(), key], - 'NX', - ); + // allowing only master/leader node to alter distant cache to reduce risk of race conditions + if (!this.dexHelper.config.isSlave) { + // no need to await we want the set to have the pool key but it's not blocking + this.dexHelper.cache.zadd( + this.notExistingPoolSetKey, + [Date.now(), key], + 'NX', + ); + } // Pool does not exist for this pair, so we can set it to null // to prevent more requests for this pool From 2f170c6fdfaf38393d20b88468715cc582c47f62 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 15 Nov 2023 01:58:32 +0100 Subject: [PATCH 625/833] better logging --- src/dex/algebra/algebra.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index f45a08be5..e9edcc3c9 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -312,6 +312,11 @@ export class Algebra extends SimpleExchange implements IDex { ); this.newlyCreatedPoolKeys.delete(key); } else { + this.logger.info( + `[block=${blockNumber}][Pool=${key}] pool failed to initialize so it's marked as non existing`, + e, + ); + // allowing only master/leader node to alter distant cache to reduce risk of race conditions if (!this.dexHelper.config.isSlave) { // no need to await we want the set to have the pool key but it's not blocking @@ -325,16 +330,12 @@ export class Algebra extends SimpleExchange implements IDex { // Pool does not exist for this pair, so we can set it to null // to prevent more requests for this pool pool = null; - this.logger.info( - `[block=${blockNumber}][Pool=${key}] pool failed to initialize, probably not existing`, - e, - ); } } else { // on unknown error mark as failed and increase retryCount for retry init strategy // note: state would be null by default which allows to fallback this.logger.warn( - `Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, + `[block=${blockNumber}][Pool=${key}] Can not generate pool state for srcAddress=${srcAddress}, destAddress=${destAddress} pool fallback to rpc and retry every ${this.config.initRetryFrequency} times, initRetryAttemptCount=${pool.initRetryAttemptCount}`, e, ); pool.initFailed = true; From 526af6f61199db457421db7e9b14fa3090ef6952 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 15 Nov 2023 02:01:20 +0100 Subject: [PATCH 626/833] 2.42.11-algebra-bugfix-missed-created-pools.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cfca9f5fe..79d6951c2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.10", + "version": "2.42.11-algebra-bugfix-missed-created-pools.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From cb245db280a0c334491217864a5de35b1b2d0779 Mon Sep 17 00:00:00 2001 From: cicixxue Date: Tue, 14 Nov 2023 20:12:50 -0500 Subject: [PATCH 627/833] migrate to v3 on Paraswap --- package.json | 2 +- src/abi/hashflow/HashflowRouter.abi.json | 1062 +++++++++++++---- src/dex/hashflow/config.ts | 16 +- src/dex/hashflow/hashflow-integration.test.ts | 15 +- src/dex/hashflow/hashflow.ts | 155 ++- src/dex/hashflow/rate-fetcher.ts | 6 +- src/dex/hashflow/types.ts | 4 +- src/dex/hashflow/validators.ts | 15 +- src/lib/fetcher/fetcher.ts | 18 +- tests/tenderly-simulation.ts | 7 +- yarn.lock | 118 +- 11 files changed, 1039 insertions(+), 379 deletions(-) diff --git a/package.json b/package.json index cfca9f5fe..a246c3226 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "dependencies": { "@0x/utils": "^4.5.2", "@hashflow/sdk": "1.2.4", - "@hashflow/taker-js": "0.0.2", + "@hashflow/taker-js": "0.3.4", "@paraswap/core": "1.1.0", "async": "^3.2.4", "axios": "0.26.0", diff --git a/src/abi/hashflow/HashflowRouter.abi.json b/src/abi/hashflow/HashflowRouter.abi.json index 3d364001c..5bff2950b 100644 --- a/src/abi/hashflow/HashflowRouter.abi.json +++ b/src/abi/hashflow/HashflowRouter.abi.json @@ -5,28 +5,53 @@ { "indexed": false, "internalType": "address", - "name": "governance", + "name": "guardian", "type": "address" - }, + } + ], + "name": "UpdateLimitOrderGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { "indexed": false, "internalType": "address", - "name": "prevGovernance", + "name": "pool", "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "authorized", + "type": "bool" } ], - "name": "UpdateGovernance", + "name": "UpdatePoolAuthorizaton", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "migrationRouter", + "name": "pool", "type": "address" }, + { + "indexed": false, + "internalType": "uint16", + "name": "otherHashflowChainId", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "caller", + "type": "bytes32" + }, { "indexed": false, "internalType": "bool", @@ -34,18 +59,24 @@ "type": "bool" } ], - "name": "UpdateMigrationRouterStatus", + "name": "UpdateXChainCallerAuthorization", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", "name": "pool", "type": "address" }, + { + "indexed": false, + "internalType": "address", + "name": "xChainMessenger", + "type": "address" + }, { "indexed": false, "internalType": "bool", @@ -53,26 +84,63 @@ "type": "bool" } ], - "name": "UpdatePoolAuthorizaton", + "name": "UpdateXChainMessengerAuthorization", "type": "event" }, { "anonymous": false, "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "callee", + "type": "address" + }, { "indexed": false, "internalType": "address", - "name": "xChainUa", + "name": "xChainMessenger", "type": "address" }, { "indexed": false, + "internalType": "bool", + "name": "authorized", + "type": "bool" + } + ], + "name": "UpdateXChainMessengerCallerAuthorization", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, "internalType": "address", - "name": "prevXChainUa", + "name": "pool", "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "otherHashflowChainId", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "otherChainPool", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bool", + "name": "authorized", + "type": "bool" } ], - "name": "UpdateXChainUA", + "name": "UpdateXChainPoolAuthorization", "type": "event" }, { @@ -81,21 +149,395 @@ "internalType": "address", "name": "pool", "type": "address" + } + ], + "name": "authorizedPools", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dstContract", + "type": "address" + }, + { + "internalType": "uint16", + "name": "srcHashflowChainId", + "type": "uint16" }, + { + "internalType": "bytes32", + "name": "caller", + "type": "bytes32" + } + ], + "name": "authorizedXChainCallers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "token", + "name": "callee", + "type": "address" + }, + { + "internalType": "address", + "name": "messenger", + "type": "address" + } + ], + "name": "authorizedXChainMessengersByCallee", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "messenger", + "type": "address" + } + ], + "name": "authorizedXChainMessengersByPool", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dstPool", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "srcHChainId", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "srcPool", + "type": "bytes32" + } + ], + "name": "authorizedXChainPools", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "srcHashflowChainId", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "srcPool", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "dstPool", + "type": "address" + }, + { + "internalType": "address", + "name": "dstExternalAccount", + "type": "address" + }, + { + "internalType": "address", + "name": "dstTrader", + "type": "address" + }, + { + "internalType": "address", + "name": "quoteToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "quoteTokenAmount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txid", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "srcCaller", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "dstContract", + "type": "address" + }, + { + "internalType": "bytes", + "name": "dstContractCalldata", + "type": "bytes" + } + ], + "internalType": "struct IHashflowRouter.XChainFillMessage", + "name": "fillMessage", + "type": "tuple" + } + ], + "name": "fillXChain", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + } + ], + "name": "forceUnauthorizePool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "factory", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "pool", "type": "address" }, { - "internalType": "uint256", - "name": "amount", - "type": "uint256" + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "killswitchPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "externalAccount", + "type": "address" + }, + { + "internalType": "address", + "name": "trader", + "type": "address" + }, + { + "internalType": "address", + "name": "baseToken", + "type": "address" + }, + { + "internalType": "address", + "name": "quoteToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "baseTokenAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "quoteTokenAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "quoteExpiry", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txid", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "takerSignature", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "makerSignature", + "type": "bytes" + } + ], + "internalType": "struct IQuote.RFQMQuote", + "name": "quote", + "type": "tuple" + } + ], + "name": "tradeRFQM", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "externalAccount", + "type": "address" + }, + { + "internalType": "address", + "name": "trader", + "type": "address" + }, + { + "internalType": "address", + "name": "baseToken", + "type": "address" + }, + { + "internalType": "address", + "name": "quoteToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "baseTokenAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "quoteTokenAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "quoteExpiry", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txid", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "takerSignature", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "makerSignature", + "type": "bytes" + } + ], + "internalType": "struct IQuote.RFQMQuote", + "name": "quote", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "guardianSignature", + "type": "bytes" } ], - "name": "addLiquidityPrivatePool", + "name": "tradeRFQMLimitOrder", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { @@ -109,124 +551,63 @@ }, { "internalType": "address", - "name": "token", + "name": "externalAccount", + "type": "address" + }, + { + "internalType": "address", + "name": "trader", + "type": "address" + }, + { + "internalType": "address", + "name": "baseToken", + "type": "address" + }, + { + "internalType": "address", + "name": "quoteToken", "type": "address" }, { "internalType": "uint256", - "name": "amount", + "name": "baseTokenAmount", "type": "uint256" }, { "internalType": "uint256", - "name": "nonce", + "name": "quoteTokenAmount", "type": "uint256" }, + { + "internalType": "uint256", + "name": "quoteExpiry", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txid", + "type": "bytes32" + }, { "internalType": "bytes", - "name": "signature", + "name": "takerSignature", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "makerSignature", "type": "bytes" } ], - "internalType": "struct IQuote.Deposit", - "name": "deposit", + "internalType": "struct IQuote.RFQMQuote", + "name": "quote", "type": "tuple" - } - ], - "name": "addLiquidityPublicPool", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - } - ], - "name": "isPoolAuthorized", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "name": "killswitchPool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "migrationRouter", - "type": "address" - } - ], - "name": "migratePoolAuthorization", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "burnAmount", - "type": "uint256" - } - ], - "name": "removeLiquidityPublicPool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "pool", - "type": "address" - }, - { - "internalType": "address", - "name": "token", - "type": "address" }, { - "internalType": "uint256", - "name": "burnAmount", - "type": "uint256" + "internalType": "bytes", + "name": "guardianSignature", + "type": "bytes" }, { "internalType": "uint256", @@ -249,12 +630,12 @@ "type": "bytes32" }, { - "internalType": "bool", - "name": "approveMax", - "type": "bool" + "internalType": "uint256", + "name": "amountToApprove", + "type": "uint256" } ], - "name": "removeLiquidityPublicPoolWithPermit", + "name": "tradeRFQMLimitOrderWithPermit", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -278,11 +659,6 @@ "name": "trader", "type": "address" }, - { - "internalType": "address", - "name": "effectiveTrader", - "type": "address" - }, { "internalType": "address", "name": "baseToken", @@ -295,17 +671,12 @@ }, { "internalType": "uint256", - "name": "effectiveBaseTokenAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxBaseTokenAmount", + "name": "baseTokenAmount", "type": "uint256" }, { "internalType": "uint256", - "name": "maxQuoteTokenAmount", + "name": "quoteTokenAmount", "type": "uint256" }, { @@ -313,11 +684,6 @@ "name": "quoteExpiry", "type": "uint256" }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, { "internalType": "bytes32", "name": "txid", @@ -325,28 +691,48 @@ }, { "internalType": "bytes", - "name": "signature", + "name": "takerSignature", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "makerSignature", "type": "bytes" } ], - "internalType": "struct IQuote.RFQTQuote[]", - "name": "quotes", - "type": "tuple[]" + "internalType": "struct IQuote.RFQMQuote", + "name": "quote", + "type": "tuple" }, { - "internalType": "address", - "name": "baseToken", - "type": "address" + "internalType": "uint256", + "name": "deadline", + "type": "uint256" }, { - "internalType": "address", - "name": "quoteToken", - "type": "address" + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amountToApprove", + "type": "uint256" } ], - "name": "tradeMultiHop", + "name": "tradeRFQMWithPermit", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { @@ -368,6 +754,11 @@ "name": "trader", "type": "address" }, + { + "internalType": "address", + "name": "effectiveTrader", + "type": "address" + }, { "internalType": "address", "name": "baseToken", @@ -378,6 +769,11 @@ "name": "quoteToken", "type": "address" }, + { + "internalType": "uint256", + "name": "effectiveBaseTokenAmount", + "type": "uint256" + }, { "internalType": "uint256", "name": "baseTokenAmount", @@ -393,6 +789,11 @@ "name": "quoteExpiry", "type": "uint256" }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, { "internalType": "bytes32", "name": "txid", @@ -400,23 +801,18 @@ }, { "internalType": "bytes", - "name": "takerSignature", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "makerSignature", + "name": "signature", "type": "bytes" } ], - "internalType": "struct IQuote.RFQMQuote", + "internalType": "struct IQuote.RFQTQuote", "name": "quote", "type": "tuple" } ], - "name": "tradeRFQm", + "name": "tradeRFQT", "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "function" }, { @@ -438,6 +834,11 @@ "name": "trader", "type": "address" }, + { + "internalType": "address", + "name": "effectiveTrader", + "type": "address" + }, { "internalType": "address", "name": "baseToken", @@ -448,6 +849,11 @@ "name": "quoteToken", "type": "address" }, + { + "internalType": "uint256", + "name": "effectiveBaseTokenAmount", + "type": "uint256" + }, { "internalType": "uint256", "name": "baseTokenAmount", @@ -464,22 +870,22 @@ "type": "uint256" }, { - "internalType": "bytes32", - "name": "txid", - "type": "bytes32" + "internalType": "uint256", + "name": "nonce", + "type": "uint256" }, { - "internalType": "bytes", - "name": "takerSignature", - "type": "bytes" + "internalType": "bytes32", + "name": "txid", + "type": "bytes32" }, { "internalType": "bytes", - "name": "makerSignature", + "name": "signature", "type": "bytes" } ], - "internalType": "struct IQuote.RFQMQuote", + "internalType": "struct IQuote.RFQTQuote", "name": "quote", "type": "tuple" }, @@ -504,12 +910,12 @@ "type": "bytes32" }, { - "internalType": "bool", - "name": "approveMax", - "type": "bool" + "internalType": "uint256", + "name": "amountToApprove", + "type": "uint256" } ], - "name": "tradeRFQmWithPermit", + "name": "tradeRFQTWithPermit", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -518,25 +924,45 @@ "inputs": [ { "components": [ + { + "internalType": "uint16", + "name": "srcChainId", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "dstChainId", + "type": "uint16" + }, { "internalType": "address", - "name": "pool", + "name": "srcPool", "type": "address" }, + { + "internalType": "bytes32", + "name": "dstPool", + "type": "bytes32" + }, { "internalType": "address", - "name": "externalAccount", + "name": "srcExternalAccount", "type": "address" }, + { + "internalType": "bytes32", + "name": "dstExternalAccount", + "type": "bytes32" + }, { "internalType": "address", "name": "trader", "type": "address" }, { - "internalType": "address", - "name": "effectiveTrader", - "type": "address" + "internalType": "bytes32", + "name": "dstTrader", + "type": "bytes32" }, { "internalType": "address", @@ -544,23 +970,18 @@ "type": "address" }, { - "internalType": "address", + "internalType": "bytes32", "name": "quoteToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "effectiveBaseTokenAmount", - "type": "uint256" + "type": "bytes32" }, { "internalType": "uint256", - "name": "maxBaseTokenAmount", + "name": "baseTokenAmount", "type": "uint256" }, { "internalType": "uint256", - "name": "maxQuoteTokenAmount", + "name": "quoteTokenAmount", "type": "uint256" }, { @@ -568,28 +989,43 @@ "name": "quoteExpiry", "type": "uint256" }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, { "internalType": "bytes32", "name": "txid", "type": "bytes32" }, + { + "internalType": "address", + "name": "xChainMessenger", + "type": "address" + }, { "internalType": "bytes", - "name": "signature", + "name": "takerSignature", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "makerSignature", "type": "bytes" } ], - "internalType": "struct IQuote.RFQTQuote", + "internalType": "struct IQuote.XChainRFQMQuote", "name": "quote", "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "dstContract", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "dstCalldata", + "type": "bytes" } ], - "name": "tradeSingleHop", + "name": "tradeXChainRFQM", "outputs": [], "stateMutability": "payable", "type": "function" @@ -633,15 +1069,20 @@ "name": "trader", "type": "address" }, + { + "internalType": "bytes32", + "name": "dstTrader", + "type": "bytes32" + }, { "internalType": "address", "name": "baseToken", "type": "address" }, { - "internalType": "address", + "internalType": "bytes32", "name": "quoteToken", - "type": "address" + "type": "bytes32" }, { "internalType": "uint256", @@ -658,33 +1099,68 @@ "name": "quoteExpiry", "type": "uint256" }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, { "internalType": "bytes32", "name": "txid", "type": "bytes32" }, + { + "internalType": "address", + "name": "xChainMessenger", + "type": "address" + }, { "internalType": "bytes", - "name": "signature", + "name": "takerSignature", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "makerSignature", "type": "bytes" } ], - "internalType": "struct IQuote.XChainRFQTQuote", + "internalType": "struct IQuote.XChainRFQMQuote", "name": "quote", "type": "tuple" }, { - "internalType": "enum IHashflowXChainUA.XChainMessageProtocol", - "name": "protocol", + "internalType": "bytes32", + "name": "dstContract", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "dstCalldata", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amountToApprove", + "type": "uint256" } ], - "name": "tradeXChain", + "name": "tradeXChainRFQMWithPermit", "outputs": [], "stateMutability": "payable", "type": "function" @@ -724,9 +1200,9 @@ "type": "bytes32" }, { - "internalType": "address", - "name": "trader", - "type": "address" + "internalType": "bytes32", + "name": "dstTrader", + "type": "bytes32" }, { "internalType": "address", @@ -734,9 +1210,14 @@ "type": "address" }, { - "internalType": "address", + "internalType": "bytes32", "name": "quoteToken", - "type": "address" + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "effectiveBaseTokenAmount", + "type": "uint256" }, { "internalType": "uint256", @@ -753,33 +1234,43 @@ "name": "quoteExpiry", "type": "uint256" }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, { "internalType": "bytes32", "name": "txid", "type": "bytes32" }, { - "internalType": "bytes", - "name": "takerSignature", - "type": "bytes" + "internalType": "address", + "name": "xChainMessenger", + "type": "address" }, { "internalType": "bytes", - "name": "makerSignature", + "name": "signature", "type": "bytes" } ], - "internalType": "struct IQuote.XChainRFQMQuote", + "internalType": "struct IQuote.XChainRFQTQuote", "name": "quote", "type": "tuple" }, { - "internalType": "enum IHashflowXChainUA.XChainMessageProtocol", - "name": "protocol", - "type": "uint8" + "internalType": "bytes32", + "name": "dstContract", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "dstCalldata", + "type": "bytes" } ], - "name": "tradeXChainRFQm", + "name": "tradeXChainRFQT", "outputs": [], "stateMutability": "payable", "type": "function" @@ -819,9 +1310,9 @@ "type": "bytes32" }, { - "internalType": "address", - "name": "trader", - "type": "address" + "internalType": "bytes32", + "name": "dstTrader", + "type": "bytes32" }, { "internalType": "address", @@ -829,9 +1320,14 @@ "type": "address" }, { - "internalType": "address", + "internalType": "bytes32", "name": "quoteToken", - "type": "address" + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "effectiveBaseTokenAmount", + "type": "uint256" }, { "internalType": "uint256", @@ -848,30 +1344,40 @@ "name": "quoteExpiry", "type": "uint256" }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, { "internalType": "bytes32", "name": "txid", "type": "bytes32" }, { - "internalType": "bytes", - "name": "takerSignature", - "type": "bytes" + "internalType": "address", + "name": "xChainMessenger", + "type": "address" }, { "internalType": "bytes", - "name": "makerSignature", + "name": "signature", "type": "bytes" } ], - "internalType": "struct IQuote.XChainRFQMQuote", + "internalType": "struct IQuote.XChainRFQTQuote", "name": "quote", "type": "tuple" }, { - "internalType": "enum IHashflowXChainUA.XChainMessageProtocol", - "name": "protocol", - "type": "uint8" + "internalType": "bytes32", + "name": "dstContract", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "dstCalldata", + "type": "bytes" }, { "internalType": "uint256", @@ -894,12 +1400,12 @@ "type": "bytes32" }, { - "internalType": "bool", - "name": "approveMax", - "type": "bool" + "internalType": "uint256", + "name": "amountToApprove", + "type": "uint256" } ], - "name": "tradeXChainRFQmWithPermit", + "name": "tradeXChainRFQTWithPermit", "outputs": [], "stateMutability": "payable", "type": "function" @@ -908,11 +1414,11 @@ "inputs": [ { "internalType": "address", - "name": "governance", + "name": "guardian", "type": "address" } ], - "name": "updateGovernance", + "name": "updateLimitOrderGuardian", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -921,16 +1427,39 @@ "inputs": [ { "internalType": "address", - "name": "router", + "name": "pool", "type": "address" }, { "internalType": "bool", - "name": "status", + "name": "authorized", + "type": "bool" + } + ], + "name": "updatePoolAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "otherHashflowChainId", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "caller", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "authorized", "type": "bool" } ], - "name": "updateMigrationRouterStatus", + "name": "updateXChainCallerAuthorization", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -939,7 +1468,7 @@ "inputs": [ { "internalType": "address", - "name": "pool", + "name": "xChainMessenger", "type": "address" }, { @@ -948,7 +1477,48 @@ "type": "bool" } ], - "name": "updatePoolAuthorization", + "name": "updateXChainMessengerAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "xChainMessenger", + "type": "address" + }, + { + "internalType": "bool", + "name": "authorized", + "type": "bool" + } + ], + "name": "updateXChainMessengerCallerAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "otherHashflowChainId", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "otherPool", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "authorized", + "type": "bool" + } + ], + "name": "updateXChainPoolAuthorization", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -957,11 +1527,11 @@ "inputs": [ { "internalType": "address", - "name": "xChainUa", + "name": "token", "type": "address" } ], - "name": "updateXChainUa", + "name": "withdrawFunds", "outputs": [], "stateMutability": "nonpayable", "type": "function" diff --git a/src/dex/hashflow/config.ts b/src/dex/hashflow/config.ts index e2042d7d2..2a2e05fcd 100644 --- a/src/dex/hashflow/config.ts +++ b/src/dex/hashflow/config.ts @@ -1,26 +1,26 @@ -import { DexParams } from './types'; -import { DexConfigMap, AdapterMappings } from '../../types'; import { Network, SwapSide } from '../../constants'; +import { AdapterMappings, DexConfigMap } from '../../types'; +import { DexParams } from './types'; export const HashflowConfig: DexConfigMap = { Hashflow: { [Network.MAINNET]: { - routerAddress: '0xf6a94dfd0e6ea9ddfdffe4762ad4236576136613', + routerAddress: '0x55084eE0fEf03f14a305cd24286359A35D735151', }, [Network.POLYGON]: { - routerAddress: '0x72550597dc0b2e0bec24e116add353599eff2e35', + routerAddress: '0x55084eE0fEf03f14a305cd24286359A35D735151', }, [Network.BSC]: { - routerAddress: '0x0acffb0fb2cddd9bd35d03d359f3d899e32facc9', + routerAddress: '0x55084eE0fEf03f14a305cd24286359A35D735151', }, [Network.ARBITRUM]: { - routerAddress: '0x1f772fa3bc263160ea09bb16ce1a6b8fc0fab36a', + routerAddress: '0x55084eE0fEf03f14a305cd24286359A35D735151', }, [Network.AVALANCHE]: { - routerAddress: '0x64d2f9f44fe26c157d552ae7eaa613ca6587b59e', + routerAddress: '0x55084eE0fEf03f14a305cd24286359A35D735151', }, [Network.OPTIMISM]: { - routerAddress: '0xb3999f658c0391d94a37f7ff328f3fec942bcadc', + routerAddress: '0xCa310B1B942A30Ff4b40a5E1b69AB4607eC79Bc1', }, }, }; diff --git a/src/dex/hashflow/hashflow-integration.test.ts b/src/dex/hashflow/hashflow-integration.test.ts index 3fb4982d7..24d079b09 100644 --- a/src/dex/hashflow/hashflow-integration.test.ts +++ b/src/dex/hashflow/hashflow-integration.test.ts @@ -2,16 +2,17 @@ import dotenv from 'dotenv'; dotenv.config(); -import { DummyDexHelper } from '../../dex-helper/index'; -import { Network, SwapSide } from '../../constants'; -import { BI_POWS } from '../../bigint-constants'; -import { Hashflow } from './hashflow'; +import { Tokens } from '../../../tests/constants-e2e'; import { + checkConstantPoolPrices, checkPoolPrices, checkPoolsLiquidity, - checkConstantPoolPrices, + sleep, } from '../../../tests/utils'; -import { Tokens } from '../../../tests/constants-e2e'; +import { BI_POWS } from '../../bigint-constants'; +import { Network, SwapSide } from '../../constants'; +import { DummyDexHelper } from '../../dex-helper/index'; +import { Hashflow } from './hashflow'; async function testPricingOnNetwork( hashflow: Hashflow, @@ -104,6 +105,8 @@ describe('Hashflow', function () { beforeAll(async () => { blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); hashflow = new Hashflow(network, dexKey, dexHelper); + await hashflow.initializePricing(0); + await sleep(5000); }); it('getPoolIdentifiers and getPricesVolume SELL', async function () { diff --git a/src/dex/hashflow/hashflow.ts b/src/dex/hashflow/hashflow.ts index e64bf8675..5faf8ea5e 100644 --- a/src/dex/hashflow/hashflow.ts +++ b/src/dex/hashflow/hashflow.ts @@ -1,62 +1,61 @@ +import { ChainId, ZERO_ADDRESS } from '@hashflow/sdk'; +import { Chain, ChainType, HashflowApi } from '@hashflow/taker-js'; import { - Token, + MarketMakersResponse, + PriceLevelsResponse, + RfqResponse, +} from '@hashflow/taker-js/dist/types/rest'; +import BigNumber from 'bignumber.js'; +import { Interface } from 'ethers/lib/utils'; +import { assert } from 'ts-essentials'; +import routerAbi from '../../abi/hashflow/HashflowRouter.abi.json'; +import { BI_MAX_UINT256 } from '../../bigint-constants'; +import { BN_0, BN_1, getBigNumberPow } from '../../bignumber-constants'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { + CACHE_PREFIX, + ETHER_ADDRESS, + Network, + SwapSide, +} from '../../constants'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { IDex } from '../../dex/idex'; +import { + AdapterExchangeParam, Address, ExchangePrices, - PoolPrices, - AdapterExchangeParam, - SimpleExchangeParam, - PoolLiquidity, - Logger, ExchangeTxInfo, + Logger, OptimalSwapExchange, + PoolLiquidity, + PoolPrices, PreprocessTransactionOptions, + SimpleExchangeParam, + Token, } from '../../types'; -import { - SwapSide, - Network, - ETHER_ADDRESS, - CACHE_PREFIX, -} from '../../constants'; -import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { getDexKeysWithNetwork } from '../../utils'; -import { IDex } from '../../dex/idex'; -import { IDexHelper } from '../../dex-helper/idex-helper'; -import { - HashflowData, - PriceLevel, - RfqError, - RFQType, - SlippageCheckError, -} from './types'; +import { TooStrictSlippageCheckError } from '../generic-rfq/types'; import { SimpleExchange } from '../simple-exchange'; import { Adapters, HashflowConfig } from './config'; -import { HashflowApi } from '@hashflow/taker-js'; -import { RateFetcher } from './rate-fetcher'; -import routerAbi from '../../abi/hashflow/HashflowRouter.abi.json'; -import BigNumber from 'bignumber.js'; -import { BN_0, BN_1, getBigNumberPow } from '../../bignumber-constants'; -import { Interface } from 'ethers/lib/utils'; -import { ChainId, ZERO_ADDRESS } from '@hashflow/sdk'; -import { - MarketMakersResponse, - PriceLevelsResponse, - RfqResponse, -} from '@hashflow/taker-js/dist/types/rest'; -import { assert } from 'ts-essentials'; import { - HASHFLOW_BLACKLIST_TTL_S, - HASHFLOW_MM_RESTRICT_TTL_S, HASHFLOW_API_CLIENT_NAME, - HASHFLOW_API_URL, - HASHFLOW_API_PRICES_POLLING_INTERVAL_MS, HASHFLOW_API_MARKET_MAKERS_POLLING_INTERVAL_MS, - HASHFLOW_PRICES_CACHES_TTL_S, - HASHFLOW_MARKET_MAKERS_CACHES_TTL_S, + HASHFLOW_API_PRICES_POLLING_INTERVAL_MS, + HASHFLOW_API_URL, + HASHFLOW_BLACKLIST_TTL_S, HASHFLOW_GAS_COST, + HASHFLOW_MARKET_MAKERS_CACHES_TTL_S, HASHFLOW_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION, + HASHFLOW_MM_RESTRICT_TTL_S, + HASHFLOW_PRICES_CACHES_TTL_S, } from './constants'; -import { BI_MAX_UINT256 } from '../../bigint-constants'; -import { TooStrictSlippageCheckError } from '../generic-rfq/types'; +import { RateFetcher } from './rate-fetcher'; +import { + HashflowData, + PriceLevel, + RfqError, + SlippageCheckError, +} from './types'; export class Hashflow extends SimpleExchange implements IDex { readonly isStatePollingDex = true; @@ -121,19 +120,21 @@ export class Hashflow extends SimpleExchange implements IDex { markerMakersIntervalMs: HASHFLOW_API_MARKET_MAKERS_POLLING_INTERVAL_MS, marketMakersReqParams: { - url: `${HASHFLOW_API_URL}/taker/v1/marketMakers`, + url: `${HASHFLOW_API_URL}/taker/v3/market-makers`, params: { - networkId: this.network, + baseChainId: this.network, source: HASHFLOW_API_CLIENT_NAME, + baseChainType: 'evm', }, headers: { Authorization: this.hashFlowAuthToken }, }, pricesReqParams: { - url: `${HASHFLOW_API_URL}/taker/v2/price-levels`, + url: `${HASHFLOW_API_URL}/taker/v3/price-levels`, params: { - networkId: this.network, + baseChainId: this.network, source: HASHFLOW_API_CLIENT_NAME, marketMakers: [], + baseChainType: 'evm', }, headers: { Authorization: this.hashFlowAuthToken }, }, @@ -321,8 +322,8 @@ export class Hashflow extends SimpleExchange implements IDex { priceLevels: PriceLevel[], ): { level: BigNumber; price: BigNumber }[] => priceLevels.map(l => ({ - level: new BigNumber(l.level), - price: new BigNumber(l.price), + level: new BigNumber(l.q), + price: new BigNumber(l.p), })); computeLevelsQuote( @@ -488,7 +489,7 @@ export class Hashflow extends SimpleExchange implements IDex { new BigNumber(a.toString()).dividedBy(divider), ); const firstLevelRaw = levels[0]; - const firstLevelAmountBN = new BigNumber(firstLevelRaw.level); + const firstLevelAmountBN = new BigNumber(firstLevelRaw.q); if (amountsRaw[amountsRaw.length - 1].lt(firstLevelAmountBN)) { return null; @@ -496,7 +497,7 @@ export class Hashflow extends SimpleExchange implements IDex { if (firstLevelAmountBN.gt(0)) { // Add zero level for price computation - levels.unshift({ level: '0', price: firstLevelRaw.price }); + levels.unshift({ q: '0', p: firstLevelRaw.p }); } const unitPrice = this.computePricesFromLevels( @@ -565,14 +566,15 @@ export class Hashflow extends SimpleExchange implements IDex { `${this.dexKey}-${this.network}: MM was not provided in data`, ); const chainId = this.network as ChainId; - + let chainType: ChainType = 'evm'; + const chain: Chain = { chainType, chainId }; const normalizedSrcToken = this.normalizeToken(srcToken); const normalizedDestToken = this.normalizeToken(destToken); let rfq: RfqResponse; try { rfq = await this.api.requestQuote({ - chainId, + baseChain: chain, baseToken: normalizedSrcToken.address, quoteToken: normalizedDestToken.address, ...(side === SwapSide.SELL @@ -594,7 +596,7 @@ export class Hashflow extends SimpleExchange implements IDex { )}: ${JSON.stringify(rfq)}`; this.logger.warn(message); throw new RfqError(message); - } else if (!rfq.quoteData) { + } else if (!rfq.quotes[0].quoteData) { const message = `${this.dexKey}-${ this.network }: Failed to fetch RFQ for ${this.getPairName( @@ -603,7 +605,7 @@ export class Hashflow extends SimpleExchange implements IDex { )}. Missing quote data`; this.logger.warn(message); throw new RfqError(message); - } else if (!rfq.signature) { + } else if (!rfq.quotes[0].signature) { const message = `${this.dexKey}-${ this.network }: Failed to fetch RFQ for ${this.getPairName( @@ -612,40 +614,22 @@ export class Hashflow extends SimpleExchange implements IDex { )}. Missing signature`; this.logger.warn(message); throw new RfqError(message); - } else if (!rfq.gasEstimate) { - const message = `${this.dexKey}-${ - this.network - }: Failed to fetch RFQ for ${this.getPairName( - normalizedSrcToken.address, - normalizedDestToken.address, - )}. No gas estimate.`; - this.logger.warn(message); - throw new RfqError(message); - } else if (rfq.quoteData.rfqType !== RFQType.RFQT) { - const message = `${this.dexKey}-${ - this.network - }: Failed to fetch RFQ for ${this.getPairName( - normalizedSrcToken.address, - normalizedDestToken.address, - )}. Invalid RFQ type.`; - this.logger.warn(message); - throw new RfqError(message); } assert( - rfq.quoteData.baseToken === normalizedSrcToken.address, - `QuoteData baseToken=${rfq.quoteData.baseToken} is different from srcToken=${normalizedSrcToken.address}`, + rfq.quotes[0].quoteData.baseToken === normalizedSrcToken.address, + `QuoteData baseToken=${rfq.quotes[0].quoteData.baseToken} is different from srcToken=${normalizedSrcToken.address}`, ); assert( - rfq.quoteData.quoteToken === normalizedDestToken.address, - `QuoteData baseToken=${rfq.quoteData.quoteToken} is different from srcToken=${normalizedDestToken.address}`, + rfq.quotes[0].quoteData.quoteToken === normalizedDestToken.address, + `QuoteData baseToken=${rfq.quotes[0].quoteData.quoteToken} is different from srcToken=${normalizedDestToken.address}`, ); - const expiryAsBigInt = BigInt(rfq.quoteData.quoteExpiry); + const expiryAsBigInt = BigInt(rfq.quotes[0].quoteData.quoteExpiry); const minDeadline = expiryAsBigInt > 0 ? expiryAsBigInt : BI_MAX_UINT256; - const baseTokenAmount = BigInt(rfq.quoteData.baseTokenAmount); - const quoteTokenAmount = BigInt(rfq.quoteData.quoteTokenAmount); + const baseTokenAmount = BigInt(rfq.quotes[0].quoteData.baseTokenAmount); + const quoteTokenAmount = BigInt(rfq.quotes[0].quoteData.quoteTokenAmount); const srcAmount = BigInt(optimalSwapExchange.srcAmount); const destAmount = BigInt(optimalSwapExchange.destAmount); @@ -721,9 +705,8 @@ export class Hashflow extends SimpleExchange implements IDex { ...optimalSwapExchange, data: { mm, - quoteData: rfq.quoteData, - signature: rfq.signature, - gasEstimate: rfq.gasEstimate, + quoteData: rfq.quotes[0].quoteData, + signature: rfq.quotes[0].signature, }, }, { deadline: minDeadline }, @@ -818,7 +801,7 @@ export class Hashflow extends SimpleExchange implements IDex { { pool: quoteData.pool, quoteToken: quoteData.quoteToken, - externalAccount: quoteData.eoa ?? ZERO_ADDRESS, + externalAccount: quoteData.externalAccount ?? ZERO_ADDRESS, baseTokenAmount: quoteData.baseTokenAmount, quoteTokenAmount: quoteData.quoteTokenAmount, quoteExpiry: quoteData.quoteExpiry, @@ -882,7 +865,7 @@ export class Hashflow extends SimpleExchange implements IDex { const swapData = this.routerInterface.encodeFunctionData('tradeSingleHop', [ [ quoteData.pool, - quoteData.eoa ?? ZERO_ADDRESS, + quoteData.externalAccount ?? ZERO_ADDRESS, quoteData.trader, quoteData.effectiveTrader ?? quoteData.trader, quoteData.baseToken, @@ -924,7 +907,7 @@ export class Hashflow extends SimpleExchange implements IDex { levels: PriceLevel[], baseTokenPriceUsd: number, ): number => { - const maxLevel = new BigNumber(levels[levels.length - 1]?.level ?? '0'); + const maxLevel = new BigNumber(levels[levels.length - 1]?.q ?? '0'); return maxLevel.multipliedBy(baseTokenPriceUsd).toNumber(); }; diff --git a/src/dex/hashflow/rate-fetcher.ts b/src/dex/hashflow/rate-fetcher.ts index 29b5ba6a5..1b58de149 100644 --- a/src/dex/hashflow/rate-fetcher.ts +++ b/src/dex/hashflow/rate-fetcher.ts @@ -1,14 +1,14 @@ +import { Network } from '../../constants'; import { IDexHelper } from '../../dex-helper'; import { Fetcher, SkippingRequest } from '../../lib/fetcher/fetcher'; import { validateAndCast } from '../../lib/validators'; import { Logger } from '../../types'; import { + HashflowMarketMakersResponse, HashflowRateFetcherConfig, HashflowRatesResponse, - HashflowMarketMakersResponse, } from './types'; -import { pricesResponseValidator, marketMakersValidator } from './validators'; -import { Network } from '../../constants'; +import { marketMakersValidator, pricesResponseValidator } from './validators'; export class RateFetcher { private rateFetcher: Fetcher; diff --git a/src/dex/hashflow/types.ts b/src/dex/hashflow/types.ts index ff28311ad..9d73c34c4 100644 --- a/src/dex/hashflow/types.ts +++ b/src/dex/hashflow/types.ts @@ -13,8 +13,8 @@ export type DexParams = { }; export interface PriceLevel { - level: string; - price: string; + q: string; + p: string; } export class RfqError extends Error {} diff --git a/src/dex/hashflow/validators.ts b/src/dex/hashflow/validators.ts index 4e66c521c..d82e3d2d8 100644 --- a/src/dex/hashflow/validators.ts +++ b/src/dex/hashflow/validators.ts @@ -12,17 +12,24 @@ export const levelValidator = joi.array().items( }), levels: joi.array().items( joi.object({ - level: joi.string().min(1).required(), - price: joi.string().min(1).required(), + q: joi.string().min(1).required(), + p: joi.string().min(1).required(), }), ), - includesFees: joi.boolean().required(), }), ); export const pricesResponseValidator = joi.object({ status: joi.string().required(), - networkId: joi.number().required(), + // networkId: joi.number().required(), + baseChain: joi.object({ + chainType: joi.string().required(), + chainId: joi.number().required(), + }), + quoteChain: joi.object({ + chainType: joi.string().required(), + chainId: joi.number().required(), + }), levels: joi.object().pattern(joi.string().min(1), levelValidator), }); diff --git a/src/lib/fetcher/fetcher.ts b/src/lib/fetcher/fetcher.ts index 278d18e26..3b856fdea 100644 --- a/src/lib/fetcher/fetcher.ts +++ b/src/lib/fetcher/fetcher.ts @@ -1,7 +1,7 @@ -import { IRequestWrapper } from '../../dex-helper'; +import { isFunction } from 'lodash'; import { Logger } from 'log4js'; +import { IRequestWrapper } from '../../dex-helper'; import { RequestConfig, Response } from '../../dex-helper/irequest-wrapper'; -import { isFunction } from 'lodash'; const FETCH_TIMEOUT_MS = 10 * 1000; const FETCH_FAIL_MAX_ATTEMPT = 5; @@ -100,12 +100,12 @@ export class Fetcher { results.map(result => { if (!(result instanceof Error || result instanceof SkippingRequest)) { - this.logger.info( - 'Results Data:', - JSON.stringify((result as any).data) - .replace(/(?:\r\n|\r|\n)/g, ' ') - .substring(0, 1000), - ); + // this.logger.info( + // 'Results Data:', + // JSON.stringify((result as any).data) + // .replace(/(?:\r\n|\r|\n)/g, ' ') + // .substring(0, 1000), + // ); } }); @@ -142,7 +142,7 @@ export class Fetcher { const reqInfo = this.requests[i]; const info = reqInfo.info; const options = reqInfo.info.requestOptions; - this.logger.debug(`(${options.url}) received new data`); + // this.logger.debug(`(${options.url}) received new data`); try { const parsedData = info.caster(response.data); diff --git a/tests/tenderly-simulation.ts b/tests/tenderly-simulation.ts index ddc53c786..7b5ba0a32 100644 --- a/tests/tenderly-simulation.ts +++ b/tests/tenderly-simulation.ts @@ -1,7 +1,7 @@ /* eslint-disable no-console */ -import axios from 'axios'; -import { Address } from '@paraswap/core'; import { Provider } from '@ethersproject/providers'; +import { Address } from '@paraswap/core'; +import axios from 'axios'; import { TxObject } from '../src/types'; import { StateOverrides, StateSimulateApiOverride } from './smart-tokens'; @@ -76,6 +76,7 @@ export class TenderlySimulation implements TransactionSimulator { } try { + await process.nextTick(() => {}); // https://stackoverflow.com/questions/69169492/async-external-function-leaves-open-handles-jest-supertest-express let res = await axios.post( `https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/fork`, { @@ -109,6 +110,7 @@ export class TenderlySimulation implements TransactionSimulator { }; try { if (stateOverrides) { + await process.nextTick(() => {}); // https://stackoverflow.com/questions/69169492/async-external-function-leaves-open-handles-jest-supertest-express const result = await axios.post( ` https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/contracts/encode-states`, @@ -133,6 +135,7 @@ export class TenderlySimulation implements TransactionSimulator { ); } + await process.nextTick(() => {}); // https://stackoverflow.com/questions/69169492/async-external-function-leaves-open-handles-jest-supertest-express const { data } = await axios.post( `https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/fork/${this.forkId}/simulate`, _params, diff --git a/yarn.lock b/yarn.lock index eb77e24a1..6d436ba94 100644 --- a/yarn.lock +++ b/yarn.lock @@ -41,6 +41,11 @@ js-sha3 "^0.7.0" lodash "^4.17.11" +"@adraffy/ens-normalize@1.10.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" + integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== + "@ampproject/remapping@^2.1.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" @@ -797,6 +802,20 @@ dependencies: "@hapi/hoek" "^9.0.0" +"@hashflow/contracts-evm@2.0.10": + version "2.0.10" + resolved "https://registry.yarnpkg.com/@hashflow/contracts-evm/-/contracts-evm-2.0.10.tgz#60babe34e2685b055dec56307167550993f4f0aa" + integrity sha512-Hxvd9cOn21klYHZhCFGdKaVGawaeOPo5ej1BVersjP9/HBFw+8O/lYqrmcykth69kHSpzf3tUBnsm7ef9Yx9Hg== + dependencies: + "@openzeppelin/contracts" "4.9.2" + +"@hashflow/contracts-evm@2.0.8": + version "2.0.8" + resolved "https://registry.yarnpkg.com/@hashflow/contracts-evm/-/contracts-evm-2.0.8.tgz#89177de2758e0ee1a2dc72a01ae81423f794e36f" + integrity sha512-TZznNsLShvVcTblU0nVgVWVs4dg7Ao0CJF0N02dkdGeRvLZqrcyIeDk7vn+ulcYS8rKHP+BplszVlDelGoCEVg== + dependencies: + "@openzeppelin/contracts" "4.9.2" + "@hashflow/governance@1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@hashflow/governance/-/governance-1.0.4.tgz#6ef8805226652e59417bbdf4ec1421c5d2335775" @@ -804,11 +823,25 @@ dependencies: "@openzeppelin/contracts" "^4.7.3" +"@hashflow/hashverse-contracts-evm@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@hashflow/hashverse-contracts-evm/-/hashverse-contracts-evm-1.0.0.tgz#2689a2dfc576a88a70f244a839f1d76bcf198520" + integrity sha512-ZFSdSFF9XvfWCCkJGzimYJFsXFhD0uyz5nOCnjSk7dX3o3lncUvTWTWa3XZfzcp6WfPmIoEmOY4OIf8+xOA/AA== + dependencies: + "@hashflow/contracts-evm" "2.0.8" + "@openzeppelin/contracts" "4.9.2" + "@openzeppelin/contracts-upgradeable" "4.9.2" + "@hashflow/hashverse-contracts@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@hashflow/hashverse-contracts/-/hashverse-contracts-1.0.2.tgz#f1eec8f8796ef8c79af5388273cae076c0d9fc0c" integrity sha512-u3hkcrNCuVW9oCkfn7Em9FDHutGpKzXjQyyGVdcGbKPDqm7e0QCnfHLpqOMDlQhp7sDByo8gHDoaHRYhjnKOlg== +"@hashflow/hashverse-contracts@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@hashflow/hashverse-contracts/-/hashverse-contracts-1.3.1.tgz#7d769f4cb46398dc2cb0fadfb40e5305319eb1ce" + integrity sha512-kYUNsRnSzr12XiHYrXfPw+9mvlygl+BUFXwPAfymEnvC8igiN/2EOHjkFvgbtZq8A0COgZYibL69FRQICDs2JQ== + "@hashflow/protocol@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@hashflow/protocol/-/protocol-1.0.3.tgz#59e1620941767ae1919eadaf4c8542b4fac0a03a" @@ -817,7 +850,7 @@ "@openzeppelin/contracts" "^4.7.3" "@openzeppelin/contracts-upgradeable" "^4.7.3" -"@hashflow/sdk@1.2.4", "@hashflow/sdk@^1.0.1": +"@hashflow/sdk@1.2.4": version "1.2.4" resolved "https://registry.yarnpkg.com/@hashflow/sdk/-/sdk-1.2.4.tgz#edf2d7208d04e6bee1bf69aeaa7df68156db30b1" integrity sha512-gEhRudo8e3x3lwzdsfZfhXQHE0C63sH8tcHIT2K/L6sEPUkIz7jbTkfQFaiDVcpGjvUDlCKCEjqGHWE8btnk7Q== @@ -830,14 +863,25 @@ "@hashflow/hashverse-contracts" "1.0.2" "@hashflow/protocol" "1.0.3" -"@hashflow/taker-js@0.0.2": - version "0.0.2" - resolved "https://registry.yarnpkg.com/@hashflow/taker-js/-/taker-js-0.0.2.tgz#cadcd396ab29ce2fab1cb94f8a2b6f9bc8658c54" - integrity sha512-3Yly8Eglvs06OpVbnBcNDBfPSmkEiJRSA8HsBwbPrfppagFOnzLCs6Z0U4A8Ztdnic4rbWVokb7r5YEJ0TxgWg== +"@hashflow/sdk@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@hashflow/sdk/-/sdk-2.2.1.tgz#a805879791300d7b8afc16430d9faeab8e97a1bb" + integrity sha512-qXQrkEIaU98woAIA/pkvWE4UC8+5PT+S3ISwjenlL0uCrFEDMvYQX8k8Qep8IO2bD7B2OaRU6g2IMCvdaLDa8A== + dependencies: + "@hashflow/contracts-evm" "2.0.10" + "@hashflow/governance" "1.0.4" + "@hashflow/hashverse-contracts" "1.3.1" + "@hashflow/hashverse-contracts-evm" "1.0.0" + "@hashflow/protocol" "1.0.3" + +"@hashflow/taker-js@0.3.4": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@hashflow/taker-js/-/taker-js-0.3.4.tgz#254a3ca5e14bce00c920ffe4cdb3f743020c6b8f" + integrity sha512-/lJmW/gZndUZNyBv1sZR/g+H8VqsZDOQ4QsbUL93RrBeAHBd00nLXyr2Wgg5FlpZzTyMz8ea5+3BDB6K/0Xi2w== dependencies: - "@hashflow/sdk" "^1.0.1" + "@hashflow/sdk" "^2.2.0" axios "^0.27.2" - ethers "^5.7.0" + ethers "^6.7.0" "@humanwhocodes/config-array@^0.11.8": version "0.11.8" @@ -1136,11 +1180,23 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" +"@noble/curves@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + "@noble/hashes@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + "@noble/hashes@~1.1.1": version "1.1.5" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.5.tgz#1a0377f3b9020efe2fae03290bd2a12140c95c11" @@ -1375,6 +1431,11 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.7.3.tgz#f1d606e2827d409053f3e908ba4eb8adb1dd6995" integrity sha512-+wuegAMaLcZnLCJIvrVUDzA9z/Wp93f0Dla/4jJvIhijRrPabjQbZe6fWiECLaJyfn5ci9fqf9vTw3xpQOad2A== +"@openzeppelin/contracts-upgradeable@4.9.2": + version "4.9.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.9.2.tgz#a817c75688f8daede420052fbcb34e52482e769e" + integrity sha512-siviV3PZV/fHfPaoIC51rf1Jb6iElkYWnNYZ0leO23/ukXuvOyoC/ahy8jqiV7g+++9Nuo3n/rk5ajSN/+d/Sg== + "@openzeppelin/contracts-upgradeable@^4.7.3": version "4.8.1" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.1.tgz#363f7dd08f25f8f77e16d374350c3d6b43340a7a" @@ -1385,6 +1446,11 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.3.tgz#939534757a81f8d69cc854c7692805684ff3111e" integrity sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw== +"@openzeppelin/contracts@4.9.2": + version "4.9.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.2.tgz#1cb2d5e4d3360141a17dbc45094a8cad6aac16c1" + integrity sha512-mO+y6JaqXjWeMh9glYVzVu8HYPGknAAnWyxTRhGeckOruyXQMNnlcW6w/Dx9ftLeIQk6N+ZJFuVmTwF7lEIFrg== + "@openzeppelin/contracts@^4.7.3": version "4.8.1" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.1.tgz#709cfc4bbb3ca9f4460d60101f15dac6b7a2d5e4" @@ -1763,6 +1829,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.3.tgz#78a6d7ec962b596fc2d2ec102c4dd3ef073fea6a" integrity sha512-fNjDQzzOsZeKZu5NATgXUPsaFaTxeRgFXoosrHivTl8RGeV733OLawXsGfEk9a8/tySyZUyiZ6E8LcjPFZ2y1A== +"@types/node@18.15.13": + version "18.15.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" + integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== + "@types/node@^12.12.6": version "12.20.55" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" @@ -2016,6 +2087,11 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -3835,6 +3911,19 @@ ethers@^5.6.5, ethers@^5.7.0: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" +ethers@^6.7.0: + version "6.8.1" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.8.1.tgz#ee2a1a39b5f62a13678f90ccd879175391d0a2b4" + integrity sha512-iEKm6zox5h1lDn6scuRWdIdFJUCGg3+/aQWu0F4K0GVyEZiktFkqrJbRjTn1FlYEPz7RKA707D6g5Kdk6j7Ljg== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.5.0" + ethers@~4.0.4: version "4.0.49" resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.49.tgz#0eb0e9161a0c8b4761be547396bbe2fb121a8894" @@ -7354,16 +7443,16 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" +tslib@2.4.0, tslib@^2.0.3: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + tslib@^1.8.1, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.3: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== - tsort@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" @@ -7993,6 +8082,11 @@ ws@7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" From aed9e2c1b8964633a733b39723a03c17e415054d Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 15 Nov 2023 10:42:22 +0100 Subject: [PATCH 628/833] camelot: force rpc fallback --- src/dex/algebra/config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dex/algebra/config.ts b/src/dex/algebra/config.ts index 5809d2037..1e9390b8d 100644 --- a/src/dex/algebra/config.ts +++ b/src/dex/algebra/config.ts @@ -83,6 +83,7 @@ export const AlgebraConfig: DexConfigMap = { uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', deployer: '0x6dd3fb9653b10e806650f107c3b5a0a6ff974f65', version: 'v1.9', + forceRPC: true, }, }, }; From 052ab5d66ae101b59db362b3b8c5ccaa542f4c00 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 15 Nov 2023 10:45:23 +0100 Subject: [PATCH 629/833] do not log if fallback involved --- src/dex/algebra/algebra.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 2a20eeac7..4788e5e72 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -389,9 +389,11 @@ export class Algebra extends SimpleExchange implements IDex { side: SwapSide, pool: IAlgebraEventPool, ): Promise | null> { - this.logger.warn( - `fallback to rpc for ${from.address}_${to.address}_${pool.name}_${pool.poolAddress} pool(s)`, - ); + if (!this.config.forceRPC) { + this.logger.warn( + `fallback to rpc for ${from.address}_${to.address}_${pool.name}_${pool.poolAddress} pool(s)`, + ); + } const unitVolume = getBigIntPow( (side === SwapSide.SELL ? from : to).decimals, From aab175e37a77db7dc5691903f782abe1123825c2 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 15 Nov 2023 10:46:31 +0100 Subject: [PATCH 630/833] 2.42.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cfca9f5fe..db1dd2043 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.10", + "version": "2.42.11", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From ad701e43d06d890bfcd3ff5d0e0f489ac79acb79 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 15 Nov 2023 12:47:16 +0200 Subject: [PATCH 631/833] fix: acc to review --- src/dex/dexalot/dexalot.ts | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 913548434..06ba02634 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -581,20 +581,20 @@ export class Dexalot extends SimpleExchange implements IDex { const makerToken = normalizedDestToken; const takerToken = normalizedSrcToken; - const slippageBps = - side === SwapSide.SELL - ? BigNumber(1) - .minus(options.slippageFactor) - .multipliedBy(10000) - .toFixed(0) - : options.slippageFactor.minus(1).multipliedBy(10000).toFixed(0); + const isSell = side === SwapSide.SELL; + const isBuy = side === SwapSide.BUY; + + const slippageBps = isSell + ? BigNumber(1) + .minus(options.slippageFactor) + .multipliedBy(10000) + .toFixed(0) + : options.slippageFactor.minus(1).multipliedBy(10000).toFixed(0); const rfqParams = { makerAsset: ethers.utils.getAddress(makerToken.address), takerAsset: ethers.utils.getAddress(takerToken.address), - makerAmount: - side === SwapSide.BUY ? optimalSwapExchange.destAmount : undefined, - takerAmount: - side === SwapSide.SELL ? optimalSwapExchange.srcAmount : undefined, + makerAmount: isBuy ? optimalSwapExchange.destAmount : undefined, + takerAmount: isSell ? optimalSwapExchange.srcAmount : undefined, userAddress: options.txOrigin, chainid: this.network, partner: options.partner, @@ -627,7 +627,7 @@ export class Dexalot extends SimpleExchange implements IDex { order.takerAsset.toLowerCase() === takerToken.address, `QuoteData takerAsset=${order.takerAsset} is different from Paraswap takerAsset=${takerToken.address}`, ); - if (side === SwapSide.SELL) { + if (isSell) { assert( order.takerAmount === optimalSwapExchange.srcAmount, `QuoteData takerAmount=${order.takerAmount} is different from Paraswap srcAmount=${optimalSwapExchange.srcAmount}`, @@ -646,7 +646,7 @@ export class Dexalot extends SimpleExchange implements IDex { let isFailOnSlippage = false; let slippageErrorMessage = ''; - if (side === SwapSide.SELL) { + if (isSell) { if ( BigInt(order.makerAmount) < BigInt( @@ -685,7 +685,7 @@ export class Dexalot extends SimpleExchange implements IDex { let isTooStrictSlippage = false; if ( isFailOnSlippage && - side === SwapSide.SELL && + isSell && new BigNumber(1) .minus(slippageFactor) .lt(DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION) @@ -693,7 +693,7 @@ export class Dexalot extends SimpleExchange implements IDex { isTooStrictSlippage = true; } else if ( isFailOnSlippage && - side === SwapSide.BUY && + isBuy && slippageFactor .minus(1) .lt(DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION) From 283df31d175f1733cf500bb3b4689c54242240bb Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 15 Nov 2023 13:23:26 +0200 Subject: [PATCH 632/833] fix: acc to review --- src/dex/swaap-v2/constants.ts | 2 -- src/dex/swaap-v2/swaap-v2.ts | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/dex/swaap-v2/constants.ts b/src/dex/swaap-v2/constants.ts index c438b08c7..512481fb2 100644 --- a/src/dex/swaap-v2/constants.ts +++ b/src/dex/swaap-v2/constants.ts @@ -30,8 +30,6 @@ export const SWAAP_429_TTL_S = 60 * 60 * 1; // 1 hour export const SWAAP_POOL_RESTRICT_TTL_S = 60 * 30; // 30 minutes -export const SWAAP_RESTRICTED_CACHE_KEY = 'restricted'; - export const GAS_COST_ESTIMATION = 170_000; export const BATCH_SWAP_SELECTOR = '0x945bcec9'; diff --git a/src/dex/swaap-v2/swaap-v2.ts b/src/dex/swaap-v2/swaap-v2.ts index aa9472748..2bb083847 100644 --- a/src/dex/swaap-v2/swaap-v2.ts +++ b/src/dex/swaap-v2/swaap-v2.ts @@ -29,7 +29,6 @@ import { SwaapV2APIParameters, SwaapV2QuoteError, TokensMap, - SwaapV2NotificationRequest, SwaapV2NotificationResponse, } from './types'; import { SimpleExchange } from '../simple-exchange'; @@ -53,7 +52,6 @@ import { SWAAP_429_TTL_S, SWAAP_RFQ_TOKENS_ENDPOINT, SWAAP_POOL_RESTRICT_TTL_S, - SWAAP_RESTRICTED_CACHE_KEY, SWAAP_RFQ_API_TOKENS_POLLING_INTERVAL_MS, SWAAP_RFQ_TOKENS_CACHES_TTL_S, SWAAP_PRICES_CACHE_KEY, From 0db403deb5e545913e7ce4a10ef2defd51600ed6 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 15 Nov 2023 16:31:18 +0200 Subject: [PATCH 633/833] fix: acc to review --- src/dex/swaap-v2/swaap-v2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/swaap-v2/swaap-v2.ts b/src/dex/swaap-v2/swaap-v2.ts index 2bb083847..635afc71c 100644 --- a/src/dex/swaap-v2/swaap-v2.ts +++ b/src/dex/swaap-v2/swaap-v2.ts @@ -643,7 +643,7 @@ export class SwaapV2 extends SimpleExchange implements IDex { this.runtimeMMsRestrictHashMapKey, poolIdentifier, ); - const wasNotRestricted = createdAt == null; + const wasNotRestricted = createdAt === null; if (wasNotRestricted) { return false; } From 874d2c4345477cad12a8bb05506ced4aae26ade7 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 15 Nov 2023 18:54:42 +0200 Subject: [PATCH 634/833] 2.42.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index db1dd2043..7190d4a5e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.11", + "version": "2.42.12", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From ed6797809b6e2061832a3d297db0a96e59837ab0 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 15 Nov 2023 19:17:35 +0200 Subject: [PATCH 635/833] 2.42.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7190d4a5e..215b70d29 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.12", + "version": "2.42.13", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 733f02202927ed693a7c748ffe6b352c18619741 Mon Sep 17 00:00:00 2001 From: cicixxue Date: Wed, 15 Nov 2023 19:30:02 -0500 Subject: [PATCH 636/833] update rate-fetchers --- src/dex/hashflow/hashflow-e2e.test.ts | 8 ++++---- src/dex/hashflow/rate-fetcher.ts | 8 +++----- src/dex/hashflow/types.ts | 7 +++---- src/lib/fetcher/fetcher.ts | 14 +++++++------- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/dex/hashflow/hashflow-e2e.test.ts b/src/dex/hashflow/hashflow-e2e.test.ts index abd15126f..a4e001c59 100644 --- a/src/dex/hashflow/hashflow-e2e.test.ts +++ b/src/dex/hashflow/hashflow-e2e.test.ts @@ -1,15 +1,15 @@ import dotenv from 'dotenv'; dotenv.config(); -import { testE2E } from '../../../tests/utils-e2e'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { - Tokens, Holders, NativeTokenSymbols, + Tokens, } from '../../../tests/constants-e2e'; -import { Network, ContractMethod, SwapSide } from '../../constants'; -import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { testE2E } from '../../../tests/utils-e2e'; import { generateConfig } from '../../config'; +import { ContractMethod, Network, SwapSide } from '../../constants'; // Give time for rate fetcher to fill the cache const sleepMs = 3000; diff --git a/src/dex/hashflow/rate-fetcher.ts b/src/dex/hashflow/rate-fetcher.ts index 1b58de149..2df301a41 100644 --- a/src/dex/hashflow/rate-fetcher.ts +++ b/src/dex/hashflow/rate-fetcher.ts @@ -30,7 +30,6 @@ export class RateFetcher { this.pricesCacheTTL = config.rateConfig.pricesCacheTTLSecs; this.marketMakersCacheKey = config.rateConfig.marketMakersCacheKey; this.marketMakersCacheTTL = config.rateConfig.marketMakersCacheTTLSecs; - this.marketMakersFetcher = new Fetcher( dexHelper.httpRequest, { @@ -69,10 +68,9 @@ export class RateFetcher { ); } - const prices = await dexHelper.httpRequest.request({ - ...options, - params: { ...options.params, marketMakers: filteredMarketMakers }, - }); + options.params.marketMakers = filteredMarketMakers; + + const prices = await dexHelper.httpRequest.request(options); return prices; }, diff --git a/src/dex/hashflow/types.ts b/src/dex/hashflow/types.ts index 9d73c34c4..562458465 100644 --- a/src/dex/hashflow/types.ts +++ b/src/dex/hashflow/types.ts @@ -1,11 +1,10 @@ -import { QuoteData } from '@hashflow/taker-js/dist/types/common'; +import { Chain, QuoteData } from '@hashflow/taker-js/dist/types/common'; import { RequestHeaders } from '../../dex-helper'; export type HashflowData = { mm: string; quoteData?: QuoteData; signature?: string; - gasEstimate?: number; }; export type DexParams = { @@ -29,7 +28,6 @@ export class SlippageCheckError extends Error {} export type HashflowRatesLevel = { pair: Record; levels: Array>; - includesFees: boolean; }; export type HashflowMarketMakersResponse = { @@ -38,7 +36,8 @@ export type HashflowMarketMakersResponse = { export type HashflowRatesResponse = { status: string; - networkId: string; + baseChain: Chain; + quoteChain: Chain; levels: Record>; }; diff --git a/src/lib/fetcher/fetcher.ts b/src/lib/fetcher/fetcher.ts index 3b856fdea..449a368df 100644 --- a/src/lib/fetcher/fetcher.ts +++ b/src/lib/fetcher/fetcher.ts @@ -100,12 +100,12 @@ export class Fetcher { results.map(result => { if (!(result instanceof Error || result instanceof SkippingRequest)) { - // this.logger.info( - // 'Results Data:', - // JSON.stringify((result as any).data) - // .replace(/(?:\r\n|\r|\n)/g, ' ') - // .substring(0, 1000), - // ); + this.logger.info( + 'Results Data:', + JSON.stringify((result as any).data) + .replace(/(?:\r\n|\r|\n)/g, ' ') + .substring(0, 1000), + ); } }); @@ -142,7 +142,7 @@ export class Fetcher { const reqInfo = this.requests[i]; const info = reqInfo.info; const options = reqInfo.info.requestOptions; - // this.logger.debug(`(${options.url}) received new data`); + this.logger.debug(`(${options.url}) received new data`); try { const parsedData = info.caster(response.data); From 43acfb9cd7c246c47560f7540b392fe3e6d84b7e Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Thu, 16 Nov 2023 15:06:18 +0100 Subject: [PATCH 637/833] 2.42.14-algebra-bugfix-missed-created-pools.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 215b70d29..d8c837754 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.13", + "version": "2.42.14-algebra-bugfix-missed-created-pools.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 52a18ffa9a092032be64774919e698130db47120 Mon Sep 17 00:00:00 2001 From: David Bouba Date: Thu, 16 Nov 2023 17:43:42 +0100 Subject: [PATCH 638/833] feature: updated swaap-v2 gas estimate --- src/dex/swaap-v2/constants.ts | 4 +++- src/dex/swaap-v2/stable-coins.ts | 26 ++++++++++++++++++++++++++ src/dex/swaap-v2/swaap-v2.ts | 20 +++++++++++++++++--- src/dex/swaap-v2/utils.ts | 19 ++++++++++++++++++- 4 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 src/dex/swaap-v2/stable-coins.ts diff --git a/src/dex/swaap-v2/constants.ts b/src/dex/swaap-v2/constants.ts index 512481fb2..4e9f6f996 100644 --- a/src/dex/swaap-v2/constants.ts +++ b/src/dex/swaap-v2/constants.ts @@ -30,7 +30,9 @@ export const SWAAP_429_TTL_S = 60 * 60 * 1; // 1 hour export const SWAAP_POOL_RESTRICT_TTL_S = 60 * 30; // 30 minutes -export const GAS_COST_ESTIMATION = 170_000; +export const STABLE_SWAP_GAS_COST_ESTIMATION = 105_000; + +export const VOLATILE_SWAP_GAS_COST_ESTIMATION = 135_000; export const BATCH_SWAP_SELECTOR = '0x945bcec9'; diff --git a/src/dex/swaap-v2/stable-coins.ts b/src/dex/swaap-v2/stable-coins.ts new file mode 100644 index 000000000..f1c10831f --- /dev/null +++ b/src/dex/swaap-v2/stable-coins.ts @@ -0,0 +1,26 @@ +import { Token } from '../../../src/types'; +import { Network } from '../../../src/constants'; + +// addresses must be consistant with utils.normalizeTokenAddress +export const STABLE_COINS: { + [network: number]: { [symbol: string]: boolean }; +} = { + [Network.MAINNET]: { + '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': true, // USDT + '0xdac17f958d2ee523a2206206994597c13d831ec7': true, // USDC + '0x6b175474e89094c44da98b954eedeac495271d0f': true, // DAI + '0x853d955acef822db058eb8505911ed77f175b99e': true, // FRAX + }, + [Network.POLYGON]: { + '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359': true, // USDC + '0x2791bca1f2de4661ed88a30c99a7a9449aa84174': true, // USDC.e + '0xc2132d05d31c914a87c6611c10748aeb04b58e8f': true, // USDT + '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063': true, // DAI + }, + [Network.ARBITRUM]: { + '0xaf88d065e77c8cc2239327c5edb3a432268e5831': true, // USDC + '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8': true, // USDC.e + '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9': true, // USDT + '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1': true, // DAI + }, +}; diff --git a/src/dex/swaap-v2/swaap-v2.ts b/src/dex/swaap-v2/swaap-v2.ts index 635afc71c..569cbcdcc 100644 --- a/src/dex/swaap-v2/swaap-v2.ts +++ b/src/dex/swaap-v2/swaap-v2.ts @@ -45,7 +45,8 @@ import { SWAAP_RFQ_QUOTE_ENDPOINT, SWAAP_RFQ_API_PRICES_POLLING_INTERVAL_MS, SWAAP_RFQ_PRICES_CACHES_TTL_S, - GAS_COST_ESTIMATION, + STABLE_SWAP_GAS_COST_ESTIMATION, + VOLATILE_SWAP_GAS_COST_ESTIMATION, BATCH_SWAP_SELECTOR, CALLER_SLOT, SWAAP_403_TTL_S, @@ -62,7 +63,12 @@ import { SWAAP_BANNED_CODE, SWAAP_NOTIFY_ENDPOINT, } from './constants'; -import { getPoolIdentifier, normalizeTokenAddress, getPairName } from './utils'; +import { + getPoolIdentifier, + normalizeTokenAddress, + getPairName, + isStablePair, +} from './utils'; import { Method } from '../../dex-helper/irequest-wrapper'; import { SlippageCheckError, @@ -404,8 +410,16 @@ export class SwaapV2 extends SimpleExchange implements IDex { return null; } + const gasCost = isStablePair( + this.network, + normalizedSrcToken.address, + normalizedDestToken.address, + ) + ? STABLE_SWAP_GAS_COST_ESTIMATION + : VOLATILE_SWAP_GAS_COST_ESTIMATION; + return { - gasCost: GAS_COST_ESTIMATION, + gasCost: gasCost, exchange: this.dexKey, data: {}, prices, diff --git a/src/dex/swaap-v2/utils.ts b/src/dex/swaap-v2/utils.ts index 9790aa7d4..32bdcbb39 100644 --- a/src/dex/swaap-v2/utils.ts +++ b/src/dex/swaap-v2/utils.ts @@ -1,5 +1,7 @@ -import { Address } from '../../types'; +import { Address, Token } from '../../types'; import { ETHER_ADDRESS, NULL_ADDRESS } from '../../constants'; +import { Network } from '../../../src/constants'; +import { STABLE_COINS } from './stable-coins'; export const getIdentifierPrefix = ( dexKey: string, @@ -27,3 +29,18 @@ export const normalizeTokenAddress = (address: string): string => { ? NULL_ADDRESS : address.toLowerCase(); }; + +export const isStablePair = ( + network: Network, + normalizedSrcTokenAddress: string, + normalizedDestTokenAddress: string, +): boolean => { + const networkStableCoins = STABLE_COINS[network]; + if (networkStableCoins == undefined) { + return false; + } + return ( + networkStableCoins[normalizedSrcTokenAddress] === true && + networkStableCoins[normalizedDestTokenAddress] === true + ); +}; From c63c74f82a5494bc1d35fcb7011386a4c5440361 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Mon, 20 Nov 2023 15:44:07 +0200 Subject: [PATCH 639/833] add script to find broken block handling --- src/dex/algebra/scripts/validate-state.ts | 292 ++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 src/dex/algebra/scripts/validate-state.ts diff --git a/src/dex/algebra/scripts/validate-state.ts b/src/dex/algebra/scripts/validate-state.ts new file mode 100644 index 000000000..bfe7c036c --- /dev/null +++ b/src/dex/algebra/scripts/validate-state.ts @@ -0,0 +1,292 @@ +/* eslint-disable no-console */ +import dotenv from 'dotenv'; +dotenv.config(); + +import { Network } from '../../../constants'; +import { DummyDexHelper } from '../../../dex-helper'; +import { Algebra } from '../algebra'; +import { uint256ToBigInt } from '../../../lib/decoders'; +import { + DecodedStateMultiCallResultWithRelativeBitmapsV1_9, + PoolState_v1_9, +} from '../types'; +import { decodeStateMultiCallResultWithRelativeBitmapsV1_9 } from '../utils'; +import { MultiCallParams, MultiWrapper } from '../../../lib/multi-wrapper'; +import Web3 from 'web3'; +import multiABIV2 from '../../../abi/multi-v2.json'; +import ERC20ABI from '../../../abi/erc20.json'; +import { getLogger } from '../../../lib/log4js'; +import { Interface } from 'ethers/lib/utils'; +import { AbiItem } from 'web3-utils'; +import AlgebraStateMulticallABI from '../../../abi/algebra/AlgebraStateMulticall.abi.json'; +import { TICK_BITMAP_TO_USE, TICK_BITMAP_BUFFER } from '../constants'; +import { BlockHeader } from 'web3-eth'; +import { ethers } from 'ethers'; + +// public RPC, replace to RPC with archive node +const web3Provider = new Web3(''); + +// pool and tokens for specific broken tx - 0x9a296a13f7c5eb8ce838e15ecbe3888e8998a14803a1ec46838611e1ff118d6e +const factoryAddress = '0x1a3c9b1d2f0529d97f2afc5136cc23e58f1fd35b'; +const poolAddress = '0xb1026b8e7276e7ac75410f1fcbbe21796e8f7526'; +const srcToken = { + address: `0x82af49447d8a07e3bd95bd0d56f35241523fbab1`, + decimals: 18, +}; +const destToken = { + address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831', + decimals: 6, +}; +const blockHeaders: Record = {}; + +const multiContract = new web3Provider.eth.Contract( + multiABIV2 as any, + '0x7eCfBaa8742fDf5756DAC92fbc8b90a19b8815bF', +); +const stateMultiContract = new web3Provider.eth.Contract( + AlgebraStateMulticallABI as AbiItem[], + '0x2cB568442a102dF518b3D37CBD0d2884523C940B', +); + +const multiWrapper = new MultiWrapper(multiContract, getLogger(`Ticks`)); +const erc20Interface = new Interface(ERC20ABI); + +function getBitmapRangeToRequest() { + return TICK_BITMAP_TO_USE + TICK_BITMAP_BUFFER; +} + +async function _fetchPoolState_v1_9SingleStep( + blockNumber: number, +): Promise< + [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmapsV1_9] +> { + const callData: MultiCallParams< + bigint | DecodedStateMultiCallResultWithRelativeBitmapsV1_9 + >[] = [ + { + target: srcToken.address, + callData: erc20Interface.encodeFunctionData('balanceOf', [poolAddress]), + decodeFunction: uint256ToBigInt, + }, + { + target: destToken.address, + callData: erc20Interface.encodeFunctionData('balanceOf', [poolAddress]), + decodeFunction: uint256ToBigInt, + }, + { + target: stateMultiContract.options.address, + callData: stateMultiContract.methods + .getFullStateWithRelativeBitmaps( + factoryAddress, + srcToken.address, + destToken.address, + getBitmapRangeToRequest(), + getBitmapRangeToRequest(), + ) + .encodeABI(), + decodeFunction: decodeStateMultiCallResultWithRelativeBitmapsV1_9, + }, + ]; + + const [resBalance0, resBalance1, resState] = await multiWrapper.tryAggregate< + bigint | DecodedStateMultiCallResultWithRelativeBitmapsV1_9 + >(false, callData, blockNumber, multiWrapper.defaultBatchSize, false); + + const [balance0, balance1, _state] = [ + resBalance0.returnData, + resBalance1.returnData, + resState.returnData, + ] as [bigint, bigint, DecodedStateMultiCallResultWithRelativeBitmapsV1_9]; + + return [balance0, balance1, _state]; +} + +function preprocessField(value: any): string { + if ( + typeof value === 'bigint' || + typeof value === 'number' || + ethers.BigNumber.isBigNumber(value) + ) { + return value.toString(); + } + return value; +} + +function compareAndLogDifferences( + obj1: T, + obj2: Y, + keyNames: Array, + checkEachKey = false, +) { + let isValid = true; + let keys = keyNames; + + if (checkEachKey) { + // find common keys + const keys1 = Object.keys(obj1); + const keys2 = new Set(Object.keys(obj2)); + keys = keys1.filter(key => keys2.has(key)) as Array; + } + + for (let fieldName of keys) { + const value1 = preprocessField(obj1[fieldName]); + const value2 = preprocessField(obj2[fieldName]); + + if (value1 !== value2) { + console.log( + `${fieldName.toString()} mismatch: actual: ${value1} vs pool: ${value2}`, + ); + isValid = false; + } + } + + return isValid; +} + +async function isPoolStateEqualToReal( + state: PoolState_v1_9, + blockNumber: number, +) { + const [balance0, balance1, contractState] = + await _fetchPoolState_v1_9SingleStep(blockNumber); + + const isValidBalances = compareAndLogDifferences( + state, + { balance0, balance1, ...contractState }, + ['balance0', 'balance1', 'liquidity', 'tickSpacing'], + ); + + const isValidGlobalState = compareAndLogDifferences( + state.globalState, + contractState.globalState, + // can check only for one of them, because they are directly co-related + ['price', 'tick'], + ); + + const isValidTickBitmap = compareAndLogDifferences( + state.tickBitmap, + contractState.tickBitmap, + [], + true, + ); + + let isValidTicks = true; + for (let tick of contractState.ticks) { + const stateTick = state?.ticks[tick.index]; + + const isValidTick = compareAndLogDifferences(stateTick, tick.value, [ + 'liquidityGross', + 'liquidityNet', + // next fields doesn't affect pricing, so skip checks + // 'initialized', + // 'secondsOutside', + // 'secondsPerLiquidityOutsideX128', + // 'tickCumulativeOutside' + ]); + + if (isValidTicks && !isValidTick) { + isValidTicks = false; + } + } + + return ( + isValidBalances && isValidGlobalState && isValidTicks && isValidTickBitmap + ); +} + +async function checkPoolStateForBlockRange( + startBlockNumber: number, + endBlockNumber: number, +): Promise { + const network = Network.ARBITRUM; + const dexKey = 'CamelotV3'; + const dexHelper = new DummyDexHelper(network); + + const algebra = new Algebra(network, dexKey, dexHelper); + const pool = await algebra.getPool( + srcToken.address, + destToken.address, + startBlockNumber, + ); + + const logsToDispatch = await dexHelper.provider.getLogs({ + fromBlock: startBlockNumber, + toBlock: endBlockNumber, + address: poolAddress, + }); + + console.log(logsToDispatch.length); + + // group logs by block number + const logsByBlockNumber: Record = {}; + for (let log of logsToDispatch) { + if (!logsByBlockNumber[log.blockNumber]) { + logsByBlockNumber[log.blockNumber] = []; + } + logsByBlockNumber[log.blockNumber].push(log); + } + + const sortedBlocks = Object.keys(logsByBlockNumber) + .map(Number) + .sort((a, b) => Number(a) - Number(b)); + + for (let blockNumber of sortedBlocks) { + if (!blockHeaders[blockNumber]) { + blockHeaders[blockNumber] = await dexHelper.web3Provider.eth.getBlock( + blockNumber, + ); + } + + await pool?.update(logsByBlockNumber[blockNumber], { + [blockNumber]: blockHeaders[blockNumber], + }); + } + + const state = pool?.getState(startBlockNumber) as PoolState_v1_9; + return isPoolStateEqualToReal(state, endBlockNumber); +} + +async function findBreakingBlock(startBlock: number, endBlock: number) { + let left = startBlock; + let right = endBlock; + + // If the state is valid at the start, then there's no breaking block in the range + if (await checkPoolStateForBlockRange(left, right)) { + return -1; // Indicates no breaking block found + } + + while (left <= right) { + const mid = left + Math.floor((right - left) / 2); + const isValid = await checkPoolStateForBlockRange(startBlock, mid); + + if (isValid) { + // If the state is valid up to mid, the issue must be in the second half + left = mid + 1; + } else { + // If the state is not valid up to mid, the issue is in the first half + // But we need to check if mid is the first occurrence of the issue + if ( + mid === startBlock || + (await checkPoolStateForBlockRange(startBlock, mid - 1)) + ) { + return mid; // Found the breaking block + } + right = mid - 1; + } + } + + return -1; // Should not reach here if there's a breaking block +} + +async function main() { + // use findBreakingBlock to find the block where the state is broken + // console.log(await findBreakingBlock(startBlockNumber, endBlockNumber)); + // previously broken block 150502863 + // console.log(await checkPoolStateForBlockRange(150502853, 150502873)); + // console.log(await checkPoolStateForBlockRange(152087800, 152287800)); + // console.log(await checkPoolStateForBlockRange(152100945, 152100947)); +} + +main() + .then(() => console.log('Done')) + .catch(e => console.error(e)); From de562f906c39e828d33d8f02bf646480dd037de1 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Mon, 20 Nov 2023 15:44:40 +0200 Subject: [PATCH 640/833] algebra: fix incorrect price calculation --- src/dex/algebra/lib/AlgebraMath.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/dex/algebra/lib/AlgebraMath.ts b/src/dex/algebra/lib/AlgebraMath.ts index c6efbd6c4..c6f24cecb 100644 --- a/src/dex/algebra/lib/AlgebraMath.ts +++ b/src/dex/algebra/lib/AlgebraMath.ts @@ -588,7 +588,7 @@ class AlgebraMathClass { // equivalent of PriceMovementMath.movePriceTowardsTarget const result = SwapMath.computeSwapStep( - poolState.globalState.price, + currentPrice, zeroToOne == step.nextTickPrice < newSqrtPriceX96 ? newSqrtPriceX96 : step.nextTickPrice, @@ -651,6 +651,18 @@ class AlgebraMathClass { } } + _require( + currentPrice == newSqrtPriceX96, + `LOGIC ERROR: calculated currentPrice and price from event ('newSqrtPriceX96') should always be equal at the end`, + { currentPrice, newSqrtPriceX96 }, + ); + + _require( + currentTick == newTick, + `LOGIC ERROR: calculated currentTick and tick from event ('newTick') should always be equal at the end`, + { currentTick, newTick }, + ); + let [amount0, amount1] = zeroToOne == cache.exactInput // the amount to provide could be less then initially specified (e.g. reached limit) ? [cache.amountRequiredInitial - amountRequired, cache.amountCalculated] // the amount to get could be less then initially specified (e.g. reached limit) From f65f05d7bef548c861b1f3becb2798f694907255 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Mon, 20 Nov 2023 15:46:08 +0200 Subject: [PATCH 641/833] 2.42.14-algebra-price-fix.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 215b70d29..878fb436f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.13", + "version": "2.42.14-algebra-price-fix.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 34b272f2d09f397140d18eadee4d2624a91422e0 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 20 Nov 2023 22:34:55 +0100 Subject: [PATCH 642/833] more logs --- src/dex/algebra/algebra.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 57f479891..3c895a788 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -267,7 +267,7 @@ export class Algebra extends SimpleExchange implements IDex { ); } - this.logger.trace(`starting to listen to new pool: ${key}`); + this.logger.info(`starting to listen to new pool: ${key}`); pool = pool || new this.AlgebraPoolImplem( @@ -296,10 +296,13 @@ export class Algebra extends SimpleExchange implements IDex { }, }); + this.logger.info(`pool ${key} initialised`); + if (this.newlyCreatedPoolKeys.has(key)) { this.newlyCreatedPoolKeys.delete(key); } } catch (e) { + this.logger.info(`pool ${key} failed to initialise`, e); if (e instanceof Error && e.message.endsWith('Pool does not exist')) { /* protection against 2 race conditions From 3528e30eaa778116693060c05caf489e858e3cd0 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 20 Nov 2023 22:36:43 +0100 Subject: [PATCH 643/833] 2.42.14-algebra-bugfix-missed-created-pools.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d8c837754..af1f9ca3d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.14-algebra-bugfix-missed-created-pools.0", + "version": "2.42.14-algebra-bugfix-missed-created-pools.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 773c2733fbd4d3fb331cd856c5b38c1e550672ba Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 20 Nov 2023 23:36:32 +0100 Subject: [PATCH 644/833] Revert "more logs" This reverts commit 34b272f2d09f397140d18eadee4d2624a91422e0. --- src/dex/algebra/algebra.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 3c895a788..57f479891 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -267,7 +267,7 @@ export class Algebra extends SimpleExchange implements IDex { ); } - this.logger.info(`starting to listen to new pool: ${key}`); + this.logger.trace(`starting to listen to new pool: ${key}`); pool = pool || new this.AlgebraPoolImplem( @@ -296,13 +296,10 @@ export class Algebra extends SimpleExchange implements IDex { }, }); - this.logger.info(`pool ${key} initialised`); - if (this.newlyCreatedPoolKeys.has(key)) { this.newlyCreatedPoolKeys.delete(key); } } catch (e) { - this.logger.info(`pool ${key} failed to initialise`, e); if (e instanceof Error && e.message.endsWith('Pool does not exist')) { /* protection against 2 race conditions From 1d519e4bd93f048ca513dd4bfdfbe95a05352fb7 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 20 Nov 2023 23:39:24 +0100 Subject: [PATCH 645/833] remove leader only flag as non existing pool as logic does not reach there --- src/dex/algebra/algebra.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 57f479891..aa0ee3838 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -317,15 +317,12 @@ export class Algebra extends SimpleExchange implements IDex { e, ); - // allowing only master/leader node to alter distant cache to reduce risk of race conditions - if (!this.dexHelper.config.isSlave) { - // no need to await we want the set to have the pool key but it's not blocking - this.dexHelper.cache.zadd( - this.notExistingPoolSetKey, - [Date.now(), key], - 'NX', - ); - } + // no need to await we want the set to have the pool key but it's not blocking + this.dexHelper.cache.zadd( + this.notExistingPoolSetKey, + [Date.now(), key], + 'NX', + ); // Pool does not exist for this pair, so we can set it to null // to prevent more requests for this pool From 79793a43334aa35c07a05dd9d1687cd3493bbe74 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 20 Nov 2023 23:44:46 +0100 Subject: [PATCH 646/833] 2.42.14-algebra-bugfix-missed-created-pools.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index af1f9ca3d..a9fc52218 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.14-algebra-bugfix-missed-created-pools.1", + "version": "2.42.14-algebra-bugfix-missed-created-pools.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 6bea21527064470ed1b27f82313dab630296511f Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 21 Nov 2023 10:55:50 +0200 Subject: [PATCH 647/833] 2.42.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 878fb436f..cdf92d74b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.14-algebra-price-fix.0", + "version": "2.42.14", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 70e2c7d39542da2c9829716090d73e84085d9b40 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 21 Nov 2023 11:01:10 +0100 Subject: [PATCH 648/833] remove unsafe cleanup --- src/dex/algebra/algebra.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index aa0ee3838..a145f03b0 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -308,9 +308,8 @@ export class Algebra extends SimpleExchange implements IDex { */ if (this.newlyCreatedPoolKeys.has(key)) { this.logger.warn( - `[block=${blockNumber}][Pool=${key}] newly created pool failed to initialise`, + `[block=${blockNumber}][Pool=${key}] newly created pool failed to initialise, trying on next request`, ); - this.newlyCreatedPoolKeys.delete(key); } else { this.logger.info( `[block=${blockNumber}][Pool=${key}] pool failed to initialize so it's marked as non existing`, From 4b7eae554790eb3a55c942c4b546911ea4026c5a Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 21 Nov 2023 11:06:24 +0100 Subject: [PATCH 649/833] 2.42.15-algebra-bugfix-missed-created-pools.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cdf92d74b..d98c796e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.14", + "version": "2.42.15-algebra-bugfix-missed-created-pools.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e442127b51a6ebb5eeda00a75735b58d5a8ea508 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 21 Nov 2023 12:56:06 +0200 Subject: [PATCH 650/833] algebra: add condition log & combine _require --- src/dex/algebra/lib/AlgebraMath.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/dex/algebra/lib/AlgebraMath.ts b/src/dex/algebra/lib/AlgebraMath.ts index c6f24cecb..fa1dea21a 100644 --- a/src/dex/algebra/lib/AlgebraMath.ts +++ b/src/dex/algebra/lib/AlgebraMath.ts @@ -652,15 +652,10 @@ class AlgebraMathClass { } _require( - currentPrice == newSqrtPriceX96, - `LOGIC ERROR: calculated currentPrice and price from event ('newSqrtPriceX96') should always be equal at the end`, - { currentPrice, newSqrtPriceX96 }, - ); - - _require( - currentTick == newTick, - `LOGIC ERROR: calculated currentTick and tick from event ('newTick') should always be equal at the end`, - { currentTick, newTick }, + currentPrice === newSqrtPriceX96 && currentTick === newTick, + 'LOGIC ERROR: calculated (currentPrice,currentTick) and (newSqrtPriceX96, newTick) from event should always be equal at the end', + { currentPrice, newSqrtPriceX96, currentTick, newTick }, + 'currentPrice === newSqrtPriceX96 && currentTick === newTick', ); let [amount0, amount1] = From 57c4824987990d770c46e01710ed38962bb17ead Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 21 Nov 2023 12:56:31 +0200 Subject: [PATCH 651/833] 2.42.15 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cdf92d74b..c05650aa4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.14", + "version": "2.42.15", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 910179a4410bff239b554a8916d863f965b4a845 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Wed, 22 Nov 2023 10:56:54 +0100 Subject: [PATCH 652/833] 2.42.16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c05650aa4..f6d5694b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.15", + "version": "2.42.16", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From d636818cf8ef0101f9cb1ea2dcfd2d912e0dc917 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 23 Nov 2023 19:55:40 +0200 Subject: [PATCH 653/833] fix: refactor tests --- src/dex/wombat/wombat-e2e.test.ts | 348 +++++++----------------------- 1 file changed, 74 insertions(+), 274 deletions(-) diff --git a/src/dex/wombat/wombat-e2e.test.ts b/src/dex/wombat/wombat-e2e.test.ts index 98edae4aa..14292ef71 100644 --- a/src/dex/wombat/wombat-e2e.test.ts +++ b/src/dex/wombat/wombat-e2e.test.ts @@ -11,207 +11,39 @@ import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; -// function testForNetwork( -// network: Network, -// dexKey: string, -// tokenASymbol: string, -// tokenBSymbol: string, -// tokenAAmount: string, -// tokenBAmount: string, -// nativeTokenAmount: string, -// slippage?: number | undefined, -// ) { -// const provider = new StaticJsonRpcProvider( -// generateConfig(network).privateHttpProvider, -// network, -// ); -// const tokens = Tokens[network]; -// const holders = Holders[network]; -// const nativeTokenSymbol = NativeTokenSymbols[network]; - -// const sideToContractMethods = new Map([ -// [ -// SwapSide.SELL, -// [ -// ContractMethod.simpleSwap, -// // ContractMethod.multiSwap, -// // ContractMethod.megaSwap, -// ], -// ], -// [SwapSide.BUY, [ContractMethod.simpleBuy /* ContractMethod.buy */]], -// ]); - -// describe(`${network}`, () => { -// sideToContractMethods.forEach((contractMethods, side) => -// describe(`${side}`, () => { -// 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, -// 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, -// 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, -// network, -// provider, -// undefined, -// undefined, -// undefined, -// slippage, -// ); -// }); -// }); -// }); -// }), -// ); -// }); -// } - -// describe(`${network}`, () => { -// sideToContractMethods.forEach((contractMethods, side) => -// describe(`${side}`, () => { -// 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, -// network, -// provider, -// ); -// }); -// it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { -// await testE2E( -// tokens[tokenASymbol], -// tokens[nativeTokenSymbol], -// holders[tokenASymbol], -// side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, -// side, -// dexKey, -// contractMethod, -// network, -// provider, -// ); -// }); -// it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { -// await testE2E( -// tokens[tokenASymbol], -// tokens[tokenBSymbol], -// holders[tokenASymbol], -// side === SwapSide.SELL ? tokenAAmount : tokenBAmount, -// side, -// dexKey, -// contractMethod, -// network, -// provider, -// ); -// }); -// }); -// }); -// }), -// ); -// }); -// } - -// TODO: Rewrite with testForNetwork -describe('Wombat E2E', () => { - const dexKey = 'Wombat'; - - describe('BSC', () => { - const network = Network.BSC; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const sideToContractMethods = new Map([ +type Pairs = { name: string; sellAmount: string; buyAmount: string }[][]; + +function testForNetwork( + network: Network, + dexKey: string, + pairs: Pairs, + slippage?: number | undefined, +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - ], + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, ], - [SwapSide.BUY, [ContractMethod.simpleBuy /* ContractMethod.buy */]], - ]); - - const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ - [ - { - name: 'USDC', - sellAmount: '1000000000', - buyAmount: '1000000000', - }, - { - name: 'USDT', - sellAmount: '1000000000', - buyAmount: '1000000000', - }, - ], - // [ - // { - // name: 'BNB', - // sellAmount: '1000000000000000000', - // buyAmount: '1000000000', - // }, - // { - // name: 'BNBx', - // sellAmount: '1000000000', - // buyAmount: '1000000000000000000', - // }, - // ], - ]; + ], + [SwapSide.BUY, [ContractMethod.simpleBuy /* ContractMethod.buy */]], + ]); + describe(`${network}`, () => { sideToContractMethods.forEach((contractMethods, side) => describe(`${side}`, () => { contractMethods.forEach((contractMethod: ContractMethod) => { - pairs.forEach(pair => { - describe(`${contractMethod}`, () => { + describe(`${contractMethod}`, () => { + pairs.forEach(pair => { it(`${pair[0].name} -> ${pair[1].name}`, async () => { await testE2E( tokens[pair[0].name], @@ -225,8 +57,13 @@ describe('Wombat E2E', () => { contractMethod, network, provider, + undefined, + undefined, + undefined, + slippage, ); }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { await testE2E( tokens[pair[1].name], @@ -240,6 +77,10 @@ describe('Wombat E2E', () => { contractMethod, network, provider, + undefined, + undefined, + undefined, + slippage, ); }); }); @@ -248,29 +89,48 @@ describe('Wombat E2E', () => { }), ); }); +} - describe('Arbitrum', () => { - const network = Network.ARBITRUM; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); +describe('Wombat E2E', () => { + const dexKey = 'Wombat'; - const sideToContractMethods = new Map([ + describe('BSC', () => { + const network = Network.BSC; + + const pairs: Pairs = [ [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - ], + { + name: 'USDC', + sellAmount: '1000000000', + buyAmount: '1000000000', + }, + { + name: 'USDT', + sellAmount: '1000000000', + buyAmount: '1000000000', + }, ], - [SwapSide.BUY, [ContractMethod.simpleBuy /* ContractMethod.buy */]], - ]); + // [ + // { + // name: 'BNB', + // sellAmount: '1000000000000000000', + // buyAmount: '1000000000', + // }, + // { + // name: 'BNBx', + // sellAmount: '1000000000', + // buyAmount: '1000000000000000000', + // }, + // ], + ]; - const pairs: { name: string; sellAmount: string; buyAmount: string }[][] = [ + testForNetwork(network, dexKey, pairs); + }); + + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + + const pairs: Pairs = [ [ { name: 'USDC', @@ -285,66 +145,6 @@ describe('Wombat E2E', () => { ], ]; - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - contractMethods.forEach((contractMethod: ContractMethod) => { - pairs.forEach(pair => { - describe(`${contractMethod}`, () => { - it(`${pair[0].name} -> ${pair[1].name}`, async () => { - await testE2E( - tokens[pair[0].name], - tokens[pair[1].name], - holders[pair[0].name], - side === SwapSide.SELL - ? pair[0].sellAmount - : pair[0].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - it(`${pair[1].name} -> ${pair[0].name}`, async () => { - await testE2E( - tokens[pair[1].name], - tokens[pair[0].name], - holders[pair[1].name], - side === SwapSide.SELL - ? pair[1].sellAmount - : pair[1].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }); - }); - }), - ); + testForNetwork(network, dexKey, pairs); }); - - // describe('Arbitrum', () => { - // const network = Network.ARBITRUM; - - // const tokenASymbol: string = 'USDC'; - // const tokenBSymbol: string = 'USDT'; - - // const tokenAAmount: string = '100000000'; - // const tokenBAmount: string = '100000000'; - // const nativeTokenAmount = '1000000000000000000'; - - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // nativeTokenAmount, - // ); - // }); }); From 91b601d5c6c2726dce195aa5c6a9fc500edee3fe Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 23 Nov 2023 20:06:03 +0200 Subject: [PATCH 654/833] fix: refactor test order --- src/dex/wombat/wombat-e2e.test.ts | 86 ++++++++++++++----------------- 1 file changed, 40 insertions(+), 46 deletions(-) diff --git a/src/dex/wombat/wombat-e2e.test.ts b/src/dex/wombat/wombat-e2e.test.ts index 14292ef71..61335e399 100644 --- a/src/dex/wombat/wombat-e2e.test.ts +++ b/src/dex/wombat/wombat-e2e.test.ts @@ -38,57 +38,51 @@ function testForNetwork( [SwapSide.BUY, [ContractMethod.simpleBuy /* ContractMethod.buy */]], ]); - describe(`${network}`, () => { - sideToContractMethods.forEach((contractMethods, side) => - describe(`${side}`, () => { - contractMethods.forEach((contractMethod: ContractMethod) => { + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { + contractMethods.forEach((contractMethod: ContractMethod) => { + pairs.forEach(pair => { describe(`${contractMethod}`, () => { - pairs.forEach(pair => { - it(`${pair[0].name} -> ${pair[1].name}`, async () => { - await testE2E( - tokens[pair[0].name], - tokens[pair[1].name], - holders[pair[0].name], - side === SwapSide.SELL - ? pair[0].sellAmount - : pair[0].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - undefined, - undefined, - undefined, - slippage, - ); - }); + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL ? pair[0].sellAmount : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + undefined, + undefined, + undefined, + slippage, + ); + }); - it(`${pair[1].name} -> ${pair[0].name}`, async () => { - await testE2E( - tokens[pair[1].name], - tokens[pair[0].name], - holders[pair[1].name], - side === SwapSide.SELL - ? pair[1].sellAmount - : pair[1].buyAmount, - side, - dexKey, - contractMethod, - network, - provider, - undefined, - undefined, - undefined, - slippage, - ); - }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL ? pair[1].sellAmount : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + undefined, + undefined, + undefined, + slippage, + ); }); }); }); - }), - ); - }); + }); + }), + ); } describe('Wombat E2E', () => { From 52c91cce8bcb313dc8cc9b0c3df9423daa9b9ccb Mon Sep 17 00:00:00 2001 From: Koala <142200506+koala0814@users.noreply.github.com> Date: Fri, 24 Nov 2023 18:43:33 +0800 Subject: [PATCH 655/833] add wombat native token swap support and update e2e tests --- src/dex/wombat/config.ts | 8 +- src/dex/wombat/wombat-e2e.test.ts | 123 +++++++++++++++++++--- src/dex/wombat/wombat-integration.test.ts | 10 +- src/dex/wombat/wombat.ts | 30 +++--- tests/constants-e2e.ts | 12 ++- 5 files changed, 145 insertions(+), 38 deletions(-) diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts index 6550dea74..306fda542 100644 --- a/src/dex/wombat/config.ts +++ b/src/dex/wombat/config.ts @@ -19,9 +19,9 @@ export const WombatConfig: DexConfigMap = { [Network.BASE]: { bmwAddress: '0x6521a549834F5E6d253CD2e5F4fbe4048f86cd7b', }, - [Network.OPTIMISM]: { - bmwAddress: '0x82E62f4e174E3C5e1641Df670c91Ac6Ab8541518', - }, + // [Network.OPTIMISM]: { + // bmwAddress: '0x82E62f4e174E3C5e1641Df670c91Ac6Ab8541518', + // }, }, }; @@ -59,5 +59,3 @@ export const Adapters: Record = { ], }, }; - -export const LIQUIDITY_THRESHOLD_IN_USD = 100; diff --git a/src/dex/wombat/wombat-e2e.test.ts b/src/dex/wombat/wombat-e2e.test.ts index 61335e399..b478bad7a 100644 --- a/src/dex/wombat/wombat-e2e.test.ts +++ b/src/dex/wombat/wombat-e2e.test.ts @@ -104,18 +104,18 @@ describe('Wombat E2E', () => { buyAmount: '1000000000', }, ], - // [ - // { - // name: 'BNB', - // sellAmount: '1000000000000000000', - // buyAmount: '1000000000', - // }, - // { - // name: 'BNBx', - // sellAmount: '1000000000', - // buyAmount: '1000000000000000000', - // }, - // ], + [ + { + name: 'BNB', + sellAmount: '1000000000000000000', + buyAmount: '1000000000000000000', + }, + { + name: 'BNBx', + sellAmount: '1000000000000000000', + buyAmount: '1000000000000000000', + }, + ], ]; testForNetwork(network, dexKey, pairs); @@ -137,6 +137,105 @@ describe('Wombat E2E', () => { buyAmount: '100000000', }, ], + [ + { + name: 'ETH', + sellAmount: '10000000000000000', + buyAmount: '10000000000000000', + }, + { + name: 'wstETH', + sellAmount: '10000000000000000', + buyAmount: '10000000000000000', + }, + ], + ]; + + testForNetwork(network, dexKey, pairs); + }); + + describe('Ethereum', () => { + const network = Network.MAINNET; + + const pairs: Pairs = [ + [ + { + name: 'USDC', + sellAmount: '100000000', + buyAmount: '100000000', + }, + { + name: 'USDT', + sellAmount: '100000000', + buyAmount: '100000000', + }, + ], + [ + { + name: 'ETH', + sellAmount: '1000000000000000000', + buyAmount: '1000000000000000000', + }, + { + name: 'wstETH', + sellAmount: '1000000000000000000', + buyAmount: '1000000000000000000', + }, + ], + ]; + + testForNetwork(network, dexKey, pairs); + }); + + describe('Avalanche', () => { + const network = Network.AVALANCHE; + + const pairs: Pairs = [ + [ + { + name: 'USDC', + sellAmount: '10000000', + buyAmount: '10000000', + }, + { + name: 'USDT', + sellAmount: '10000000', + buyAmount: '10000000', + }, + ], + [ + { + name: 'AVAX', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + { + name: 'sAVAX', + sellAmount: '100000000000000000000', + buyAmount: '100000000000000000000', + }, + ], + ]; + + testForNetwork(network, dexKey, pairs); + }); + + describe('Base', () => { + const network = Network.BASE; + + const pairs: Pairs = [ + [ + { + name: 'USDC', + sellAmount: '100000000', + buyAmount: '100000000', + }, + { + name: 'USDbC', + sellAmount: '100000000', + buyAmount: '100000000', + }, + ], ]; testForNetwork(network, dexKey, pairs); diff --git a/src/dex/wombat/wombat-integration.test.ts b/src/dex/wombat/wombat-integration.test.ts index 778669fa4..bca769b4c 100644 --- a/src/dex/wombat/wombat-integration.test.ts +++ b/src/dex/wombat/wombat-integration.test.ts @@ -188,11 +188,11 @@ describe('Wombat', function () { 10n * BI_POWS[tokens[destTokenSymbol].decimals], ]; - // BASE and OPTIMISM have very low liquidity currently, so we have to use very small amounts - if (network === Network.BASE || network === Network.OPTIMISM) { - amountsForSell = amountsForSell.map(a => a / 100n); - amountsForBuy = amountsForBuy.map(a => a / 100n); - } + // OPTIMISM has very low liquidity currently, so we have to use very small amounts + // if (network === Network.OPTIMISM) { + // amountsForSell = amountsForSell.map(a => a / 100n); + // amountsForBuy = amountsForBuy.map(a => a / 100n); + // } beforeAll(async () => { blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 6f097b014..98ec4d41c 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -14,7 +14,7 @@ import { } from '../../types'; import { Network } from '../../constants'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { getBigIntPow, getDexKeysWithNetwork } from '../../utils'; +import { getBigIntPow, getDexKeysWithNetwork, isETHAddress } from '../../utils'; import { IDex } from '../idex'; import { IDexHelper } from '../../dex-helper'; import { DexParams, PoolState, WombatData } from './types'; @@ -22,7 +22,7 @@ import { getLocalDeadlineAsFriendlyPlaceholder, SimpleExchange, } from '../simple-exchange'; -import { Adapters, LIQUIDITY_THRESHOLD_IN_USD, WombatConfig } from './config'; +import { Adapters, WombatConfig } from './config'; import PoolABI from '../../abi/wombat/pool.json'; import AssetABI from '../../abi/wombat/asset.json'; import ERC20ABI from '../../abi/erc20.json'; @@ -131,8 +131,8 @@ export class Wombat extends SimpleExchange implements IDex { await this.updatePoolState(); return ( await this.findPools( - srcToken.address.toLowerCase(), - destToken.address.toLowerCase(), + this.dexHelper.config.wrapETH(srcToken).address.toLowerCase(), + this.dexHelper.config.wrapETH(destToken).address.toLowerCase(), blockNumber, ) ).map(p => this.getPoolIdentifier(p)); @@ -158,8 +158,12 @@ export class Wombat extends SimpleExchange implements IDex { this.logger.error(`Missing pools for ${this.dexKey} in getPricesVolume`); return null; } - const srcTokenAddress = srcToken.address.toLowerCase(); - const destTokenAddress = destToken.address.toLowerCase(); + const srcTokenAddress = this.dexHelper.config + .wrapETH(srcToken) + .address.toLowerCase(); + const destTokenAddress = this.dexHelper.config + .wrapETH(destToken) + .address.toLowerCase(); if (srcTokenAddress === destTokenAddress) return null; const pools = ( @@ -225,7 +229,6 @@ export class Wombat extends SimpleExchange implements IDex { srcTokenAddress: Address, destTokenAddress: Address, blockNumber: number, - liquidityThresholdInUSD = 0, ): Promise { const pools: Address[] = []; for (const [poolAddress, pool] of Object.entries(this.pools)) { @@ -242,10 +245,7 @@ export class Wombat extends SimpleExchange implements IDex { state && !state.params.paused && state.asset[srcTokenAddress] && - state.asset[destTokenAddress] && - (liquidityThresholdInUSD === 0 || - (this.poolLiquidityUSD![poolAddress] && - this.poolLiquidityUSD![poolAddress] > liquidityThresholdInUSD)) + state.asset[destTokenAddress] ) { pools.push(poolAddress); } @@ -303,7 +303,7 @@ export class Wombat extends SimpleExchange implements IDex { srcToken, destToken, srcAmount, - 1 /** @todo assume slippage tolorence is 2% and set the minimum receive accordingly */, + destAmount, this.augustusAddress, getLocalDeadlineAsFriendlyPlaceholder(), ]); @@ -385,7 +385,11 @@ export class Wombat extends SimpleExchange implements IDex { limit: number, ): Promise { if (!this.poolLiquidityUSD) await this.updatePoolState(); - tokenAddress = tokenAddress.toLowerCase(); + tokenAddress = ( + isETHAddress(tokenAddress) + ? this.dexHelper.config.data.wrappedNativeTokenAddress + : tokenAddress + ).toLowerCase(); const pools: string[] = []; const poolStates: { [poolAddress: string]: DeepReadonly } = {}; for (const [poolAddress, eventPool] of Object.entries(this.pools)) { diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index f0b323ce3..3faf6748d 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -551,8 +551,8 @@ export const Tokens: { decimals: 18, }, BNBx: { - address: '0xab824b47806fea52276fef231e5e2d5fb3d4cf4e', - decimals: 9, + address: '0x1bdd3Cf7F79cfB8EdbB955f20ad99211551BA275', + decimals: 18, }, BUSD: { address: '0xe9e7cea3dedca5984780bafc599bd69add087d56', @@ -853,6 +853,10 @@ export const Tokens: { address: '0x3d9907f9a368ad0a51be60f7da3b97cf940982d8', decimals: 18, }, + wstETH: { + address: '0x5979D7b546E38E414F7E9822514be443A4800529', + decimals: 18, + }, }, [Network.OPTIMISM]: { DAI: { @@ -1109,6 +1113,7 @@ export const Holders: { FRAX: '0xEB4576fE753DAB07635c0Bb6c8f0A355e1Db5d31', frxETH: '0xf324adC872005197A6f7DAE214d3b63aa0C3625F', USDFI: '0x2E00D722e091836B39Db3e4dcE6eE51c90c5B221', + BNBx: '0xFF4606bd3884554CDbDabd9B6e25E2faD4f6fc54', }, [Network.AVALANCHE]: { AVAX: '0xD6216fC19DB775Df9774a6E33526131dA7D19a2c', @@ -1149,7 +1154,7 @@ export const Holders: { DAI: '0x07d7f291e731a41d3f0ea4f1ae5b6d920ffb3fe0', WETH: '0xc31e54c7a869b9fcbecc14363cf510d1c41fa443', USDCe: '0x62383739d68dd0f844103db8dfb05a7eded5bbe6', - USDC: '0xa843392198862f98d17e3aa1421b08f2c2020cff', + USDC: '0xb38e8c17e38363af6ebdcb3dae12e0243582891d', OHM: '0xebce5f29ff5ca9aa330ebdf7ec6b5f474bff271e', USDT: '0x5ff47d4ab75bcaff6807c81f1367abb53439883c', POPS: '0x4b78b52e7de4d8b7d367297cb8a87c1875a9d591', @@ -1166,6 +1171,7 @@ export const Holders: { ZYB: '0x3ec0eddcd1e25025077327886a78133589082fb2', WBTC: '0xd9d611c6943585bc0e18e51034af8fa28778f7da', RDNT: '0x62383739d68dd0f844103db8dfb05a7eded5bbe6', + wstETH: '0x916792f7734089470de27297903bed8a4630b26d', }, [Network.OPTIMISM]: { ETH: '0x9ef21bE1C270AA1c3c3d750F458442397fBFFCB6', From 6d72ec40487e088912a542a323064de0d08bab43 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 24 Nov 2023 13:49:13 +0100 Subject: [PATCH 656/833] univ2/rebaseTokens: add sync call everytime rebase token as srcToken --- src/dex/simple-exchange.ts | 15 ++++++-- .../uniswap-v2-e2e-avalanche.test.ts | 14 ++++++++ src/dex/uniswap-v2/uniswap-v2.ts | 35 +++++++++++++++++-- src/rebase-tokens.json | 17 +++++++++ tests/constants-e2e.ts | 7 +++- 5 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 src/rebase-tokens.json diff --git a/src/dex/simple-exchange.ts b/src/dex/simple-exchange.ts index 6a7dd302b..4d6909988 100644 --- a/src/dex/simple-exchange.ts +++ b/src/dex/simple-exchange.ts @@ -157,6 +157,7 @@ export class SimpleExchange { swapCallee: Address, spender?: Address, networkFee: NumberAsString = '0', + preCalls?: Omit, ): Promise { const approveParam = await this.getApproveSimpleParam( src, @@ -168,9 +169,17 @@ export class SimpleExchange { ).toString(); return { - callees: [...approveParam.callees, swapCallee], - calldata: [...approveParam.calldata, swapCallData], - values: [...approveParam.values, swapValue], + callees: [ + ...(preCalls?.callees || []), + ...approveParam.callees, + swapCallee, + ], + calldata: [ + ...(preCalls?.calldata || []), + ...approveParam.calldata, + swapCallData, + ], + values: [...(preCalls?.values || []), ...approveParam.values, swapValue], networkFee, }; } diff --git a/src/dex/uniswap-v2/uniswap-v2-e2e-avalanche.test.ts b/src/dex/uniswap-v2/uniswap-v2-e2e-avalanche.test.ts index 7eed0311c..3097ac917 100644 --- a/src/dex/uniswap-v2/uniswap-v2-e2e-avalanche.test.ts +++ b/src/dex/uniswap-v2/uniswap-v2-e2e-avalanche.test.ts @@ -241,6 +241,20 @@ describe('UniswapV2 E2E Avalanche', () => { provider, ); }); + + it('AMPL -> MIM', async () => { + await testE2E( + tokens.AMPL, + tokens.MIM, + holders.AMPL, + '1000000000', + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); }); describe('multiSwap', () => { diff --git a/src/dex/uniswap-v2/uniswap-v2.ts b/src/dex/uniswap-v2/uniswap-v2.ts index 134a3b40c..d49262bca 100644 --- a/src/dex/uniswap-v2/uniswap-v2.ts +++ b/src/dex/uniswap-v2/uniswap-v2.ts @@ -52,6 +52,21 @@ import { Contract } from 'web3-eth-contract'; import { UniswapV2Config, Adapters } from './config'; import { Uniswapv2ConstantProductPool } from './uniswap-v2-constant-product-pool'; import { applyTransferFee } from '../../lib/token-transfer-fee'; +import _rebaseTokens from '../../rebase-tokens.json'; + +const rebaseTokens = _rebaseTokens as { chainId: number; address: string }[]; + +const rebaseTokensSetsByChain = rebaseTokens.reduce<{ + [chainId: number]: Set; +}>((acc, curr) => { + if (!acc[curr.chainId]) { + acc[curr.chainId] = new Set(); + } + + acc[curr.chainId].add(curr.address.toLowerCase()); + + return acc; +}, {}); const DefaultUniswapV2PoolGasCost = 90 * 1000; @@ -68,7 +83,7 @@ interface UniswapV2PoolState { feeCode: number; } -const uniswapV2Iface = new Interface(uniswapV2ABI); +const uniswapV2PoolIface = new Interface(uniswapV2ABI); const erc20iface = new Interface(erc20ABI); const coder = new AbiCoder(); @@ -104,7 +119,7 @@ export class UniswapV2EventPool extends StatefulEventSubscriber number, - private iface: Interface = uniswapV2Iface, + private iface: Interface = uniswapV2PoolIface, ) { super( parentName, @@ -219,7 +234,7 @@ export class UniswapV2 protected poolGasCost: number = (UniswapV2Config[dexKey] && UniswapV2Config[dexKey][network].poolGasCost) ?? DefaultUniswapV2PoolGasCost, - protected decoderIface: Interface = uniswapV2Iface, + protected decoderIface: Interface = uniswapV2PoolIface, protected adapters = (UniswapV2Config[dexKey] && UniswapV2Config[dexKey][network].adapters) ?? Adapters[network], @@ -772,6 +787,17 @@ export class UniswapV2 side === SwapSide.SELL ? UniswapV2Functions.swap : UniswapV2Functions.buy, [src, srcAmount, destAmount, weth, pools], ); + + const maybeSyncCall = rebaseTokensSetsByChain[this.network]?.has( + src.toLowerCase(), + ) + ? { + callees: [data.pools[0].address], + calldata: [uniswapV2PoolIface.encodeFunctionData('sync')], + values: ['0'], + } + : undefined; + return this.buildSimpleParamWithoutWETHConversion( src, srcAmount, @@ -779,6 +805,9 @@ export class UniswapV2 destAmount, swapData, data.router, + data.router, + '0', + maybeSyncCall, ); } diff --git a/src/rebase-tokens.json b/src/rebase-tokens.json new file mode 100644 index 000000000..2fbef4167 --- /dev/null +++ b/src/rebase-tokens.json @@ -0,0 +1,17 @@ +[ + { + "symbol": "AMPL", + "chainId": 1, + "address": "0xd46ba6d942050d489dbd938a2c909a5d5039a161" + }, + { + "symbol": "AMPL", + "chainId": 56, + "address": "0xDB021b1B247fe2F1fa57e0A87C748Cc1E321F07F" + }, + { + "symbol": "AMPL", + "chainId": 43114, + "address": "0x027dbca046ca156de9622cd1e2d907d375e53aa7" + } +] diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index a0ea53363..96336c5e4 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -762,6 +762,10 @@ export const Tokens: { address: '0x502580fc390606b47fc3b741d6d49909383c28a9', decimals: 18, }, + AMPL: { + address: '0x027dbcA046ca156De9622cD1e2D907d375e53aa7', + decimals: 9, + }, }, [Network.ARBITRUM]: { DAI: { @@ -1115,7 +1119,7 @@ export const Holders: { HATCHY: '0x14ec295ec8def851ec6e2959df872dd24e422631', USDCe: '0x3a2434c698f8d79af1f5a9e43013157ca8b11a66', USDC: '0x0d0707963952f2fba59dd06f2b425ace40b492fe', - USDTe: '0x84d34f4f83a87596cd3fb6887cff8f17bf5a7b83', + USDTe: '0x693b75eeD71dFA1BE188Fdb53472c8fC51c5A0A0', WETHe: '0xD291B51f7a1a1F4917D085F2a7731A447E4aF82D', POPS: '0x5268c2331658cb0b2858cfa9db27d8f22f5434bc', ETH: '0x9852e84b5AA485683d8AeE7B0332e42442763b75', @@ -1138,6 +1142,7 @@ export const Holders: { avWETH: '0x92d78e32b990d10aeca0875dc5585f1a6f958179', YUSD: '0x6c1a5ef2acde1fd2fc68def440d2c1eb35bae24a', BTCb: '0x84c06d3c27821d0136f66306f5028d43ceac268d', + AMPL: '0xfcaA5ea7F8eb0631BcA72C345025C0A5a6D93f0E', }, [Network.ARBITRUM]: { ARB: '0xb65edba80a3d81903ecd499c8eb9cf0e19096bd0', From d9574258b23e257e34dc6a54c72fb8c2228e095e Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 24 Nov 2023 13:54:19 +0100 Subject: [PATCH 657/833] add destToken case --- .../uniswap-v2-e2e-avalanche.test.ts | 14 ++++++++++ src/dex/uniswap-v2/uniswap-v2.ts | 26 +++++++++++++------ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/dex/uniswap-v2/uniswap-v2-e2e-avalanche.test.ts b/src/dex/uniswap-v2/uniswap-v2-e2e-avalanche.test.ts index 3097ac917..c0e207916 100644 --- a/src/dex/uniswap-v2/uniswap-v2-e2e-avalanche.test.ts +++ b/src/dex/uniswap-v2/uniswap-v2-e2e-avalanche.test.ts @@ -255,6 +255,20 @@ describe('UniswapV2 E2E Avalanche', () => { provider, ); }); + + it('MIM -> AMPL', async () => { + await testE2E( + tokens.MIM, + tokens.AMPL, + holders.MIM, + '1000000000000000000', + SwapSide.SELL, + dexKey, + ContractMethod.simpleSwap, + network, + provider, + ); + }); }); describe('multiSwap', () => { diff --git a/src/dex/uniswap-v2/uniswap-v2.ts b/src/dex/uniswap-v2/uniswap-v2.ts index d49262bca..45be5a2e8 100644 --- a/src/dex/uniswap-v2/uniswap-v2.ts +++ b/src/dex/uniswap-v2/uniswap-v2.ts @@ -788,15 +788,25 @@ export class UniswapV2 [src, srcAmount, destAmount, weth, pools], ); - const maybeSyncCall = rebaseTokensSetsByChain[this.network]?.has( + const hasRebaseTokenSrc = rebaseTokensSetsByChain[this.network]?.has( src.toLowerCase(), - ) - ? { - callees: [data.pools[0].address], - calldata: [uniswapV2PoolIface.encodeFunctionData('sync')], - values: ['0'], - } - : undefined; + ); + const hasRebaseTokenDest = rebaseTokensSetsByChain[this.network]?.has( + dest.toLowerCase(), + ); + + const maybeSyncCall = + hasRebaseTokenSrc || hasRebaseTokenDest + ? { + callees: [ + hasRebaseTokenSrc + ? data.pools[0].address + : data.pools[data.pools.length - 1].address, + ], + calldata: [uniswapV2PoolIface.encodeFunctionData('sync')], + values: ['0'], + } + : undefined; return this.buildSimpleParamWithoutWETHConversion( src, From c2c4736ad1b675de3107e79088f406460452ac6e Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 24 Nov 2023 13:58:04 +0100 Subject: [PATCH 658/833] 2.42.17-univ2-rebase-tokens-sync-pool.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f6d5694b3..7f2ff19e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.16", + "version": "2.42.17-univ2-rebase-tokens-sync-pool.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 92b543d9470bfdd86a627accce9989225c6eda31 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 24 Nov 2023 15:28:37 +0100 Subject: [PATCH 659/833] 2.42.17 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7f2ff19e9..8d90d3c77 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.17-univ2-rebase-tokens-sync-pool.0", + "version": "2.42.17", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1257f6353c79b8c29f474a78c01804f93e353fe1 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 25 Nov 2023 11:59:25 +0100 Subject: [PATCH 660/833] fix(algebra): adjust the amount of tick data we fetch on zkevm --- src/dex/algebra/algebra-pool-v1_1.ts | 19 +++++++++++++++-- src/dex/algebra/algebra-pool-v1_9.ts | 19 +++++++++++++++-- src/dex/algebra/algebra.ts | 1 + src/dex/algebra/constants.ts | 10 +++++++++ src/dex/algebra/lib/AlgebraMath.ts | 9 ++++++++ src/dex/algebra/lib/TickTable.ts | 31 +++++++++++++++++++--------- 6 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/dex/algebra/algebra-pool-v1_1.ts b/src/dex/algebra/algebra-pool-v1_1.ts index dc6f77843..179c16d56 100644 --- a/src/dex/algebra/algebra-pool-v1_1.ts +++ b/src/dex/algebra/algebra-pool-v1_1.ts @@ -41,7 +41,12 @@ import { import { Constants } from './lib/Constants'; import { Network, NULL_ADDRESS } from '../../constants'; import { TickTable } from './lib/TickTable'; -import { TICK_BITMAP_BUFFER, TICK_BITMAP_TO_USE } from './constants'; +import { + TICK_BITMAP_BUFFER, + TICK_BITMAP_BUFFER_BY_CHAIH, + TICK_BITMAP_TO_USE, + TICK_BITMAP_TO_USE_BY_CHAIN, +} from './constants'; const BN_ZERO = BigNumber.from(0); const MAX_BATCH_SIZE = 100; @@ -194,7 +199,14 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber } getBitmapRangeToRequest() { - return TICK_BITMAP_TO_USE + TICK_BITMAP_BUFFER; + const networkId = this.dexHelper.config.data.network; + + const tickBitmapToUse = + TICK_BITMAP_TO_USE_BY_CHAIN[networkId] ?? TICK_BITMAP_TO_USE; + const tickBuffer = + TICK_BITMAP_BUFFER_BY_CHAIH[networkId] ?? TICK_BITMAP_BUFFER; + + return tickBitmapToUse + tickBuffer; } async fetchPoolStateSingleStep( @@ -657,6 +669,7 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber const zeroForOne = amount0 > 0n; const [, , , , , communityFee] = AlgebraMath._calculateSwapAndLock( + this.dexHelper.config.data.network, pool, zeroForOne, newSqrtPriceX96, @@ -714,6 +727,7 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber pool.blockTimestamp = bigIntify(blockHeader.timestamp); AlgebraMath._updatePositionTicksAndFees( + this.dexHelper.config.data.network, pool, bottomTick, topTick, @@ -738,6 +752,7 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber pool.blockTimestamp = bigIntify(blockHeader.timestamp); AlgebraMath._updatePositionTicksAndFees( + this.dexHelper.config.data.network, pool, bottomTick, topTick, diff --git a/src/dex/algebra/algebra-pool-v1_9.ts b/src/dex/algebra/algebra-pool-v1_9.ts index 4758139fa..6900699b6 100644 --- a/src/dex/algebra/algebra-pool-v1_9.ts +++ b/src/dex/algebra/algebra-pool-v1_9.ts @@ -28,7 +28,12 @@ import { } from '../uniswap-v3/contract-math/utils'; import { Network } from '../../constants'; import { TickTable } from './lib/TickTable'; -import { TICK_BITMAP_BUFFER, TICK_BITMAP_TO_USE } from './constants'; +import { + TICK_BITMAP_BUFFER, + TICK_BITMAP_BUFFER_BY_CHAIH, + TICK_BITMAP_TO_USE, + TICK_BITMAP_TO_USE_BY_CHAIN, +} from './constants'; export class AlgebraEventPoolV1_9 extends StatefulEventSubscriber { handlers: { @@ -168,7 +173,14 @@ export class AlgebraEventPoolV1_9 extends StatefulEventSubscriber 0n; const [, , , , , communityFee] = AlgebraMath._calculateSwapAndLock( + this.dexHelper.config.data.network, pool, zeroForOne, newSqrtPriceX96, @@ -460,6 +473,7 @@ export class AlgebraEventPoolV1_9 extends StatefulEventSubscriber { ): OutputResult | null { try { const outputsResult = AlgebraMath.queryOutputs( + this.network, state, amounts, zeroForOne, diff --git a/src/dex/algebra/constants.ts b/src/dex/algebra/constants.ts index 918c6a64d..2ce87d436 100644 --- a/src/dex/algebra/constants.ts +++ b/src/dex/algebra/constants.ts @@ -1,7 +1,17 @@ +import { Network } from '../../constants'; + /// THIS FILE CONTAINS OVERRIDES OF UniswapV3's constant file export const TICK_BITMAP_TO_USE = 400n; export const TICK_BITMAP_BUFFER = 800n; +export const TICK_BITMAP_TO_USE_BY_CHAIN: Record = { + [Network.ZKEVM]: 10n, +}; + +export const TICK_BITMAP_BUFFER_BY_CHAIH: Record = { + [Network.ZKEVM]: 4n, +}; + export const MAX_PRICING_COMPUTATION_STEPS_ALLOWED = 4096; diff --git a/src/dex/algebra/lib/AlgebraMath.ts b/src/dex/algebra/lib/AlgebraMath.ts index fa1dea21a..ea9f06df7 100644 --- a/src/dex/algebra/lib/AlgebraMath.ts +++ b/src/dex/algebra/lib/AlgebraMath.ts @@ -54,6 +54,7 @@ const isPoolV1_9 = ( // % START OF COPY PASTA FROM UNISWAPV3 % function _priceComputationCycles( + networkId: number, poolState: DeepReadonly, ticksCopy: Record, state: PriceComputationState, @@ -112,6 +113,7 @@ function _priceComputationCycles( try { [step.tickNext, step.initialized] = TickTable.nextInitializedTickWithinOneWord( + networkId, poolState, state.tick, zeroForOne, @@ -228,6 +230,7 @@ function _priceComputationCycles( class AlgebraMathClass { queryOutputs( + networkId: number, poolState: DeepReadonly, amounts: bigint[], zeroForOne: boolean, @@ -309,6 +312,7 @@ class AlgebraMathClass { if (!isOutOfRange) { const [finalState, { latestFullCycleState, latestFullCycleCache }] = _priceComputationCycles( + networkId, poolState, ticksCopy, state, @@ -414,6 +418,7 @@ class AlgebraMathClass { } _updatePositionTicksAndFees( + networkId: number, state: PoolStateV1_1 | PoolState_v1_9, bottomTick: bigint, topTick: bigint, @@ -447,6 +452,7 @@ class AlgebraMathClass { ) { toggledBottom = true; TickTable.toggleTick( + networkId, state, bottomTick, state.areTicksCompressed ? state.tickSpacing : undefined, @@ -467,6 +473,7 @@ class AlgebraMathClass { ) { toggledTop = true; TickTable.toggleTick( + networkId, state, topTick, state.areTicksCompressed ? state.tickSpacing : undefined, @@ -507,6 +514,7 @@ class AlgebraMathClass { } _calculateSwapAndLock( + networkId: number, poolState: PoolStateV1_1 | PoolState_v1_9, zeroToOne: boolean, newSqrtPriceX96: bigint, @@ -577,6 +585,7 @@ class AlgebraMathClass { //equivalent of tickTable.nextTickInTheSameRow(currentTick, zeroToOne); [step.nextTick, step.initialized] = TickTable.nextInitializedTickWithinOneWord( + networkId, poolState, currentTick, zeroToOne, diff --git a/src/dex/algebra/lib/TickTable.ts b/src/dex/algebra/lib/TickTable.ts index edad424d6..2d61292ff 100644 --- a/src/dex/algebra/lib/TickTable.ts +++ b/src/dex/algebra/lib/TickTable.ts @@ -4,9 +4,15 @@ import { DeepReadonly } from 'ts-essentials'; import { OUT_OF_RANGE_ERROR_POSTFIX } from '../../uniswap-v3/constants'; import { TickMath } from '../../uniswap-v3/contract-math/TickMath'; import { Yul } from './yul-helper'; -import { TICK_BITMAP_BUFFER, TICK_BITMAP_TO_USE } from '../constants'; +import { + TICK_BITMAP_BUFFER, + TICK_BITMAP_BUFFER_BY_CHAIH, + TICK_BITMAP_TO_USE, + TICK_BITMAP_TO_USE_BY_CHAIN, +} from '../constants'; function isWordPosOut( + networkId: number, wordPos: bigint, startTickBitmap: bigint, // For pricing we use wider range to check price impact. If function called from event @@ -16,14 +22,17 @@ function isWordPosOut( let lowerTickBitmapLimit; let upperTickBitmapLimit; + const tickBitmapToUse = + TICK_BITMAP_TO_USE_BY_CHAIN[networkId] ?? TICK_BITMAP_TO_USE; + const tickBuffer = + TICK_BITMAP_BUFFER_BY_CHAIH[networkId] ?? TICK_BITMAP_BUFFER; + if (isPriceQuery) { - lowerTickBitmapLimit = - startTickBitmap - (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE); - upperTickBitmapLimit = - startTickBitmap + (TICK_BITMAP_BUFFER + TICK_BITMAP_TO_USE); + lowerTickBitmapLimit = startTickBitmap - (tickBuffer + tickBitmapToUse); + upperTickBitmapLimit = startTickBitmap + (tickBuffer + tickBitmapToUse); } else { - lowerTickBitmapLimit = startTickBitmap - TICK_BITMAP_BUFFER; - upperTickBitmapLimit = startTickBitmap + TICK_BITMAP_BUFFER; + lowerTickBitmapLimit = startTickBitmap - tickBuffer; + upperTickBitmapLimit = startTickBitmap + tickBuffer; } _require( @@ -45,6 +54,7 @@ export class TickTable { } static toggleTick( + networkId: number, state: Pick, tick: bigint, tickSpacing?: bigint, @@ -57,7 +67,7 @@ export class TickTable { // toggleTick is used only in _updatePosition which is always state changing event // Therefore it is never used in price query - isWordPosOut(rowNumber, state.startTickBitmap, false); + isWordPosOut(networkId, rowNumber, state.startTickBitmap, false); const stringWordPos = rowNumber.toString(); if (state.tickBitmap[stringWordPos] === undefined) { @@ -71,6 +81,7 @@ export class TickTable { } static nextInitializedTickWithinOneWord( + networkId: number, state: DeepReadonly< Pick >, @@ -93,7 +104,7 @@ export class TickTable { } if (lte) { const [rowNumber, bitNumber] = TickTable.position(tick); - isWordPosOut(rowNumber, state.startTickBitmap, isPriceQuery); + isWordPosOut(networkId, rowNumber, state.startTickBitmap, isPriceQuery); let tickBitmapValue = state.tickBitmap[rowNumber.toString()]; tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; @@ -109,7 +120,7 @@ export class TickTable { tick += 1n; const [rowNumber, bitNumber] = TickTable.position(tick); - isWordPosOut(rowNumber, state.startTickBitmap, isPriceQuery); + isWordPosOut(networkId, rowNumber, state.startTickBitmap, isPriceQuery); let tickBitmapValue = state.tickBitmap[rowNumber.toString()]; tickBitmapValue = tickBitmapValue === undefined ? 0n : tickBitmapValue; From 843a2889a9c78c1268558db5d9a6bf1b4895137d Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 25 Nov 2023 12:01:11 +0100 Subject: [PATCH 661/833] 2.42.18 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8d90d3c77..ce17ac968 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.17", + "version": "2.42.18", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 859d8af667c1650efdf6ac10d86e4732f7260252 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 25 Nov 2023 13:07:41 +0100 Subject: [PATCH 662/833] naming --- src/dex/algebra/algebra-pool-v1_1.ts | 4 ++-- src/dex/algebra/algebra-pool-v1_9.ts | 4 ++-- src/dex/algebra/lib/TickTable.ts | 12 +++++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/dex/algebra/algebra-pool-v1_1.ts b/src/dex/algebra/algebra-pool-v1_1.ts index 179c16d56..f49c89c0f 100644 --- a/src/dex/algebra/algebra-pool-v1_1.ts +++ b/src/dex/algebra/algebra-pool-v1_1.ts @@ -203,10 +203,10 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber const tickBitmapToUse = TICK_BITMAP_TO_USE_BY_CHAIN[networkId] ?? TICK_BITMAP_TO_USE; - const tickBuffer = + const tickBitmapBuffer = TICK_BITMAP_BUFFER_BY_CHAIH[networkId] ?? TICK_BITMAP_BUFFER; - return tickBitmapToUse + tickBuffer; + return tickBitmapToUse + tickBitmapBuffer; } async fetchPoolStateSingleStep( diff --git a/src/dex/algebra/algebra-pool-v1_9.ts b/src/dex/algebra/algebra-pool-v1_9.ts index 6900699b6..69184f233 100644 --- a/src/dex/algebra/algebra-pool-v1_9.ts +++ b/src/dex/algebra/algebra-pool-v1_9.ts @@ -177,10 +177,10 @@ export class AlgebraEventPoolV1_9 extends StatefulEventSubscriber Date: Sat, 25 Nov 2023 13:45:30 +0100 Subject: [PATCH 663/833] typo --- src/dex/algebra/algebra-pool-v1_1.ts | 4 ++-- src/dex/algebra/algebra-pool-v1_9.ts | 4 ++-- src/dex/algebra/constants.ts | 2 +- src/dex/algebra/lib/TickTable.ts | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/dex/algebra/algebra-pool-v1_1.ts b/src/dex/algebra/algebra-pool-v1_1.ts index f49c89c0f..92132c4a0 100644 --- a/src/dex/algebra/algebra-pool-v1_1.ts +++ b/src/dex/algebra/algebra-pool-v1_1.ts @@ -43,7 +43,7 @@ import { Network, NULL_ADDRESS } from '../../constants'; import { TickTable } from './lib/TickTable'; import { TICK_BITMAP_BUFFER, - TICK_BITMAP_BUFFER_BY_CHAIH, + TICK_BITMAP_BUFFER_BY_CHAIN, TICK_BITMAP_TO_USE, TICK_BITMAP_TO_USE_BY_CHAIN, } from './constants'; @@ -204,7 +204,7 @@ export class AlgebraEventPoolV1_1 extends StatefulEventSubscriber const tickBitmapToUse = TICK_BITMAP_TO_USE_BY_CHAIN[networkId] ?? TICK_BITMAP_TO_USE; const tickBitmapBuffer = - TICK_BITMAP_BUFFER_BY_CHAIH[networkId] ?? TICK_BITMAP_BUFFER; + TICK_BITMAP_BUFFER_BY_CHAIN[networkId] ?? TICK_BITMAP_BUFFER; return tickBitmapToUse + tickBitmapBuffer; } diff --git a/src/dex/algebra/algebra-pool-v1_9.ts b/src/dex/algebra/algebra-pool-v1_9.ts index 69184f233..308fef47b 100644 --- a/src/dex/algebra/algebra-pool-v1_9.ts +++ b/src/dex/algebra/algebra-pool-v1_9.ts @@ -30,7 +30,7 @@ import { Network } from '../../constants'; import { TickTable } from './lib/TickTable'; import { TICK_BITMAP_BUFFER, - TICK_BITMAP_BUFFER_BY_CHAIH, + TICK_BITMAP_BUFFER_BY_CHAIN, TICK_BITMAP_TO_USE, TICK_BITMAP_TO_USE_BY_CHAIN, } from './constants'; @@ -178,7 +178,7 @@ export class AlgebraEventPoolV1_9 extends StatefulEventSubscriber = { [Network.ZKEVM]: 10n, }; -export const TICK_BITMAP_BUFFER_BY_CHAIH: Record = { +export const TICK_BITMAP_BUFFER_BY_CHAIN: Record = { [Network.ZKEVM]: 4n, }; diff --git a/src/dex/algebra/lib/TickTable.ts b/src/dex/algebra/lib/TickTable.ts index a72941e1c..da600e7df 100644 --- a/src/dex/algebra/lib/TickTable.ts +++ b/src/dex/algebra/lib/TickTable.ts @@ -6,7 +6,7 @@ import { TickMath } from '../../uniswap-v3/contract-math/TickMath'; import { Yul } from './yul-helper'; import { TICK_BITMAP_BUFFER, - TICK_BITMAP_BUFFER_BY_CHAIH, + TICK_BITMAP_BUFFER_BY_CHAIN, TICK_BITMAP_TO_USE, TICK_BITMAP_TO_USE_BY_CHAIN, } from '../constants'; @@ -25,7 +25,7 @@ function isWordPosOut( const tickBitmapToUse = TICK_BITMAP_TO_USE_BY_CHAIN[networkId] ?? TICK_BITMAP_TO_USE; const tickBitmapBuffer = - TICK_BITMAP_BUFFER_BY_CHAIH[networkId] ?? TICK_BITMAP_BUFFER; + TICK_BITMAP_BUFFER_BY_CHAIN[networkId] ?? TICK_BITMAP_BUFFER; if (isPriceQuery) { lowerTickBitmapLimit = From 45ebf425e5e5eab475c454b270f483741ab93a3c Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Sun, 26 Nov 2023 23:41:12 +0200 Subject: [PATCH 664/833] fix: update adapters & implement `getAdapterParams` --- src/config.ts | 3 +- src/dex/wombat/config.ts | 68 ++++++++++++++++++++++++------- src/dex/wombat/wombat-e2e.test.ts | 4 +- src/dex/wombat/wombat.ts | 11 +++-- 4 files changed, 65 insertions(+), 21 deletions(-) diff --git a/src/config.ts b/src/config.ts index 0886ebf6a..bb66c143b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -165,7 +165,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_56`]?.split(',') || [], adapterAddresses: { BscAdapter01: '0xA31d9C571DF00e0F428B0bD24c34D103E8112222', - BscAdapter02: '0xEECA9223063bD13e8ca77ed9e39a07f2BD1923E6', + // BscAdapter02: '0xEECA9223063bD13e8ca77ed9e39a07f2BD1923E6', + BscAdapter02: '0x5b8268F34993A48247Ac0d182a8A343518bca204', BscBuyAdapter: '0x301c2813e3ceb43A448a12f21551EDBcdC37F157', }, rpcPollingMaxAllowedStateDelayInBlocks: 1, diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts index 306fda542..031bc286c 100644 --- a/src/dex/wombat/config.ts +++ b/src/dex/wombat/config.ts @@ -29,33 +29,71 @@ export const Adapters: Record = { [Network.BSC]: { [SwapSide.SELL]: [ { - // TODO: implement - name: 'BscAdapter01', - index: 3, + name: 'BscAdapter02', + index: 7, }, ], - [SwapSide.BUY]: [ + // [SwapSide.BUY]: [ + // { + // name: 'BscBuyAdapter', + // index: 1, + // }, + // ], + }, + [Network.ARBITRUM]: { + [SwapSide.SELL]: [ { - // TODO: implement - name: 'BscBuyAdapter', - index: 1, + name: 'ArbitrumAdapter02', + index: 7, }, ], + // [SwapSide.BUY]: [ + // { + // name: 'ArbitrumBuyAdapter', + // index: 1, + // }, + // ], }, - [Network.ARBITRUM]: { + [Network.MAINNET]: { [SwapSide.SELL]: [ { - // TODO: implement - name: 'ArbitrumAdapter01', - index: 2, + name: 'Adapter04', + index: 6, }, ], - [SwapSide.BUY]: [ + // [SwapSide.BUY]: [ + // { + // name: 'BscBuyAdapter', + // index: 1, + // }, + // ], + }, + [Network.AVALANCHE]: { + [SwapSide.SELL]: [ + { + name: 'AvalancheAdapter02', + index: 7, + }, + ], + // [SwapSide.BUY]: [ + // { + // name: 'BscBuyAdapter', + // index: 1, + // }, + // ], + }, + [Network.BASE]: { + [SwapSide.SELL]: [ { - // TODO: implement - name: 'ArbitrumBuyAdapter', - index: 1, + name: 'BaseAdapter01', + index: 7, }, ], + // [SwapSide.BUY]: [ + // { + // name: 'BscBuyAdapter', + // index: 1, + // }, + // ], }, }; diff --git a/src/dex/wombat/wombat-e2e.test.ts b/src/dex/wombat/wombat-e2e.test.ts index b478bad7a..138f977a2 100644 --- a/src/dex/wombat/wombat-e2e.test.ts +++ b/src/dex/wombat/wombat-e2e.test.ts @@ -31,8 +31,8 @@ function testForNetwork( SwapSide.SELL, [ ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, ], ], [SwapSide.BUY, [ContractMethod.simpleBuy /* ContractMethod.buy */]], diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 98ec4d41c..062f8b481 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -271,11 +271,16 @@ export class Wombat extends SimpleExchange implements IDex { data: WombatData, side: SwapSide, ): AdapterExchangeParam { - // TODO: complete me! const { exchange } = data; - // Encode here the payload for adapter - const payload = '0x'; + const payload = this.abiCoder.encodeParameter( + { + ParentStruct: { + deadline: 'uint256', + }, + }, + { deadline: getLocalDeadlineAsFriendlyPlaceholder() }, + ); return { targetExchange: exchange, From 902c97e00b6f9f6ef8d6f810246f72238228fedf Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Fri, 24 Nov 2023 11:52:36 +0200 Subject: [PATCH 665/833] algebra: add support for tax tokens --- src/abi/algebra/SwapRouter.json | 281 ++++++++++++++++++++++++++++ src/dex/algebra/algebra-e2e.test.ts | 200 +++++++++++++------- src/dex/algebra/algebra.ts | 181 +++++++++++++----- src/dex/algebra/types.ts | 15 +- tests/constants-e2e.ts | 7 +- 5 files changed, 568 insertions(+), 116 deletions(-) create mode 100644 src/abi/algebra/SwapRouter.json diff --git a/src/abi/algebra/SwapRouter.json b/src/abi/algebra/SwapRouter.json new file mode 100644 index 000000000..c41ec4a89 --- /dev/null +++ b/src/abi/algebra/SwapRouter.json @@ -0,0 +1,281 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "_factory", "type": "address" }, + { "internalType": "address", "name": "_WNativeToken", "type": "address" }, + { "internalType": "address", "name": "_poolDeployer", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "WNativeToken", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "int256", "name": "amount0Delta", "type": "int256" }, + { "internalType": "int256", "name": "amount1Delta", "type": "int256" }, + { "internalType": "bytes", "name": "_data", "type": "bytes" } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "bytes", "name": "path", "type": "bytes" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { + "internalType": "uint256", + "name": "amountOutMinimum", + "type": "uint256" + } + ], + "internalType": "struct ISwapRouter.ExactInputParams", + "name": "params", + "type": "tuple" + } + ], + "name": "exactInput", + "outputs": [ + { "internalType": "uint256", "name": "amountOut", "type": "uint256" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "tokenIn", "type": "address" }, + { "internalType": "address", "name": "tokenOut", "type": "address" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { + "internalType": "uint256", + "name": "amountOutMinimum", + "type": "uint256" + }, + { + "internalType": "uint160", + "name": "limitSqrtPrice", + "type": "uint160" + } + ], + "internalType": "struct ISwapRouter.ExactInputSingleParams", + "name": "params", + "type": "tuple" + } + ], + "name": "exactInputSingleSupportingFeeOnTransferTokens", + "outputs": [ + { "internalType": "uint256", "name": "amountOut", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "bytes", "name": "path", "type": "bytes" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOut", "type": "uint256" }, + { + "internalType": "uint256", + "name": "amountInMaximum", + "type": "uint256" + } + ], + "internalType": "struct ISwapRouter.ExactOutputParams", + "name": "params", + "type": "tuple" + } + ], + "name": "exactOutput", + "outputs": [ + { "internalType": "uint256", "name": "amountIn", "type": "uint256" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "tokenIn", "type": "address" }, + { "internalType": "address", "name": "tokenOut", "type": "address" }, + { "internalType": "uint24", "name": "fee", "type": "uint24" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOut", "type": "uint256" }, + { + "internalType": "uint256", + "name": "amountInMaximum", + "type": "uint256" + }, + { + "internalType": "uint160", + "name": "limitSqrtPrice", + "type": "uint160" + } + ], + "internalType": "struct ISwapRouter.ExactOutputSingleParams", + "name": "params", + "type": "tuple" + } + ], + "name": "exactOutputSingle", + "outputs": [ + { "internalType": "uint256", "name": "amountIn", "type": "uint256" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "factory", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes[]", "name": "data", "type": "bytes[]" } + ], + "name": "multicall", + "outputs": [ + { "internalType": "bytes[]", "name": "results", "type": "bytes[]" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "poolDeployer", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "refundNativeToken", + "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": "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": "token", "type": "address" }, + { "internalType": "uint256", "name": "amountMinimum", "type": "uint256" }, + { "internalType": "address", "name": "recipient", "type": "address" } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "amountMinimum", "type": "uint256" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "feeBips", "type": "uint256" }, + { "internalType": "address", "name": "feeRecipient", "type": "address" } + ], + "name": "sweepTokenWithFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountMinimum", "type": "uint256" }, + { "internalType": "address", "name": "recipient", "type": "address" } + ], + "name": "unwrapWNativeToken", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountMinimum", "type": "uint256" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "feeBips", "type": "uint256" }, + { "internalType": "address", "name": "feeRecipient", "type": "address" } + ], + "name": "unwrapWNativeTokenWithFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { "stateMutability": "payable", "type": "receive" } +] diff --git a/src/dex/algebra/algebra-e2e.test.ts b/src/dex/algebra/algebra-e2e.test.ts index 318378069..b8bfe4c43 100644 --- a/src/dex/algebra/algebra-e2e.test.ts +++ b/src/dex/algebra/algebra-e2e.test.ts @@ -11,6 +11,7 @@ import { import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; +import { TransferFeeParams } from '../../types'; /* README @@ -59,6 +60,12 @@ function testForNetwork( tokenAAmount: string, tokenBAmount: string, nativeTokenAmount: string, + transferFees: TransferFeeParams = { + srcFee: 0, + destFee: 0, + srcDexFee: 0, + destDexFee: 0, + }, ) { const provider = new StaticJsonRpcProvider( generateConfig(network).privateHttpProvider, @@ -74,12 +81,13 @@ function testForNetwork( SwapSide.SELL, [ ContractMethod.simpleSwap, - ContractMethod.multiSwap, - ContractMethod.megaSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, ], ], // TODO: If buy is not supported remove the buy contract methods - [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + // [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + [SwapSide.BUY, [ContractMethod.simpleBuy]], ]); describe(`${network}`, () => { @@ -87,43 +95,78 @@ function testForNetwork( describe(`${side}`, () => { contractMethods.forEach((contractMethod: ContractMethod) => { describe(`${contractMethod}`, () => { - it(`${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { await testE2E( - tokens[nativeTokenSymbol], tokens[tokenASymbol], - holders[nativeTokenSymbol], - side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, side, dexKey, contractMethod, network, provider, + undefined, + undefined, + transferFees, ); }); - it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { + it(`${tokenBSymbol} -> ${tokenASymbol}`, async () => { await testE2E( + tokens[tokenBSymbol], tokens[tokenASymbol], + holders[tokenBSymbol], + side === SwapSide.SELL ? tokenBAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + undefined, + undefined, + // switch src and dest fee when tax token is dest token + { + ...transferFees, + srcDexFee: transferFees.destDexFee, + destDexFee: transferFees.srcDexFee, + }, + ); + }); + it(`${nativeTokenSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( tokens[nativeTokenSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, + tokens[tokenASymbol], + holders[nativeTokenSymbol], + side === SwapSide.SELL ? nativeTokenAmount : tokenAAmount, side, dexKey, contractMethod, network, provider, + undefined, + undefined, + // switch src and dest fee when tax token is dest token + { + ...transferFees, + srcDexFee: transferFees.destDexFee, + destDexFee: transferFees.srcDexFee, + }, ); }); - it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { + it(`${tokenASymbol} -> ${nativeTokenSymbol}`, async () => { await testE2E( tokens[tokenASymbol], - tokens[tokenBSymbol], + tokens[nativeTokenSymbol], holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side === SwapSide.SELL ? tokenAAmount : nativeTokenAmount, side, dexKey, contractMethod, network, provider, + undefined, + undefined, + transferFees, ); }); }); @@ -134,61 +177,85 @@ function testForNetwork( } describe('Algebra', () => { - describe('QuickSwapV3 E2E', () => { - const dexKey = 'QuickSwapV3'; + // describe('QuickSwapV3 E2E', () => { + // const dexKey = 'QuickSwapV3'; - describe('Polygon', () => { - const network = Network.POLYGON; - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'DAI'; + // describe('Polygon', () => { + // const network = Network.POLYGON; + // const tokenASymbol: string = 'USDC'; + // const tokenBSymbol: string = 'DAI'; - const tokenAAmount: string = '1000000000'; - const tokenBAmount: string = '1000000000000000000000'; - const nativeTokenAmount = '1000000000000000000'; + // const tokenAAmount: string = '1000000000'; + // const tokenBAmount: string = '1000000000000000000000'; + // const nativeTokenAmount = '1000000000000000000'; - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); - }); + // testForNetwork( + // network, + // dexKey, + // tokenASymbol, + // tokenBSymbol, + // tokenAAmount, + // tokenBAmount, + // nativeTokenAmount, + // ); + // }); + // }); - describe('ZyberSwapV3', () => { - const dexKey = 'ZyberSwapV3'; + // describe('ZyberSwapV3', () => { + // const dexKey = 'ZyberSwapV3'; - describe('Arbitrum', () => { - const network = Network.ARBITRUM; - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'DAI'; + // describe('Arbitrum', () => { + // const network = Network.ARBITRUM; + // const tokenASymbol: string = 'USDC'; + // const tokenBSymbol: string = 'DAI'; - const tokenAAmount: string = '1000000000'; - const tokenBAmount: string = '1000000000000000000000'; - const nativeTokenAmount = '1000000000000000000'; + // const tokenAAmount: string = '1000000000'; + // const tokenBAmount: string = '1000000000000000000000'; + // const nativeTokenAmount = '1000000000000000000'; - testForNetwork( - network, - dexKey, - tokenASymbol, - tokenBSymbol, - tokenAAmount, - tokenBAmount, - nativeTokenAmount, - ); - }); + // testForNetwork( + // network, + // dexKey, + // tokenASymbol, + // tokenBSymbol, + // tokenAAmount, + // tokenBAmount, + // nativeTokenAmount, + // ); + // }); - describe('Optimism', () => { - const network = Network.OPTIMISM; - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; + // describe('Optimism', () => { + // const network = Network.OPTIMISM; + // const tokenASymbol: string = 'USDC'; + // const tokenBSymbol: string = 'USDT'; + + // const tokenAAmount: string = '100000000'; + // const tokenBAmount: string = '50000'; + // const nativeTokenAmount = '100000000000000'; + + // testForNetwork( + // network, + // dexKey, + // tokenASymbol, + // tokenBSymbol, + // tokenAAmount, + // tokenBAmount, + // nativeTokenAmount, + // ); + // }); + // }); + + describe('CamelotV3', () => { + const dexKey = 'CamelotV3'; + const network = Network.ARBITRUM; - const tokenAAmount: string = '100000000'; - const tokenBAmount: string = '50000'; - const nativeTokenAmount = '100000000000000'; + describe('Arbitrum: Tax Tokens', () => { + const tokenASymbol: string = 'RDPX'; + const tokenBSymbol: string = 'WETH'; + + const tokenAAmount: string = '100000000000000000000'; + const tokenBAmount: string = '100000000000000000'; + const nativeTokenAmount = '1000000000000000000'; testForNetwork( network, @@ -198,16 +265,17 @@ describe('Algebra', () => { tokenAAmount, tokenBAmount, nativeTokenAmount, + { + srcFee: 0, + destFee: 0, + srcDexFee: 1000, + destDexFee: 0, + }, ); }); - }); - - describe('CamelotV3', () => { - const dexKey = 'CamelotV3'; - describe('Arbitrum', () => { - const network = Network.ARBITRUM; - const tokenASymbol: string = 'USDC'; + describe('Arbitrum: Non-Tax tokens', () => { + const tokenASymbol: string = 'USDCe'; const tokenBSymbol: string = 'USDT'; const tokenAAmount: string = '1000000000'; diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index e289f9c32..29a785561 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -4,21 +4,36 @@ import { AbiItem } from 'web3-utils'; import { pack } from '@ethersproject/solidity'; import _ from 'lodash'; import { - Token, - Address, ExchangePrices, PoolPrices, AdapterExchangeParam, SimpleExchangeParam, - PoolLiquidity, Logger, + TransferFeeParams, + Address, + PoolLiquidity, + Token, } from '../../types'; import { SwapSide, Network, CACHE_PREFIX } from '../../constants'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { getBigIntPow, getDexKeysWithNetwork, interpolate } from '../../utils'; +import { + _require, + getBigIntPow, + getDexKeysWithNetwork, + interpolate, + isDestTokenTransferFeeToBeExchanged, + isSrcTokenTransferFeeToBeExchanged, +} from '../../utils'; import { IDex } from '../../dex/idex'; import { IDexHelper } from '../../dex-helper/idex-helper'; -import { AlgebraData, DexParams, IAlgebraPoolState } from './types'; +import { + AlgebraData, + AlgebraDataWithFee, + AlgebraDataWithoutFee, + AlgebraFunctions, + DexParams, + IAlgebraPoolState, +} from './types'; import { SimpleExchange, getLocalDeadlineAsFriendlyPlaceholder, @@ -26,19 +41,16 @@ import { import { AlgebraConfig, Adapters } from './config'; import { Contract } from 'web3-eth-contract'; import { Interface } from 'ethers/lib/utils'; -import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; +import SwapRouter from '../../abi/algebra/SwapRouter.json'; import AlgebraQuoterABI from '../../abi/algebra/AlgebraQuoter.abi.json'; import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; import AlgebraStateMulticallABI from '../../abi/algebra/AlgebraStateMulticall.abi.json'; -import { - OutputResult, - UniswapV3Functions, - UniswapV3SimpleSwapParams, -} from '../uniswap-v3/types'; +import { OutputResult } from '../uniswap-v3/types'; import { AlgebraMath } from './lib/AlgebraMath'; import { AlgebraEventPoolV1_1 } from './algebra-pool-v1_1'; import { AlgebraEventPoolV1_9 } from './algebra-pool-v1_9'; import { AlgebraFactory, OnPoolCreatedCallback } from './algebra-factory'; +import { applyTransferFee } from '../../lib/token-transfer-fee'; type PoolPairsInfo = { token0: Address; @@ -61,7 +73,7 @@ type IAlgebraEventPool = AlgebraEventPoolV1_1 | AlgebraEventPoolV1_9; export class Algebra extends SimpleExchange implements IDex { private readonly factory: AlgebraFactory; - readonly isFeeOnTransferSupported: boolean = false; + readonly isFeeOnTransferSupported: boolean = true; protected eventPools: Record = {}; private newlyCreatedPoolKeys: Set = new Set(); @@ -85,12 +97,15 @@ export class Algebra extends SimpleExchange implements IDex { | typeof AlgebraEventPoolV1_1 | typeof AlgebraEventPoolV1_9; + readonly SRC_TOKEN_DEX_TRANSFERS = 1; + readonly DEST_TOKEN_DEX_TRANSFERS = 1; + constructor( protected network: Network, dexKey: string, protected dexHelper: IDexHelper, protected adapters = Adapters[network] || {}, - readonly routerIface = new Interface(UniswapV3RouterABI), // same abi as uniswapV3 + readonly routerIface = new Interface(SwapRouter), // same abi as uniswapV3 readonly quoterIface = new Interface(AlgebraQuoterABI), readonly config = AlgebraConfig[dexKey][network], ) { @@ -508,6 +523,12 @@ export class Algebra extends SimpleExchange implements IDex { side: SwapSide, blockNumber: number, limitPools?: string[], + transferFees: TransferFeeParams = { + srcFee: 0, + destFee: 0, + srcDexFee: 0, + destDexFee: 0, + }, ): Promise> { try { const _srcToken = this.dexHelper.config.wrapETH(srcToken); @@ -601,16 +622,38 @@ export class Algebra extends SimpleExchange implements IDex { const balanceDestToken = _destAddress === pool.token0 ? state.balance0 : state.balance1; + const _isSrcTokenTransferFeeToBeExchanged = + isSrcTokenTransferFeeToBeExchanged(transferFees); + const _isDestTokenTransferFeeToBeExchanged = + isDestTokenTransferFeeToBeExchanged(transferFees); + + if (_isSrcTokenTransferFeeToBeExchanged && side == SwapSide.BUY) { + this.logger.error( + `pool: ${pool.poolAddress} doesn't support buy for tax srcToken ${srcToken.address}`, + ); + return null; + } + + const [unitAmountWithFee, ...amountsWithFee] = + _isSrcTokenTransferFeeToBeExchanged + ? applyTransferFee( + [unitAmount, ..._amounts], + side, + transferFees.srcDexFee, + this.SRC_TOKEN_DEX_TRANSFERS, + ) + : [unitAmount, ..._amounts]; + const unitResult = this._getOutputs( state, - [unitAmount], + [unitAmountWithFee], zeroForOne, side, balanceDestToken, ); const pricesResult = this._getOutputs( state, - _amounts, + amountsWithFee, zeroForOne, side, balanceDestToken, @@ -621,10 +664,20 @@ export class Algebra extends SimpleExchange implements IDex { return null; } - const prices = [0n, ...pricesResult.outputs]; + const [unitResultWithFee, ...pricesResultWithFee] = + _isDestTokenTransferFeeToBeExchanged + ? applyTransferFee( + [unitResult.outputs[0], ...pricesResult.outputs], + side, + transferFees.destDexFee, + this.DEST_TOKEN_DEX_TRANSFERS, + ) + : [unitResult.outputs[0], ...pricesResult.outputs]; + + const prices = [0n, ...pricesResultWithFee]; const gasCost = [ 0, - ...pricesResult.outputs.map((p, index) => { + ...pricesResultWithFee.map((p, index) => { if (p == 0n) { return 0; } else { @@ -639,16 +692,21 @@ export class Algebra extends SimpleExchange implements IDex { return [ { - unit: unitResult.outputs[0], + unit: unitResultWithFee, prices, - data: { - path: [ - { + data: _isSrcTokenTransferFeeToBeExchanged + ? { tokenIn: _srcAddress, tokenOut: _destAddress, + } + : { + path: [ + { + tokenIn: _srcAddress, + tokenOut: _destAddress, + }, + ], }, - ], - }, poolIdentifier: this.getPoolIdentifier(pool.token0, pool.token1), exchange: this.dexKey, gasCost: gasCost, @@ -674,8 +732,14 @@ export class Algebra extends SimpleExchange implements IDex { data: AlgebraData, side: SwapSide, ): AdapterExchangeParam { - const { path: rawPath } = data; - const path = this._encodePath(rawPath, side); + let path; + if (this.isAlgebraDataWithoutFee(data)) { + path = this._encodePath(data.path, side); + } else { + path = this._encodePath([{ ...data }], side); + } + // const { path: rawPath } = data; + // const path = this._encodePath(rawPath, side); const payload = this.abiCoder.encodeParameter( { @@ -722,6 +786,10 @@ export class Algebra extends SimpleExchange implements IDex { return arr; } + isAlgebraDataWithoutFee(data: AlgebraData): data is AlgebraDataWithoutFee { + return (data as AlgebraDataWithoutFee).path !== undefined; + } + async getSimpleParam( srcToken: string, destToken: string, @@ -730,30 +798,47 @@ export class Algebra extends SimpleExchange implements IDex { data: AlgebraData, side: SwapSide, ): Promise { - const swapFunction = - side === SwapSide.SELL - ? UniswapV3Functions.exactInput - : UniswapV3Functions.exactOutput; - - const path = this._encodePath(data.path, side); - const swapFunctionParams: UniswapV3SimpleSwapParams = - side === SwapSide.SELL - ? { - recipient: this.augustusAddress, - deadline: getLocalDeadlineAsFriendlyPlaceholder(), - amountIn: srcAmount, - amountOutMinimum: destAmount, - path, - } - : { - recipient: this.augustusAddress, - deadline: getLocalDeadlineAsFriendlyPlaceholder(), - amountOut: destAmount, - amountInMaximum: srcAmount, - path, - }; + const withoutFee = this.isAlgebraDataWithoutFee(data); + let swapFunction; + let swapParams; + + if (!withoutFee) { + swapFunction = AlgebraFunctions.exactInputWithFeeToken; + swapParams = { + limitSqrtPrice: '0', + recipient: this.augustusAddress, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), + amountIn: srcAmount, + amountOutMinimum: destAmount, + tokenIn: data.tokenIn, + tokenOut: data.tokenOut, + }; + } else { + const path = this._encodePath(data.path, side); + swapParams = + side === SwapSide.SELL + ? { + recipient: this.augustusAddress, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), + amountIn: srcAmount, + amountOutMinimum: destAmount, + path, + } + : { + recipient: this.augustusAddress, + deadline: getLocalDeadlineAsFriendlyPlaceholder(), + amountOut: destAmount, + amountInMaximum: srcAmount, + path, + }; + swapFunction = + side === SwapSide.SELL + ? AlgebraFunctions.exactInput + : AlgebraFunctions.exactOutput; + } + const swapData = this.routerIface.encodeFunctionData(swapFunction, [ - swapFunctionParams, + swapParams, ]); return this.buildSimpleParamWithoutWETHConversion( diff --git a/src/dex/algebra/types.ts b/src/dex/algebra/types.ts index 31514b972..9899eba98 100644 --- a/src/dex/algebra/types.ts +++ b/src/dex/algebra/types.ts @@ -53,7 +53,9 @@ export type PoolState_v1_9 = { export type FactoryState = Record; -export type AlgebraData = { +export type AlgebraData = AlgebraDataWithoutFee | AlgebraDataWithFee; + +export type AlgebraDataWithoutFee = { path: { tokenIn: Address; tokenOut: Address; @@ -61,6 +63,17 @@ export type AlgebraData = { isApproved?: boolean; }; +export type AlgebraDataWithFee = { + tokenIn: Address; + tokenOut: Address; +}; + +export enum AlgebraFunctions { + exactInput = 'exactInput', + exactOutput = 'exactOutput', + exactInputWithFeeToken = 'exactInputSingleSupportingFeeOnTransferTokens', +} + export type DexParams = { router: Address; quoter: Address; diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 96336c5e4..c8cd5335f 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -853,6 +853,10 @@ export const Tokens: { address: '0x3d9907f9a368ad0a51be60f7da3b97cf940982d8', decimals: 18, }, + RDPX: { + address: '0x32eb7902d4134bf98a28b963d26de779af92a212', + decimals: 18, + }, }, [Network.OPTIMISM]: { DAI: { @@ -1145,12 +1149,13 @@ export const Holders: { AMPL: '0xfcaA5ea7F8eb0631BcA72C345025C0A5a6D93f0E', }, [Network.ARBITRUM]: { + RDPX: '0x2fa6f21ecfe274f594f470c376f5bdd061e08a37', ARB: '0xb65edba80a3d81903ecd499c8eb9cf0e19096bd0', ETH: '0xF977814e90dA44bFA03b6295A0616a897441aceC', DAI: '0x07d7f291e731a41d3f0ea4f1ae5b6d920ffb3fe0', WETH: '0xc31e54c7a869b9fcbecc14363cf510d1c41fa443', USDCe: '0x62383739d68dd0f844103db8dfb05a7eded5bbe6', - USDC: '0xa843392198862f98d17e3aa1421b08f2c2020cff', + USDC: '0x489ee077994b6658eafa855c308275ead8097c4a', OHM: '0xebce5f29ff5ca9aa330ebdf7ec6b5f474bff271e', USDT: '0x5ff47d4ab75bcaff6807c81f1367abb53439883c', POPS: '0x4b78b52e7de4d8b7d367297cb8a87c1875a9d591', From 195796e43568804cff18728471531e52a1df1d4e Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Fri, 24 Nov 2023 22:14:25 +0200 Subject: [PATCH 666/833] algebra: fork uniswap & add feeOnTransfer handling --- src/config.ts | 3 +- src/dex/algebra/algebra-e2e.test.ts | 8 +- src/dex/algebra/algebra.ts | 116 ++++++++++++++++------------ src/dex/algebra/config.ts | 3 +- src/dex/algebra/types.ts | 5 +- 5 files changed, 76 insertions(+), 59 deletions(-) diff --git a/src/config.ts b/src/config.ts index 0886ebf6a..3a5e26392 100644 --- a/src/config.ts +++ b/src/config.ts @@ -281,7 +281,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], adapterAddresses: { ArbitrumAdapter01: '0xD8134ACfc9c71Ab51452b5bA23A31354F4739032', - ArbitrumAdapter02: '0x248009f6F78b5AcD5EA2fc86d56b77A7AeEe2eFc', + // temporary address, tenderly fork + ArbitrumAdapter02: '0x9a9CDf4c155Ac58044CcA2D7a21d058d44d331e7', ArbitrumBuyAdapter: '0xEECA9223063bD13e8ca77ed9e39a07f2BD1923E6', }, uniswapV2ExchangeRouterAddress: diff --git a/src/dex/algebra/algebra-e2e.test.ts b/src/dex/algebra/algebra-e2e.test.ts index b8bfe4c43..448102f22 100644 --- a/src/dex/algebra/algebra-e2e.test.ts +++ b/src/dex/algebra/algebra-e2e.test.ts @@ -81,13 +81,13 @@ function testForNetwork( SwapSide.SELL, [ ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, ], ], // TODO: If buy is not supported remove the buy contract methods - // [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], - [SwapSide.BUY, [ContractMethod.simpleBuy]], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], + // [SwapSide.BUY, [ContractMethod.simpleBuy]], ]); describe(`${network}`, () => { diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 29a785561..5c999b09f 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -28,8 +28,6 @@ import { IDex } from '../../dex/idex'; import { IDexHelper } from '../../dex-helper/idex-helper'; import { AlgebraData, - AlgebraDataWithFee, - AlgebraDataWithoutFee, AlgebraFunctions, DexParams, IAlgebraPoolState, @@ -424,6 +422,12 @@ export class Algebra extends SimpleExchange implements IDex { amounts: bigint[], side: SwapSide, pool: IAlgebraEventPool, + transferFees: TransferFeeParams = { + srcFee: 0, + destFee: 0, + srcDexFee: 0, + destDexFee: 0, + }, ): Promise | null> { if (!this.config.forceRPC) { this.logger.warn( @@ -431,6 +435,11 @@ export class Algebra extends SimpleExchange implements IDex { ); } + const _isSrcTokenTransferFeeToBeExchanged = + isSrcTokenTransferFeeToBeExchanged(transferFees); + const _isDestTokenTransferFeeToBeExchanged = + isDestTokenTransferFeeToBeExchanged(transferFees); + const unitVolume = getBigIntPow( (side === SwapSide.SELL ? from : to).decimals, ); @@ -445,7 +454,16 @@ export class Algebra extends SimpleExchange implements IDex { ), ); - const calldata = _amounts.map(_amount => ({ + const _amountsWithFee = _isSrcTokenTransferFeeToBeExchanged + ? applyTransferFee( + _amounts, + side, + transferFees.srcDexFee, + this.SRC_TOKEN_DEX_TRANSFERS, + ) + : _amounts; + + const calldata = _amountsWithFee.map(_amount => ({ target: this.config.quoter, gasLimit: ALGEBRA_QUOTE_GASLIMIT, callData: @@ -486,12 +504,22 @@ export class Algebra extends SimpleExchange implements IDex { : Math.round(totalGasCost / totalSuccessFullSwaps); let i = 0; - const _rates = _amounts.map(() => decode(i++)); - const unit: bigint = _rates[0]; + const _rates = _amountsWithFee.map(() => decode(i++)); + + const _ratesWithFee = _isDestTokenTransferFeeToBeExchanged + ? applyTransferFee( + _rates, + side, + transferFees.destDexFee, + this.DEST_TOKEN_DEX_TRANSFERS, + ) + : _rates; + + const unit: bigint = _ratesWithFee[0]; const prices = interpolate( - _amounts.slice(1), - _rates.slice(1), + _amountsWithFee.slice(1), + _ratesWithFee.slice(1), amounts, side, ); @@ -501,6 +529,7 @@ export class Algebra extends SimpleExchange implements IDex { prices, unit, data: { + feeOnTransfer: _isSrcTokenTransferFeeToBeExchanged, path: [ { tokenIn: from.address, @@ -539,6 +568,11 @@ export class Algebra extends SimpleExchange implements IDex { _destToken, ); + const _isSrcTokenTransferFeeToBeExchanged = + isSrcTokenTransferFeeToBeExchanged(transferFees); + const _isDestTokenTransferFeeToBeExchanged = + isDestTokenTransferFeeToBeExchanged(transferFees); + if (_srcAddress === _destAddress) return null; if ( @@ -547,9 +581,15 @@ export class Algebra extends SimpleExchange implements IDex { return null; const pool = await this.getPool(_srcAddress, _destAddress, blockNumber); - if (!pool) return null; + if (_isSrcTokenTransferFeeToBeExchanged && side == SwapSide.BUY) { + this.logger.error( + `pool: ${pool.poolAddress} doesn't support buy for tax srcToken ${srcToken.address}`, + ); + return null; + } + if (this.config.forceRPC) { const rpcPrice = await this.getPricingFromRpc( _srcToken, @@ -557,6 +597,7 @@ export class Algebra extends SimpleExchange implements IDex { amounts, side, pool, + transferFees, ); return rpcPrice; @@ -591,6 +632,7 @@ export class Algebra extends SimpleExchange implements IDex { amounts, side, pool, + transferFees, ); return rpcPrice; @@ -622,18 +664,6 @@ export class Algebra extends SimpleExchange implements IDex { const balanceDestToken = _destAddress === pool.token0 ? state.balance0 : state.balance1; - const _isSrcTokenTransferFeeToBeExchanged = - isSrcTokenTransferFeeToBeExchanged(transferFees); - const _isDestTokenTransferFeeToBeExchanged = - isDestTokenTransferFeeToBeExchanged(transferFees); - - if (_isSrcTokenTransferFeeToBeExchanged && side == SwapSide.BUY) { - this.logger.error( - `pool: ${pool.poolAddress} doesn't support buy for tax srcToken ${srcToken.address}`, - ); - return null; - } - const [unitAmountWithFee, ...amountsWithFee] = _isSrcTokenTransferFeeToBeExchanged ? applyTransferFee( @@ -694,19 +724,15 @@ export class Algebra extends SimpleExchange implements IDex { { unit: unitResultWithFee, prices, - data: _isSrcTokenTransferFeeToBeExchanged - ? { + data: { + feeOnTransfer: _isSrcTokenTransferFeeToBeExchanged, + path: [ + { tokenIn: _srcAddress, tokenOut: _destAddress, - } - : { - path: [ - { - tokenIn: _srcAddress, - tokenOut: _destAddress, - }, - ], }, + ], + }, poolIdentifier: this.getPoolIdentifier(pool.token0, pool.token1), exchange: this.dexKey, gasCost: gasCost, @@ -732,25 +758,20 @@ export class Algebra extends SimpleExchange implements IDex { data: AlgebraData, side: SwapSide, ): AdapterExchangeParam { - let path; - if (this.isAlgebraDataWithoutFee(data)) { - path = this._encodePath(data.path, side); - } else { - path = this._encodePath([{ ...data }], side); - } - // const { path: rawPath } = data; - // const path = this._encodePath(rawPath, side); + let path = this._encodePath(data.path, side); const payload = this.abiCoder.encodeParameter( { ParentStruct: { path: 'bytes', deadline: 'uint256', + feeOnTransfer: 'bool', }, }, { path, deadline: getLocalDeadlineAsFriendlyPlaceholder(), // FIXME: more gas efficient to pass block.timestamp in adapter + feeOnTransfer: data.feeOnTransfer, }, ); @@ -786,10 +807,6 @@ export class Algebra extends SimpleExchange implements IDex { return arr; } - isAlgebraDataWithoutFee(data: AlgebraData): data is AlgebraDataWithoutFee { - return (data as AlgebraDataWithoutFee).path !== undefined; - } - async getSimpleParam( srcToken: string, destToken: string, @@ -798,11 +815,10 @@ export class Algebra extends SimpleExchange implements IDex { data: AlgebraData, side: SwapSide, ): Promise { - const withoutFee = this.isAlgebraDataWithoutFee(data); let swapFunction; let swapParams; - if (!withoutFee) { + if (data.feeOnTransfer) { swapFunction = AlgebraFunctions.exactInputWithFeeToken; swapParams = { limitSqrtPrice: '0', @@ -810,10 +826,14 @@ export class Algebra extends SimpleExchange implements IDex { deadline: getLocalDeadlineAsFriendlyPlaceholder(), amountIn: srcAmount, amountOutMinimum: destAmount, - tokenIn: data.tokenIn, - tokenOut: data.tokenOut, + tokenIn: data.path[0].tokenIn, + tokenOut: data.path[0].tokenOut, }; } else { + swapFunction = + side === SwapSide.SELL + ? AlgebraFunctions.exactInput + : AlgebraFunctions.exactOutput; const path = this._encodePath(data.path, side); swapParams = side === SwapSide.SELL @@ -831,10 +851,6 @@ export class Algebra extends SimpleExchange implements IDex { amountInMaximum: srcAmount, path, }; - swapFunction = - side === SwapSide.SELL - ? AlgebraFunctions.exactInput - : AlgebraFunctions.exactOutput; } const swapData = this.routerIface.encodeFunctionData(swapFunction, [ diff --git a/src/dex/algebra/config.ts b/src/dex/algebra/config.ts index 1e9390b8d..6c66458ff 100644 --- a/src/dex/algebra/config.ts +++ b/src/dex/algebra/config.ts @@ -98,7 +98,8 @@ export const Adapters: Record = { [SwapSide.BUY]: [{ name: 'PolygonZkEvmBuyAdapter', index: 1 }], }, [Network.ARBITRUM]: { - [SwapSide.SELL]: [{ name: 'ArbitrumAdapter01', index: 3 }], + // [SwapSide.SELL]: [{ name: 'ArbitrumAdapter01', index: 3 }], + [SwapSide.SELL]: [{ name: 'ArbitrumAdapter02', index: 7 }], [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 2 }], }, [Network.OPTIMISM]: { diff --git a/src/dex/algebra/types.ts b/src/dex/algebra/types.ts index 9899eba98..195a85e9a 100644 --- a/src/dex/algebra/types.ts +++ b/src/dex/algebra/types.ts @@ -53,13 +53,12 @@ export type PoolState_v1_9 = { export type FactoryState = Record; -export type AlgebraData = AlgebraDataWithoutFee | AlgebraDataWithFee; - -export type AlgebraDataWithoutFee = { +export type AlgebraData = { path: { tokenIn: Address; tokenOut: Address; }[]; + feeOnTransfer: boolean; isApproved?: boolean; }; From f13730970f656ac46854cbb39e7bad6455bda876 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Mon, 27 Nov 2023 19:05:29 +0200 Subject: [PATCH 667/833] chore(algebra): remove unrelevant comment --- src/dex/algebra/algebra.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index 5c999b09f..ef78823b8 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -103,7 +103,7 @@ export class Algebra extends SimpleExchange implements IDex { dexKey: string, protected dexHelper: IDexHelper, protected adapters = Adapters[network] || {}, - readonly routerIface = new Interface(SwapRouter), // same abi as uniswapV3 + readonly routerIface = new Interface(SwapRouter), readonly quoterIface = new Interface(AlgebraQuoterABI), readonly config = AlgebraConfig[dexKey][network], ) { From a111c6773ab672a09713e5e664075209da78a38b Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Mon, 27 Nov 2023 20:34:18 +0200 Subject: [PATCH 668/833] algebra: update ArbitrumAdapter02 --- src/config.ts | 3 +- src/dex/algebra/algebra-e2e.test.ts | 117 ++++++++++++++-------------- src/dex/algebra/config.ts | 1 - 3 files changed, 61 insertions(+), 60 deletions(-) diff --git a/src/config.ts b/src/config.ts index 3a5e26392..d81eb806a 100644 --- a/src/config.ts +++ b/src/config.ts @@ -281,8 +281,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], adapterAddresses: { ArbitrumAdapter01: '0xD8134ACfc9c71Ab51452b5bA23A31354F4739032', - // temporary address, tenderly fork - ArbitrumAdapter02: '0x9a9CDf4c155Ac58044CcA2D7a21d058d44d331e7', + ArbitrumAdapter02: '0x7b0c7f946c845bb0d43ad41ece7027e1fc11bea7', ArbitrumBuyAdapter: '0xEECA9223063bD13e8ca77ed9e39a07f2BD1923E6', }, uniswapV2ExchangeRouterAddress: diff --git a/src/dex/algebra/algebra-e2e.test.ts b/src/dex/algebra/algebra-e2e.test.ts index 448102f22..9aaa162b9 100644 --- a/src/dex/algebra/algebra-e2e.test.ts +++ b/src/dex/algebra/algebra-e2e.test.ts @@ -95,6 +95,9 @@ function testForNetwork( describe(`${side}`, () => { contractMethods.forEach((contractMethod: ContractMethod) => { describe(`${contractMethod}`, () => { + // if src token is tax token and BUY side, then should fail (skip) + if (!!transferFees?.srcDexFee && side === SwapSide.BUY) return; + it(`${tokenASymbol} -> ${tokenBSymbol}`, async () => { await testE2E( tokens[tokenASymbol], @@ -177,73 +180,73 @@ function testForNetwork( } describe('Algebra', () => { - // describe('QuickSwapV3 E2E', () => { - // const dexKey = 'QuickSwapV3'; + describe('QuickSwapV3 E2E', () => { + const dexKey = 'QuickSwapV3'; - // describe('Polygon', () => { - // const network = Network.POLYGON; - // const tokenASymbol: string = 'USDC'; - // const tokenBSymbol: string = 'DAI'; + describe('Polygon', () => { + const network = Network.POLYGON; + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'DAI'; - // const tokenAAmount: string = '1000000000'; - // const tokenBAmount: string = '1000000000000000000000'; - // const nativeTokenAmount = '1000000000000000000'; + const tokenAAmount: string = '1000000000'; + const tokenBAmount: string = '1000000000000000000000'; + const nativeTokenAmount = '1000000000000000000'; - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // nativeTokenAmount, - // ); - // }); - // }); + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + }); - // describe('ZyberSwapV3', () => { - // const dexKey = 'ZyberSwapV3'; + describe('ZyberSwapV3', () => { + const dexKey = 'ZyberSwapV3'; - // describe('Arbitrum', () => { - // const network = Network.ARBITRUM; - // const tokenASymbol: string = 'USDC'; - // const tokenBSymbol: string = 'DAI'; + describe('Arbitrum', () => { + const network = Network.ARBITRUM; + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'DAI'; - // const tokenAAmount: string = '1000000000'; - // const tokenBAmount: string = '1000000000000000000000'; - // const nativeTokenAmount = '1000000000000000000'; + const tokenAAmount: string = '1000000000'; + const tokenBAmount: string = '1000000000000000000000'; + const nativeTokenAmount = '1000000000000000000'; - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // nativeTokenAmount, - // ); - // }); + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); - // describe('Optimism', () => { - // const network = Network.OPTIMISM; - // const tokenASymbol: string = 'USDC'; - // const tokenBSymbol: string = 'USDT'; + describe('Optimism', () => { + const network = Network.OPTIMISM; + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; - // const tokenAAmount: string = '100000000'; - // const tokenBAmount: string = '50000'; - // const nativeTokenAmount = '100000000000000'; + const tokenAAmount: string = '100000000'; + const tokenBAmount: string = '50000'; + const nativeTokenAmount = '100000000000000'; - // testForNetwork( - // network, - // dexKey, - // tokenASymbol, - // tokenBSymbol, - // tokenAAmount, - // tokenBAmount, - // nativeTokenAmount, - // ); - // }); - // }); + testForNetwork( + network, + dexKey, + tokenASymbol, + tokenBSymbol, + tokenAAmount, + tokenBAmount, + nativeTokenAmount, + ); + }); + }); describe('CamelotV3', () => { const dexKey = 'CamelotV3'; diff --git a/src/dex/algebra/config.ts b/src/dex/algebra/config.ts index 6c66458ff..b8a64c3e0 100644 --- a/src/dex/algebra/config.ts +++ b/src/dex/algebra/config.ts @@ -98,7 +98,6 @@ export const Adapters: Record = { [SwapSide.BUY]: [{ name: 'PolygonZkEvmBuyAdapter', index: 1 }], }, [Network.ARBITRUM]: { - // [SwapSide.SELL]: [{ name: 'ArbitrumAdapter01', index: 3 }], [SwapSide.SELL]: [{ name: 'ArbitrumAdapter02', index: 7 }], [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 2 }], }, From a9ced7cc8423df43d6b27a272ecdf31ead75278a Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Mon, 27 Nov 2023 20:36:31 +0200 Subject: [PATCH 669/833] 2.42.19 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ce17ac968..f8d90fede 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.18", + "version": "2.42.19", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 6834650cd7a9436407fe54080213e3004575d11e Mon Sep 17 00:00:00 2001 From: David Bouba Date: Mon, 27 Nov 2023 20:29:13 +0100 Subject: [PATCH 670/833] feature: updated swaap-v2 gas estimates --- src/dex/swaap-v2/constants.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/swaap-v2/constants.ts b/src/dex/swaap-v2/constants.ts index 4e9f6f996..8c6684abf 100644 --- a/src/dex/swaap-v2/constants.ts +++ b/src/dex/swaap-v2/constants.ts @@ -30,9 +30,9 @@ export const SWAAP_429_TTL_S = 60 * 60 * 1; // 1 hour export const SWAAP_POOL_RESTRICT_TTL_S = 60 * 30; // 30 minutes -export const STABLE_SWAP_GAS_COST_ESTIMATION = 105_000; +export const STABLE_SWAP_GAS_COST_ESTIMATION = 130_000; -export const VOLATILE_SWAP_GAS_COST_ESTIMATION = 135_000; +export const VOLATILE_SWAP_GAS_COST_ESTIMATION = 150_000; export const BATCH_SWAP_SELECTOR = '0x945bcec9'; From cc77b2265ccfdce8656e9bc9cb4b768d0b86df2f Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 28 Nov 2023 11:52:54 +0200 Subject: [PATCH 671/833] 2.42.19-swaap-gas-update.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ce17ac968..5dc58caaf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.18", + "version": "2.42.19-swaap-gas-update.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 6d448048c6f965da926737b3b928e37ba815464b Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 28 Nov 2023 13:42:12 +0200 Subject: [PATCH 672/833] swaap: use correct relative path --- src/dex/swaap-v2/stable-coins.ts | 3 +-- src/dex/swaap-v2/utils.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/dex/swaap-v2/stable-coins.ts b/src/dex/swaap-v2/stable-coins.ts index f1c10831f..a634f39c9 100644 --- a/src/dex/swaap-v2/stable-coins.ts +++ b/src/dex/swaap-v2/stable-coins.ts @@ -1,5 +1,4 @@ -import { Token } from '../../../src/types'; -import { Network } from '../../../src/constants'; +import { Network } from '../../constants'; // addresses must be consistant with utils.normalizeTokenAddress export const STABLE_COINS: { diff --git a/src/dex/swaap-v2/utils.ts b/src/dex/swaap-v2/utils.ts index 32bdcbb39..54458372c 100644 --- a/src/dex/swaap-v2/utils.ts +++ b/src/dex/swaap-v2/utils.ts @@ -1,6 +1,6 @@ import { Address, Token } from '../../types'; import { ETHER_ADDRESS, NULL_ADDRESS } from '../../constants'; -import { Network } from '../../../src/constants'; +import { Network } from '../../constants'; import { STABLE_COINS } from './stable-coins'; export const getIdentifierPrefix = ( From 44e7cada4fc2ebb350627296f74a8418c2306e20 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 28 Nov 2023 13:43:13 +0200 Subject: [PATCH 673/833] 2.42.19-swaap-gas-update-v1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5dc58caaf..480d01e38 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.19-swaap-gas-update.0", + "version": "2.42.19-swaap-gas-update-v1.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e98152039e37b736c2f8049b8ae0016341c1022f Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 28 Nov 2023 14:15:54 +0200 Subject: [PATCH 674/833] swaap: replace == with === --- src/dex/swaap-v2/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/swaap-v2/utils.ts b/src/dex/swaap-v2/utils.ts index 54458372c..ee7572b7d 100644 --- a/src/dex/swaap-v2/utils.ts +++ b/src/dex/swaap-v2/utils.ts @@ -36,7 +36,7 @@ export const isStablePair = ( normalizedDestTokenAddress: string, ): boolean => { const networkStableCoins = STABLE_COINS[network]; - if (networkStableCoins == undefined) { + if (networkStableCoins === undefined) { return false; } return ( From 6925e71e8287d3a510bbbff7c84351eee06ad7db Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 28 Nov 2023 14:20:35 +0200 Subject: [PATCH 675/833] 2.42.20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 480d01e38..ff22f8b63 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.19-swaap-gas-update-v1.0", + "version": "2.42.20", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 28ad4353f331ba4aa6001b41f187f2dab5a57f52 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 28 Nov 2023 14:38:49 +0200 Subject: [PATCH 676/833] 2.42.21-algebra-tax-tokens --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f8d90fede..3b37d93e4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.19", + "version": "2.42.21-algebra-tax-tokens", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From fc2df07a9803821a98f3f437f18fb0b0ae13e768 Mon Sep 17 00:00:00 2001 From: cicixxue Date: Tue, 28 Nov 2023 09:59:58 -0500 Subject: [PATCH 677/833] Update Contract Call function name --- src/dex/hashflow/hashflow.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/hashflow/hashflow.ts b/src/dex/hashflow/hashflow.ts index 5faf8ea5e..19e13ef8d 100644 --- a/src/dex/hashflow/hashflow.ts +++ b/src/dex/hashflow/hashflow.ts @@ -862,7 +862,7 @@ export class Hashflow extends SimpleExchange implements IDex { ); // Encode here the transaction arguments - const swapData = this.routerInterface.encodeFunctionData('tradeSingleHop', [ + const swapData = this.routerInterface.encodeFunctionData('tradeRFQT', [ [ quoteData.pool, quoteData.externalAccount ?? ZERO_ADDRESS, From 9f3844e6e1202f10aca38735205aa65d494a9767 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 28 Nov 2023 17:40:19 +0200 Subject: [PATCH 678/833] fix: remove `deadline` from `getAdapterParam` --- src/dex/wombat/wombat.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 062f8b481..3fb775e74 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -260,9 +260,6 @@ export class Wombat extends SimpleExchange implements IDex { return CALLDATA_GAS_COST.DEX_NO_PAYLOAD; } - // Encode params required by the exchange adapter - // Used for multiSwap, buy & megaSwap - // Hint: abiCoder.encodeParameter() could be useful getAdapterParam( srcToken: string, destToken: string, @@ -273,18 +270,9 @@ export class Wombat extends SimpleExchange implements IDex { ): AdapterExchangeParam { const { exchange } = data; - const payload = this.abiCoder.encodeParameter( - { - ParentStruct: { - deadline: 'uint256', - }, - }, - { deadline: getLocalDeadlineAsFriendlyPlaceholder() }, - ); - return { targetExchange: exchange, - payload, + payload: '0x', networkFee: '0', }; } From dfb85a72daf25deb6471c033e7f0ec3809cbac0d Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 28 Nov 2023 20:24:00 +0200 Subject: [PATCH 679/833] 2.42.20-hashflow-v3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 415398339..afcc855e5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.20", + "version": "2.42.20-hashflow-v3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 752b83c2853777b0a353b180d671c8c2d501ec40 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 28 Nov 2023 21:55:15 +0200 Subject: [PATCH 680/833] algebra: add check for multihop onFeeTransfer for adapter --- src/dex/algebra/algebra.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/dex/algebra/algebra.ts b/src/dex/algebra/algebra.ts index ef78823b8..86cf53eeb 100644 --- a/src/dex/algebra/algebra.ts +++ b/src/dex/algebra/algebra.ts @@ -819,6 +819,12 @@ export class Algebra extends SimpleExchange implements IDex { let swapParams; if (data.feeOnTransfer) { + _require( + data.path.length !== 1, + `LOGIC ERROR: multihop is not supported for feeOnTransfer token, passed: ${data.path + .map(p => `${p?.tokenIn}->${p?.tokenOut}`) + .join(' ')}`, + ); swapFunction = AlgebraFunctions.exactInputWithFeeToken; swapParams = { limitSqrtPrice: '0', From 866a9dc49d20af12b0a71b9c5e18256dd6f32c85 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 28 Nov 2023 21:55:44 +0200 Subject: [PATCH 681/833] 2.42.21 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3b37d93e4..281529b1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.21-algebra-tax-tokens", + "version": "2.42.21", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 0c7495361f53841201758a5136752505e52f8d62 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 28 Nov 2023 22:00:42 +0200 Subject: [PATCH 682/833] 2.42.22 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 281529b1b..5b952cd56 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.21", + "version": "2.42.22", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 2a5c6ee7d5fc47158f27ed8b4b430685e6d17b50 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 30 Nov 2023 11:38:52 +0200 Subject: [PATCH 683/833] fix: update adapters --- src/config.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/config.ts b/src/config.ts index 0886ebf6a..937766ff4 100644 --- a/src/config.ts +++ b/src/config.ts @@ -51,9 +51,9 @@ const baseConfigs: { [network: number]: BaseConfig } = { adapterAddresses: { Adapter01: '0x9bE264469eF954c139Da4A45Cf76CbCC5e3A6A73', Adapter02: '0xFC2Ba6E830a04C25e207B8214b26d8C713F6881F', - Adapter03: '0xfb2a3de6c7B8c77b520E3da16021f3D8A4E93168', + Adapter03: '0xBAEeb4540f59d30E567a5B563CC0c4587eDd9366', Adapter04: '0x654dE10890f8B2C5bF54E50Af169a7E93165C416', - BuyAdapter: '0x1310dE2C69e9753bee19B5522bad39c5f788efd9', + BuyAdapter: '0x84bEF12C9931cE12662cc9F2366b6a5029E4BD29', BuyAdapter02: '0xA10c9a84E72d9DfF424Fe2284B6460784bed407E', }, uniswapV2ExchangeRouterAddress: @@ -165,8 +165,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_56`]?.split(',') || [], adapterAddresses: { BscAdapter01: '0xA31d9C571DF00e0F428B0bD24c34D103E8112222', - BscAdapter02: '0xEECA9223063bD13e8ca77ed9e39a07f2BD1923E6', - BscBuyAdapter: '0x301c2813e3ceb43A448a12f21551EDBcdC37F157', + BscAdapter02: '0x84bEF12C9931cE12662cc9F2366b6a5029E4BD29', + BscBuyAdapter: '0xBAEeb4540f59d30E567a5B563CC0c4587eDd9366', }, rpcPollingMaxAllowedStateDelayInBlocks: 1, rpcPollingBlocksBackToTriggerUpdate: 1, @@ -193,8 +193,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_137`]?.split(',') || [], adapterAddresses: { PolygonAdapter01: '0xE44769f42E1e9592f86B82f206407a8f7C84b4ed', - PolygonAdapter02: '0x654cD2Cf97D23059B3db4FaA38BB2b1F8351211d', - PolygonBuyAdapter: '0x4426a1F87Ee7e366542c58e29c02AFa2b5878b37', + PolygonAdapter02: '0xEECA9223063bD13e8ca77ed9e39a07f2BD1923E6', + PolygonBuyAdapter: '0xA10c9a84E72d9DfF424Fe2284B6460784bed407E', }, uniswapV2ExchangeRouterAddress: '0xf3938337F7294fEf84e9B2c6D548A93F956Cc281', @@ -224,8 +224,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { dexalotAuthToken: process.env.API_KEY_DEXALOT_AUTH_TOKEN || '', adapterAddresses: { AvalancheAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9', - AvalancheAdapter02: '0x2cdB0cDc2a9321ac2ED5b741828a5216C265Be80', - AvalancheBuyAdapter: '0x9Aa41A24A10af2a965A6D406b913a7Cd9C6886ea', + AvalancheAdapter02: '0xA10c9a84E72d9DfF424Fe2284B6460784bed407E', + AvalancheBuyAdapter: '0x654dE10890f8B2C5bF54E50Af169a7E93165C416', }, uniswapV2ExchangeRouterAddress: '0x53e693c6C7FFC4446c53B205Cf513105Bf140D7b', @@ -280,9 +280,9 @@ const baseConfigs: { [network: number]: BaseConfig } = { hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], adapterAddresses: { - ArbitrumAdapter01: '0xD8134ACfc9c71Ab51452b5bA23A31354F4739032', - ArbitrumAdapter02: '0x248009f6F78b5AcD5EA2fc86d56b77A7AeEe2eFc', - ArbitrumBuyAdapter: '0xEECA9223063bD13e8ca77ed9e39a07f2BD1923E6', + ArbitrumAdapter01: '0x369A2FDb910d432f0a07381a5E3d27572c876713', + ArbitrumAdapter02: '0xe07678E5Fd104cbabb239049148b8a4E9dA5d07E', + ArbitrumBuyAdapter: '0xe53d24CD81cC81bbf271AD7B02D0d67f851D727c', }, uniswapV2ExchangeRouterAddress: '0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC', @@ -310,8 +310,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_10`]?.split(',') || [], adapterAddresses: { - OptimismAdapter01: '0x3ad7f275E27AC579cA88e0b4765828242A9E8C49', - OptimismBuyAdapter: '0xfdDD975FE4c1af20c24A3Ad2b33e8609a62DDC73', + OptimismAdapter01: '0x654dE10890f8B2C5bF54E50Af169a7E93165C416', + OptimismBuyAdapter: '0xA10c9a84E72d9DfF424Fe2284B6460784bed407E', }, uniswapV2ExchangeRouterAddress: '0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC', @@ -366,7 +366,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', hashFlowDisabledMMs: [], adapterAddresses: { - BaseAdapter01: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', + BaseAdapter01: '0x654dE10890f8B2C5bF54E50Af169a7E93165C416', BaseBuyAdapter: '0xB11bCA7B01b425afD0743A4D77B4f593883f94C0', }, uniswapV2ExchangeRouterAddress: From 145f97e7afa88a7a628ae4ac494eee940ae92d3f Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Thu, 30 Nov 2023 15:17:52 +0000 Subject: [PATCH 684/833] chore: increase min slippage factor threshold --- src/dex/dexalot/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/dexalot/constants.ts b/src/dex/dexalot/constants.ts index 458ff9010..4d1dc589f 100644 --- a/src/dex/dexalot/constants.ts +++ b/src/dex/dexalot/constants.ts @@ -27,6 +27,6 @@ export const DEXALOT_RESTRICT_TTL_S = 60 * 30; // 30 minutes export const DEXALOT_RESTRICTED_CACHE_KEY = 'restricted'; export const DEXALOT_MIN_SLIPPAGE_FACTOR_THRESHOLD_FOR_RESTRICTION = - new BigNumber('0.001'); + new BigNumber('0.005'); export const DEXALOT_FIRM_QUOTE_TIMEOUT_MS = 2000; From 7091c7f779fee9c13f2e6ae37c7d66c04d15c526 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 30 Nov 2023 18:36:39 +0300 Subject: [PATCH 685/833] 2.42.23-dexalot-increase-min-slippage-factor-threshold --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5b952cd56..8d75f1bd9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.22", + "version": "2.42.23-dexalot-increase-min-slippage-factor-threshold", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 5ab58d22f7897119232edbaa2e7af998de148ed2 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 30 Nov 2023 19:39:39 +0200 Subject: [PATCH 686/833] fix: change holders --- tests/constants-e2e.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 96336c5e4..88a790ffc 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1150,7 +1150,7 @@ export const Holders: { DAI: '0x07d7f291e731a41d3f0ea4f1ae5b6d920ffb3fe0', WETH: '0xc31e54c7a869b9fcbecc14363cf510d1c41fa443', USDCe: '0x62383739d68dd0f844103db8dfb05a7eded5bbe6', - USDC: '0xa843392198862f98d17e3aa1421b08f2c2020cff', + USDC: '0x463f5d63e5a5edb8615b0e485a090a18aba08578', OHM: '0xebce5f29ff5ca9aa330ebdf7ec6b5f474bff271e', USDT: '0x5ff47d4ab75bcaff6807c81f1367abb53439883c', POPS: '0x4b78b52e7de4d8b7d367297cb8a87c1875a9d591', @@ -1173,7 +1173,7 @@ export const Holders: { DAI: '0x1337bedc9d22ecbe766df105c9623922a27963ec', WETH: '0x68F5C0A2DE713a54991E01858Fd27a3832401849', POPS: '0x3cbd9044aaabef08ce93a68448e093cff405ad76', - USDC: '0xEBb8EA128BbdFf9a1780A4902A9380022371d466', + USDC: ' 0x9f7b6e20bc64f12adaabeb739ead802fc7765d03', USDT: '0xEBb8EA128BbdFf9a1780A4902A9380022371d466', OP: '0xEBb8EA128BbdFf9a1780A4902A9380022371d466', aOptWETH: '0x7B7D80C40415F744864f051B806b466e2fbB8E68', From 3ff2b9bb156b9746c1605e6460996f86328396d9 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 30 Nov 2023 19:40:45 +0200 Subject: [PATCH 687/833] 2.42.20-hashflow-v3.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index afcc855e5..a51dc1880 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.20-hashflow-v3", + "version": "2.42.20-hashflow-v3.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 599adb15ecf5e820b26630c42775dc465d607bb8 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 30 Nov 2023 20:21:43 +0200 Subject: [PATCH 688/833] fix: update arb adapter --- src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index 937766ff4..4e62e1e00 100644 --- a/src/config.ts +++ b/src/config.ts @@ -281,7 +281,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], adapterAddresses: { ArbitrumAdapter01: '0x369A2FDb910d432f0a07381a5E3d27572c876713', - ArbitrumAdapter02: '0xe07678E5Fd104cbabb239049148b8a4E9dA5d07E', + ArbitrumAdapter02: '0xe9166234DFB6d3ec05C82404109C02Ca82b16c22', ArbitrumBuyAdapter: '0xe53d24CD81cC81bbf271AD7B02D0d67f851D727c', }, uniswapV2ExchangeRouterAddress: From 4406ac0d64641ec5f12ea47c39009665e834b523 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 30 Nov 2023 20:22:55 +0200 Subject: [PATCH 689/833] 2.42.20-hashflow-v3.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a51dc1880..059935e34 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.20-hashflow-v3.2", + "version": "2.42.20-hashflow-v3.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From a6837b7293f280d060a752e122f78c83b63cb5f4 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Fri, 1 Dec 2023 13:56:58 +0200 Subject: [PATCH 690/833] wombat: update adapters --- src/config.ts | 10 +++++----- src/dex/wombat/config.ts | 6 +++--- tests/constants-e2e.ts | 8 +++++++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/config.ts b/src/config.ts index bb66c143b..1bd0b7ece 100644 --- a/src/config.ts +++ b/src/config.ts @@ -51,7 +51,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { adapterAddresses: { Adapter01: '0x9bE264469eF954c139Da4A45Cf76CbCC5e3A6A73', Adapter02: '0xFC2Ba6E830a04C25e207B8214b26d8C713F6881F', - Adapter03: '0xfb2a3de6c7B8c77b520E3da16021f3D8A4E93168', + Adapter03: '0xBAEeb4540f59d30E567a5B563CC0c4587eDd9366', Adapter04: '0x654dE10890f8B2C5bF54E50Af169a7E93165C416', BuyAdapter: '0x1310dE2C69e9753bee19B5522bad39c5f788efd9', BuyAdapter02: '0xA10c9a84E72d9DfF424Fe2284B6460784bed407E', @@ -166,7 +166,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { adapterAddresses: { BscAdapter01: '0xA31d9C571DF00e0F428B0bD24c34D103E8112222', // BscAdapter02: '0xEECA9223063bD13e8ca77ed9e39a07f2BD1923E6', - BscAdapter02: '0x5b8268F34993A48247Ac0d182a8A343518bca204', + BscAdapter02: '0x84bEF12C9931cE12662cc9F2366b6a5029E4BD29', BscBuyAdapter: '0x301c2813e3ceb43A448a12f21551EDBcdC37F157', }, rpcPollingMaxAllowedStateDelayInBlocks: 1, @@ -225,7 +225,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { dexalotAuthToken: process.env.API_KEY_DEXALOT_AUTH_TOKEN || '', adapterAddresses: { AvalancheAdapter01: '0x745Ec73855CeC7249E5fF4c9DD81cc65b4D297a9', - AvalancheAdapter02: '0x2cdB0cDc2a9321ac2ED5b741828a5216C265Be80', + AvalancheAdapter02: '0xA10c9a84E72d9DfF424Fe2284B6460784bed407E', AvalancheBuyAdapter: '0x9Aa41A24A10af2a965A6D406b913a7Cd9C6886ea', }, uniswapV2ExchangeRouterAddress: @@ -282,7 +282,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], adapterAddresses: { ArbitrumAdapter01: '0xD8134ACfc9c71Ab51452b5bA23A31354F4739032', - ArbitrumAdapter02: '0x248009f6F78b5AcD5EA2fc86d56b77A7AeEe2eFc', + ArbitrumAdapter02: '0xe9166234DFB6d3ec05C82404109C02Ca82b16c22', ArbitrumBuyAdapter: '0xEECA9223063bD13e8ca77ed9e39a07f2BD1923E6', }, uniswapV2ExchangeRouterAddress: @@ -367,7 +367,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', hashFlowDisabledMMs: [], adapterAddresses: { - BaseAdapter01: '0x30F6B9b6485ff0B67E881f5ac80D3F1c70A4B23d', + BaseAdapter01: '0x654dE10890f8B2C5bF54E50Af169a7E93165C416', BaseBuyAdapter: '0xB11bCA7B01b425afD0743A4D77B4f593883f94C0', }, uniswapV2ExchangeRouterAddress: diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts index 031bc286c..6b6d4d276 100644 --- a/src/dex/wombat/config.ts +++ b/src/dex/wombat/config.ts @@ -44,7 +44,7 @@ export const Adapters: Record = { [SwapSide.SELL]: [ { name: 'ArbitrumAdapter02', - index: 7, + index: 8, }, ], // [SwapSide.BUY]: [ @@ -57,8 +57,8 @@ export const Adapters: Record = { [Network.MAINNET]: { [SwapSide.SELL]: [ { - name: 'Adapter04', - index: 6, + name: 'Adapter03', + index: 15, }, ], // [SwapSide.BUY]: [ diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 3faf6748d..40218a8dc 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -768,6 +768,10 @@ export const Tokens: { }, }, [Network.ARBITRUM]: { + SEN: { + address: '0x154388a4650D63acC823e06Ef9e47C1eDdD3cBb2', + decimals: 18, + }, DAI: { address: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', decimals: 18, @@ -1149,6 +1153,8 @@ export const Holders: { BTCb: '0x84c06d3c27821d0136f66306f5028d43ceac268d', }, [Network.ARBITRUM]: { + SEN: '0xcb19b6b4971bd4206bab176c75b1efe3e28ee5a8', + RDPX: '0x2fa6f21ecfe274f594f470c376f5bdd061e08a37', ARB: '0xb65edba80a3d81903ecd499c8eb9cf0e19096bd0', ETH: '0xF977814e90dA44bFA03b6295A0616a897441aceC', DAI: '0x07d7f291e731a41d3f0ea4f1ae5b6d920ffb3fe0', @@ -1156,7 +1162,7 @@ export const Holders: { USDCe: '0x62383739d68dd0f844103db8dfb05a7eded5bbe6', USDC: '0xb38e8c17e38363af6ebdcb3dae12e0243582891d', OHM: '0xebce5f29ff5ca9aa330ebdf7ec6b5f474bff271e', - USDT: '0x5ff47d4ab75bcaff6807c81f1367abb53439883c', + USDT: '0xf977814e90da44bfa03b6295a0616a897441acec', POPS: '0x4b78b52e7de4d8b7d367297cb8a87c1875a9d591', FRAX: '0x59bf0545fca0e5ad48e13da269facd2e8c886ba4', nUSD: '0x9dd329f5411466d9e0c488ff72519ca9fef0cb40', From 0ef99d2a56d0e39ace6b9c54a13315907ebeea1a Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 1 Dec 2023 15:33:48 +0200 Subject: [PATCH 691/833] 2.42.23 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 851bbca95..2a2c0e1c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.22", + "version": "2.42.23", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From aadf7f42bd93f11ea3a69bf354adcdf3adab8023 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 4 Dec 2023 16:43:33 +0300 Subject: [PATCH 692/833] solve merge conflicts --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 8d75f1bd9..a99602d54 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "dependencies": { "@0x/utils": "^4.5.2", "@hashflow/sdk": "1.2.4", - "@hashflow/taker-js": "0.0.2", + "@hashflow/taker-js": "0.3.4", "@paraswap/core": "1.1.0", "async": "^3.2.4", "axios": "0.26.0", diff --git a/yarn.lock b/yarn.lock index 6d436ba94..ae2781615 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3912,9 +3912,9 @@ ethers@^5.6.5, ethers@^5.7.0: "@ethersproject/wordlists" "5.7.0" ethers@^6.7.0: - version "6.8.1" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.8.1.tgz#ee2a1a39b5f62a13678f90ccd879175391d0a2b4" - integrity sha512-iEKm6zox5h1lDn6scuRWdIdFJUCGg3+/aQWu0F4K0GVyEZiktFkqrJbRjTn1FlYEPz7RKA707D6g5Kdk6j7Ljg== + version "6.9.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.9.0.tgz#a4534bdcdfde306aee94ef32f3d5c70d7e33fcb9" + integrity sha512-pmfNyQzc2mseLe91FnT2vmNaTt8dDzhxZ/xItAV7uGsF4dI4ek2ufMu3rAkgQETL/TIs0GS5A+U05g9QyWnv3Q== dependencies: "@adraffy/ens-normalize" "1.10.0" "@noble/curves" "1.2.0" From 6b5eb31e8be095cc96d870158f8b9565dcd87859 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 4 Dec 2023 16:45:14 +0300 Subject: [PATCH 693/833] 2.42.24-dexalot-increase-min-slippage-factor-threshold --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a99602d54..d07857c50 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.23-dexalot-increase-min-slippage-factor-threshold", + "version": "2.42.24-dexalot-increase-min-slippage-factor-threshold", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 43cfedae06f6868be34f16fd8885b48d4bb1236b Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 4 Dec 2023 19:00:05 +0200 Subject: [PATCH 694/833] fix: add config for subgraphs & add tokens/holders --- src/config.ts | 11 +++++++++++ src/dex/index.ts | 2 ++ src/types.ts | 1 + tests/constants-e2e.ts | 21 +++++++++++++++++++++ 4 files changed, 35 insertions(+) diff --git a/src/config.ts b/src/config.ts index 4e62e1e00..766c14f4a 100644 --- a/src/config.ts +++ b/src/config.ts @@ -31,6 +31,7 @@ type BaseConfig = { hashFlowDisabledMMs: string[]; swaapV2AuthToken?: string; dexalotAuthToken?: string; + smardexSubgraphAuthToken?: string; forceRpcFallbackDexs: string[]; }; @@ -62,6 +63,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { rpcPollingBlocksBackToTriggerUpdate: 0, swaapV2AuthToken: process.env.API_KEY_SWAAP_V2_AUTH_TOKEN || '', hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_1`]?.split(',') || [], uniswapV3EventLoggingSampleRate: 0, @@ -161,6 +163,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { multicallV2Address: '0xC50F4c1E81c873B2204D7eFf7069Ffec6Fbe136D', privateHttpProvider: process.env.HTTP_PROVIDER_56, hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_56`]?.split(',') || [], adapterAddresses: { @@ -189,6 +192,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { multicallV2Address: '0x275617327c958bD06b5D6b871E7f491D76113dd8', privateHttpProvider: process.env.HTTP_PROVIDER_137, hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_137`]?.split(',') || [], adapterAddresses: { @@ -219,6 +223,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { multicallV2Address: '0xd7Fc8aD069f95B6e2835f4DEff03eF84241cF0E1', privateHttpProvider: process.env.HTTP_PROVIDER_43114, hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_43114`]?.split(',') || [], dexalotAuthToken: process.env.API_KEY_DEXALOT_AUTH_TOKEN || '', @@ -248,6 +253,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { multicallV2Address: '0xdC6E2b14260F972ad4e5a31c68294Fba7E720701', privateHttpProvider: process.env.HTTP_PROVIDER_250, hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_250`]?.split(',') || [], @@ -276,6 +282,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { multicallV2Address: '0x7eCfBaa8742fDf5756DAC92fbc8b90a19b8815bF', privateHttpProvider: process.env.HTTP_PROVIDER_42161, hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', swaapV2AuthToken: process.env.API_KEY_SWAAP_V2_AUTH_TOKEN || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], @@ -306,6 +313,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { multicallV2Address: '0x2DC0E2aa608532Da689e89e237dF582B783E552C', privateHttpProvider: process.env.HTTP_PROVIDER_10, hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_10`]?.split(',') || [], @@ -342,6 +350,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { rpcPollingMaxAllowedStateDelayInBlocks: 0, rpcPollingBlocksBackToTriggerUpdate: 0, hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_10`]?.split(',') || [], uniswapV3EventLoggingSampleRate: 0, @@ -364,6 +373,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { multicallV2Address: '0xeDF6D2a16e8081F777eB623EeB4411466556aF3d', privateHttpProvider: process.env.HTTP_PROVIDER_8453, hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', + smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', hashFlowDisabledMMs: [], adapterAddresses: { BaseAdapter01: '0x654dE10890f8B2C5bF54E50Af169a7E93165C416', @@ -417,6 +427,7 @@ export function generateConfig(network: number): Config { rpcPollingBlocksBackToTriggerUpdate: baseConfig.rpcPollingBlocksBackToTriggerUpdate, hashFlowAuthToken: baseConfig.hashFlowAuthToken, + smardexSubgraphAuthToken: baseConfig.smardexSubgraphAuthToken, swaapV2AuthToken: baseConfig.swaapV2AuthToken, dexalotAuthToken: baseConfig.dexalotAuthToken, hashFlowDisabledMMs: baseConfig.hashFlowDisabledMMs, diff --git a/src/dex/index.ts b/src/dex/index.ts index a4f58e878..cf18bd78c 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -80,6 +80,7 @@ import { Algebra } from './algebra/algebra'; import { QuickPerps } from './quick-perps/quick-perps'; import { NomiswapV2 } from './uniswap-v2/nomiswap-v2'; import { Dexalot } from './dexalot/dexalot'; +import { Smardex } from './smardex/smardex'; const LegacyDexes = [ CurveV2, @@ -157,6 +158,7 @@ const Dexes = [ SwaapV2, QuickPerps, NomiswapV2, + Smardex, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< diff --git a/src/types.ts b/src/types.ts index 4e9133013..c89e0d544 100644 --- a/src/types.ts +++ b/src/types.ts @@ -277,6 +277,7 @@ export type Config = { uniswapV3EventLoggingSampleRate?: number; swaapV2AuthToken?: string; dexalotAuthToken?: string; + smardexSubgraphAuthToken?: string; forceRpcFallbackDexs: string[]; }; diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 623f96a44..b8e32f893 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -457,6 +457,10 @@ export const Tokens: { address: '0xa3fa99a148fa48d14ed51d610c367c61876997f1', decimals: 18, }, + SDEX: { + address: '0x6899fAcE15c14348E1759371049ab64A3a06bFA6', + decimals: 18, + }, }, [Network.FANTOM]: { FTM: { address: ETHER_ADDRESS, decimals: 18 }, @@ -615,6 +619,10 @@ export const Tokens: { address: '0x1d2f0da169ceb9fc7b3144628db156f3f6c60dbe', decimals: 18, }, + SDEX: { + address: '0xFdc66A08B0d0Dc44c17bbd471B88f49F50CdD20F', + decimals: 18, + }, }, [Network.AVALANCHE]: { USDCe: { @@ -861,6 +869,10 @@ export const Tokens: { address: '0x32eb7902d4134bf98a28b963d26de779af92a212', decimals: 18, }, + SDEX: { + address: '0xabD587f2607542723b17f14d00d99b987C29b074', + decimals: 18, + }, }, [Network.OPTIMISM]: { DAI: { @@ -968,6 +980,10 @@ export const Tokens: { address: '0xbeFD5C25A59ef2C1316c5A4944931171F30Cd3E4', decimals: 18, }, + SDEX: { + address: '0xFd4330b0312fdEEC6d4225075b82E00493FF2e3f', + decimals: 18, + }, ETH: { address: ETHER_ADDRESS, decimals: 18 }, }, }; @@ -1039,6 +1055,7 @@ export const Holders: { wibBTC: '0xFbdCA68601f835b27790D98bbb8eC7f05FDEaA9B', MATIC: '0x7073783eee7e9b3e6e4ddac4d7f49dc46044dd9a', POL: '0x57B6Ad484ccdd902C4419424bA648ba6Ed45dc68', + SDEX: '0xB0470cF15B22a6A32c49a7C20E3821B944A76058', }, [Network.ROPSTEN]: { ETH: '0x43262A12d8610AA70C15DbaeAC321d51613c9071', @@ -1074,6 +1091,7 @@ export const Holders: { amUSDT: '0x832b11846a27b3ba25d68ae80c39fab155d18c49', amUSDC: '0x6e7f19cd23049c7118e14470e2bf85d2e26ee0ae', MAI: '0x9a8cf02f3e56c664ce75e395d0e4f3dc3dafe138', + SDEX: '0xB0470cF15B22a6A32c49a7C20E3821B944A76058', }, [Network.FANTOM]: { DAI: '0x370f4b2dcf75c94d8d4450b493661a9c6170d0b5', @@ -1117,6 +1135,7 @@ export const Holders: { FRAX: '0xEB4576fE753DAB07635c0Bb6c8f0A355e1Db5d31', frxETH: '0xf324adC872005197A6f7DAE214d3b63aa0C3625F', USDFI: '0x2E00D722e091836B39Db3e4dcE6eE51c90c5B221', + SDEX: '0xB0470cF15B22a6A32c49a7C20E3821B944A76058', }, [Network.AVALANCHE]: { AVAX: '0xD6216fC19DB775Df9774a6E33526131dA7D19a2c', @@ -1176,6 +1195,7 @@ export const Holders: { ZYB: '0x3ec0eddcd1e25025077327886a78133589082fb2', WBTC: '0xd9d611c6943585bc0e18e51034af8fa28778f7da', RDNT: '0x62383739d68dd0f844103db8dfb05a7eded5bbe6', + SDEX: '0xb0470cf15b22a6a32c49a7c20e3821b944a76058', }, [Network.OPTIMISM]: { ETH: '0x9ef21bE1C270AA1c3c3d750F458442397fBFFCB6', @@ -1211,6 +1231,7 @@ export const Holders: { DAI: '0x20f03e26968b179025f65c1f4afadfd3959c8d03', BAL: '0x854b004700885a61107b458f11ecc169a019b764', GOLD: '0x1374c25b3710758c326ee0c70ec48b595d5ccf8c', + SDEX: '0xa5d378c05192e3f1f365d6298921879c4d51c5a3', }, }; From 70f1a2249b9f1d83b6e7d19d77a94f3c12ebee08 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 5 Dec 2023 14:31:44 +0300 Subject: [PATCH 695/833] 2.42.24 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d07857c50..87eef33bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.24-dexalot-increase-min-slippage-factor-threshold", + "version": "2.42.24", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 28f1f5629ddc5d0a60adc5fb0d8ff62c2091ac55 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 5 Dec 2023 15:18:25 +0200 Subject: [PATCH 696/833] wombat: return doesPreProcessingRequireSequentiality --- src/dex/index.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/dex/index.ts b/src/dex/index.ts index 771c69426..46999ff6e 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -325,4 +325,13 @@ export class DexAdapterService { ? this.sellAdapters[specialDexKey] : this.buyAdapters[specialDexKey]; } + + doesPreProcessingRequireSequentiality(dexKey: string): boolean { + try { + const dex = this.getDexByKey(dexKey); + return !!dex.needsSequentialPreprocessing; + } catch (e) { + return false; + } + } } From 905b57f8e396efae54a3dda0c83a228a0f7e0ab4 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 5 Dec 2023 16:35:50 +0200 Subject: [PATCH 697/833] wombat: add new optimism adapter and update constants --- src/config.ts | 3 +-- src/dex/wombat/config.ts | 44 ++++++++----------------------- src/dex/wombat/wombat-e2e.test.ts | 21 +++++++++++++++ tests/constants-e2e.ts | 4 +-- tests/utils-e2e.ts | 3 +-- 5 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/config.ts b/src/config.ts index 1bd0b7ece..7e5423489 100644 --- a/src/config.ts +++ b/src/config.ts @@ -309,9 +309,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { hashFlowAuthToken: process.env.API_KEY_HASHFLOW_AUTH_TOKEN || '', hashFlowDisabledMMs: process.env[`HASHFLOW_DISABLED_MMS_10`]?.split(',') || [], - adapterAddresses: { - OptimismAdapter01: '0x3ad7f275E27AC579cA88e0b4765828242A9E8C49', + OptimismAdapter01: '0x5dcf544b0c9689fa67dcb713fd2656d217e25a59', OptimismBuyAdapter: '0xfdDD975FE4c1af20c24A3Ad2b33e8609a62DDC73', }, uniswapV2ExchangeRouterAddress: diff --git a/src/dex/wombat/config.ts b/src/dex/wombat/config.ts index 6b6d4d276..986d36fbe 100644 --- a/src/dex/wombat/config.ts +++ b/src/dex/wombat/config.ts @@ -19,9 +19,9 @@ export const WombatConfig: DexConfigMap = { [Network.BASE]: { bmwAddress: '0x6521a549834F5E6d253CD2e5F4fbe4048f86cd7b', }, - // [Network.OPTIMISM]: { - // bmwAddress: '0x82E62f4e174E3C5e1641Df670c91Ac6Ab8541518', - // }, + [Network.OPTIMISM]: { + bmwAddress: '0x25C9dd8a3774EF7C918cd28ff59cF9e29504C914', + }, }, }; @@ -33,12 +33,6 @@ export const Adapters: Record = { index: 7, }, ], - // [SwapSide.BUY]: [ - // { - // name: 'BscBuyAdapter', - // index: 1, - // }, - // ], }, [Network.ARBITRUM]: { [SwapSide.SELL]: [ @@ -47,12 +41,6 @@ export const Adapters: Record = { index: 8, }, ], - // [SwapSide.BUY]: [ - // { - // name: 'ArbitrumBuyAdapter', - // index: 1, - // }, - // ], }, [Network.MAINNET]: { [SwapSide.SELL]: [ @@ -61,12 +49,6 @@ export const Adapters: Record = { index: 15, }, ], - // [SwapSide.BUY]: [ - // { - // name: 'BscBuyAdapter', - // index: 1, - // }, - // ], }, [Network.AVALANCHE]: { [SwapSide.SELL]: [ @@ -75,12 +57,6 @@ export const Adapters: Record = { index: 7, }, ], - // [SwapSide.BUY]: [ - // { - // name: 'BscBuyAdapter', - // index: 1, - // }, - // ], }, [Network.BASE]: { [SwapSide.SELL]: [ @@ -89,11 +65,13 @@ export const Adapters: Record = { index: 7, }, ], - // [SwapSide.BUY]: [ - // { - // name: 'BscBuyAdapter', - // index: 1, - // }, - // ], + }, + [Network.OPTIMISM]: { + [SwapSide.SELL]: [ + { + name: 'OptimismAdapter01', + index: 12, + }, + ], }, }; diff --git a/src/dex/wombat/wombat-e2e.test.ts b/src/dex/wombat/wombat-e2e.test.ts index 138f977a2..ecafcd416 100644 --- a/src/dex/wombat/wombat-e2e.test.ts +++ b/src/dex/wombat/wombat-e2e.test.ts @@ -240,4 +240,25 @@ describe('Wombat E2E', () => { testForNetwork(network, dexKey, pairs); }); + + describe('Optimism', () => { + const network = Network.OPTIMISM; + + const pairs: Pairs = [ + [ + { + name: 'USDC', + sellAmount: '100000000', + buyAmount: '100000000', + }, + { + name: 'USDT', + sellAmount: '100000000', + buyAmount: '100000000', + }, + ], + ]; + + testForNetwork(network, dexKey, pairs); + }); }); diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 40218a8dc..f2fa18b95 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1184,8 +1184,8 @@ export const Holders: { DAI: '0x1337bedc9d22ecbe766df105c9623922a27963ec', WETH: '0x68F5C0A2DE713a54991E01858Fd27a3832401849', POPS: '0x3cbd9044aaabef08ce93a68448e093cff405ad76', - USDC: '0xEBb8EA128BbdFf9a1780A4902A9380022371d466', - USDT: '0xEBb8EA128BbdFf9a1780A4902A9380022371d466', + USDC: '0xdecc0c09c3b5f6e92ef4184125d5648a66e35298', + USDT: '0xf977814e90da44bfa03b6295a0616a897441acec', OP: '0xEBb8EA128BbdFf9a1780A4902A9380022371d466', aOptWETH: '0x7B7D80C40415F744864f051B806b466e2fbB8E68', aOptUSDC: '0x8c0Fcf914E90fF5d7f2D02c1576BF4245FaD2B7F', diff --git a/tests/utils-e2e.ts b/tests/utils-e2e.ts index 539002508..ba76b010a 100644 --- a/tests/utils-e2e.ts +++ b/tests/utils-e2e.ts @@ -85,7 +85,7 @@ const MULTISIG: { [nid: number]: string } = { [Network.POLYGON]: '0x46DF4eb6f7A3B0AdF526f6955b15d3fE02c618b7', [Network.FANTOM]: '0xECaB2dac955b94e49Ec09D6d68672d3B397BbdAd', [Network.AVALANCHE]: '0x1e2ECA5e812D08D2A7F8664D69035163ff5BfEC2', - [Network.OPTIMISM]: '0xf01121e808F782d7F34E857c27dA31AD1f151b39', + [Network.OPTIMISM]: '0x3b28A6f6291f7e8277751f2911Ac49C585d049f6', [Network.ARBITRUM]: '0x90DfD8a6454CFE19be39EaB42ac93CD850c7f339', [Network.BASE]: '0x6C674c8Df1aC663b822c4B6A56B4E5e889379AE0', }; @@ -379,7 +379,6 @@ export async function testE2E( poolIdentifiers, transferFees, ); - console.log('price route: ', util.inspect(priceRoute, false, null, true)); expect(parseFloat(priceRoute.destAmount)).toBeGreaterThan(0); // Calculate slippage. Default is 1% From 23b6e35d4634301d0cdd6c5abd20150ea2795ba6 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 5 Dec 2023 16:39:26 +0200 Subject: [PATCH 698/833] 2.42.17-wombat.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f6d5694b3..b1a7fdf37 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.16", + "version": "2.42.17-wombat.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From ebf873ff32c3e2a77b9251d79c8c80c5e2088d85 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Tue, 5 Dec 2023 16:48:12 +0200 Subject: [PATCH 699/833] 2.42.25-wombat.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 87eef33bb..8be7d2e69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.24", + "version": "2.42.25-wombat.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From ecf063f93aa74d01663da062308bb8bb4bb55748 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 5 Dec 2023 20:09:43 +0200 Subject: [PATCH 700/833] fix: update adapter config --- src/dex/smardex/config.ts | 20 +++++------ src/dex/smardex/smardex-e2e.test.ts | 51 ++++++----------------------- src/dex/smardex/smardex.ts | 11 ++++--- 3 files changed, 27 insertions(+), 55 deletions(-) diff --git a/src/dex/smardex/config.ts b/src/dex/smardex/config.ts index f6aa9e127..ae0e286d6 100644 --- a/src/dex/smardex/config.ts +++ b/src/dex/smardex/config.ts @@ -45,23 +45,23 @@ export const SmardexConfig: DexConfigMap = { export const Adapters: Record = { [Network.MAINNET]: { - [SwapSide.SELL]: [{ name: '', index: 0 }], - [SwapSide.BUY]: [{ name: '', index: 0 }], + [SwapSide.SELL]: [{ name: 'Adapter04', index: 6 }], + [SwapSide.BUY]: [{ name: 'BuyAdapter02', index: 2 }], }, [Network.ARBITRUM]: { - [SwapSide.SELL]: [{ name: '', index: 0 }], - [SwapSide.BUY]: [{ name: '', index: 0 }], + [SwapSide.SELL]: [{ name: 'ArbitrumAdapter02', index: 9 }], + [SwapSide.BUY]: [{ name: 'ArbitrumBuyAdapter', index: 9 }], }, [Network.BSC]: { - [SwapSide.SELL]: [{ name: '', index: 0 }], - [SwapSide.BUY]: [{ name: '', index: 0 }], + [SwapSide.SELL]: [{ name: 'BscAdapter02', index: 8 }], + [SwapSide.BUY]: [{ name: 'BscBuyAdapter', index: 7 }], }, [Network.POLYGON]: { - [SwapSide.SELL]: [{ name: '', index: 0 }], - [SwapSide.BUY]: [{ name: '', index: 0 }], + [SwapSide.SELL]: [{ name: 'PolygonAdapter02', index: 9 }], + [SwapSide.BUY]: [{ name: 'PolygonBuyAdapter', index: 8 }], }, [Network.BASE]: { - [SwapSide.SELL]: [{ name: '', index: 0 }], - [SwapSide.BUY]: [{ name: '', index: 0 }], + [SwapSide.SELL]: [{ name: 'BaseAdapter01', index: 8 }], + [SwapSide.BUY]: [{ name: 'BaseBuyAdapter', index: 5 }], }, }; diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index c486da5d1..b772f8150 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -7,7 +7,6 @@ import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; - function testForNetwork( network: Network, dexKey: string, @@ -25,17 +24,11 @@ function testForNetwork( SwapSide.SELL, [ ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - ], - ], - [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - // ContractMethod.buy, + ContractMethod.multiSwap, + ContractMethod.megaSwap, ], ], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], ]); sideToContractMethods.forEach((contractMethods, side) => @@ -48,9 +41,7 @@ function testForNetwork( tokens[pair[0].name], tokens[pair[1].name], holders[pair[0].name], - side === SwapSide.SELL - ? pair[0].sellAmount - : pair[0].buyAmount, + side === SwapSide.SELL ? pair[0].sellAmount : pair[0].buyAmount, side, dexKey, contractMethod, @@ -63,9 +54,7 @@ function testForNetwork( tokens[pair[1].name], tokens[pair[0].name], holders[pair[1].name], - side === SwapSide.SELL - ? pair[1].sellAmount - : pair[1].buyAmount, + side === SwapSide.SELL ? pair[1].sellAmount : pair[1].buyAmount, side, dexKey, contractMethod, @@ -113,11 +102,7 @@ describe('SmarDex E2E', () => { ], ]; - testForNetwork( - network, - dexKey, - pairs, - ); + testForNetwork(network, dexKey, pairs); }); describe('ARBITRUM', () => { @@ -150,11 +135,7 @@ describe('SmarDex E2E', () => { ], ]; - testForNetwork( - network, - dexKey, - pairs - ); + testForNetwork(network, dexKey, pairs); }); describe('BSC', () => { @@ -199,11 +180,7 @@ describe('SmarDex E2E', () => { ], ]; - testForNetwork( - network, - dexKey, - pairs - ); + testForNetwork(network, dexKey, pairs); }); describe('POLYGON', () => { @@ -260,11 +237,7 @@ describe('SmarDex E2E', () => { ], ]; - testForNetwork( - network, - dexKey, - pairs, - ); + testForNetwork(network, dexKey, pairs); }); describe('BASE', () => { @@ -297,10 +270,6 @@ describe('SmarDex E2E', () => { ], ]; - testForNetwork( - network, - dexKey, - pairs, - ); + testForNetwork(network, dexKey, pairs); }); }); diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 0c2d77453..201b476cb 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -40,7 +40,8 @@ import { SmardexRouterFunctions, directSmardexFunctionName, DefaultSmardexPoolGasCost, - SUBGRAPH_TIMEOUT, FEES_LAYER_ONE, + SUBGRAPH_TIMEOUT, + FEES_LAYER_ONE, } from '../smardex/constants'; import { SmardexData, SmardexParam } from '../smardex/types'; import { IDex } from '../..'; @@ -695,12 +696,14 @@ export class Smardex const payload = this.abiCoder.encodeParameter( { ParentStruct: { - path: 'address[] calldata', + path: 'address[]', receiver: 'address', - deadline: 'uint256' }, }, - { path: data.path, receiver: data.receiver, deadline: data.deadline }, + { + path: data.path, + receiver: data.receiver, + }, ); return { targetExchange: data.router, From f373032c82d2a69004bb511991ed30a0bd40d065 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Wed, 6 Dec 2023 13:36:47 +0200 Subject: [PATCH 701/833] wombat: remove unused errors from ABI --- src/abi/wombat/asset.json | 26 -------------- src/abi/wombat/pool.json | 75 --------------------------------------- 2 files changed, 101 deletions(-) diff --git a/src/abi/wombat/asset.json b/src/abi/wombat/asset.json index 86a045b59..588a16cbe 100644 --- a/src/abi/wombat/asset.json +++ b/src/abi/wombat/asset.json @@ -20,32 +20,6 @@ "stateMutability": "nonpayable", "type": "constructor" }, - { - "inputs": [], - "name": "ASSET_OVERFLOW", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidShortString", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "str", - "type": "string" - } - ], - "name": "StringTooLong", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_FORBIDDEN", - "type": "error" - }, { "anonymous": false, "inputs": [ diff --git a/src/abi/wombat/pool.json b/src/abi/wombat/pool.json index 33cfc0f48..c9859e9bf 100644 --- a/src/abi/wombat/pool.json +++ b/src/abi/wombat/pool.json @@ -1,79 +1,4 @@ [ - { - "inputs": [], - "name": "CORE_UNDERFLOW", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_AMOUNT_TOO_LOW", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ASSET_ALREADY_EXIST", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ASSET_ALREADY_PAUSED", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ASSET_NOT_EXISTS", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ASSET_NOT_PAUSED", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_CASH_NOT_ENOUGH", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_COV_RATIO_LIMIT_EXCEEDED", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_EXPIRED", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_FORBIDDEN", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_INVALID_VALUE", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_SAME_ADDRESS", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ZERO_ADDRESS", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ZERO_AMOUNT", - "type": "error" - }, - { - "inputs": [], - "name": "WOMBAT_ZERO_LIQUIDITY", - "type": "error" - }, { "anonymous": false, "inputs": [ From a7cb5b08801bfba64a0706d0d3696b689c72caac Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Wed, 6 Dec 2023 13:39:01 +0200 Subject: [PATCH 702/833] 2.42.25-wombat.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8be7d2e69..b5a84f342 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.25-wombat.0", + "version": "2.42.25-wombat.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 2fde8ca3728c170c99322d4a4e2a8ba7ea6e01a3 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 6 Dec 2023 15:06:47 +0200 Subject: [PATCH 703/833] fix: update adapters --- src/config.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/config.ts b/src/config.ts index 766c14f4a..096ffe233 100644 --- a/src/config.ts +++ b/src/config.ts @@ -53,9 +53,9 @@ const baseConfigs: { [network: number]: BaseConfig } = { Adapter01: '0x9bE264469eF954c139Da4A45Cf76CbCC5e3A6A73', Adapter02: '0xFC2Ba6E830a04C25e207B8214b26d8C713F6881F', Adapter03: '0xBAEeb4540f59d30E567a5B563CC0c4587eDd9366', - Adapter04: '0x654dE10890f8B2C5bF54E50Af169a7E93165C416', + Adapter04: '0x9F7A886ec44d8bc181e311D76b68C9B8aE2E0BC2', BuyAdapter: '0x84bEF12C9931cE12662cc9F2366b6a5029E4BD29', - BuyAdapter02: '0xA10c9a84E72d9DfF424Fe2284B6460784bed407E', + BuyAdapter02: '0xBA0E780Db34927F1e702717FAC21b52803D7cE25', }, uniswapV2ExchangeRouterAddress: '0xF9234CB08edb93c0d4a4d4c70cC3FfD070e78e07', @@ -168,8 +168,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_56`]?.split(',') || [], adapterAddresses: { BscAdapter01: '0xA31d9C571DF00e0F428B0bD24c34D103E8112222', - BscAdapter02: '0x84bEF12C9931cE12662cc9F2366b6a5029E4BD29', - BscBuyAdapter: '0xBAEeb4540f59d30E567a5B563CC0c4587eDd9366', + BscAdapter02: '0x9A92D2649C38415860FA59ba8B9a9960cd2839Db', + BscBuyAdapter: '0xd32C191e0febaa6Cc93A29Cb676474c72486E00b', }, rpcPollingMaxAllowedStateDelayInBlocks: 1, rpcPollingBlocksBackToTriggerUpdate: 1, @@ -197,8 +197,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_137`]?.split(',') || [], adapterAddresses: { PolygonAdapter01: '0xE44769f42E1e9592f86B82f206407a8f7C84b4ed', - PolygonAdapter02: '0xEECA9223063bD13e8ca77ed9e39a07f2BD1923E6', - PolygonBuyAdapter: '0xA10c9a84E72d9DfF424Fe2284B6460784bed407E', + PolygonAdapter02: '0x84bEF12C9931cE12662cc9F2366b6a5029E4BD29', + PolygonBuyAdapter: '0xBAEeb4540f59d30E567a5B563CC0c4587eDd9366', }, uniswapV2ExchangeRouterAddress: '0xf3938337F7294fEf84e9B2c6D548A93F956Cc281', @@ -288,8 +288,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { process.env[`HASHFLOW_DISABLED_MMS_42161`]?.split(',') || [], adapterAddresses: { ArbitrumAdapter01: '0x369A2FDb910d432f0a07381a5E3d27572c876713', - ArbitrumAdapter02: '0xe9166234DFB6d3ec05C82404109C02Ca82b16c22', - ArbitrumBuyAdapter: '0xe53d24CD81cC81bbf271AD7B02D0d67f851D727c', + ArbitrumAdapter02: '0x58a5f0b73969800FAFf8556cD2187E3FCE71A6cb', + ArbitrumBuyAdapter: '0x4483Ae378897eB9FbF7f15Df98Bf07233ffFEe8b', }, uniswapV2ExchangeRouterAddress: '0xB41dD984730dAf82f5C41489E21ac79D5e3B61bC', @@ -376,8 +376,8 @@ const baseConfigs: { [network: number]: BaseConfig } = { smardexSubgraphAuthToken: process.env.API_KEY_SMARDEX_SUBGRAPH || '', hashFlowDisabledMMs: [], adapterAddresses: { - BaseAdapter01: '0x654dE10890f8B2C5bF54E50Af169a7E93165C416', - BaseBuyAdapter: '0xB11bCA7B01b425afD0743A4D77B4f593883f94C0', + BaseAdapter01: '0xA10c9a84E72d9DfF424Fe2284B6460784bed407E', + BaseBuyAdapter: '0xEECA9223063bD13e8ca77ed9e39a07f2BD1923E6', }, uniswapV2ExchangeRouterAddress: '0x75d199EfB540e47D27D52c62Da3E7daC2B9e834F', From c9840c4989ae9ad494959226cce01e17caa1b23d Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Wed, 6 Dec 2023 15:08:57 +0200 Subject: [PATCH 704/833] wombat: hide getTopPoolsForToken --- src/dex/wombat/wombat-integration.test.ts | 190 +++++++++++----------- src/dex/wombat/wombat.ts | 81 ++++----- 2 files changed, 137 insertions(+), 134 deletions(-) diff --git a/src/dex/wombat/wombat-integration.test.ts b/src/dex/wombat/wombat-integration.test.ts index bca769b4c..aa9fa1f74 100644 --- a/src/dex/wombat/wombat-integration.test.ts +++ b/src/dex/wombat/wombat-integration.test.ts @@ -150,109 +150,109 @@ describe('Wombat', function () { let blockNumber: number; let wombat: Wombat; - Object.keys(WombatConfig[dexKey]).forEach(key => { - describe(`network ${key}`, () => { - const network = Number(key) as Network; - const dexHelper = new DummyDexHelper(network); + // Object.keys(WombatConfig[dexKey]).forEach(key => { + // describe(`network ${key}`, () => { + // const network = Number(key) as Network; + // const dexHelper = new DummyDexHelper(network); - const tokens = Tokens[network]; + // const tokens = Tokens[network]; - const srcTokenSymbol = 'USDC'; - const destTokenSymbol = network == Network.BASE ? 'USDbC' : 'USDT'; + // const srcTokenSymbol = 'USDC'; + // const destTokenSymbol = network == Network.BASE ? 'USDbC' : 'USDT'; - let amountsForSell = [ - 0n, - 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - 10n * BI_POWS[tokens[srcTokenSymbol].decimals], - ]; + // let amountsForSell = [ + // 0n, + // 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + // 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + // ]; - let amountsForBuy = [ - 0n, - 1n * BI_POWS[tokens[destTokenSymbol].decimals], - 2n * BI_POWS[tokens[destTokenSymbol].decimals], - 3n * BI_POWS[tokens[destTokenSymbol].decimals], - 4n * BI_POWS[tokens[destTokenSymbol].decimals], - 5n * BI_POWS[tokens[destTokenSymbol].decimals], - 6n * BI_POWS[tokens[destTokenSymbol].decimals], - 7n * BI_POWS[tokens[destTokenSymbol].decimals], - 8n * BI_POWS[tokens[destTokenSymbol].decimals], - 9n * BI_POWS[tokens[destTokenSymbol].decimals], - 10n * BI_POWS[tokens[destTokenSymbol].decimals], - ]; + // let amountsForBuy = [ + // 0n, + // 1n * BI_POWS[tokens[destTokenSymbol].decimals], + // 2n * BI_POWS[tokens[destTokenSymbol].decimals], + // 3n * BI_POWS[tokens[destTokenSymbol].decimals], + // 4n * BI_POWS[tokens[destTokenSymbol].decimals], + // 5n * BI_POWS[tokens[destTokenSymbol].decimals], + // 6n * BI_POWS[tokens[destTokenSymbol].decimals], + // 7n * BI_POWS[tokens[destTokenSymbol].decimals], + // 8n * BI_POWS[tokens[destTokenSymbol].decimals], + // 9n * BI_POWS[tokens[destTokenSymbol].decimals], + // 10n * BI_POWS[tokens[destTokenSymbol].decimals], + // ]; - // OPTIMISM has very low liquidity currently, so we have to use very small amounts - // if (network === Network.OPTIMISM) { - // amountsForSell = amountsForSell.map(a => a / 100n); - // amountsForBuy = amountsForBuy.map(a => a / 100n); - // } + // // OPTIMISM has very low liquidity currently, so we have to use very small amounts + // // if (network === Network.OPTIMISM) { + // // amountsForSell = amountsForSell.map(a => a / 100n); + // // amountsForBuy = amountsForBuy.map(a => a / 100n); + // // } - beforeAll(async () => { - blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - wombat = new Wombat(network, dexKey, dexHelper); - }); + // beforeAll(async () => { + // blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + // wombat = new Wombat(network, dexKey, dexHelper); + // }); - it('getTopPoolsForToken', async function () { - // We have to check without calling initializePricing, because - // pool-tracker is not calling that function - if (wombat.updatePoolState) { - await wombat.updatePoolState(); - } - const poolLiquidity = await wombat.getTopPoolsForToken( - tokens[srcTokenSymbol].address, - 10, - ); - console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + // it('getTopPoolsForToken', async function () { + // // We have to check without calling initializePricing, because + // // pool-tracker is not calling that function + // if (wombat.updatePoolState) { + // await wombat.updatePoolState(); + // } + // const poolLiquidity = await wombat.getTopPoolsForToken( + // tokens[srcTokenSymbol].address, + // 10, + // ); + // console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - if (!wombat.hasConstantPriceLargeAmounts) { - checkPoolsLiquidity( - poolLiquidity, - Tokens[network][srcTokenSymbol].address, - dexKey, - ); - } - }); + // if (!wombat.hasConstantPriceLargeAmounts) { + // checkPoolsLiquidity( + // poolLiquidity, + // Tokens[network][srcTokenSymbol].address, + // dexKey, + // ); + // } + // }); - it('getPoolIdentifiers and getPricesVolume SELL', async function () { - if (wombat.initializePricing) { - await wombat.initializePricing(blockNumber); - } - await testPricingOnNetwork( - wombat, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.SELL, - amountsForSell, - 'quotePotentialSwap', - ); - }); + // it('getPoolIdentifiers and getPricesVolume SELL', async function () { + // if (wombat.initializePricing) { + // await wombat.initializePricing(blockNumber); + // } + // await testPricingOnNetwork( + // wombat, + // network, + // dexKey, + // blockNumber, + // srcTokenSymbol, + // destTokenSymbol, + // SwapSide.SELL, + // amountsForSell, + // 'quotePotentialSwap', + // ); + // }); - it('getPoolIdentifiers and getPricesVolume BUY', async function () { - if (wombat.initializePricing) { - await wombat.initializePricing(blockNumber); - } - await testPricingOnNetwork( - wombat, - network, - dexKey, - blockNumber, - srcTokenSymbol, - destTokenSymbol, - SwapSide.BUY, - amountsForBuy, - 'quotePotentialSwap', - ); - }); - }); - }); + // it('getPoolIdentifiers and getPricesVolume BUY', async function () { + // if (wombat.initializePricing) { + // await wombat.initializePricing(blockNumber); + // } + // await testPricingOnNetwork( + // wombat, + // network, + // dexKey, + // blockNumber, + // srcTokenSymbol, + // destTokenSymbol, + // SwapSide.BUY, + // amountsForBuy, + // 'quotePotentialSwap', + // ); + // }); + // }); + // }); }); diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 3fb775e74..fcf2561a1 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -377,45 +377,48 @@ export class Wombat extends SimpleExchange implements IDex { tokenAddress: Address, limit: number, ): Promise { - if (!this.poolLiquidityUSD) await this.updatePoolState(); - tokenAddress = ( - isETHAddress(tokenAddress) - ? this.dexHelper.config.data.wrappedNativeTokenAddress - : tokenAddress - ).toLowerCase(); - const pools: string[] = []; - const poolStates: { [poolAddress: string]: DeepReadonly } = {}; - for (const [poolAddress, eventPool] of Object.entries(this.pools)) { - let state = await eventPool.getState(); - if (!state) { - this.logger.warn( - `State of ${poolAddress} is null in getTopPoolsForToken, skipping...`, - ); - continue; - } - if ( - state.value.underlyingAddresses.includes(tokenAddress) && - this.poolLiquidityUSD![poolAddress] - ) { - poolStates[poolAddress] = state.value; - pools.push(poolAddress); - } - } - - // sort by liquidity - pools.sort((a, b) => this.poolLiquidityUSD![b] - this.poolLiquidityUSD![a]); - return pools.slice(0, limit).map(poolAddress => ({ - exchange: this.dexKey, - address: poolAddress, - // other tokens in the same pool - connectorTokens: poolStates[poolAddress].underlyingAddresses - .filter(t => t !== tokenAddress) - .map(t => ({ - decimals: poolStates[poolAddress].asset[t].underlyingTokenDecimals, - address: t, - })), - liquidityUSD: this.poolLiquidityUSD![poolAddress], - })); + // getTopPoolsForToken shouldn't use block manager + // TODO: update getTopPoolsForToken to work without block manager + return []; + // if (!this.poolLiquidityUSD) await this.updatePoolState(); + // tokenAddress = ( + // isETHAddress(tokenAddress) + // ? this.dexHelper.config.data.wrappedNativeTokenAddress + // : tokenAddress + // ).toLowerCase(); + // const pools: string[] = []; + // const poolStates: { [poolAddress: string]: DeepReadonly } = {}; + // for (const [poolAddress, eventPool] of Object.entries(this.pools)) { + // let state = await eventPool.getState(); + // if (!state) { + // this.logger.warn( + // `State of ${poolAddress} is null in getTopPoolsForToken, skipping...`, + // ); + // continue; + // } + // if ( + // state.value.underlyingAddresses.includes(tokenAddress) && + // this.poolLiquidityUSD![poolAddress] + // ) { + // poolStates[poolAddress] = state.value; + // pools.push(poolAddress); + // } + // } + + // // sort by liquidity + // pools.sort((a, b) => this.poolLiquidityUSD![b] - this.poolLiquidityUSD![a]); + // return pools.slice(0, limit).map(poolAddress => ({ + // exchange: this.dexKey, + // address: poolAddress, + // // other tokens in the same pool + // connectorTokens: poolStates[poolAddress].underlyingAddresses + // .filter(t => t !== tokenAddress) + // .map(t => ({ + // decimals: poolStates[poolAddress].asset[t].underlyingTokenDecimals, + // address: t, + // })), + // liquidityUSD: this.poolLiquidityUSD![poolAddress], + // })); } // This is optional function in case if your implementation has acquired any resources From f8d6203e5eef2ad811c207839a35ba07918c89f5 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Wed, 6 Dec 2023 15:09:32 +0200 Subject: [PATCH 705/833] wombat: prevent logging failed multicalls --- src/dex/wombat/wombat-pool.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/dex/wombat/wombat-pool.ts b/src/dex/wombat/wombat-pool.ts index 5514e0743..c687b7467 100644 --- a/src/dex/wombat/wombat-pool.ts +++ b/src/dex/wombat/wombat-pool.ts @@ -187,6 +187,11 @@ export class WombatPool extends StatefulRpcPoller< >( false, multiCalls as MultiCallParams[], + undefined, + undefined, + // multiCalls includes calls asset.isPaused, asset.getRelativePrice + // some of the contracts don't have these methods, so prevent logging errors + false, )) as [MultiResult, ...MultiResult[]]; return this.parseStateFromMultiResultsWithBlockInfo( From 944b63dcfff570a69ebcf2c1fa2dad07a807fc03 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 6 Dec 2023 15:10:03 +0200 Subject: [PATCH 706/833] 2.42.24-smardex --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 87eef33bb..8f1ecd051 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.24", + "version": "2.42.24-smardex", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 7f730badcc2c3e896a766229b9f30a841fc384eb Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 6 Dec 2023 19:29:06 +0200 Subject: [PATCH 707/833] fix: update USDbC holder --- tests/constants-e2e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index b8e32f893..f686c091d 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1227,7 +1227,7 @@ export const Holders: { ETH: '0xdd9176ea3e7559d6b68b537ef555d3e89403f742', MAV: '0x7499785aa5d1bdf0a0ac862c1ef3698d3cba6568', USDC: '0xaac391f166f33cdaefaa4afa6616a3bea66b694d', - USDbC: '0xc9d05a1c3c8e01dcb701d6185cdc21a5bb94becb', + USDbC: '0xc68a33de9ceac7bdaed242ae1dc40d673ed4f643', DAI: '0x20f03e26968b179025f65c1f4afadfd3959c8d03', BAL: '0x854b004700885a61107b458f11ecc169a019b764', GOLD: '0x1374c25b3710758c326ee0c70ec48b595d5ccf8c', From f5c5a0b0b871507e686676eada9c0427787c635e Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Thu, 7 Dec 2023 13:46:52 +0200 Subject: [PATCH 708/833] wombat: enable StatePollingManager --- src/dex/wombat/wombat.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index fcf2561a1..230ecda4b 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -30,6 +30,7 @@ import { WombatQuoter } from './wombat-quoter'; import { WombatBmw } from './wombat-bmw'; import { fromWad } from './utils'; import { WombatPool } from './wombat-pool'; +import { StatePollingManager } from '../../lib/stateful-rpc-poller/state-polling-manager'; export class Wombat extends SimpleExchange implements IDex { // export class Wombat implements IDex { @@ -37,6 +38,7 @@ export class Wombat extends SimpleExchange implements IDex { static readonly erc20Interface = new Interface(ERC20ABI); static readonly poolInterface = new Interface(PoolABI); static readonly assetInterface = new Interface(AssetABI); + protected pollingManager: StatePollingManager; protected config: DexParams; protected poolLiquidityUSD?: { [poolAddress: string]: number }; @@ -64,6 +66,8 @@ export class Wombat extends SimpleExchange implements IDex { super(dexHelper, dexKey); this.logger = dexHelper.getLogger(dexKey); this.config = WombatConfig[dexKey][network]; + this.pollingManager = StatePollingManager.getInstance(dexHelper); + this.bmw = new WombatBmw( dexKey, this.config.bmwAddress, @@ -73,6 +77,7 @@ export class Wombat extends SimpleExchange implements IDex { this.config.bmwAddress, this.onAssetAdded.bind(this), ); + this.pollingManager.initializeAllPendingPools(); } async init(blockNumber: number) { From 63c69fe10d7bf2969f7dd6c797c90302c46d81c0 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Thu, 7 Dec 2023 13:47:37 +0200 Subject: [PATCH 709/833] 2.42.25-wombat.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b5a84f342..d213c2685 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.25-wombat.1", + "version": "2.42.25-wombat.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1f866f7bba49b76c59d65788690749ef90e67022 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Thu, 7 Dec 2023 14:36:13 +0200 Subject: [PATCH 710/833] wombat: add logs --- src/dex/wombat/wombat-bmw.ts | 1 + src/dex/wombat/wombat.ts | 1 + src/lib/stateful-rpc-poller/state-polling-manager.ts | 3 +++ 3 files changed, 5 insertions(+) diff --git a/src/dex/wombat/wombat-bmw.ts b/src/dex/wombat/wombat-bmw.ts index fcb41e4b9..57d39d0b7 100644 --- a/src/dex/wombat/wombat-bmw.ts +++ b/src/dex/wombat/wombat-bmw.ts @@ -53,6 +53,7 @@ export class WombatBmw extends StatefulEventSubscriber { BmwABI as any, this.bmwAddress, ); + this.logger.info(`Initialized ${name} event subscriber (WombatBMW)`); // users-actions handlers this.handlers['Add'] = this.handleAdd.bind(this); diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 230ecda4b..58814890c 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -65,6 +65,7 @@ export class Wombat extends SimpleExchange implements IDex { ) { super(dexHelper, dexKey); this.logger = dexHelper.getLogger(dexKey); + this.logger.info(`Initializing WOMBAT ${dexKey} on ${network} DEX`); this.config = WombatConfig[dexKey][network]; this.pollingManager = StatePollingManager.getInstance(dexHelper); diff --git a/src/lib/stateful-rpc-poller/state-polling-manager.ts b/src/lib/stateful-rpc-poller/state-polling-manager.ts index 85367d7a6..9f8f0efc6 100644 --- a/src/lib/stateful-rpc-poller/state-polling-manager.ts +++ b/src/lib/stateful-rpc-poller/state-polling-manager.ts @@ -238,6 +238,9 @@ export class StatePollingManager { return; } + this.logger.info( + `Initializing all pending pools: ${this._registeredPendingPools.length}`, + ); this._registeredPendingPools.forEach(p => { this.initializePool(p); }); From f59c35db8338bc69052db5853dacb841404774d2 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Thu, 7 Dec 2023 14:37:16 +0200 Subject: [PATCH 711/833] 2.42.25-wombat.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d213c2685..80c9b297c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.25-wombat.2", + "version": "2.42.25-wombat.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 3e8f1708252c108a8c4ea7a6ae1fd44d0e65e9d8 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 7 Dec 2023 14:37:35 +0200 Subject: [PATCH 712/833] fix: update config --- src/dex/smardex/config.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/dex/smardex/config.ts b/src/dex/smardex/config.ts index ae0e286d6..6bb90caa1 100644 --- a/src/dex/smardex/config.ts +++ b/src/dex/smardex/config.ts @@ -4,39 +4,39 @@ import { Network, SwapSide } from '../../constants'; const GATEWAY_SUBGRAPH = 'https://subgraph.smardex.io'; const MAINNET_INIT_HASH = - '0xb477a06204165d50e6d795c7c216306290eff5d6015f8b65bb46002a8775b548'; + '0xc762a0f9885cc92b9fd8eef224b75997682b634460611bc0f2138986e20b653f'; const LAYER2_INIT_HASH = '0x33bee911475f015247aeb1eebe149d1c6d2669be54126c29d85df6b0abb4c4e9'; export const SmardexConfig: DexConfigMap = { Smardex: { [Network.MAINNET]: { - factoryAddress: '0x7753F36E711B66a0350a753aba9F5651BAE76A1D', - router: '0xEf2f9b48d7EC80440Ab4573dF1A2aBDBE06D3f60', + factoryAddress: '0xB878DC600550367e14220d4916Ff678fB284214F', + router: '0xC33984ABcAe20f47a754eF78f6526FeF266c0C6F', initCode: MAINNET_INIT_HASH, subgraphURL: `${GATEWAY_SUBGRAPH}/ethereum`, }, [Network.ARBITRUM]: { factoryAddress: '0x41A00e3FbE7F479A99bA6822704d9c5dEB611F22', - router: '0xdd4536dD9636564D891c919416880a3e250f975A', + router: '0xDA3970a20cdc2B1269fc96C4E8D300E0fdDB7b3D', initCode: LAYER2_INIT_HASH, subgraphURL: `${GATEWAY_SUBGRAPH}/arbitrum`, }, [Network.BSC]: { factoryAddress: '0xA8EF6FEa013034E62E2C4A9Ec1CDb059fE23Af33', - router: '0x391BeCc8DAaf32b9ba8e602e9527Bf9DA04C8deb', + router: '0xaB3699B71e89a53c529eC037C3389B5A2Caf545A', initCode: LAYER2_INIT_HASH, subgraphURL: `${GATEWAY_SUBGRAPH}/bsc`, }, [Network.POLYGON]: { factoryAddress: '0x9A1e1681f6D59Ca051776410465AfAda6384398f', - router: '0xA8EF6FEa013034E62E2C4A9Ec1CDb059fE23Af33', + router: '0xedD758D17175Dc9131992ebd02F55Cc4ebeb7B7c', initCode: LAYER2_INIT_HASH, subgraphURL: `${GATEWAY_SUBGRAPH}/polygon`, }, [Network.BASE]: { factoryAddress: '0xdd4536dD9636564D891c919416880a3e250f975A', - router: '0x5C622Dcc96b6D96ac6c154f99CF081815094CBC9', + router: '0xF03D133627364E5eDDaB8134faB3A030cf7b3020', initCode: LAYER2_INIT_HASH, subgraphURL: `${GATEWAY_SUBGRAPH}/base`, }, From 2a30046135730640485b0b010f911fc2cf27ce8b Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 7 Dec 2023 20:46:18 +0800 Subject: [PATCH 713/833] add quotes around BigInt (bug). change USDT->USDC --- src/dex/solidly-v3/constants.ts | 7 +-- .../solidly-v3/solidly-v3-integration.test.ts | 44 ++++++++++++------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/dex/solidly-v3/constants.ts b/src/dex/solidly-v3/constants.ts index 204e0f25f..56c78908e 100644 --- a/src/dex/solidly-v3/constants.ts +++ b/src/dex/solidly-v3/constants.ts @@ -36,6 +36,7 @@ export enum DirectMethods { directSell = 'directUniV3Swap', directBuy = 'directUniV3Buy', } -export const MIN_SQRT_RATIO = BigInt(4295128739); -export const MAX_SQRT_RATIO = - BigInt(1461446703485210103287273052203988822378723970342); +export const MIN_SQRT_RATIO = BigInt('4295128739'); +export const MAX_SQRT_RATIO = BigInt( + '1461446703485210103287273052203988822378723970342', +); diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index c82f86a67..8f5327fd9 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -3,18 +3,18 @@ import dotenv from 'dotenv'; dotenv.config(); import { Interface, Result } from '@ethersproject/abi'; -import {DummyDexHelper, IDexHelper} from '../../dex-helper/index'; +import { DummyDexHelper, IDexHelper } from '../../dex-helper/index'; import { Network, SwapSide } from '../../constants'; import { BI_POWS } from '../../bigint-constants'; import { SolidlyV3 } from './solidly-v3'; -import { MIN_SQRT_RATIO, MAX_SQRT_RATIO } from "./constants"; +import { MIN_SQRT_RATIO, MAX_SQRT_RATIO } from './constants'; import { checkPoolPrices, checkPoolsLiquidity, checkConstantPoolPrices, } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; -import {Address} from "@paraswap/core"; +import { Address } from '@paraswap/core'; import SolidlyV3PoolABI from '../../abi/solidly-v3/SolidlyV3Pool.abi.json'; /* @@ -36,11 +36,16 @@ const network = Network.MAINNET; const dexHelper = new DummyDexHelper(network); const WETH = Tokens[network]['WETH']; -const USDT = Tokens[network]['USDT']; +const USDT = Tokens[network]['USDC']; const amounts = [0n, 1n * BI_POWS[18], 2n * BI_POWS[18]]; // Sell WETH to receive 1000 USDT, 2000 UDST, and 3000 USDT -const amountsBuy = [0n, 1000n * BI_POWS[6], 2000n * BI_POWS[6], 3000n * BI_POWS[6]]; +const amountsBuy = [ + 0n, + 1000n * BI_POWS[6], + 2000n * BI_POWS[6], + 3000n * BI_POWS[6], +]; function getReaderCalldata( exchangeAddress: string, @@ -49,14 +54,14 @@ function getReaderCalldata( funcName: string, zeroForOne: boolean, sqrtPriceLimitX96: bigint, - exactInput: boolean + exactInput: boolean, ) { return amounts.map(amount => ({ target: exchangeAddress, callData: readerIface.encodeFunctionData(funcName, [ zeroForOne, exactInput ? amount.toString() : `-${amount.toString()}`, - sqrtPriceLimitX96.toString() + sqrtPriceLimitX96.toString(), ]), })); } @@ -65,13 +70,15 @@ function decodeReaderResult( results: Result, readerIface: Interface, funcName: string, - exactInput: boolean + exactInput: boolean, ) { return results.map(result => { const parsed = readerIface.decodeFunctionResult(funcName, result); // exactInput determines whether we want to get amount0 or amount1 const index = exactInput ? 1 : 0; - return parsed[index]._hex[0] == '-' ? BigInt(parsed[index]._hex.slice(1)) : BigInt(parsed[index]._hex); + return parsed[index]._hex[0] == '-' + ? BigInt(parsed[index]._hex.slice(1)) + : BigInt(parsed[index]._hex); }); } @@ -84,7 +91,7 @@ async function checkOnChainPricing( tokenOut: Address, tickSpacing: bigint, _amounts: bigint[], - exactInput: boolean + exactInput: boolean, ) { const readerIface = new Interface(SolidlyV3PoolABI); @@ -103,8 +110,10 @@ async function checkOnChainPricing( _amounts.slice(1), 'quoteSwap', tokenIn < tokenOut, - tokenIn < tokenOut ? MIN_SQRT_RATIO + BigInt(1) : MAX_SQRT_RATIO - BigInt(1), - exactInput + tokenIn < tokenOut + ? MIN_SQRT_RATIO + BigInt(1) + : MAX_SQRT_RATIO - BigInt(1), + exactInput, ); let readerResult; @@ -217,7 +226,6 @@ describe('SolidlyV3', function () { }); it('getPoolIdentifiers and getPricesVolume SELL', async function () { - const pools = await solidlyV3.getPoolIdentifiers( WETH, USDT, @@ -244,7 +252,8 @@ describe('SolidlyV3', function () { let falseChecksCounter = 0; await Promise.all( poolPrices!.map(async price => { - const tickSpacing = solidlyV3.eventPools[price.poolIdentifier!]!.tickSpacing; + const tickSpacing = + solidlyV3.eventPools[price.poolIdentifier!]!.tickSpacing; const res = await checkOnChainPricing( dexHelper, blockNumber, @@ -254,7 +263,7 @@ describe('SolidlyV3', function () { USDT.address, tickSpacing, amounts, - true + true, ); if (res === false) falseChecksCounter++; }), @@ -290,7 +299,8 @@ describe('SolidlyV3', function () { let falseChecksCounter = 0; await Promise.all( poolPrices!.map(async price => { - const tickSpacing = solidlyV3.eventPools[price.poolIdentifier!]!.tickSpacing; + const tickSpacing = + solidlyV3.eventPools[price.poolIdentifier!]!.tickSpacing; const res = await checkOnChainPricing( dexHelper, blockNumber, @@ -300,7 +310,7 @@ describe('SolidlyV3', function () { USDT.address, tickSpacing, amountsBuy, - false + false, ); if (res === false) falseChecksCounter++; }), From b442594525f8cdfb3ed4fa052a369ee9e0dff1e1 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Thu, 7 Dec 2023 14:59:16 +0200 Subject: [PATCH 714/833] wombat: initializeAllPendingPools on init --- src/dex/wombat/wombat.ts | 2 +- src/lib/stateful-rpc-poller/state-polling-manager.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 58814890c..c3aa45db1 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -78,12 +78,12 @@ export class Wombat extends SimpleExchange implements IDex { this.config.bmwAddress, this.onAssetAdded.bind(this), ); - this.pollingManager.initializeAllPendingPools(); } async init(blockNumber: number) { if (!this.bmw.isInitialized) { await this.bmw.initialize(blockNumber); + this.pollingManager.initializeAllPendingPools(); } } diff --git a/src/lib/stateful-rpc-poller/state-polling-manager.ts b/src/lib/stateful-rpc-poller/state-polling-manager.ts index 9f8f0efc6..35ea7031f 100644 --- a/src/lib/stateful-rpc-poller/state-polling-manager.ts +++ b/src/lib/stateful-rpc-poller/state-polling-manager.ts @@ -234,13 +234,13 @@ export class StatePollingManager { // So all state will be initialized. It is not part of constructor, because and that time we don't have // all classes built initializeAllPendingPools() { + this.logger.info( + `${this?.constructor?.name}: Initializing all pending pools: ${this._registeredPendingPools.length}`, + ); if (this._registeredPendingPools.length === 0) { return; } - this.logger.info( - `Initializing all pending pools: ${this._registeredPendingPools.length}`, - ); this._registeredPendingPools.forEach(p => { this.initializePool(p); }); From 368c1e4685d657559ca0de48954ead45cfe6a19d Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Thu, 7 Dec 2023 14:59:51 +0200 Subject: [PATCH 715/833] 2.42.25-wombat.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 80c9b297c..7415ec0f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.25-wombat.3", + "version": "2.42.25-wombat.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 234f8fe11c03091c9a45cbe1c316796692d066a8 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 7 Dec 2023 15:04:51 +0200 Subject: [PATCH 716/833] fix: update tests --- src/dex/smardex/smardex-e2e.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/smardex/smardex-e2e.test.ts b/src/dex/smardex/smardex-e2e.test.ts index b772f8150..79fb2a821 100644 --- a/src/dex/smardex/smardex-e2e.test.ts +++ b/src/dex/smardex/smardex-e2e.test.ts @@ -90,9 +90,9 @@ describe('SmarDex E2E', () => { ], [ { - name: 'USDT', - sellAmount: '1200000000', - buyAmount: '1200000000', + name: 'SDEX', + sellAmount: '300000000000000000000000', + buyAmount: '30000000000', }, { name: 'ETH', From 774217435068e716e77cff3b1c24dbd0ee15b279 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 7 Dec 2023 15:08:20 +0200 Subject: [PATCH 717/833] 2.42.24-smardex.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8f1ecd051..4b76c85fa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.24-smardex", + "version": "2.42.24-smardex.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 4f8e934fcda550c60aea4103ef6240caaaed679e Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 7 Dec 2023 21:26:59 +0800 Subject: [PATCH 718/833] Fix bug, should be using zeroForOne instead of exactInput in decodeReaderResult --- src/dex/solidly-v3/solidly-v3-integration.test.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 8f5327fd9..2d60f713a 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -70,12 +70,12 @@ function decodeReaderResult( results: Result, readerIface: Interface, funcName: string, - exactInput: boolean, + zeroForOne: boolean, ) { return results.map(result => { const parsed = readerIface.decodeFunctionResult(funcName, result); - // exactInput determines whether we want to get amount0 or amount1 - const index = exactInput ? 1 : 0; + // zeroForOne determines whether we want to get amount0 or amount1 + const index = zeroForOne ? 1 : 0; return parsed[index]._hex[0] == '-' ? BigInt(parsed[index]._hex.slice(1)) : BigInt(parsed[index]._hex); @@ -132,7 +132,12 @@ async function checkOnChainPricing( } const expectedPrices = [0n].concat( - decodeReaderResult(readerResult, readerIface, 'quoteSwap', exactInput), + decodeReaderResult( + readerResult, + readerIface, + 'quoteSwap', + tokenIn < tokenOut, + ), ); console.log('EXPECTED PRICES: ', expectedPrices); From af9a19a7e5e9a02f2623756722ca9c493a66b9dc Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 7 Dec 2023 21:29:02 +0800 Subject: [PATCH 719/833] rename USDT -> USDC --- .../solidly-v3/solidly-v3-integration.test.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 2d60f713a..2a716bcb0 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -36,10 +36,10 @@ const network = Network.MAINNET; const dexHelper = new DummyDexHelper(network); const WETH = Tokens[network]['WETH']; -const USDT = Tokens[network]['USDC']; +const USDC = Tokens[network]['USDC']; const amounts = [0n, 1n * BI_POWS[18], 2n * BI_POWS[18]]; -// Sell WETH to receive 1000 USDT, 2000 UDST, and 3000 USDT +// Sell WETH to receive 1000 USDC, 2000 UDST, and 3000 USDC const amountsBuy = [ 0n, 1000n * BI_POWS[6], @@ -220,7 +220,7 @@ describe('SolidlyV3', function () { // TODO: Put here token Symbol to check against // Don't forget to update relevant tokens in constant-e2e.ts const srcTokenSymbol = 'WETH'; - const destTokenSymbol = 'USDT'; + const destTokenSymbol = 'USDC'; beforeAll(async () => { blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); @@ -233,23 +233,23 @@ describe('SolidlyV3', function () { it('getPoolIdentifiers and getPricesVolume SELL', async function () { const pools = await solidlyV3.getPoolIdentifiers( WETH, - USDT, + USDC, SwapSide.SELL, blockNumber, ); - console.log(`WETH <> USDT Pool Identifiers: `, pools); + console.log(`WETH <> USDC Pool Identifiers: `, pools); expect(pools.length).toBeGreaterThan(0); const poolPrices = await solidlyV3.getPricesVolume( WETH, - USDT, + USDC, amounts, SwapSide.SELL, blockNumber, pools, ); - console.log(`WETH <> USDT Pool Prices: `, poolPrices); + console.log(`WETH <> USDC Pool Prices: `, poolPrices); expect(poolPrices).not.toBeNull(); checkPoolPrices(poolPrices!, amounts, SwapSide.SELL, dexKey); @@ -265,7 +265,7 @@ describe('SolidlyV3', function () { solidlyV3.eventPools[price.poolIdentifier!]!.poolAddress, price.prices, WETH.address, - USDT.address, + USDC.address, tickSpacing, amounts, true, @@ -280,23 +280,23 @@ describe('SolidlyV3', function () { it('getPoolIdentifiers and getPricesVolume BUY', async function () { const pools = await solidlyV3.getPoolIdentifiers( WETH, - USDT, + USDC, SwapSide.BUY, blockNumber, ); - console.log(`WETH <> USDT Pool Identifiers: `, pools); + console.log(`WETH <> USDC Pool Identifiers: `, pools); expect(pools.length).toBeGreaterThan(0); const poolPrices = await solidlyV3.getPricesVolume( WETH, - USDT, + USDC, amountsBuy, SwapSide.BUY, blockNumber, pools, ); - console.log(`WETH <> USDT Pool Prices: `, poolPrices); + console.log(`WETH <> USDC Pool Prices: `, poolPrices); expect(poolPrices).not.toBeNull(); checkPoolPrices(poolPrices!, amountsBuy, SwapSide.BUY, dexKey); @@ -312,7 +312,7 @@ describe('SolidlyV3', function () { solidlyV3.eventPools[price.poolIdentifier!]!.poolAddress, price.prices, WETH.address, - USDT.address, + USDC.address, tickSpacing, amountsBuy, false, From bf9b5c60eed5fe608c3d7c73cf31291297f0e85b Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 7 Dec 2023 21:50:33 +0800 Subject: [PATCH 720/833] add another param to decodeReaderResult - this function should be correct now --- src/dex/solidly-v3/solidly-v3-integration.test.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/dex/solidly-v3/solidly-v3-integration.test.ts b/src/dex/solidly-v3/solidly-v3-integration.test.ts index 2a716bcb0..c5f961dc9 100644 --- a/src/dex/solidly-v3/solidly-v3-integration.test.ts +++ b/src/dex/solidly-v3/solidly-v3-integration.test.ts @@ -66,16 +66,24 @@ function getReaderCalldata( })); } +// We are only using this function to decode `quoteSwap` on SolidlyV3Pool. The output param we consider relevant +// depends on `zeroForOne` and `exactInput`. function decodeReaderResult( results: Result, readerIface: Interface, funcName: string, zeroForOne: boolean, + exactInput: boolean, ) { return results.map(result => { const parsed = readerIface.decodeFunctionResult(funcName, result); // zeroForOne determines whether we want to get amount0 or amount1 - const index = zeroForOne ? 1 : 0; + let index; + if (zeroForOne == exactInput) { + index = 1; + } else { + index = 0; + } return parsed[index]._hex[0] == '-' ? BigInt(parsed[index]._hex.slice(1)) : BigInt(parsed[index]._hex); @@ -137,6 +145,7 @@ async function checkOnChainPricing( readerIface, 'quoteSwap', tokenIn < tokenOut, + exactInput, ), ); From bd79b93c8919817fd7f27fadef0ec40013d1f9ab Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Thu, 7 Dec 2023 15:53:37 +0200 Subject: [PATCH 721/833] wombat: specify isStatePollingDex --- src/dex/wombat/wombat.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index c3aa45db1..e41635824 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -45,6 +45,8 @@ export class Wombat extends SimpleExchange implements IDex { public bmw: WombatBmw; public pools: { [poolAddress: string]: WombatPool } = {}; + readonly isStatePollingDex = true; + readonly hasConstantPriceLargeAmounts = false; readonly needWrapNative = true; @@ -78,12 +80,12 @@ export class Wombat extends SimpleExchange implements IDex { this.config.bmwAddress, this.onAssetAdded.bind(this), ); + this.pollingManager.initializeAllPendingPools(); } async init(blockNumber: number) { if (!this.bmw.isInitialized) { await this.bmw.initialize(blockNumber); - this.pollingManager.initializeAllPendingPools(); } } From b0669e7a7c607929262bc1cebb5c7af773287a7c Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Thu, 7 Dec 2023 15:54:20 +0200 Subject: [PATCH 722/833] 2.42.25-wombat.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7415ec0f2..621cf5cb5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.25-wombat.4", + "version": "2.42.25-wombat.5", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From b9dfcc370c05309b71acd72775ab83a2f14131c7 Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 7 Dec 2023 22:05:59 +0800 Subject: [PATCH 723/833] change USDT -> USDC. change USDC holder --- src/dex/solidly-v3/solidly-v3-e2e.test.ts | 4 ++-- tests/constants-e2e.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-e2e.test.ts b/src/dex/solidly-v3/solidly-v3-e2e.test.ts index ad5da48d5..a3436a699 100644 --- a/src/dex/solidly-v3/solidly-v3-e2e.test.ts +++ b/src/dex/solidly-v3/solidly-v3-e2e.test.ts @@ -64,7 +64,7 @@ describe('SolidlyV3 E2E', () => { ); const tokenASymbol: string = 'WETH'; - const tokenBSymbol: string = 'USDT'; + const tokenBSymbol: string = 'USDC'; const nativeTokenSymbol = NativeTokenSymbols[network]; const tokenAAmount: string = '11000000000000000000'; @@ -116,7 +116,7 @@ describe('SolidlyV3 E2E', () => { sideToContractMethods.forEach((contractMethods, side) => contractMethods.forEach((contractMethod: ContractMethod) => { describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${tokenBSymbol} -> ${tokenBSymbol}`, async () => { + it(`${network} ${side} ${contractMethod} ${tokenBSymbol} -> ${tokenASymbol}`, async () => { await testE2E( tokens[tokenBSymbol], tokens[tokenASymbol], diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index f596301db..64690d7f4 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -925,7 +925,7 @@ export const Holders: { } = { [Network.MAINNET]: { ETH: '0x176F3DAb24a159341c0509bB36B833E7fdd0a132', - USDC: '0x79E2Ba942B0e8fDB6ff3d406e930289d10B49ADe', + USDC: '0xcee284f754e854890e311e3280b767f80797180d', WBTC: '0x1cb17a66dc606a52785f69f08f4256526abd4943', sBTC: '0xA2e3475D13776C6E42ff37B47286827d959B2195', BADGER: '0x34e2741a3f8483dbe5231f61c005110ff4b9f50a', From 943e4613619f8a87eeea164026b542c0f8c9ae5e Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Thu, 7 Dec 2023 16:10:07 +0200 Subject: [PATCH 724/833] wombat: remove logs --- src/dex/wombat/wombat-bmw.ts | 1 - src/dex/wombat/wombat.ts | 1 - src/lib/stateful-rpc-poller/state-polling-manager.ts | 3 --- 3 files changed, 5 deletions(-) diff --git a/src/dex/wombat/wombat-bmw.ts b/src/dex/wombat/wombat-bmw.ts index 57d39d0b7..fcb41e4b9 100644 --- a/src/dex/wombat/wombat-bmw.ts +++ b/src/dex/wombat/wombat-bmw.ts @@ -53,7 +53,6 @@ export class WombatBmw extends StatefulEventSubscriber { BmwABI as any, this.bmwAddress, ); - this.logger.info(`Initialized ${name} event subscriber (WombatBMW)`); // users-actions handlers this.handlers['Add'] = this.handleAdd.bind(this); diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index e41635824..79f0fc6f3 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -67,7 +67,6 @@ export class Wombat extends SimpleExchange implements IDex { ) { super(dexHelper, dexKey); this.logger = dexHelper.getLogger(dexKey); - this.logger.info(`Initializing WOMBAT ${dexKey} on ${network} DEX`); this.config = WombatConfig[dexKey][network]; this.pollingManager = StatePollingManager.getInstance(dexHelper); diff --git a/src/lib/stateful-rpc-poller/state-polling-manager.ts b/src/lib/stateful-rpc-poller/state-polling-manager.ts index 35ea7031f..85367d7a6 100644 --- a/src/lib/stateful-rpc-poller/state-polling-manager.ts +++ b/src/lib/stateful-rpc-poller/state-polling-manager.ts @@ -234,9 +234,6 @@ export class StatePollingManager { // So all state will be initialized. It is not part of constructor, because and that time we don't have // all classes built initializeAllPendingPools() { - this.logger.info( - `${this?.constructor?.name}: Initializing all pending pools: ${this._registeredPendingPools.length}`, - ); if (this._registeredPendingPools.length === 0) { return; } From bcca8c43ff637b7558dcf0a184c9fdee15483768 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Thu, 7 Dec 2023 16:10:55 +0200 Subject: [PATCH 725/833] 2.42.25-wombat.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 621cf5cb5..944f2cb6d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.25-wombat.5", + "version": "2.42.25-wombat.6", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1722cd5b10a669e55f92ffb941e05d6c086a2aea Mon Sep 17 00:00:00 2001 From: Autistic Dev Date: Thu, 7 Dec 2023 22:17:08 +0800 Subject: [PATCH 726/833] change USDC holder to match with master --- tests/constants-e2e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 64690d7f4..3bda57392 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -925,7 +925,7 @@ export const Holders: { } = { [Network.MAINNET]: { ETH: '0x176F3DAb24a159341c0509bB36B833E7fdd0a132', - USDC: '0xcee284f754e854890e311e3280b767f80797180d', + USDC: '0x7713974908be4bed47172370115e8b1219f4a5f0', WBTC: '0x1cb17a66dc606a52785f69f08f4256526abd4943', sBTC: '0xA2e3475D13776C6E42ff37B47286827d959B2195', BADGER: '0x34e2741a3f8483dbe5231f61c005110ff4b9f50a', From 9aac0e4eae34d9785f0acc38b41921e12829262f Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 7 Dec 2023 19:00:36 +0200 Subject: [PATCH 727/833] fix: update abi & update `ethers` version --- package.json | 2 +- src/abi/smardex/all/smardex-router.json | 213 ++++++++- src/abi/smardex/layer-1/smardex-factory.json | 216 ++++++--- src/abi/smardex/layer-1/smardex-pool.json | 376 +++------------ src/abi/smardex/layer-2/smardex-factory.json | 114 +---- src/abi/smardex/layer-2/smardex-pool.json | 462 +++---------------- src/dex/smardex/smardex-events.test.ts | 3 +- yarn.lock | 2 +- 8 files changed, 481 insertions(+), 907 deletions(-) diff --git a/package.json b/package.json index 4b76c85fa..7ed3d746f 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "bignumber.js": "9.1.0", "cross-fetch": "^3.1.5", "es6-promise": "^4.2.8", - "ethers": "^5.6.5", + "ethers": "5.7.2", "joi": "^17.7.0", "lens.ts": "^0.5.1", "lodash": "4.17.21", diff --git a/src/abi/smardex/all/smardex-router.json b/src/abi/smardex/all/smardex-router.json index 6b6828461..f4f5a4f3c 100644 --- a/src/abi/smardex/all/smardex-router.json +++ b/src/abi/smardex/all/smardex-router.json @@ -7,6 +7,31 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "tokenA", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "tokenB", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "pair", + "type": "address" + } + ], + "name": "PairWhitelisted", + "type": "event" + }, { "inputs": [], "name": "WETH", @@ -16,20 +41,50 @@ }, { "inputs": [ - { "internalType": "address", "name": "_tokenA", "type": "address" }, - { "internalType": "address", "name": "_tokenB", "type": "address" }, - { - "internalType": "uint256", - "name": "_amountADesired", - "type": "uint256" - }, { - "internalType": "uint256", - "name": "_amountBDesired", - "type": "uint256" + "components": [ + { "internalType": "address", "name": "tokenA", "type": "address" }, + { "internalType": "address", "name": "tokenB", "type": "address" }, + { + "internalType": "uint256", + "name": "amountADesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountAMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountBMin", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "fictiveReserveB", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "fictiveReserveAMin", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "fictiveReserveAMax", + "type": "uint128" + } + ], + "internalType": "struct ISmardexRouter.AddLiquidityParams", + "name": "_params", + "type": "tuple" }, - { "internalType": "uint256", "name": "_amountAMin", "type": "uint256" }, - { "internalType": "uint256", "name": "_amountBMin", "type": "uint256" }, { "internalType": "address", "name": "_to", "type": "address" }, { "internalType": "uint256", "name": "_deadline", "type": "uint256" } ], @@ -44,18 +99,44 @@ }, { "inputs": [ - { "internalType": "address", "name": "_token", "type": "address" }, - { - "internalType": "uint256", - "name": "_amountTokenDesired", - "type": "uint256" - }, { - "internalType": "uint256", - "name": "_amountTokenMin", - "type": "uint256" + "components": [ + { "internalType": "address", "name": "token", "type": "address" }, + { + "internalType": "uint256", + "name": "amountTokenDesired", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountTokenMin", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amountETHMin", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "fictiveReserveETH", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "fictiveReserveTokenMin", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "fictiveReserveTokenMax", + "type": "uint128" + } + ], + "internalType": "struct ISmardexRouter.AddLiquidityETHParams", + "name": "_params", + "type": "tuple" }, - { "internalType": "uint256", "name": "_amountETHMin", "type": "uint256" }, { "internalType": "address", "name": "_to", "type": "address" }, { "internalType": "uint256", "name": "_deadline", "type": "uint256" } ], @@ -68,6 +149,18 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { "internalType": "address", "name": "_tokenA", "type": "address" }, + { "internalType": "address", "name": "_tokenB", "type": "address" } + ], + "name": "addPairToWhitelist", + "outputs": [ + { "internalType": "address", "name": "pair_", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "factory", @@ -430,6 +523,25 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "_amountOutMin", "type": "uint256" }, + { "internalType": "address[]", "name": "_path", "type": "address[]" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" }, + { "internalType": "bool", "name": "_approveMax", "type": "bool" }, + { "internalType": "uint8", "name": "_v", "type": "uint8" }, + { "internalType": "bytes32", "name": "_r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_s", "type": "bytes32" } + ], + "name": "swapExactTokensForETHWithPermit", + "outputs": [ + { "internalType": "uint256", "name": "amountOut_", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { "internalType": "uint256", "name": "_amountIn", "type": "uint256" }, @@ -445,6 +557,25 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "_amountOutMin", "type": "uint256" }, + { "internalType": "address[]", "name": "_path", "type": "address[]" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" }, + { "internalType": "bool", "name": "_approveMax", "type": "bool" }, + { "internalType": "uint8", "name": "_v", "type": "uint8" }, + { "internalType": "bytes32", "name": "_r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_s", "type": "bytes32" } + ], + "name": "swapExactTokensForTokensWithPermit", + "outputs": [ + { "internalType": "uint256", "name": "amountOut_", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { "internalType": "uint256", "name": "_amountOut", "type": "uint256" }, @@ -460,6 +591,25 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amountOut", "type": "uint256" }, + { "internalType": "uint256", "name": "_amountInMax", "type": "uint256" }, + { "internalType": "address[]", "name": "_path", "type": "address[]" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" }, + { "internalType": "bool", "name": "_approveMax", "type": "bool" }, + { "internalType": "uint8", "name": "_v", "type": "uint8" }, + { "internalType": "bytes32", "name": "_r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_s", "type": "bytes32" } + ], + "name": "swapTokensForExactETHWithPermit", + "outputs": [ + { "internalType": "uint256", "name": "amountIn_", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { "internalType": "uint256", "name": "_amountOut", "type": "uint256" }, @@ -475,5 +625,24 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { "internalType": "uint256", "name": "_amountOut", "type": "uint256" }, + { "internalType": "uint256", "name": "_amountInMax", "type": "uint256" }, + { "internalType": "address[]", "name": "_path", "type": "address[]" }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_deadline", "type": "uint256" }, + { "internalType": "bool", "name": "_approveMax", "type": "bool" }, + { "internalType": "uint8", "name": "_v", "type": "uint8" }, + { "internalType": "bytes32", "name": "_r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "_s", "type": "bytes32" } + ], + "name": "swapTokensForExactTokensWithPermit", + "outputs": [ + { "internalType": "uint256", "name": "amountIn_", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "stateMutability": "payable", "type": "receive" } ] diff --git a/src/abi/smardex/layer-1/smardex-factory.json b/src/abi/smardex/layer-1/smardex-factory.json index f534230a0..1691074d9 100644 --- a/src/abi/smardex/layer-1/smardex-factory.json +++ b/src/abi/smardex/layer-1/smardex-factory.json @@ -1,14 +1,63 @@ [ + { "inputs": [], "name": "EmptyPair", "type": "error" }, + { "inputs": [], "name": "WhitelistNotClosed", "type": "error" }, + { "inputs": [], "name": "WhitelistNotOpen", "type": "error" }, { + "anonymous": false, "inputs": [ { + "indexed": true, + "internalType": "address", + "name": "previousFeeTo", + "type": "address" + }, + { + "indexed": true, "internalType": "address", - "name": "_feeToSetter", + "name": "newFeeTo", "type": "address" } ], - "stateMutability": "nonpayable", - "type": "constructor" + "name": "FeeToUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "feesLP", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "feesPool", + "type": "uint256" + } + ], + "name": "FeesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" }, { "anonymous": false, @@ -38,61 +87,78 @@ "type": "uint256" } ], - "name": "PairCreated", + "name": "PairAdded", "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "allPairs", - "outputs": [ + "indexed": true, + "internalType": "address", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token1", + "type": "address" + }, { + "indexed": false, "internalType": "address", - "name": "", + "name": "pair", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalPair", + "type": "uint256" } ], + "name": "PairCreated", + "type": "event" + }, + { + "inputs": [ + { "internalType": "address", "name": "_pair", "type": "address" } + ], + "name": "addPair", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "allPairs", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "allPairsLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "closeWhitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ - { - "internalType": "address", - "name": "_tokenA", - "type": "address" - }, - { - "internalType": "address", - "name": "_tokenB", - "type": "address" - } + { "internalType": "address", "name": "_tokenA", "type": "address" }, + { "internalType": "address", "name": "_tokenB", "type": "address" } ], "name": "createPair", "outputs": [ - { - "internalType": "address", - "name": "pair_", - "type": "address" - } + { "internalType": "address", "name": "pair_", "type": "address" } ], "stateMutability": "nonpayable", "type": "function" @@ -100,60 +166,47 @@ { "inputs": [], "name": "feeTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], - "name": "feeToSetter", + "name": "getDefaultFees", "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } + { "internalType": "uint128", "name": "feesLP_", "type": "uint128" }, + { "internalType": "uint128", "name": "feesPool_", "type": "uint128" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" } ], "name": "getPair", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ - { - "internalType": "address", - "name": "_feeTo", - "type": "address" - } + { "internalType": "address", "name": "_feeTo", "type": "address" } ], "name": "setFeeTo", "outputs": [], @@ -162,15 +215,28 @@ }, { "inputs": [ - { - "internalType": "address", - "name": "_feeToSetter", - "type": "address" - } + { "internalType": "uint128", "name": "_feesLP", "type": "uint128" }, + { "internalType": "uint128", "name": "_feesPool", "type": "uint128" } ], - "name": "setFeeToSetter", + "name": "setFees", "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newOwner", "type": "address" } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "whitelistOpen", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" } ] diff --git a/src/abi/smardex/layer-1/smardex-pool.json b/src/abi/smardex/layer-1/smardex-pool.json index 8e6b2a9a9..b37eec378 100644 --- a/src/abi/smardex/layer-1/smardex-pool.json +++ b/src/abi/smardex/layer-1/smardex-pool.json @@ -1,9 +1,5 @@ [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, { "anonymous": false, "inputs": [ @@ -193,103 +189,45 @@ { "inputs": [], "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" } ], "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } + { "internalType": "address", "name": "account", "type": "address" } ], "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - } - ], + "inputs": [{ "internalType": "address", "name": "_to", "type": "address" }], "name": "burn", "outputs": [ - { - "internalType": "uint256", - "name": "amount0_", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount1_", - "type": "uint256" - } + { "internalType": "uint256", "name": "amount0_", "type": "uint256" }, + { "internalType": "uint256", "name": "amount1_", "type": "uint256" } ], "stateMutability": "nonpayable", "type": "function" @@ -297,23 +235,13 @@ { "inputs": [], "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, + { "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "subtractedValue", @@ -321,26 +249,14 @@ } ], "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "factory", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, @@ -348,16 +264,8 @@ "inputs": [], "name": "getFees", "outputs": [ - { - "internalType": "uint256", - "name": "fees0_", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fees1_", - "type": "uint256" - } + { "internalType": "uint256", "name": "fees0_", "type": "uint256" }, + { "internalType": "uint256", "name": "fees1_", "type": "uint256" } ], "stateMutability": "view", "type": "function" @@ -407,16 +315,8 @@ "inputs": [], "name": "getReserves", "outputs": [ - { - "internalType": "uint256", - "name": "reserve0_", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserve1_", - "type": "uint256" - } + { "internalType": "uint256", "name": "reserve0_", "type": "uint256" }, + { "internalType": "uint256", "name": "reserve1_", "type": "uint256" } ], "stateMutability": "view", "type": "function" @@ -472,40 +372,18 @@ }, { "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "addedValue", "type": "uint256" } ], "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "_token0", - "type": "address" - }, - { - "internalType": "address", - "name": "_token1", - "type": "address" - } + { "internalType": "address", "name": "_token0", "type": "address" }, + { "internalType": "address", "name": "_token1", "type": "address" } ], "name": "initialize", "outputs": [], @@ -514,34 +392,14 @@ }, { "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount0", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_amount1", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_payer", - "type": "address" - } + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_amount0", "type": "uint256" }, + { "internalType": "uint256", "name": "_amount1", "type": "uint256" }, + { "internalType": "address", "name": "_payer", "type": "address" } ], "name": "mint", "outputs": [ - { - "internalType": "uint256", - "name": "liquidity_", - "type": "uint256" - } + { "internalType": "uint256", "name": "liquidity_", "type": "uint256" } ], "stateMutability": "nonpayable", "type": "function" @@ -549,72 +407,28 @@ { "inputs": [], "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } + { "internalType": "address", "name": "owner", "type": "address" } ], "name": "nonces", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "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" - } + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "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": "permit", "outputs": [], @@ -623,39 +437,19 @@ }, { "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "bool", - "name": "_zeroForOne", - "type": "bool" - }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "bool", "name": "_zeroForOne", "type": "bool" }, { "internalType": "int256", "name": "_amountSpecified", "type": "int256" }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } + { "internalType": "bytes", "name": "_data", "type": "bytes" } ], "name": "swap", "outputs": [ - { - "internalType": "int256", - "name": "amount0_", - "type": "int256" - }, - { - "internalType": "int256", - "name": "amount1_", - "type": "int256" - } + { "internalType": "int256", "name": "amount0_", "type": "int256" }, + { "internalType": "int256", "name": "amount1_", "type": "int256" } ], "stateMutability": "nonpayable", "type": "function" @@ -663,105 +457,49 @@ { "inputs": [], "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "token0", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "token1", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" } diff --git a/src/abi/smardex/layer-2/smardex-factory.json b/src/abi/smardex/layer-2/smardex-factory.json index 9dc5bc77b..40b08cef5 100644 --- a/src/abi/smardex/layer-2/smardex-factory.json +++ b/src/abi/smardex/layer-2/smardex-factory.json @@ -88,57 +88,27 @@ "type": "event" }, { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "name": "allPairs", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "allPairsLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "_tokenA", - "type": "address" - }, - { - "internalType": "address", - "name": "_tokenB", - "type": "address" - } + { "internalType": "address", "name": "_tokenA", "type": "address" }, + { "internalType": "address", "name": "_tokenB", "type": "address" } ], "name": "createPair", "outputs": [ - { - "internalType": "address", - "name": "pair_", - "type": "address" - } + { "internalType": "address", "name": "pair_", "type": "address" } ], "stateMutability": "nonpayable", "type": "function" @@ -146,13 +116,7 @@ { "inputs": [], "name": "feeTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, @@ -160,54 +124,26 @@ "inputs": [], "name": "getDefaultFees", "outputs": [ - { - "internalType": "uint128", - "name": "feesLP_", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "feesPool_", - "type": "uint128" - } + { "internalType": "uint128", "name": "feesLP_", "type": "uint128" }, + { "internalType": "uint128", "name": "feesPool_", "type": "uint128" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" } ], "name": "getPair", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, @@ -220,11 +156,7 @@ }, { "inputs": [ - { - "internalType": "address", - "name": "_feeTo", - "type": "address" - } + { "internalType": "address", "name": "_feeTo", "type": "address" } ], "name": "setFeeTo", "outputs": [], @@ -233,16 +165,8 @@ }, { "inputs": [ - { - "internalType": "uint128", - "name": "_feesLP", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "_feesPool", - "type": "uint128" - } + { "internalType": "uint128", "name": "_feesLP", "type": "uint128" }, + { "internalType": "uint128", "name": "_feesPool", "type": "uint128" } ], "name": "setFees", "outputs": [], @@ -251,11 +175,7 @@ }, { "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } + { "internalType": "address", "name": "newOwner", "type": "address" } ], "name": "transferOwnership", "outputs": [], diff --git a/src/abi/smardex/layer-2/smardex-pool.json b/src/abi/smardex/layer-2/smardex-pool.json index f8e62aac2..22c5e2a13 100644 --- a/src/abi/smardex/layer-2/smardex-pool.json +++ b/src/abi/smardex/layer-2/smardex-pool.json @@ -1,22 +1,8 @@ [ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { "inputs": [], "name": "InvalidShortString", "type": "error" }, { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "InvalidShortString", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "str", - "type": "string" - } - ], + "inputs": [{ "internalType": "string", "name": "str", "type": "string" }], "name": "StringTooLong", "type": "error" }, @@ -234,103 +220,45 @@ { "inputs": [], "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" } ], "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } + { "internalType": "address", "name": "account", "type": "address" } ], "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - } - ], + "inputs": [{ "internalType": "address", "name": "_to", "type": "address" }], "name": "burn", "outputs": [ - { - "internalType": "uint256", - "name": "amount0_", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount1_", - "type": "uint256" - } + { "internalType": "uint256", "name": "amount0_", "type": "uint256" }, + { "internalType": "uint256", "name": "amount1_", "type": "uint256" } ], "stateMutability": "nonpayable", "type": "function" @@ -338,23 +266,13 @@ { "inputs": [], "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, + { "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "subtractedValue", @@ -362,13 +280,7 @@ } ], "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }, @@ -376,41 +288,17 @@ "inputs": [], "name": "eip712Domain", "outputs": [ - { - "internalType": "bytes1", - "name": "fields", - "type": "bytes1" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - }, - { - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - }, + { "internalType": "bytes1", "name": "fields", "type": "bytes1" }, + { "internalType": "string", "name": "name", "type": "string" }, + { "internalType": "string", "name": "version", "type": "string" }, + { "internalType": "uint256", "name": "chainId", "type": "uint256" }, { "internalType": "address", "name": "verifyingContract", "type": "address" }, - { - "internalType": "bytes32", - "name": "salt", - "type": "bytes32" - }, - { - "internalType": "uint256[]", - "name": "extensions", - "type": "uint256[]" - } + { "internalType": "bytes32", "name": "salt", "type": "bytes32" }, + { "internalType": "uint256[]", "name": "extensions", "type": "uint256[]" } ], "stateMutability": "view", "type": "function" @@ -418,13 +306,7 @@ { "inputs": [], "name": "factory", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, @@ -432,16 +314,8 @@ "inputs": [], "name": "getFeeToAmounts", "outputs": [ - { - "internalType": "uint256", - "name": "fees0_", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fees1_", - "type": "uint256" - } + { "internalType": "uint256", "name": "fees0_", "type": "uint256" }, + { "internalType": "uint256", "name": "fees1_", "type": "uint256" } ], "stateMutability": "view", "type": "function" @@ -468,16 +342,8 @@ "inputs": [], "name": "getPairFees", "outputs": [ - { - "internalType": "uint128", - "name": "feesLP_", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "feesPool_", - "type": "uint128" - } + { "internalType": "uint128", "name": "feesLP_", "type": "uint128" }, + { "internalType": "uint128", "name": "feesPool_", "type": "uint128" } ], "stateMutability": "view", "type": "function" @@ -509,16 +375,8 @@ "inputs": [], "name": "getReserves", "outputs": [ - { - "internalType": "uint256", - "name": "reserve0_", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserve1_", - "type": "uint256" - } + { "internalType": "uint256", "name": "reserve0_", "type": "uint256" }, + { "internalType": "uint256", "name": "reserve1_", "type": "uint256" } ], "stateMutability": "view", "type": "function" @@ -574,50 +432,20 @@ }, { "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "addedValue", "type": "uint256" } ], "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "_token0", - "type": "address" - }, - { - "internalType": "address", - "name": "_token1", - "type": "address" - }, - { - "internalType": "uint128", - "name": "_feesLP", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "_feesPool", - "type": "uint128" - } + { "internalType": "address", "name": "_token0", "type": "address" }, + { "internalType": "address", "name": "_token1", "type": "address" }, + { "internalType": "uint128", "name": "_feesLP", "type": "uint128" }, + { "internalType": "uint128", "name": "_feesPool", "type": "uint128" } ], "name": "initialize", "outputs": [], @@ -626,34 +454,14 @@ }, { "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount0", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_amount1", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_payer", - "type": "address" - } + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "uint256", "name": "_amount0", "type": "uint256" }, + { "internalType": "uint256", "name": "_amount1", "type": "uint256" }, + { "internalType": "address", "name": "_payer", "type": "address" } ], "name": "mint", "outputs": [ - { - "internalType": "uint256", - "name": "liquidity_", - "type": "uint256" - } + { "internalType": "uint256", "name": "liquidity_", "type": "uint256" } ], "stateMutability": "nonpayable", "type": "function" @@ -661,72 +469,28 @@ { "inputs": [], "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } + { "internalType": "address", "name": "owner", "type": "address" } ], "name": "nonces", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "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" - } + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "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": "permit", "outputs": [], @@ -735,16 +499,8 @@ }, { "inputs": [ - { - "internalType": "uint128", - "name": "_feesLP", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "_feesPool", - "type": "uint128" - } + { "internalType": "uint128", "name": "_feesLP", "type": "uint128" }, + { "internalType": "uint128", "name": "_feesPool", "type": "uint128" } ], "name": "setFees", "outputs": [], @@ -753,39 +509,19 @@ }, { "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "bool", - "name": "_zeroForOne", - "type": "bool" - }, + { "internalType": "address", "name": "_to", "type": "address" }, + { "internalType": "bool", "name": "_zeroForOne", "type": "bool" }, { "internalType": "int256", "name": "_amountSpecified", "type": "int256" }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } + { "internalType": "bytes", "name": "_data", "type": "bytes" } ], "name": "swap", "outputs": [ - { - "internalType": "int256", - "name": "amount0_", - "type": "int256" - }, - { - "internalType": "int256", - "name": "amount1_", - "type": "int256" - } + { "internalType": "int256", "name": "amount0_", "type": "int256" }, + { "internalType": "int256", "name": "amount1_", "type": "int256" } ], "stateMutability": "nonpayable", "type": "function" @@ -793,105 +529,49 @@ { "inputs": [], "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "token0", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "token1", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" } diff --git a/src/dex/smardex/smardex-events.test.ts b/src/dex/smardex/smardex-events.test.ts index f80a9c423..5d758584f 100644 --- a/src/dex/smardex/smardex-events.test.ts +++ b/src/dex/smardex/smardex-events.test.ts @@ -6,7 +6,8 @@ dotenv.config(); import SmardexPoolLayerOneABI from '../../abi/smardex/layer-1/smardex-pool.json'; import SmardexPoolLayerTwoABI from '../../abi/smardex/layer-2/smardex-pool.json'; -import { Smardex, SmardexEventPool } from './smardex'; +import { Smardex } from './smardex'; +import { SmardexEventPool } from './smardex-event-pool'; import { Network } from '../../constants'; import { DummyDexHelper } from '../../dex-helper/index'; import { testEventSubscriber } from '../../../tests/utils-events'; diff --git a/yarn.lock b/yarn.lock index ae2781615..849f96ee5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3875,7 +3875,7 @@ ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: ethereum-cryptography "^0.1.3" rlp "^2.2.4" -ethers@^5.6.5, ethers@^5.7.0: +ethers@5.7.2, ethers@^5.7.0: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== From 0cb9f2f6d133cdc1c21761c8b203263161a9cfd7 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 7 Dec 2023 19:01:34 +0200 Subject: [PATCH 728/833] 2.42.24-smardex.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7ed3d746f..5fbf2c145 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.24-smardex.2", + "version": "2.42.24-smardex.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 7adf7ba2860a2a1b212bb11da5f5f8a6cb480fea Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 7 Dec 2023 19:29:49 +0200 Subject: [PATCH 729/833] fix: upgrade ethers --- package.json | 2 +- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5fbf2c145..e3d1fff1c 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "bignumber.js": "9.1.0", "cross-fetch": "^3.1.5", "es6-promise": "^4.2.8", - "ethers": "5.7.2", + "ethers": "^5.7.2", "joi": "^17.7.0", "lens.ts": "^0.5.1", "lodash": "4.17.21", diff --git a/yarn.lock b/yarn.lock index 849f96ee5..cf26f6f93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3875,7 +3875,7 @@ ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.5: ethereum-cryptography "^0.1.3" rlp "^2.2.4" -ethers@5.7.2, ethers@^5.7.0: +ethers@^5.7.0, ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== From cf07e21b16f550a1a2d2ac3350b9cc17245ac3a7 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 7 Dec 2023 19:32:47 +0200 Subject: [PATCH 730/833] 2.42.24-smardex.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e3d1fff1c..5796b0167 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.24-smardex.3", + "version": "2.42.24-smardex.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 807712aa1849687678693efae75a094b5c538929 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 7 Dec 2023 19:55:03 +0200 Subject: [PATCH 731/833] add separate dep for abi --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 5796b0167..b317639e2 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ }, "dependencies": { "@0x/utils": "^4.5.2", + "@ethersproject/abi": "^5.7.0", "@hashflow/sdk": "1.2.4", "@hashflow/taker-js": "0.3.4", "@paraswap/core": "1.1.0", From ecbfc8b2aaba7925e31210507af71ba2c8cfdc22 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 7 Dec 2023 19:55:54 +0200 Subject: [PATCH 732/833] 2.42.24-smardex.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b317639e2..0597f1dbc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.24-smardex.4", + "version": "2.42.24-smardex.5", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 328bb1bcc5c56881fb4a09dc9cd79d6aa279efd7 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Fri, 8 Dec 2023 13:25:59 +0200 Subject: [PATCH 733/833] wombat: prevent BUY side for prices and tx build --- src/dex/wombat/wombat-e2e.test.ts | 7 +------ src/dex/wombat/wombat.ts | 6 +++++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/dex/wombat/wombat-e2e.test.ts b/src/dex/wombat/wombat-e2e.test.ts index ecafcd416..36968e240 100644 --- a/src/dex/wombat/wombat-e2e.test.ts +++ b/src/dex/wombat/wombat-e2e.test.ts @@ -2,11 +2,7 @@ import dotenv from 'dotenv'; dotenv.config(); import { testE2E } from '../../../tests/utils-e2e'; -import { - Tokens, - Holders, - NativeTokenSymbols, -} from '../../../tests/constants-e2e'; +import { Tokens, Holders } from '../../../tests/constants-e2e'; import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; @@ -35,7 +31,6 @@ function testForNetwork( ContractMethod.megaSwap, ], ], - [SwapSide.BUY, [ContractMethod.simpleBuy /* ContractMethod.buy */]], ]); sideToContractMethods.forEach((contractMethods, side) => diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 79f0fc6f3..5ef0ca4b2 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -33,7 +33,6 @@ import { WombatPool } from './wombat-pool'; import { StatePollingManager } from '../../lib/stateful-rpc-poller/state-polling-manager'; export class Wombat extends SimpleExchange implements IDex { - // export class Wombat implements IDex { // contract interfaces static readonly erc20Interface = new Interface(ERC20ABI); static readonly poolInterface = new Interface(PoolABI); @@ -135,6 +134,7 @@ export class Wombat extends SimpleExchange implements IDex { side: SwapSide, blockNumber: number, ): Promise { + if (side === SwapSide.BUY) return []; await this.updatePoolState(); return ( await this.findPools( @@ -161,6 +161,7 @@ export class Wombat extends SimpleExchange implements IDex { blockNumber: number, limitPools?: string[], ): Promise> { + if (side === SwapSide.BUY) return null; // Buy side not implemented yet if (!this.pools) { this.logger.error(`Missing pools for ${this.dexKey} in getPricesVolume`); return null; @@ -275,6 +276,8 @@ export class Wombat extends SimpleExchange implements IDex { data: WombatData, side: SwapSide, ): AdapterExchangeParam { + if (side === SwapSide.BUY) throw new Error(`Buy not supported`); + const { exchange } = data; return { @@ -296,6 +299,7 @@ export class Wombat extends SimpleExchange implements IDex { data: WombatData, side: SwapSide, ): Promise { + if (side === SwapSide.BUY) throw new Error(`Buy not supported`); const { exchange } = data; // Encode here the transaction arguments From 04a3c1d377fafd536b62ef591cdfb05a147b0e8d Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Fri, 8 Dec 2023 13:51:49 +0200 Subject: [PATCH 734/833] 2.42.25 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 944f2cb6d..a8fc023d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.25-wombat.6", + "version": "2.42.25", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 9d8a75c9b15a51828083287f1982b4b3e77dd399 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 8 Dec 2023 14:03:18 +0200 Subject: [PATCH 735/833] fix: rename pool --- src/dex/smardex/smardex-event-pool.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/dex/smardex/smardex-event-pool.ts b/src/dex/smardex/smardex-event-pool.ts index 3b02b45b2..e01506e2f 100644 --- a/src/dex/smardex/smardex-event-pool.ts +++ b/src/dex/smardex/smardex-event-pool.ts @@ -23,15 +23,7 @@ export class SmardexEventPool extends StatefulEventSubscriber protected smardexFeesMulticallDecoder?: (values: any[]) => SmardexFees, private isLayerOne = true, ) { - super( - 'Smardex', - (token0.symbol || token0.address) + - '-' + - (token1.symbol || token1.address) + - ' pool', - dexHelper, - logger, - ); + super('Smardex', `${token0.address}_${token1.address}`, dexHelper, logger); } async fetchPairFeesAndLastTimestamp(blockNumber: number): Promise<{ From 636ad8e7597cd1a83bd6ad1cc437abf5b9b45769 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 8 Dec 2023 14:07:01 +0200 Subject: [PATCH 736/833] 2.42.24-smardex.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0597f1dbc..cb1a32848 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.24-smardex.5", + "version": "2.42.24-smardex.6", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 3507b4f6fa422756ddf90ae632cb67df6566cc8d Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Fri, 8 Dec 2023 15:30:22 +0200 Subject: [PATCH 737/833] wombat: initialize pooling for each pool --- src/dex/wombat/wombat.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 5ef0ca4b2..17fabc2fe 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -78,7 +78,6 @@ export class Wombat extends SimpleExchange implements IDex { this.config.bmwAddress, this.onAssetAdded.bind(this), ); - this.pollingManager.initializeAllPendingPools(); } async init(blockNumber: number) { @@ -113,6 +112,7 @@ export class Wombat extends SimpleExchange implements IDex { asset2TokenMap, ); await this.pools[pool].getState('latest', true); + this.pollingManager.initializeAllPendingPools(); } else { this.pools[pool].addAssets(asset2TokenMap); } From bdf12165eedfbe4bf4cd015862159bbe0bdbdbf5 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Fri, 8 Dec 2023 15:31:14 +0200 Subject: [PATCH 738/833] 2.42.26-wombat.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a8fc023d8..e3cdef0f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.25", + "version": "2.42.26-wombat.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 8dce649b3dbc00b2d347c8f465a9219a918f54d6 Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Fri, 8 Dec 2023 15:43:41 +0200 Subject: [PATCH 739/833] 2.42.26 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e3cdef0f7..65d280aae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.26-wombat.0", + "version": "2.42.26", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 2c4c361236913977787d9a28013ce662ed823fd3 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 8 Dec 2023 15:54:16 +0200 Subject: [PATCH 740/833] fix: acc to review --- src/dex/smardex/constants.ts | 1 - src/dex/smardex/smardex-event-pool.ts | 13 ----- src/dex/smardex/smardex.ts | 74 +-------------------------- 3 files changed, 1 insertion(+), 87 deletions(-) diff --git a/src/dex/smardex/constants.ts b/src/dex/smardex/constants.ts index 95e39fa31..4ddee903e 100644 --- a/src/dex/smardex/constants.ts +++ b/src/dex/smardex/constants.ts @@ -5,7 +5,6 @@ export enum TOPICS { SYNC_EVENT = '0x2a368c7f33bb86e2d999940a3989d849031aff29b750f67947e6b8e8c3d2ffd6', SWAP_EVENT = '0xa4228e1eb11eb9b31069d9ed20e7af9a010ca1a02d4855cee54e08e188fcc32c', FEES_EVENT = '0x64f84976d9c917a44796104a59950fdbd9b3c16a5dd348b546d738301f6bd068', - // PAIR_CREATED_EVENT = '0x0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9', } export enum SmardexRouterFunctions { diff --git a/src/dex/smardex/smardex-event-pool.ts b/src/dex/smardex/smardex-event-pool.ts index e01506e2f..5be86ca39 100644 --- a/src/dex/smardex/smardex-event-pool.ts +++ b/src/dex/smardex/smardex-event-pool.ts @@ -98,19 +98,6 @@ export class SmardexEventPool extends StatefulEventSubscriber feesLP: BigInt(event.args.feesLP), feesPool: BigInt(event.args.feesPool), }; - // case 'Swap': - // const fetchedSwap = await this.fetchPairFeesAndLastTimestamp(log.blockNumber); - // return { - // reserves0: state.reserves0, - // reserves1: state.reserves1, - // fictiveReserves0: state.fictiveReserves0, - // fictiveReserves1: state.fictiveReserves1, - // priceAverage0: state.priceAverage0, - // priceAverage1: state.priceAverage1, - // priceAverageLastTimestamp: fetchedSwap.priceAverageLastTimestamp, - // feesLP: fetchedSwap.feesLP, - // feesPool: fetchedSwap.feesPool, - // }; } return null; } diff --git a/src/dex/smardex/smardex.ts b/src/dex/smardex/smardex.ts index 201b476cb..3318f4e10 100644 --- a/src/dex/smardex/smardex.ts +++ b/src/dex/smardex/smardex.ts @@ -59,10 +59,7 @@ const smardexPoolL2 = new Interface(SmardexPoolLayerTwoABI); const coder = new AbiCoder(); -function encodePools( - pools: SmardexPool[], - // feeFactor: number, -): NumberAsString[] { +function encodePools(pools: SmardexPool[]): NumberAsString[] { return pools.map(({ fee, direction, address }) => { return ( (BigInt(fee) << 161n) + @@ -241,7 +238,6 @@ export class Smardex path: [from.address.toLowerCase(), to.address.toLowerCase()], factory: this.factoryAddress, initCode: this.initCode, - // feeFactor: this.feeFactor, pools: [ { address: pairParam.exchange, @@ -310,10 +306,6 @@ export class Smardex priceParams.feesPool, ).amount; - // uncomment to log rates - // console.log("destAmount.", utils.formatEther(destAmount.toString())) - // console.log("amountIn", utils.formatEther(amountIn.toString())) - return BigInt(amountIn.toString()); } @@ -337,9 +329,6 @@ export class Smardex priceParams.feesPool, ).amount; - // uncomment to log rates - // console.log("srcAmount.", utils.formatEther(srcAmount.toString())) - // console.log("amountOut", utils.formatEther(amountOut.toString())) return BigInt(amountOut.toString()); } @@ -581,67 +570,6 @@ export class Smardex }); } - // Necessary to get the correct path for the router - getDirectParam( - srcToken: Address, - destToken: Address, - srcAmount: NumberAsString, - destAmount: NumberAsString, - expectedAmount: NumberAsString, - _data: SmardexData, - side: SwapSide, - permit: string, - uuid: string, - feePercent: NumberAsString, - deadline: NumberAsString, - partner: string, - beneficiary: string, - contractMethod?: string, - ): TxInfo { - if (!contractMethod) throw new Error(`contractMethod need to be passed`); - if (permit !== '0x') contractMethod += 'WithPermit'; - - const swapParams = ((): SmardexParam => { - const data = _data as unknown as SmardexData; - const path = this.fixPath(data.path, srcToken, destToken); - - switch (contractMethod) { - case SmardexRouterFunctions.sellExactEth: - case SmardexRouterFunctions.sellExactToken: - case SmardexRouterFunctions.swapExactIn: - return [ - srcAmount, - destAmount, - data.path, - data.receiver, - data.deadline, - ]; - - case SmardexRouterFunctions.buyExactEth: - case SmardexRouterFunctions.buyExactToken: - case SmardexRouterFunctions.swapExactOut: - return [ - destAmount, - srcAmount, - data.path, - data.receiver, - data.deadline, - ]; - - default: - throw new Error(`contractMethod=${contractMethod} is not supported`); - } - })(); - - const encoder = (...params: SmardexParam) => - this.routerInterface.encodeFunctionData(contractMethod!, params); - return { - params: swapParams, - encoder, - networkFee: '0', - }; - } - async getPairOrderedParams( from: Token, to: Token, From f97265054b71a18109a64bd576d6972c8e5c9133 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 8 Dec 2023 16:03:37 +0200 Subject: [PATCH 741/833] 2.42.26-smardex --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b627edd3e..75d53895c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.26", + "version": "2.42.26-smardex", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 79bc3963ebedad7d7a75dfe2344862355e7338af Mon Sep 17 00:00:00 2001 From: Seraph <113269670+seraphx333@users.noreply.github.com> Date: Sun, 10 Dec 2023 20:34:35 -0800 Subject: [PATCH 742/833] fix events test --- src/dex/solidly-v3/solidly-v3-events.test.ts | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-events.test.ts b/src/dex/solidly-v3/solidly-v3-events.test.ts index 4563e9e5c..02524995e 100644 --- a/src/dex/solidly-v3/solidly-v3-events.test.ts +++ b/src/dex/solidly-v3/solidly-v3-events.test.ts @@ -74,23 +74,23 @@ async function fetchPoolStateFromContract( type EventMappings = Record; describe('SolidlyV3 Event', function () { - const poolAddress = '0x3198EAdB777b9b6C789bfc89491774644E95eD7e'; - const token0 = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'; - const token1 = '0xdac17f958d2ee523a2206206994597c13d831ec7'; + const poolAddress = '0x831BF48183B999fDe45294b14B55199072f0801B'; + const token0 = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'; + const token1 = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'; const blockNumbers: { [eventName: string]: number[] } = { // topic0 - 0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67 ['Swap']: [ - 18185415, 18185632, 18185654, 18186489, 18186623, 18186845, 18186959, 18187709, 18187816, - 18187818, 18187846, 18187849, 18187881 + 18600853, 18616106, 18616441, 18619851, 18622968, 18625121, 18626415, 18627297, 18630574, + 18718946, 18726197, 18730166, 18758602 ], - ['Burn']: [18185393], - ['Mint']: [18189645, 18189685, 18190653], - ['Collect']: [18185393], + ['Burn']: [18737937], + ['Mint']: [18708230, 18709265, 18737969], + ['Collect']: [18751597], //topic0 0x0eb63f4a36d6bdeee05aa00020a97d80c3e84f1b5b3ebf345fb67262e62b0f33 - ['SetFee']: [18180677, 18181047, 18182317, 18185660, 18186351, 18188882, 18193229], - ['Flash']: [18202148], - ['CollectProtocol']: [18203357, 18209933], + ['SetFee']: [18427614, 18423073, 18423143, 18425324, 18430069, 18442932, 18442934], + ['Flash']: [18758872], + ['CollectProtocol']: [18530529, 18577493], } describe('SolidlyV3EventPool', function () { From 1bcd6fbc1bf54b483508d547054dcdad4c2fefe8 Mon Sep 17 00:00:00 2001 From: Seraph <113269670+seraphx333@users.noreply.github.com> Date: Sun, 10 Dec 2023 20:58:41 -0800 Subject: [PATCH 743/833] Adjusted swap amounts --- src/dex/solidly-v3/solidly-v3-e2e.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-e2e.test.ts b/src/dex/solidly-v3/solidly-v3-e2e.test.ts index a3436a699..2f619b415 100644 --- a/src/dex/solidly-v3/solidly-v3-e2e.test.ts +++ b/src/dex/solidly-v3/solidly-v3-e2e.test.ts @@ -67,9 +67,9 @@ describe('SolidlyV3 E2E', () => { const tokenBSymbol: string = 'USDC'; const nativeTokenSymbol = NativeTokenSymbols[network]; - const tokenAAmount: string = '11000000000000000000'; - const tokenBAmount: string = '11000000'; - const nativeTokenAmount = '11000000000000000000'; + const tokenAAmount: string = '1100000000000000000'; + const tokenBAmount: string = '1100000000'; + const nativeTokenAmount = '1100000000000000000'; const sideToContractMethods = new Map([ [ From 44a21c2a31a77a7735e85b7d853ad0b4b3edaeba Mon Sep 17 00:00:00 2001 From: Seraph <113269670+seraphx333@users.noreply.github.com> Date: Sun, 10 Dec 2023 21:29:44 -0800 Subject: [PATCH 744/833] Support multiple TickSpacings --- src/dex/solidly-v3/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index e2dfb009d..e21f01904 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -5,7 +5,7 @@ import { Address } from '../../types'; // const SUPPORTED_FEES = [3000n]; const SUPPORTED_FEES = [500n]; -const SUPPORTED_TICK_SPACINGS = [10n]; +const SUPPORTED_TICK_SPACINGS = [1n, 10n, 50n, 100n]; // Pools that will be initialized on app startup // They are added for testing From dadbb28fb9d53d5bfe7cf008615587f7b904b494 Mon Sep 17 00:00:00 2001 From: Seraph <113269670+seraphx333@users.noreply.github.com> Date: Sun, 10 Dec 2023 21:35:32 -0800 Subject: [PATCH 745/833] Add USDC/USDT to e2e --- src/dex/solidly-v3/solidly-v3-e2e.test.ts | 79 +++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/dex/solidly-v3/solidly-v3-e2e.test.ts b/src/dex/solidly-v3/solidly-v3-e2e.test.ts index 2f619b415..cb2858602 100644 --- a/src/dex/solidly-v3/solidly-v3-e2e.test.ts +++ b/src/dex/solidly-v3/solidly-v3-e2e.test.ts @@ -112,6 +112,85 @@ describe('SolidlyV3 E2E', () => { }), ); + // tokenB -> tokenA + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${tokenBSymbol} -> ${tokenASymbol}`, async () => { + await testE2E( + tokens[tokenBSymbol], + tokens[tokenASymbol], + holders[tokenBSymbol], + side === SwapSide.SELL ? tokenBAmount : tokenAAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + }); + describe('Mainnet USDC-USDT', () => { + const network = Network.MAINNET; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + + const tokenASymbol: string = 'USDC'; + const tokenBSymbol: string = 'USDT'; + //const nativeTokenSymbol = NativeTokenSymbols[network]; + + const tokenAAmount: string = '400000000'; + const tokenBAmount: string = '500000000'; + //const nativeTokenAmount = '1100000000000000000'; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, + [ + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, + // ContractMethod.directUniV3Swap, + ], + ], + [ + SwapSide.BUY, + [ + ContractMethod.simpleBuy, + // ContractMethod.buy, + // ContractMethod.directUniV3Buy, + ], + ], + ]); + + // tokenA -> tokenB + sideToContractMethods.forEach((contractMethods, side) => + contractMethods.forEach((contractMethod: ContractMethod) => { + describe(`${contractMethod}`, () => { + it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { + await testE2E( + tokens[tokenASymbol], + tokens[tokenBSymbol], + holders[tokenASymbol], + side === SwapSide.SELL ? tokenAAmount : tokenBAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); + }), + ); + // tokenB -> tokenA sideToContractMethods.forEach((contractMethods, side) => contractMethods.forEach((contractMethod: ContractMethod) => { From fa0bab4ab99626922248b1804812b0b60cc69f69 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 11 Dec 2023 18:01:15 +0200 Subject: [PATCH 746/833] 2.42.27 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 75d53895c..d7d232883 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.26-smardex", + "version": "2.42.27", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 57287c09d16b0e23f9015a5436f1106cf9822aa2 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 12 Dec 2023 20:38:30 +0200 Subject: [PATCH 747/833] fix: rewrite tests --- src/dex/solidly-v3/solidly-v3-e2e.test.ts | 267 +++++++--------------- src/dex/solidly-v3/solidly-v3-pool.ts | 4 +- 2 files changed, 84 insertions(+), 187 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-e2e.test.ts b/src/dex/solidly-v3/solidly-v3-e2e.test.ts index cb2858602..e8885858c 100644 --- a/src/dex/solidly-v3/solidly-v3-e2e.test.ts +++ b/src/dex/solidly-v3/solidly-v3-e2e.test.ts @@ -12,204 +12,101 @@ import { Network, ContractMethod, SwapSide } from '../../constants'; import { StaticJsonRpcProvider } from '@ethersproject/providers'; import { generateConfig } from '../../config'; -/* - README - ====== - - This test script should add e2e tests for SolidlyV3. The tests - should cover as many cases as possible. Most of the DEXes follow - the following test structure: - - DexName - - ForkName + Network - - ContractMethod - - ETH -> Token swap - - Token -> ETH swap - - Token -> Token swap - - The template already enumerates the basic structure which involves - testing simpleSwap, multiSwap, megaSwap contract methods for - ETH <> TOKEN and TOKEN <> TOKEN swaps. You should replace tokenA and - tokenB with any two highly liquid tokens on SolidlyV3 for the tests - to work. If the tokens that you would like to use are not defined in - Tokens or Holders map, you can update the './tests/constants-e2e' - - Other than the standard cases that are already added by the template - it is highly recommended to add test cases which could be specific - to testing SolidlyV3 (Eg. Tests based on poolType, special tokens, - etc). - - You can run this individual test script by running: - `npx jest src/dex//-e2e.test.ts` - - e2e tests use the Tenderly fork api. Please add the following to your - .env file: - TENDERLY_TOKEN=Find this under Account>Settings>Authorization. - TENDERLY_ACCOUNT_ID=Your Tenderly account name. - TENDERLY_PROJECT=Name of a Tenderly project you have created in your - dashboard. - - (This comment should be removed from the final implementation) -*/ - -describe('SolidlyV3 E2E', () => { - const dexKey = 'SolidlyV3'; - - describe('Mainnet', () => { - const network = Network.MAINNET; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const tokenASymbol: string = 'WETH'; - const tokenBSymbol: string = 'USDC'; - const nativeTokenSymbol = NativeTokenSymbols[network]; - - const tokenAAmount: string = '1100000000000000000'; - const tokenBAmount: string = '1100000000'; - const nativeTokenAmount = '1100000000000000000'; - - const sideToContractMethods = new Map([ - [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - // ContractMethod.directUniV3Swap, - ], - ], +function testForNetwork( + network: Network, + dexKey: string, + pairs: { name: string; sellAmount: string; buyAmount: string }[][], +) { + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const tokens = Tokens[network]; + const holders = Holders[network]; + + const sideToContractMethods = new Map([ + [ + SwapSide.SELL, [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - // ContractMethod.buy, - // ContractMethod.directUniV3Buy, - ], + ContractMethod.simpleSwap, + // ContractMethod.multiSwap, + // ContractMethod.megaSwap, ], - ]); + ], + [SwapSide.BUY, [ContractMethod.simpleBuy /*, ContractMethod.buy */]], + ]); - // tokenA -> tokenB - sideToContractMethods.forEach((contractMethods, side) => + sideToContractMethods.forEach((contractMethods, side) => + describe(`${side}`, () => { contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); + pairs.forEach(pair => { + describe(`${contractMethod}`, () => { + it(`${pair[0].name} -> ${pair[1].name}`, async () => { + await testE2E( + tokens[pair[0].name], + tokens[pair[1].name], + holders[pair[0].name], + side === SwapSide.SELL ? pair[0].sellAmount : pair[0].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); + it(`${pair[1].name} -> ${pair[0].name}`, async () => { + await testE2E( + tokens[pair[1].name], + tokens[pair[0].name], + holders[pair[1].name], + side === SwapSide.SELL ? pair[1].sellAmount : pair[1].buyAmount, + side, + dexKey, + contractMethod, + network, + provider, + ); + }); }); }); - }), - ); + }); + }), + ); +} - // tokenB -> tokenA - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${tokenBSymbol} -> ${tokenASymbol}`, async () => { - await testE2E( - tokens[tokenBSymbol], - tokens[tokenASymbol], - holders[tokenBSymbol], - side === SwapSide.SELL ? tokenBAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }), - ); - }); - describe('Mainnet USDC-USDT', () => { - const network = Network.MAINNET; - const tokens = Tokens[network]; - const holders = Holders[network]; - const provider = new StaticJsonRpcProvider( - generateConfig(network).privateHttpProvider, - network, - ); - - const tokenASymbol: string = 'USDC'; - const tokenBSymbol: string = 'USDT'; - //const nativeTokenSymbol = NativeTokenSymbols[network]; +describe('SolidlyV3 E2E', () => { + const dexKey = 'SolidlyV3'; - const tokenAAmount: string = '400000000'; - const tokenBAmount: string = '500000000'; - //const nativeTokenAmount = '1100000000000000000'; + describe('Mainnet', () => { + const network = Network.MAINNET; - const sideToContractMethods = new Map([ + const pairs = [ [ - SwapSide.SELL, - [ - ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, - // ContractMethod.directUniV3Swap, - ], + { + name: 'WETH', + sellAmount: '1100000000000000000', + buyAmount: '1100000000', + }, + { + name: 'USDC', + sellAmount: '400000000', + buyAmount: '4000000', + }, ], [ - SwapSide.BUY, - [ - ContractMethod.simpleBuy, - // ContractMethod.buy, - // ContractMethod.directUniV3Buy, - ], + { + name: 'USDC', + sellAmount: '400000000', + buyAmount: '4000000', + }, + { + name: 'USDT', + sellAmount: '500000000', + buyAmount: '5000000', + }, ], - ]); - - // tokenA -> tokenB - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${tokenASymbol} -> ${tokenBSymbol}`, async () => { - await testE2E( - tokens[tokenASymbol], - tokens[tokenBSymbol], - holders[tokenASymbol], - side === SwapSide.SELL ? tokenAAmount : tokenBAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }), - ); + ]; - // tokenB -> tokenA - sideToContractMethods.forEach((contractMethods, side) => - contractMethods.forEach((contractMethod: ContractMethod) => { - describe(`${contractMethod}`, () => { - it(`${network} ${side} ${contractMethod} ${tokenBSymbol} -> ${tokenASymbol}`, async () => { - await testE2E( - tokens[tokenBSymbol], - tokens[tokenASymbol], - holders[tokenBSymbol], - side === SwapSide.SELL ? tokenBAmount : tokenAAmount, - side, - dexKey, - contractMethod, - network, - provider, - ); - }); - }); - }), - ); + testForNetwork(network, dexKey, pairs); }); }); diff --git a/src/dex/solidly-v3/solidly-v3-pool.ts b/src/dex/solidly-v3/solidly-v3-pool.ts index 6f5a4f051..e467d7c47 100644 --- a/src/dex/solidly-v3/solidly-v3-pool.ts +++ b/src/dex/solidly-v3/solidly-v3-pool.ts @@ -283,7 +283,7 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { const currentTick = bigIntify(_state.slot0.tick); const tickSpacing = bigIntify(_state.tickSpacing); - const fee = bigIntify(_state.slot0.fee) + const fee = bigIntify(_state.slot0.fee); const startTickBitmap = TickBitMap.position(currentTick / tickSpacing)[0]; const requestedRange = this.getBitmapRangeToRequest(); @@ -460,7 +460,7 @@ export class SolidlyV3EventPool extends StatefulEventSubscriber { event: any, pool: PoolState, log: Log, - blockHeader: BlockHeader + blockHeader: BlockHeader, ) { const feeNew = bigIntify(event.args.feeNew); pool.slot0.fee = feeNew; From 5228fd6d70f77868a977fe3f0bca88fc85f8553d Mon Sep 17 00:00:00 2001 From: Seraph <113269670+seraphx333@users.noreply.github.com> Date: Tue, 12 Dec 2023 12:07:17 -0800 Subject: [PATCH 748/833] preload pools --- src/dex/solidly-v3/config.ts | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index e21f01904..3114848e6 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -12,15 +12,31 @@ const SUPPORTED_TICK_SPACINGS = [1n, 10n, 50n, 100n]; export const PoolsToPreload: DexConfigMap< { token0: Address; token1: Address }[] > = { - UniswapV3: { - [Network.POLYGON]: [ + SolidlyV3: { + [Network.MAINNET]: [ + { + token0: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'.toLowerCase(), + token1: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'.toLowerCase(), + }, + { + token0: '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0'.toLowerCase(), + token1: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'.toLowerCase(), + }, + { + token0: '0x514910771AF9Ca656af840dff83E8264EcF986CA'.toLowerCase(), + token1: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'.toLowerCase(), + }, + { + token0: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599'.toLowerCase(), + token1: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'.toLowerCase(), + }, { - token0: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270'.toLowerCase(), - token1: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174'.toLowerCase(), + token0: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'.toLowerCase(), + token1: '0xdAC17F958D2ee523a2206206994597C13D831ec7'.toLowerCase(), }, { - token0: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619'.toLowerCase(), - token1: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174'.toLowerCase(), + token0: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'.toLowerCase(), + token1: '0xdAC17F958D2ee523a2206206994597C13D831ec7'.toLowerCase(), }, ], }, From 80190a233e4185c3dd2560a2fedc8d4f1896a690 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 13 Dec 2023 11:10:28 +0200 Subject: [PATCH 749/833] fix: implement `getAdapterParam` --- src/dex/solidly-v3/solidly-v3.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index 99f4db8cb..17c1d7b15 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -569,25 +569,27 @@ export class SolidlyV3 data: SolidlyV3Data, side: SwapSide, ): AdapterExchangeParam { - // const { path: rawPath } = data; - // const path = this._encodePath(rawPath, side); - const path = ''; + const sqrtPriceLimitX96 = data.zeroForOne + ? (TickMath.MIN_SQRT_RATIO + BigInt(1)).toString() + : (TickMath.MAX_SQRT_RATIO - BigInt(1)).toString(); const payload = this.abiCoder.encodeParameter( { ParentStruct: { - path: 'bytes', - deadline: 'uint256', + recipient: 'address', + zeroForOne: 'bool', + sqrtPriceLimitX96: 'uint160', }, }, { - path, - deadline: getLocalDeadlineAsFriendlyPlaceholder(), // FIXME: more gas efficient to pass block.timestamp in adapter + recipient: this.augustusAddress, + zeroForOne: data.zeroForOne, + sqrtPriceLimitX96, }, ); return { - targetExchange: this.config.router, + targetExchange: data.poolAddress, payload, networkFee: '0', }; From c4211854c03d27840ae6c038180a229431779efa Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 13 Dec 2023 19:56:52 +0200 Subject: [PATCH 750/833] fix: cleaning --- .../SolidlyV3StateMulticall.abi.json | 376 +++++++++++++++++- src/config.ts | 4 +- src/dex/solidly-v3/config.ts | 8 +- src/dex/solidly-v3/solidly-v3-e2e.test.ts | 18 +- src/dex/solidly-v3/solidly-v3.ts | 32 +- src/dex/solidly-v3/types.ts | 2 - 6 files changed, 398 insertions(+), 42 deletions(-) diff --git a/src/abi/solidly-v3/SolidlyV3StateMulticall.abi.json b/src/abi/solidly-v3/SolidlyV3StateMulticall.abi.json index 5eb67b60c..15e78b740 100644 --- a/src/abi/solidly-v3/SolidlyV3StateMulticall.abi.json +++ b/src/abi/solidly-v3/SolidlyV3StateMulticall.abi.json @@ -1 +1,375 @@ -[{"inputs":[{"internalType":"contract IUniswapV3Factory","name":"factory","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"int16","name":"tickBitmapStart","type":"int16"},{"internalType":"int16","name":"tickBitmapEnd","type":"int16"}],"name":"getAdditionalBitmapWithTicks","outputs":[{"components":[{"internalType":"int16","name":"index","type":"int16"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IUniswapV3StateMulticall.TickBitMapMappings[]","name":"tickBitmap","type":"tuple[]"},{"components":[{"internalType":"int24","name":"index","type":"int24"},{"components":[{"internalType":"uint128","name":"liquidityGross","type":"uint128"},{"internalType":"int128","name":"liquidityNet","type":"int128"},{"internalType":"bool","name":"initialized","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.TickInfo","name":"value","type":"tuple"}],"internalType":"struct IUniswapV3StateMulticall.TickInfoMappings[]","name":"ticks","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IUniswapV3Factory","name":"factory","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"int16","name":"tickBitmapStart","type":"int16"},{"internalType":"int16","name":"tickBitmapEnd","type":"int16"}],"name":"getAdditionalBitmapWithoutTicks","outputs":[{"components":[{"internalType":"int16","name":"index","type":"int16"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IUniswapV3StateMulticall.TickBitMapMappings[]","name":"tickBitmap","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IUniswapV3Factory","name":"factory","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"int16","name":"tickBitmapStart","type":"int16"},{"internalType":"int16","name":"tickBitmapEnd","type":"int16"}],"name":"getFullState","outputs":[{"components":[{"internalType":"contract IUniswapV3Pool","name":"pool","type":"address"},{"internalType":"uint256","name":"blockTimestamp","type":"uint256"},{"components":[{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"bool","name":"unlocked","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.Slot0","name":"slot0","type":"tuple"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"uint128","name":"maxLiquidityPerTick","type":"uint128"},{"components":[{"internalType":"int16","name":"index","type":"int16"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IUniswapV3StateMulticall.TickBitMapMappings[]","name":"tickBitmap","type":"tuple[]"},{"components":[{"internalType":"int24","name":"index","type":"int24"},{"components":[{"internalType":"uint128","name":"liquidityGross","type":"uint128"},{"internalType":"int128","name":"liquidityNet","type":"int128"},{"internalType":"bool","name":"initialized","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.TickInfo","name":"value","type":"tuple"}],"internalType":"struct IUniswapV3StateMulticall.TickInfoMappings[]","name":"ticks","type":"tuple[]"}],"internalType":"struct IUniswapV3StateMulticall.StateResult","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IUniswapV3Factory","name":"factory","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"int16","name":"leftBitmapAmount","type":"int16"},{"internalType":"int16","name":"rightBitmapAmount","type":"int16"}],"name":"getFullStateWithRelativeBitmaps","outputs":[{"components":[{"internalType":"contract IUniswapV3Pool","name":"pool","type":"address"},{"internalType":"uint256","name":"blockTimestamp","type":"uint256"},{"components":[{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"bool","name":"unlocked","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.Slot0","name":"slot0","type":"tuple"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"uint128","name":"maxLiquidityPerTick","type":"uint128"},{"components":[{"internalType":"int16","name":"index","type":"int16"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IUniswapV3StateMulticall.TickBitMapMappings[]","name":"tickBitmap","type":"tuple[]"},{"components":[{"internalType":"int24","name":"index","type":"int24"},{"components":[{"internalType":"uint128","name":"liquidityGross","type":"uint128"},{"internalType":"int128","name":"liquidityNet","type":"int128"},{"internalType":"bool","name":"initialized","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.TickInfo","name":"value","type":"tuple"}],"internalType":"struct IUniswapV3StateMulticall.TickInfoMappings[]","name":"ticks","type":"tuple[]"}],"internalType":"struct IUniswapV3StateMulticall.StateResult","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IUniswapV3Factory","name":"factory","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"int16","name":"tickBitmapStart","type":"int16"},{"internalType":"int16","name":"tickBitmapEnd","type":"int16"}],"name":"getFullStateWithoutTicks","outputs":[{"components":[{"internalType":"contract IUniswapV3Pool","name":"pool","type":"address"},{"internalType":"uint256","name":"blockTimestamp","type":"uint256"},{"components":[{"internalType":"uint160","name":"sqrtPriceX96","type":"uint160"},{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"bool","name":"unlocked","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.Slot0","name":"slot0","type":"tuple"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"uint128","name":"maxLiquidityPerTick","type":"uint128"},{"components":[{"internalType":"int16","name":"index","type":"int16"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IUniswapV3StateMulticall.TickBitMapMappings[]","name":"tickBitmap","type":"tuple[]"},{"components":[{"internalType":"int24","name":"index","type":"int24"},{"components":[{"internalType":"uint128","name":"liquidityGross","type":"uint128"},{"internalType":"int128","name":"liquidityNet","type":"int128"},{"internalType":"bool","name":"initialized","type":"bool"}],"internalType":"struct IUniswapV3StateMulticall.TickInfo","name":"value","type":"tuple"}],"internalType":"struct IUniswapV3StateMulticall.TickInfoMappings[]","name":"ticks","type":"tuple[]"}],"internalType":"struct IUniswapV3StateMulticall.StateResult","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"}] \ No newline at end of file +[ + { + "inputs": [ + { + "internalType": "contract IUniswapV3Factory", + "name": "factory", + "type": "address" + }, + { "internalType": "address", "name": "tokenIn", "type": "address" }, + { "internalType": "address", "name": "tokenOut", "type": "address" }, + { "internalType": "int24", "name": "tickSpacing", "type": "int24" }, + { "internalType": "int16", "name": "tickBitmapStart", "type": "int16" }, + { "internalType": "int16", "name": "tickBitmapEnd", "type": "int16" } + ], + "name": "getAdditionalBitmapWithTicks", + "outputs": [ + { + "components": [ + { "internalType": "int16", "name": "index", "type": "int16" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "internalType": "struct IUniswapV3StateMulticall.TickBitMapMappings[]", + "name": "tickBitmap", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "int24", "name": "index", "type": "int24" }, + { + "components": [ + { + "internalType": "uint128", + "name": "liquidityGross", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "liquidityNet", + "type": "int128" + }, + { "internalType": "bool", "name": "initialized", "type": "bool" } + ], + "internalType": "struct IUniswapV3StateMulticall.TickInfo", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct IUniswapV3StateMulticall.TickInfoMappings[]", + "name": "ticks", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IUniswapV3Factory", + "name": "factory", + "type": "address" + }, + { "internalType": "address", "name": "tokenIn", "type": "address" }, + { "internalType": "address", "name": "tokenOut", "type": "address" }, + { "internalType": "int24", "name": "tickSpacing", "type": "int24" }, + { "internalType": "int16", "name": "tickBitmapStart", "type": "int16" }, + { "internalType": "int16", "name": "tickBitmapEnd", "type": "int16" } + ], + "name": "getAdditionalBitmapWithoutTicks", + "outputs": [ + { + "components": [ + { "internalType": "int16", "name": "index", "type": "int16" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "internalType": "struct IUniswapV3StateMulticall.TickBitMapMappings[]", + "name": "tickBitmap", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IUniswapV3Factory", + "name": "factory", + "type": "address" + }, + { "internalType": "address", "name": "tokenIn", "type": "address" }, + { "internalType": "address", "name": "tokenOut", "type": "address" }, + { "internalType": "int24", "name": "tickSpacing", "type": "int24" }, + { "internalType": "int16", "name": "tickBitmapStart", "type": "int16" }, + { "internalType": "int16", "name": "tickBitmapEnd", "type": "int16" } + ], + "name": "getFullState", + "outputs": [ + { + "components": [ + { + "internalType": "contract IUniswapV3Pool", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint160", + "name": "sqrtPriceX96", + "type": "uint160" + }, + { "internalType": "int24", "name": "tick", "type": "int24" }, + { "internalType": "uint24", "name": "fee", "type": "uint24" }, + { "internalType": "bool", "name": "unlocked", "type": "bool" } + ], + "internalType": "struct IUniswapV3StateMulticall.Slot0", + "name": "slot0", + "type": "tuple" + }, + { "internalType": "uint128", "name": "liquidity", "type": "uint128" }, + { "internalType": "int24", "name": "tickSpacing", "type": "int24" }, + { + "internalType": "uint128", + "name": "maxLiquidityPerTick", + "type": "uint128" + }, + { + "components": [ + { "internalType": "int16", "name": "index", "type": "int16" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "internalType": "struct IUniswapV3StateMulticall.TickBitMapMappings[]", + "name": "tickBitmap", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "int24", "name": "index", "type": "int24" }, + { + "components": [ + { + "internalType": "uint128", + "name": "liquidityGross", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "liquidityNet", + "type": "int128" + }, + { + "internalType": "bool", + "name": "initialized", + "type": "bool" + } + ], + "internalType": "struct IUniswapV3StateMulticall.TickInfo", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct IUniswapV3StateMulticall.TickInfoMappings[]", + "name": "ticks", + "type": "tuple[]" + } + ], + "internalType": "struct IUniswapV3StateMulticall.StateResult", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IUniswapV3Factory", + "name": "factory", + "type": "address" + }, + { "internalType": "address", "name": "tokenIn", "type": "address" }, + { "internalType": "address", "name": "tokenOut", "type": "address" }, + { "internalType": "int24", "name": "tickSpacing", "type": "int24" }, + { "internalType": "int16", "name": "leftBitmapAmount", "type": "int16" }, + { "internalType": "int16", "name": "rightBitmapAmount", "type": "int16" } + ], + "name": "getFullStateWithRelativeBitmaps", + "outputs": [ + { + "components": [ + { + "internalType": "contract IUniswapV3Pool", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint160", + "name": "sqrtPriceX96", + "type": "uint160" + }, + { "internalType": "int24", "name": "tick", "type": "int24" }, + { "internalType": "uint24", "name": "fee", "type": "uint24" }, + { "internalType": "bool", "name": "unlocked", "type": "bool" } + ], + "internalType": "struct IUniswapV3StateMulticall.Slot0", + "name": "slot0", + "type": "tuple" + }, + { "internalType": "uint128", "name": "liquidity", "type": "uint128" }, + { "internalType": "int24", "name": "tickSpacing", "type": "int24" }, + { + "internalType": "uint128", + "name": "maxLiquidityPerTick", + "type": "uint128" + }, + { + "components": [ + { "internalType": "int16", "name": "index", "type": "int16" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "internalType": "struct IUniswapV3StateMulticall.TickBitMapMappings[]", + "name": "tickBitmap", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "int24", "name": "index", "type": "int24" }, + { + "components": [ + { + "internalType": "uint128", + "name": "liquidityGross", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "liquidityNet", + "type": "int128" + }, + { + "internalType": "bool", + "name": "initialized", + "type": "bool" + } + ], + "internalType": "struct IUniswapV3StateMulticall.TickInfo", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct IUniswapV3StateMulticall.TickInfoMappings[]", + "name": "ticks", + "type": "tuple[]" + } + ], + "internalType": "struct IUniswapV3StateMulticall.StateResult", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IUniswapV3Factory", + "name": "factory", + "type": "address" + }, + { "internalType": "address", "name": "tokenIn", "type": "address" }, + { "internalType": "address", "name": "tokenOut", "type": "address" }, + { "internalType": "int24", "name": "tickSpacing", "type": "int24" }, + { "internalType": "int16", "name": "tickBitmapStart", "type": "int16" }, + { "internalType": "int16", "name": "tickBitmapEnd", "type": "int16" } + ], + "name": "getFullStateWithoutTicks", + "outputs": [ + { + "components": [ + { + "internalType": "contract IUniswapV3Pool", + "name": "pool", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockTimestamp", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint160", + "name": "sqrtPriceX96", + "type": "uint160" + }, + { "internalType": "int24", "name": "tick", "type": "int24" }, + { "internalType": "uint24", "name": "fee", "type": "uint24" }, + { "internalType": "bool", "name": "unlocked", "type": "bool" } + ], + "internalType": "struct IUniswapV3StateMulticall.Slot0", + "name": "slot0", + "type": "tuple" + }, + { "internalType": "uint128", "name": "liquidity", "type": "uint128" }, + { "internalType": "int24", "name": "tickSpacing", "type": "int24" }, + { + "internalType": "uint128", + "name": "maxLiquidityPerTick", + "type": "uint128" + }, + { + "components": [ + { "internalType": "int16", "name": "index", "type": "int16" }, + { "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "internalType": "struct IUniswapV3StateMulticall.TickBitMapMappings[]", + "name": "tickBitmap", + "type": "tuple[]" + }, + { + "components": [ + { "internalType": "int24", "name": "index", "type": "int24" }, + { + "components": [ + { + "internalType": "uint128", + "name": "liquidityGross", + "type": "uint128" + }, + { + "internalType": "int128", + "name": "liquidityNet", + "type": "int128" + }, + { + "internalType": "bool", + "name": "initialized", + "type": "bool" + } + ], + "internalType": "struct IUniswapV3StateMulticall.TickInfo", + "name": "value", + "type": "tuple" + } + ], + "internalType": "struct IUniswapV3StateMulticall.TickInfoMappings[]", + "name": "ticks", + "type": "tuple[]" + } + ], + "internalType": "struct IUniswapV3StateMulticall.StateResult", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/config.ts b/src/config.ts index f360b8fca..fa3e37ef8 100644 --- a/src/config.ts +++ b/src/config.ts @@ -53,9 +53,9 @@ const baseConfigs: { [network: number]: BaseConfig } = { Adapter01: '0x9bE264469eF954c139Da4A45Cf76CbCC5e3A6A73', Adapter02: '0xFC2Ba6E830a04C25e207B8214b26d8C713F6881F', Adapter03: '0xBAEeb4540f59d30E567a5B563CC0c4587eDd9366', - Adapter04: '0x9F7A886ec44d8bc181e311D76b68C9B8aE2E0BC2', + Adapter04: '0xeAf1030a61Db671CA15F881eAa824f99178D7e1E', BuyAdapter: '0x84bEF12C9931cE12662cc9F2366b6a5029E4BD29', - BuyAdapter02: '0xBA0E780Db34927F1e702717FAC21b52803D7cE25', + BuyAdapter02: '0xCa1D21b5dB4789d814e27261e059ecc5c1D4056B', }, uniswapV2ExchangeRouterAddress: '0xF9234CB08edb93c0d4a4d4c70cC3FfD070e78e07', diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index 3114848e6..8756d159e 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -45,13 +45,11 @@ export const PoolsToPreload: DexConfigMap< export const SolidlyV3Config: DexConfigMap = { SolidlyV3: { [Network.MAINNET]: { - // factory: '0x1F98431c8aD98523631AE4a59f267346ea31F984', factory: '0x70Fe4a44EA505cFa3A57b95cF2862D4fd5F0f687', quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', - router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', + // router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', supportedTickSpacings: SUPPORTED_TICK_SPACINGS, stateMulticall: '0xb229563028302AA693EEaD62F80CC331aEDE4e26', - uniswapMulticall: '0x1F98415757620B543A52E61c46B32eB19261F984', chunksCount: 10, initRetryFrequency: 10, // OG uniswap initHash @@ -68,7 +66,7 @@ export const SolidlyV3Config: DexConfigMap = { export const Adapters: Record = { [Network.MAINNET]: { - [SwapSide.SELL]: [{ name: 'Adapter01', index: 6 }], - [SwapSide.BUY]: [{ name: 'BuyAdapter', index: 2 }], + [SwapSide.SELL]: [{ name: 'Adapter04', index: 7 }], + [SwapSide.BUY]: [{ name: 'BuyAdapter02', index: 3 }], }, }; diff --git a/src/dex/solidly-v3/solidly-v3-e2e.test.ts b/src/dex/solidly-v3/solidly-v3-e2e.test.ts index e8885858c..2bf696de7 100644 --- a/src/dex/solidly-v3/solidly-v3-e2e.test.ts +++ b/src/dex/solidly-v3/solidly-v3-e2e.test.ts @@ -29,11 +29,11 @@ function testForNetwork( SwapSide.SELL, [ ContractMethod.simpleSwap, - // ContractMethod.multiSwap, - // ContractMethod.megaSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, ], ], - [SwapSide.BUY, [ContractMethod.simpleBuy /*, ContractMethod.buy */]], + [SwapSide.BUY, [ContractMethod.simpleBuy, ContractMethod.buy]], ]); sideToContractMethods.forEach((contractMethods, side) => @@ -81,6 +81,18 @@ describe('SolidlyV3 E2E', () => { const network = Network.MAINNET; const pairs = [ + [ + { + name: 'ETH', + sellAmount: '110000000000000000', + buyAmount: '1100000000', + }, + { + name: 'USDC', + sellAmount: '400000000', + buyAmount: '4000000', + }, + ], [ { name: 'WETH', diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index 17c1d7b15..de97b7a60 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -1,4 +1,4 @@ -import { defaultAbiCoder, Interface } from '@ethersproject/abi'; +import { Interface } from '@ethersproject/abi'; import _ from 'lodash'; import { pack } from '@ethersproject/solidity'; import { @@ -11,19 +11,12 @@ import { Logger, NumberAsString, PoolPrices, - TxInfo, PreprocessTransactionOptions, ExchangeTxInfo, } from '../../types'; import { SwapSide, Network, CACHE_PREFIX } from '../../constants'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { - getBigIntPow, - getDexKeysWithNetwork, - interpolate, - isTruthy, - uuidToBytes16, -} from '../../utils'; +import { getBigIntPow, getDexKeysWithNetwork, isTruthy } from '../../utils'; import { IDex } from '../../dex/idex'; import { IDexHelper } from '../../dex-helper/idex-helper'; import { @@ -32,9 +25,7 @@ import { PoolState, SolidlyV3Data, SolidlyV3SimpleSwapParams, - UniswapV3Functions, UniswapV3Param, - UniswapV3SimpleSwapParams, } from './types'; import { getLocalDeadlineAsFriendlyPlaceholder, @@ -42,14 +33,11 @@ import { } from '../simple-exchange'; import { SolidlyV3Config, Adapters, PoolsToPreload } from './config'; import { SolidlyV3EventPool } from './solidly-v3-pool'; -import UniswapV3RouterABI from '../../abi/uniswap-v3/UniswapV3Router.abi.json'; import UniswapV3QuoterV2ABI from '../../abi/uniswap-v3/UniswapV3QuoterV2.abi.json'; -import UniswapV3MultiABI from '../../abi/uniswap-v3/UniswapMulti.abi.json'; import DirectSwapABI from '../../abi/DirectSwap.json'; import SolidlyV3StateMulticallABI from '../../abi/solidly-v3/SolidlyV3StateMulticall.abi.json'; import SolidlyV3PoolABI from '../../abi/solidly-v3/SolidlyV3Pool.abi.json'; import { - DirectMethods, UNISWAPV3_EFFICIENCY_FACTOR, UNISWAPV3_POOL_SEARCH_OVERHEAD, UNISWAPV3_TICK_BASE_OVERHEAD, @@ -59,12 +47,6 @@ import { assert, DeepReadonly } from 'ts-essentials'; import { uniswapV3Math } from './contract-math/uniswap-v3-math'; import { Contract } from 'web3-eth-contract'; import { AbiItem } from 'web3-utils'; -import { BalanceRequest, getBalances } from '../../lib/tokens/balancer-fetcher'; -import { - AssetType, - DEFAULT_ID_ERC20, - DEFAULT_ID_ERC20_AS_STRING, -} from '../../lib/tokens/types'; import { OptimalSwapExchange } from '@paraswap/core'; import { TickMath } from './contract-math/TickMath'; @@ -76,7 +58,6 @@ type PoolPairsInfo = { const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_TTL_MS = 60 * 60 * 24 * 1000; // 24 hours const UNISWAPV3_CLEAN_NOT_EXISTING_POOL_INTERVAL_MS = 30 * 60 * 1000; // Once in 30 minutes -const UNISWAPV3_QUOTE_GASLIMIT = 200_000; export class SolidlyV3 extends SimpleExchange @@ -97,7 +78,6 @@ export class SolidlyV3 logger: Logger; - private uniswapMulti: Contract; private stateMultiContract: Contract; private notExistingPoolSetKey: string; @@ -114,10 +94,6 @@ export class SolidlyV3 ) { super(dexHelper, dexKey); this.logger = dexHelper.getLogger(dexKey + '-' + network); - this.uniswapMulti = new this.dexHelper.web3Provider.eth.Contract( - UniswapV3MultiABI as AbiItem[], - this.config.uniswapMulticall, - ); this.stateMultiContract = new this.dexHelper.web3Provider.eth.Contract( this.config.stateMultiCallAbi !== undefined ? this.config.stateMultiCallAbi @@ -652,7 +628,7 @@ export class SolidlyV3 this.erc20Contract.options.address = this.dexHelper.config.wrapETH(srcToken).address; const allowance = await this.erc20Contract.methods - .allowance(this.augustusAddress, this.config.router) + .allowance(this.augustusAddress, optimalSwapExchange.exchange) .call(undefined, 'latest'); isApproved = BigInt(allowance.toString()) >= BigInt(optimalSwapExchange.srcAmount); @@ -821,14 +797,12 @@ export class SolidlyV3 private _toLowerForAllConfigAddresses() { // If new config property will be added, the TS will throw compile error const newConfig: DexParams = { - router: this.config.router.toLowerCase(), quoter: this.config.quoter.toLowerCase(), factory: this.config.factory.toLowerCase(), supportedTickSpacings: this.config.supportedTickSpacings, stateMulticall: this.config.stateMulticall.toLowerCase(), chunksCount: this.config.chunksCount, initRetryFrequency: this.config.initRetryFrequency, - uniswapMulticall: this.config.uniswapMulticall, deployer: this.config.deployer?.toLowerCase(), initHash: this.config.initHash, subgraphURL: this.config.subgraphURL, diff --git a/src/dex/solidly-v3/types.ts b/src/dex/solidly-v3/types.ts index 35b2fa421..9d10c4199 100644 --- a/src/dex/solidly-v3/types.ts +++ b/src/dex/solidly-v3/types.ts @@ -44,11 +44,9 @@ export type DecodeStateMultiCallFunc = ( ) => DecodedStateMultiCallResultWithRelativeBitmaps; export type DexParams = { - router: Address; quoter: Address; factory: Address; stateMulticall: Address; - uniswapMulticall: Address; supportedTickSpacings: bigint[]; chunksCount: number; initRetryFrequency: number; From dc140455108eebb51f9b2e87a2788918572061c1 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 14 Dec 2023 12:58:06 +0200 Subject: [PATCH 751/833] fix: cleaning & update adapters --- src/config.ts | 4 ++-- src/dex/solidly-v3/config.ts | 8 -------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/config.ts b/src/config.ts index fa3e37ef8..c02f6d306 100644 --- a/src/config.ts +++ b/src/config.ts @@ -53,9 +53,9 @@ const baseConfigs: { [network: number]: BaseConfig } = { Adapter01: '0x9bE264469eF954c139Da4A45Cf76CbCC5e3A6A73', Adapter02: '0xFC2Ba6E830a04C25e207B8214b26d8C713F6881F', Adapter03: '0xBAEeb4540f59d30E567a5B563CC0c4587eDd9366', - Adapter04: '0xeAf1030a61Db671CA15F881eAa824f99178D7e1E', + Adapter04: '0x369A2FDb910d432f0a07381a5E3d27572c876713', BuyAdapter: '0x84bEF12C9931cE12662cc9F2366b6a5029E4BD29', - BuyAdapter02: '0xCa1D21b5dB4789d814e27261e059ecc5c1D4056B', + BuyAdapter02: '0xe53d24CD81cC81bbf271AD7B02D0d67f851D727c', }, uniswapV2ExchangeRouterAddress: '0xF9234CB08edb93c0d4a4d4c70cC3FfD070e78e07', diff --git a/src/dex/solidly-v3/config.ts b/src/dex/solidly-v3/config.ts index 8756d159e..51f91c4db 100644 --- a/src/dex/solidly-v3/config.ts +++ b/src/dex/solidly-v3/config.ts @@ -3,8 +3,6 @@ import { DexConfigMap, AdapterMappings } from '../../types'; import { Network, SwapSide } from '../../constants'; import { Address } from '../../types'; -// const SUPPORTED_FEES = [3000n]; -const SUPPORTED_FEES = [500n]; const SUPPORTED_TICK_SPACINGS = [1n, 10n, 50n, 100n]; // Pools that will be initialized on app startup @@ -47,16 +45,10 @@ export const SolidlyV3Config: DexConfigMap = { [Network.MAINNET]: { factory: '0x70Fe4a44EA505cFa3A57b95cF2862D4fd5F0f687', quoter: '0x61fFE014bA17989E743c5F6cB21bF9697530B21e', - // router: '0xE592427A0AEce92De3Edee1F18E0157C05861564', supportedTickSpacings: SUPPORTED_TICK_SPACINGS, stateMulticall: '0xb229563028302AA693EEaD62F80CC331aEDE4e26', chunksCount: 10, initRetryFrequency: 10, - // OG uniswap initHash - // initHash: `0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54`, - // Solidly initHash prior to callbacks - // initHash: `0x2d6541efe1e24667ba5408a35ae420462924d43db1251d7580804ac81545109b`, - // Solidly initHash after callbacks initHash: `0xe9b68c5f77858eecac2e651646e208175e9b1359d68d0e14fc69f8c54e5010bf`, subgraphURL: 'https://api.thegraph.com/subgraphs/name/solidlylabs/solidly-v3', From 7a0af79bdbe2be685d606bc94c005b492d1e4681 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 14 Dec 2023 13:03:47 +0200 Subject: [PATCH 752/833] 2.42.27-solidly-v3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d7d232883..c3a32f037 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.27", + "version": "2.42.27-solidly-v3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From b94dbd172ab2e4dfb43acd06a1adcdda96db3b56 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 14 Dec 2023 20:10:08 +0200 Subject: [PATCH 753/833] fix: styles --- src/dex/uniswap-v3/contract-math/Oracle.ts | 408 ++++++++++----------- 1 file changed, 204 insertions(+), 204 deletions(-) diff --git a/src/dex/uniswap-v3/contract-math/Oracle.ts b/src/dex/uniswap-v3/contract-math/Oracle.ts index ef17f079a..19b1918d1 100644 --- a/src/dex/uniswap-v3/contract-math/Oracle.ts +++ b/src/dex/uniswap-v3/contract-math/Oracle.ts @@ -1,226 +1,226 @@ import { - OracleObservation, - OracleObservationCandidates, - PoolState, + OracleObservation, + OracleObservationCandidates, + PoolState, } from '../types'; import { _require } from '../../../utils'; import { DeepReadonly } from 'ts-essentials'; import { ZERO_ORACLE_OBSERVATION } from '../constants'; function replaceUndefinedObservationWithZero(state: PoolState, index: number) { - if (state.observations[index] === undefined) { - state.observations[index] = { ...ZERO_ORACLE_OBSERVATION }; - } + if (state.observations[index] === undefined) { + state.observations[index] = { ...ZERO_ORACLE_OBSERVATION }; + } } export class Oracle { - static transform( - state: DeepReadonly, - last: OracleObservation, - blockTimestamp: bigint, - tick: bigint, - liquidity: bigint, - ): OracleObservation { - const delta = blockTimestamp - last.blockTimestamp; - return { - blockTimestamp: state.blockTimestamp, - tickCumulative: last.tickCumulative + BigInt.asIntN(56, tick) * delta, - secondsPerLiquidityCumulativeX128: - last.secondsPerLiquidityCumulativeX128 + - (BigInt.asUintN(160, delta) << 128n) / - (liquidity > 0n ? liquidity : 1n), - initialized: true, - }; + static transform( + state: DeepReadonly, + last: OracleObservation, + blockTimestamp: bigint, + tick: bigint, + liquidity: bigint, + ): OracleObservation { + const delta = blockTimestamp - last.blockTimestamp; + return { + blockTimestamp: state.blockTimestamp, + tickCumulative: last.tickCumulative + BigInt.asIntN(56, tick) * delta, + secondsPerLiquidityCumulativeX128: + last.secondsPerLiquidityCumulativeX128 + + (BigInt.asUintN(160, delta) << 128n) / + (liquidity > 0n ? liquidity : 1n), + initialized: true, + }; + } + + static write( + state: PoolState, + index: number, + blockTimestamp: bigint, + tick: bigint, + liquidity: bigint, + cardinality: number, + cardinalityNext: number, + ): [number, number] { + const last = state.observations[index]; + + if (last.blockTimestamp == state.blockTimestamp) + return [index, cardinality]; + + let indexUpdated = 0; + let cardinalityUpdated = 0; + + if (cardinalityNext > cardinality && index == cardinality - 1) { + cardinalityUpdated = cardinalityNext; + } else { + cardinalityUpdated = cardinality; } - static write( - state: PoolState, - index: number, - blockTimestamp: bigint, - tick: bigint, - liquidity: bigint, - cardinality: number, - cardinalityNext: number, - ): [number, number] { - const last = state.observations[index]; - - if (last.blockTimestamp == state.blockTimestamp) - return [index, cardinality]; - - let indexUpdated = 0; - let cardinalityUpdated = 0; - - if (cardinalityNext > cardinality && index == cardinality - 1) { - cardinalityUpdated = cardinalityNext; - } else { - cardinalityUpdated = cardinality; - } - - indexUpdated = (index + 1) % cardinalityUpdated; - - state.observations[indexUpdated] = Oracle.transform( - state, - last, - blockTimestamp, - tick, - liquidity, - ); - if (indexUpdated !== index) { - delete state.observations[index]; - } - return [indexUpdated, cardinalityUpdated]; + indexUpdated = (index + 1) % cardinalityUpdated; + + state.observations[indexUpdated] = Oracle.transform( + state, + last, + blockTimestamp, + tick, + liquidity, + ); + if (indexUpdated !== index) { + delete state.observations[index]; } - - static lte(time: bigint, a: bigint, b: bigint): boolean { - if (a <= time && b <= time) return a <= b; - - const aAdjusted = a > time ? a : a + 2n ** 32n; - const bAdjusted = b > time ? b : b + 2n ** 32n; - return aAdjusted <= bAdjusted; - } - - static binarySearch( - state: DeepReadonly, - time: bigint, - target: bigint, - index: number, - cardinality: number, - ): OracleObservationCandidates { - let l = (index + 1) % cardinality; - let r = l + cardinality - 1; - let i; - - let beforeOrAt; - let atOrAfter; - while (true) { - i = (l + r) / 2; - - beforeOrAt = state.observations[i % cardinality]; - - // we've landed on an uninitialized tick, keep searching higher (more recently) - if (!beforeOrAt.initialized) { - l = i + 1; - continue; - } - - atOrAfter = state.observations[(i + 1) % cardinality]; - - const targetAtOrAfter = Oracle.lte( - time, - beforeOrAt.blockTimestamp, - target, - ); - - // check if we've found the answer! - if (targetAtOrAfter && Oracle.lte(time, target, atOrAfter.blockTimestamp)) - break; - - if (!targetAtOrAfter) r = i - 1; - else l = i + 1; - } - return { beforeOrAt, atOrAfter }; + return [indexUpdated, cardinalityUpdated]; + } + + static lte(time: bigint, a: bigint, b: bigint): boolean { + if (a <= time && b <= time) return a <= b; + + const aAdjusted = a > time ? a : a + 2n ** 32n; + const bAdjusted = b > time ? b : b + 2n ** 32n; + return aAdjusted <= bAdjusted; + } + + static binarySearch( + state: DeepReadonly, + time: bigint, + target: bigint, + index: number, + cardinality: number, + ): OracleObservationCandidates { + let l = (index + 1) % cardinality; + let r = l + cardinality - 1; + let i; + + let beforeOrAt; + let atOrAfter; + while (true) { + i = (l + r) / 2; + + beforeOrAt = state.observations[i % cardinality]; + + // we've landed on an uninitialized tick, keep searching higher (more recently) + if (!beforeOrAt.initialized) { + l = i + 1; + continue; + } + + atOrAfter = state.observations[(i + 1) % cardinality]; + + const targetAtOrAfter = Oracle.lte( + time, + beforeOrAt.blockTimestamp, + target, + ); + + // check if we've found the answer! + if (targetAtOrAfter && Oracle.lte(time, target, atOrAfter.blockTimestamp)) + break; + + if (!targetAtOrAfter) r = i - 1; + else l = i + 1; } - - static getSurroundingObservations( - state: DeepReadonly, - time: bigint, - target: bigint, - tick: bigint, - index: number, - liquidity: bigint, - cardinality: number, - ): OracleObservationCandidates { - let beforeOrAt = state.observations[index]; - - if (Oracle.lte(time, beforeOrAt.blockTimestamp, target)) { - if (beforeOrAt.blockTimestamp === target) { - return { beforeOrAt, atOrAfter: beforeOrAt }; - } else { - return { - beforeOrAt, - atOrAfter: Oracle.transform( - state, - beforeOrAt, - target, - tick, - liquidity, - ), - }; - } - } - - beforeOrAt = state.observations[(index + 1) % cardinality]; - if (!beforeOrAt.initialized) beforeOrAt = state.observations[0]; - - _require( - Oracle.lte(time, beforeOrAt.blockTimestamp, target), - 'OLD', - { time, beforeOrAtBlockTimestamp: beforeOrAt.blockTimestamp, target }, - 'Oracle.lte(time, beforeOrAt.blockTimestamp, target)', - ); - - return Oracle.binarySearch(state, time, target, index, cardinality); - } - - static observeSingle( - state: DeepReadonly, - time: bigint, - secondsAgo: bigint, - tick: bigint, - index: number, - liquidity: bigint, - cardinality: number, - ): [bigint, bigint] { - if (secondsAgo == 0n) { - let last = state.observations[index]; - if (last.blockTimestamp != time) - last = Oracle.transform(state, last, time, tick, liquidity); - return [last.tickCumulative, last.secondsPerLiquidityCumulativeX128]; - } - - const target = time - secondsAgo; - - const { beforeOrAt, atOrAfter } = Oracle.getSurroundingObservations( + return { beforeOrAt, atOrAfter }; + } + + static getSurroundingObservations( + state: DeepReadonly, + time: bigint, + target: bigint, + tick: bigint, + index: number, + liquidity: bigint, + cardinality: number, + ): OracleObservationCandidates { + let beforeOrAt = state.observations[index]; + + if (Oracle.lte(time, beforeOrAt.blockTimestamp, target)) { + if (beforeOrAt.blockTimestamp === target) { + return { beforeOrAt, atOrAfter: beforeOrAt }; + } else { + return { + beforeOrAt, + atOrAfter: Oracle.transform( state, - time, + beforeOrAt, target, tick, - index, liquidity, - cardinality, - ); + ), + }; + } + } + + beforeOrAt = state.observations[(index + 1) % cardinality]; + if (!beforeOrAt.initialized) beforeOrAt = state.observations[0]; + + _require( + Oracle.lte(time, beforeOrAt.blockTimestamp, target), + 'OLD', + { time, beforeOrAtBlockTimestamp: beforeOrAt.blockTimestamp, target }, + 'Oracle.lte(time, beforeOrAt.blockTimestamp, target)', + ); + + return Oracle.binarySearch(state, time, target, index, cardinality); + } + + static observeSingle( + state: DeepReadonly, + time: bigint, + secondsAgo: bigint, + tick: bigint, + index: number, + liquidity: bigint, + cardinality: number, + ): [bigint, bigint] { + if (secondsAgo == 0n) { + let last = state.observations[index]; + if (last.blockTimestamp != time) + last = Oracle.transform(state, last, time, tick, liquidity); + return [last.tickCumulative, last.secondsPerLiquidityCumulativeX128]; + } - if (target === beforeOrAt.blockTimestamp) { - return [ - beforeOrAt.tickCumulative, + const target = time - secondsAgo; + + const { beforeOrAt, atOrAfter } = Oracle.getSurroundingObservations( + state, + time, + target, + tick, + index, + liquidity, + cardinality, + ); + + if (target === beforeOrAt.blockTimestamp) { + return [ + beforeOrAt.tickCumulative, + beforeOrAt.secondsPerLiquidityCumulativeX128, + ]; + } else if (target === atOrAfter.blockTimestamp) { + return [ + atOrAfter.tickCumulative, + atOrAfter.secondsPerLiquidityCumulativeX128, + ]; + } else { + const observationTimeDelta = + atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp; + const targetDelta = target - beforeOrAt.blockTimestamp; + return [ + beforeOrAt.tickCumulative + + ((atOrAfter.tickCumulative - beforeOrAt.tickCumulative) / + observationTimeDelta) * + targetDelta, + beforeOrAt.secondsPerLiquidityCumulativeX128 + + BigInt.asUintN( + 160, + (BigInt.asUintN( + 256, + atOrAfter.secondsPerLiquidityCumulativeX128 - beforeOrAt.secondsPerLiquidityCumulativeX128, - ]; - } else if (target === atOrAfter.blockTimestamp) { - return [ - atOrAfter.tickCumulative, - atOrAfter.secondsPerLiquidityCumulativeX128, - ]; - } else { - const observationTimeDelta = - atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp; - const targetDelta = target - beforeOrAt.blockTimestamp; - return [ - beforeOrAt.tickCumulative + - ((atOrAfter.tickCumulative - beforeOrAt.tickCumulative) / - observationTimeDelta) * - targetDelta, - beforeOrAt.secondsPerLiquidityCumulativeX128 + - BigInt.asUintN( - 160, - (BigInt.asUintN( - 256, - atOrAfter.secondsPerLiquidityCumulativeX128 - - beforeOrAt.secondsPerLiquidityCumulativeX128, - ) * - targetDelta) / - observationTimeDelta, - ), - ]; - } + ) * + targetDelta) / + observationTimeDelta, + ), + ]; } + } } From e523659426bf3b913fc2fc2cc0a73d8b99ec65cf Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 15 Dec 2023 14:23:32 +0200 Subject: [PATCH 754/833] fix: add non-existent-set handling --- src/dex/solidly-v3/solidly-v3-factory.ts | 80 ++++++++++++++++++++++++ src/dex/solidly-v3/solidly-v3.ts | 54 ++++++++++++++++ src/dex/solidly-v3/types.ts | 2 + 3 files changed, 136 insertions(+) create mode 100644 src/dex/solidly-v3/solidly-v3-factory.ts diff --git a/src/dex/solidly-v3/solidly-v3-factory.ts b/src/dex/solidly-v3/solidly-v3-factory.ts new file mode 100644 index 000000000..74084778f --- /dev/null +++ b/src/dex/solidly-v3/solidly-v3-factory.ts @@ -0,0 +1,80 @@ +import { Interface } from '@ethersproject/abi'; +import { DeepReadonly } from 'ts-essentials'; +import FactoryABI from '../../abi/uniswap-v3/UniswapV3Factory.abi.json'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { Address, Log, Logger } from '../../types'; +import { LogDescription } from 'ethers/lib/utils'; +import { FactoryState } from './types'; + +export type OnPoolCreatedCallback = ({ + token0, + token1, + tickSpacing, +}: { + token0: string; + token1: string; + tickSpacing: bigint; +}) => Promise; + +/* + * "Stateless" event subscriber in order to capture "PoolCreated" event on new pools created. + * State is present, but it's a placeholder to actually make the events reach handlers (if there's no previous state - `processBlockLogs` is not called) + */ +export class SolidlyV3Factory extends StatefulEventSubscriber { + handlers: { + [event: string]: (event: any) => Promise; + } = {}; + + logDecoder: (log: Log) => any; + + public readonly factoryIface = new Interface(FactoryABI); + + constructor( + readonly dexHelper: IDexHelper, + parentName: string, + protected readonly factoryAddress: Address, + logger: Logger, + protected readonly onPoolCreated: OnPoolCreatedCallback, + mapKey: string = '', + ) { + super(parentName, `${parentName} Factory`, dexHelper, logger, true, mapKey); + + this.addressesSubscribed = [factoryAddress]; + + this.logDecoder = (log: Log) => this.factoryIface.parseLog(log); + + this.handlers['PoolCreated'] = this.handleNewPool.bind(this); + } + + generateState(): FactoryState { + return {}; + } + + protected async processLog( + _: DeepReadonly, + log: Readonly, + ): Promise { + const event = this.logDecoder(log); + if (event.name in this.handlers) { + await this.handlers[event.name](event); + } + + return {}; + } + + async handleNewPool(event: LogDescription) { + const token0 = event.args.token0.toLowerCase(); + const token1 = event.args.token1.toLowerCase(); + const tickSpacing = event.args.tickSpacing.toString(); + + this.logger.log('[handleNewPool]: New pool created', { + token0, + token1, + tickSpacing: event.args.tickSpacing, + }); + this.logger.log('[handleNewPool]: TICK spacing: ', tickSpacing); + + await this.onPoolCreated({ token0, token1, tickSpacing }); + } +} diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index de97b7a60..3f8ab7367 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -49,6 +49,7 @@ import { Contract } from 'web3-eth-contract'; import { AbiItem } from 'web3-utils'; import { OptimalSwapExchange } from '@paraswap/core'; import { TickMath } from './contract-math/TickMath'; +import { OnPoolCreatedCallback, SolidlyV3Factory } from './solidly-v3-factory'; type PoolPairsInfo = { token0: Address; @@ -82,6 +83,8 @@ export class SolidlyV3 private notExistingPoolSetKey: string; + private readonly factory: SolidlyV3Factory; + constructor( protected network: Network, dexKey: string, @@ -107,6 +110,14 @@ export class SolidlyV3 // Normalize once all config addresses and use across all scenarios this.config = this._toLowerForAllConfigAddresses(); + this.factory = new SolidlyV3Factory( + dexHelper, + dexKey, + this.config.factory, + this.logger, + this.onPoolCreatedDeleteFromNonExistingSet, + ); + this.notExistingPoolSetKey = `${CACHE_PREFIX}_${network}_${dexKey}_not_existings_pool_set`.toLowerCase(); } @@ -129,6 +140,9 @@ export class SolidlyV3 } async initializePricing(blockNumber: number) { + // Init listening to new pools creation + await this.factory.initialize(blockNumber); + // This is only for testing, because cold pool fetching is goes out of // FETCH_POOL_INDENTIFIER_TIMEOUT range await Promise.all( @@ -159,6 +173,46 @@ export class SolidlyV3 } } + /* + * When a non existing pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls + * Once the pool is created, it gets immediately flagged + */ + onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ + token0, + token1, + tickSpacing, + }) => { + const logPrefix = '[onPoolCreatedDeleteFromNonExistingSet]'; + const [_token0, _token1] = this._sortTokens(token0, token1); + const poolKey = `${_token0}_${_token1}_${tickSpacing}`; + + // consider doing it only from master pool for less calls to distant cache + + // delete entry locally to let local instance discover the pool + delete this.eventPools[ + this.getPoolIdentifier(_token0, _token1, tickSpacing) + ]; + + try { + this.logger.info( + `${logPrefix} delete pool from not existing set=${this.notExistingPoolSetKey}; key=${poolKey}`, + ); + // delete pool record from set + const result = await this.dexHelper.cache.zrem( + this.notExistingPoolSetKey, + [poolKey], + ); + this.logger.info( + `${logPrefix} delete pool from not existing set=${this.notExistingPoolSetKey}; key=${poolKey}; result: ${result}`, + ); + } catch (error) { + this.logger.error( + `${logPrefix} ERROR: failed to delete pool from set: set=${this.notExistingPoolSetKey}; key=${poolKey}`, + error, + ); + } + }; + async getPool( srcAddress: Address, destAddress: Address, diff --git a/src/dex/solidly-v3/types.ts b/src/dex/solidly-v3/types.ts index 9d10c4199..ca846e35a 100644 --- a/src/dex/solidly-v3/types.ts +++ b/src/dex/solidly-v3/types.ts @@ -4,6 +4,8 @@ import { Address } from '../../types'; import { AbiItem } from 'web3-utils'; import { MultiResult } from '../../lib/multi-wrapper'; +export type FactoryState = Record; + export type TickInfo = { liquidityGross: bigint; liquidityNet: bigint; From 0a050b95620b445ccfef8c6cff8b890ef173c5a1 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 15 Dec 2023 14:24:33 +0200 Subject: [PATCH 755/833] fix: clean --- src/dex/solidly-v3/solidly-v3-factory.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3-factory.ts b/src/dex/solidly-v3/solidly-v3-factory.ts index 74084778f..bcd4236ff 100644 --- a/src/dex/solidly-v3/solidly-v3-factory.ts +++ b/src/dex/solidly-v3/solidly-v3-factory.ts @@ -68,13 +68,6 @@ export class SolidlyV3Factory extends StatefulEventSubscriber { const token1 = event.args.token1.toLowerCase(); const tickSpacing = event.args.tickSpacing.toString(); - this.logger.log('[handleNewPool]: New pool created', { - token0, - token1, - tickSpacing: event.args.tickSpacing, - }); - this.logger.log('[handleNewPool]: TICK spacing: ', tickSpacing); - await this.onPoolCreated({ token0, token1, tickSpacing }); } } From 63663dc8b6a8e813c4d67b00fb03c9f3b3c5d96a Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 15 Dec 2023 14:35:49 +0200 Subject: [PATCH 756/833] 2.42.27-solidly-v3.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c3a32f037..835c83ae3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.27-solidly-v3", + "version": "2.42.27-solidly-v3.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From b0dd459cf5b1b4b8cd8fe2e1d24b3c3d543ebc5c Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Fri, 15 Dec 2023 15:31:40 +0200 Subject: [PATCH 757/833] fix: clean --- src/dex/solidly-v3/solidly-v3-factory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/solidly-v3/solidly-v3-factory.ts b/src/dex/solidly-v3/solidly-v3-factory.ts index bcd4236ff..21a40ab46 100644 --- a/src/dex/solidly-v3/solidly-v3-factory.ts +++ b/src/dex/solidly-v3/solidly-v3-factory.ts @@ -66,7 +66,7 @@ export class SolidlyV3Factory extends StatefulEventSubscriber { async handleNewPool(event: LogDescription) { const token0 = event.args.token0.toLowerCase(); const token1 = event.args.token1.toLowerCase(); - const tickSpacing = event.args.tickSpacing.toString(); + const tickSpacing = BigInt(event.args.tickSpacing); await this.onPoolCreated({ token0, token1, tickSpacing }); } From c8e53d0c4a99362905ebc8b65d60c5f0e769669d Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sun, 17 Dec 2023 18:23:24 +0100 Subject: [PATCH 758/833] disable wombat to prevent it from polling --- src/dex/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/index.ts b/src/dex/index.ts index 0a23fd0a1..4d16e8b4c 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -38,7 +38,7 @@ import { Excalibur } from './uniswap-v2/excalibur'; import { MakerPsm } from './maker-psm/maker-psm'; import { KyberDmm } from './kyberdmm/kyberdmm'; import { Platypus } from './platypus/platypus'; -import { Wombat } from './wombat/wombat'; +//import { Wombat } from './wombat/wombat'; import { GMX } from './gmx/gmx'; import { WooFiV2 } from './woo-fi-v2/woo-fi-v2'; import { ParaSwapLimitOrders } from './paraswap-limit-orders/paraswap-limit-orders'; @@ -160,7 +160,7 @@ const Dexes = [ QuickPerps, NomiswapV2, Smardex, - Wombat, + //Wombat, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< From 6a57f5ae87f9d87aaa95b42ebc8dc55088125088 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sun, 17 Dec 2023 18:25:25 +0100 Subject: [PATCH 759/833] 2.42.28 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d7d232883..f3ff767e2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.27", + "version": "2.42.28", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 54d656de38d3bd10b0291070a76e6b7cfeeb5a97 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 18 Dec 2023 12:33:08 +0200 Subject: [PATCH 760/833] fix: change liquidity for pools --- src/dex/solidly-v3/solidly-v3.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index 3f8ab7367..b6e995432 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -766,6 +766,7 @@ export class SolidlyV3 decimals } totalValueLockedUSD + liquidity } pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token}) { id @@ -778,6 +779,7 @@ export class SolidlyV3 decimals } totalValueLockedUSD + liquidity } }`, { @@ -803,7 +805,9 @@ export class SolidlyV3 }, ], liquidityUSD: - parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + parseFloat(pool.liquidity) > 0 + ? parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR + : 0, })); const pools1 = _.map(res.pools1, pool => ({ @@ -816,7 +820,9 @@ export class SolidlyV3 }, ], liquidityUSD: - parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + parseFloat(pool.liquidity) > 0 + ? parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR + : 0, })); const pools = _.slice( From 6584b08f51a19265a17599147d882f1df324244c Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 18 Dec 2023 12:34:05 +0200 Subject: [PATCH 761/833] 2.42.27-solidly-v3.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 835c83ae3..6aa7f6292 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.27-solidly-v3.2", + "version": "2.42.27-solidly-v3.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 682bfc8adfe59aed66efeb276a0403846cd00f38 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 18 Dec 2023 15:01:55 +0200 Subject: [PATCH 762/833] fix: acc to comments --- src/dex/solidly-v3/solidly-v3.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/dex/solidly-v3/solidly-v3.ts b/src/dex/solidly-v3/solidly-v3.ts index b6e995432..78fb4efbf 100644 --- a/src/dex/solidly-v3/solidly-v3.ts +++ b/src/dex/solidly-v3/solidly-v3.ts @@ -755,7 +755,7 @@ export class SolidlyV3 const res = await this._querySubgraph( `query ($token: Bytes!, $count: Int) { - pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token}) { + pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token, liquidity_gt: "0"}) { id token0 { id @@ -766,9 +766,8 @@ export class SolidlyV3 decimals } totalValueLockedUSD - liquidity } - pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token}) { + pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token, liquidity_gt: "0"}) { id token0 { id @@ -779,7 +778,6 @@ export class SolidlyV3 decimals } totalValueLockedUSD - liquidity } }`, { @@ -805,9 +803,7 @@ export class SolidlyV3 }, ], liquidityUSD: - parseFloat(pool.liquidity) > 0 - ? parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR - : 0, + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, })); const pools1 = _.map(res.pools1, pool => ({ @@ -820,9 +816,7 @@ export class SolidlyV3 }, ], liquidityUSD: - parseFloat(pool.liquidity) > 0 - ? parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR - : 0, + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, })); const pools = _.slice( From 2075e9a1e53ca2aa53e5a31131ec08d553797ad7 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 18 Dec 2023 15:02:55 +0200 Subject: [PATCH 763/833] 2.42.27-solidly-v3.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6aa7f6292..b68a4f66b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.27-solidly-v3.3", + "version": "2.42.27-solidly-v3.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 8882cce31dc243da29e4d2a0c172d926100010ba Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 19 Dec 2023 13:20:29 +0200 Subject: [PATCH 764/833] 2.42.29 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f3ff767e2..ac406f6d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.28", + "version": "2.42.29", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 788a99308e6dbb53fabe465926a0ddf5f256f778 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 23 Dec 2023 13:02:12 +0100 Subject: [PATCH 765/833] camelotV2: fix pool discovery logic --- src/dex/camelot/camelot.ts | 65 +++++++++++++++++++++- src/dex/uniswap-v2/uniswap-v2-factory.ts | 71 ++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 src/dex/uniswap-v2/uniswap-v2-factory.ts diff --git a/src/dex/camelot/camelot.ts b/src/dex/camelot/camelot.ts index 4163b1297..b5ee4e873 100644 --- a/src/dex/camelot/camelot.ts +++ b/src/dex/camelot/camelot.ts @@ -44,6 +44,10 @@ import { SimpleExchange } from '../simple-exchange'; import { applyTransferFee } from '../../lib/token-transfer-fee'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; import { SolidlyData } from '../solidly/types'; +import { + OnPoolCreatedCallback, + UniswapV2Factory, +} from '../uniswap-v2/uniswap-v2-factory'; const DefaultCamelotPoolGasCost = 90 * 1000; @@ -171,6 +175,10 @@ export class Camelot readonly DEST_TOKEN_DEX_TRANSFERS = 1; logger: Logger; + private readonly factoryInst: UniswapV2Factory; + + private newlyCreatedPoolKeys: Set = new Set(); + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = getDexKeysWithNetwork(CamelotConfig); @@ -205,8 +213,58 @@ export class Camelot this.routerInterface = new Interface(ParaSwapABI); this.exchangeRouterInterface = new Interface(UniswapV2ExchangeRouterABI); + + this.factoryInst = new UniswapV2Factory( + dexHelper, + dexKey, + factoryAddress, + this.logger, + this.onPoolCreatedDeleteFromNonExistingSet, + ); + } + + private _constructPoolKey(token0: string, token1: string) { + const [_token0, _token1] = + token0.toLowerCase() < token1.toLowerCase() + ? [token0, token1] + : [token1, token0]; + + const poolKey = `${token0}-${token1}`.toLowerCase(); + + return poolKey; } + /* + * When a non existing pool is queried, it's blacklisted for an arbitrary long period in order to prevent issuing too many rpc calls + * Once the pool is created, it gets immediately flagged + */ + onPoolCreatedDeleteFromNonExistingSet: OnPoolCreatedCallback = async ({ + token0, + token1, + }) => { + const logPrefix = '[onPoolCreatedDeleteFromNonExistingSet]'; + + try { + const [_token0, _token1] = + token0.toLowerCase() < token1.toLowerCase() + ? [token0, token1] + : [token1, token0]; + + const poolKey = this._constructPoolKey(token0, token1); + + this.newlyCreatedPoolKeys.add(poolKey); + + // delete entry locally to let local instance discover the pool + delete this.pairs[poolKey]; + + this.logger.info(`${logPrefix} discovered new pool ${poolKey}`); + } catch (e) { + this.logger.error( + `${logPrefix} LOGIC ERROR on ack new pool (token0=${token0},token1=${token1})`, + ); + } + }; + getPoolStatesMultiCallData(pair: CamelotPair): { callEntries: any[]; callDecoder: (data: any[]) => { @@ -328,14 +386,17 @@ export class Camelot ? [from, to] : [to, from]; - const key = `${token0.address.toLowerCase()}-${token1.address.toLowerCase()}`; + const key = this._constructPoolKey(token0.address, token1.address); let pair = this.pairs[key]; if (pair) return pair; const exchange = await this.factory.methods .getPair(token0.address, token1.address) .call(); if (exchange === NULL_ADDRESS) { - pair = { token0, token1 }; + // if the pool has been newly created to not allow this op as we can run into race condition between pool discovery and concurrent pricing request touching this pool + if (!this.newlyCreatedPoolKeys.has(key)) { + pair = { token0, token1 }; + } } else { pair = { token0, token1, exchange }; } diff --git a/src/dex/uniswap-v2/uniswap-v2-factory.ts b/src/dex/uniswap-v2/uniswap-v2-factory.ts new file mode 100644 index 000000000..3fe4d167b --- /dev/null +++ b/src/dex/uniswap-v2/uniswap-v2-factory.ts @@ -0,0 +1,71 @@ +import { Interface } from '@ethersproject/abi'; +import { DeepReadonly } from 'ts-essentials'; +import uniswapV2factoryABI from '../../abi/uniswap-v2/uniswap-v2-factory.json'; +import { IDexHelper } from '../../dex-helper/idex-helper'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { Address, Log, Logger } from '../../types'; +import { LogDescription } from 'ethers/lib/utils'; + +export type FactoryState = Record; + +export type OnPoolCreatedCallback = ({ + token0, + token1, +}: { + token0: string; + token1: string; +}) => Promise; + +/* + * "Stateless" event subscriber in order to capture "PoolCreated" event on new pools created. + * State is present, but it's a placeholder to actually make the events reach handlers (if there's no previous state - `processBlockLogs` is not called) + */ +export class UniswapV2Factory extends StatefulEventSubscriber { + handlers: { + [event: string]: (event: any) => Promise; + } = {}; + + logDecoder: (log: Log) => any; + + public readonly factoryIface = new Interface(uniswapV2factoryABI); + + constructor( + readonly dexHelper: IDexHelper, + parentName: string, + protected readonly factoryAddress: Address, + logger: Logger, + protected readonly onPoolCreated: OnPoolCreatedCallback, + mapKey: string = '', + ) { + super(parentName, `${parentName} Factory`, dexHelper, logger, true, mapKey); + + this.addressesSubscribed = [factoryAddress]; + + this.logDecoder = (log: Log) => this.factoryIface.parseLog(log); + + this.handlers['PairCreated'] = this.handleNewPool.bind(this); + } + + generateState(): FactoryState { + return {}; + } + + protected async processLog( + _: DeepReadonly, + log: Readonly, + ): Promise { + const event = this.logDecoder(log); + if (event.name in this.handlers) { + await this.handlers[event.name](event); + } + + return {}; + } + + async handleNewPool(event: LogDescription) { + const token0 = event.args.token0.toLowerCase(); + const token1 = event.args.token1.toLowerCase(); + + await this.onPoolCreated({ token0, token1 }); + } +} From ff1d7962138ae29eef8f8c91d4eb3c328b887448 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 23 Dec 2023 13:06:39 +0100 Subject: [PATCH 766/833] bump dex-lib --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ac406f6d6..ece59f79f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.29", + "version": "2.42.30-camelotv2-factory-fix.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1d9a6a043c7427157f73185f7cf075f00457c0c2 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 23 Dec 2023 19:31:54 +0100 Subject: [PATCH 767/833] remove deadcode --- src/dex/camelot/camelot.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/dex/camelot/camelot.ts b/src/dex/camelot/camelot.ts index b5ee4e873..0ba1aa0f7 100644 --- a/src/dex/camelot/camelot.ts +++ b/src/dex/camelot/camelot.ts @@ -245,11 +245,6 @@ export class Camelot const logPrefix = '[onPoolCreatedDeleteFromNonExistingSet]'; try { - const [_token0, _token1] = - token0.toLowerCase() < token1.toLowerCase() - ? [token0, token1] - : [token1, token0]; - const poolKey = this._constructPoolKey(token0, token1); this.newlyCreatedPoolKeys.add(poolKey); From 192a780703a68902fffcb5f41092fe7017c5a77b Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 23 Dec 2023 19:34:53 +0100 Subject: [PATCH 768/833] fix key construction --- src/dex/camelot/camelot.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dex/camelot/camelot.ts b/src/dex/camelot/camelot.ts index 0ba1aa0f7..a3eaa47de 100644 --- a/src/dex/camelot/camelot.ts +++ b/src/dex/camelot/camelot.ts @@ -229,7 +229,7 @@ export class Camelot ? [token0, token1] : [token1, token0]; - const poolKey = `${token0}-${token1}`.toLowerCase(); + const poolKey = `${_token0}-${_token1}`.toLowerCase(); return poolKey; } From a8c476b96a694864c2249efafe7d34bdfce4daaf Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 23 Dec 2023 19:37:44 +0100 Subject: [PATCH 769/833] add error --- src/dex/camelot/camelot.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dex/camelot/camelot.ts b/src/dex/camelot/camelot.ts index a3eaa47de..7e243729c 100644 --- a/src/dex/camelot/camelot.ts +++ b/src/dex/camelot/camelot.ts @@ -256,6 +256,7 @@ export class Camelot } catch (e) { this.logger.error( `${logPrefix} LOGIC ERROR on ack new pool (token0=${token0},token1=${token1})`, + e, ); } }; From 950d0c3dfeb8fa4175ca359286839700efc0abe3 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 23 Dec 2023 19:58:42 +0100 Subject: [PATCH 770/833] better pool identifier code --- src/dex/camelot/camelot.ts | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/dex/camelot/camelot.ts b/src/dex/camelot/camelot.ts index 7e243729c..b44378b74 100644 --- a/src/dex/camelot/camelot.ts +++ b/src/dex/camelot/camelot.ts @@ -223,13 +223,13 @@ export class Camelot ); } - private _constructPoolKey(token0: string, token1: string) { + private getPoolIdentifier(token0: string, token1: string) { const [_token0, _token1] = token0.toLowerCase() < token1.toLowerCase() ? [token0, token1] : [token1, token0]; - const poolKey = `${_token0}-${_token1}`.toLowerCase(); + const poolKey = `${this.dexKey}_${_token0}_${_token1}`.toLowerCase(); return poolKey; } @@ -245,7 +245,7 @@ export class Camelot const logPrefix = '[onPoolCreatedDeleteFromNonExistingSet]'; try { - const poolKey = this._constructPoolKey(token0, token1); + const poolKey = this.getPoolIdentifier(token0, token1); this.newlyCreatedPoolKeys.add(poolKey); @@ -382,7 +382,7 @@ export class Camelot ? [from, to] : [to, from]; - const key = this._constructPoolKey(token0.address, token1.address); + const key = this.getPoolIdentifier(token0.address, token1.address); let pair = this.pairs[key]; if (pair) return pair; const exchange = await this.factory.methods @@ -533,12 +533,9 @@ export class Camelot return []; } - const tokenAddress = [from.address.toLowerCase(), to.address.toLowerCase()] - .sort((a, b) => (a > b ? 1 : -1)) - .join('_'); + const poolKey = this.getPoolIdentifier(from.address, to.address); - const poolIdentifier = `${this.dexKey}_${tokenAddress}`; - return [poolIdentifier]; + return [poolKey]; } async getPricesVolume( @@ -564,14 +561,7 @@ export class Camelot return null; } - const tokenAddress = [ - from.address.toLowerCase(), - to.address.toLowerCase(), - ] - .sort((a, b) => (a > b ? 1 : -1)) - .join('_'); - - const poolIdentifier = `${this.dexKey}_${tokenAddress}`; + const poolIdentifier = this.getPoolIdentifier(from.address, to.address); if (limitPools && limitPools.every(p => p !== poolIdentifier)) return null; From 62c1a7f6cc796794813fcc6afa898ca04d4ef0cc Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 23 Dec 2023 20:00:36 +0100 Subject: [PATCH 771/833] 2.42.30-camelotv2-pooldiscoveryfix.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ece59f79f..5ed85b100 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.30-camelotv2-factory-fix.0", + "version": "2.42.30-camelotv2-pooldiscoveryfix.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From c034b863df078a5d3c1f3f4943d184c8a626bb56 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 23 Dec 2023 20:02:33 +0100 Subject: [PATCH 772/833] 2.42.30-camelotv2-pooldiscoveryfix.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ed85b100..04c8fa5a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.30-camelotv2-pooldiscoveryfix.0", + "version": "2.42.30-camelotv2-pooldiscoveryfix.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 22e4d2025e296b66e0280ce082a03ce668ff85f1 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 23 Dec 2023 21:51:02 +0100 Subject: [PATCH 773/833] add missing initialize --- src/dex/camelot/camelot.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/dex/camelot/camelot.ts b/src/dex/camelot/camelot.ts index b44378b74..e4b3a465b 100644 --- a/src/dex/camelot/camelot.ts +++ b/src/dex/camelot/camelot.ts @@ -223,6 +223,11 @@ export class Camelot ); } + async initializePricing(blockNumber: number) { + // Init listening to new pools creation + await this.factoryInst.initialize(blockNumber); + } + private getPoolIdentifier(token0: string, token1: string) { const [_token0, _token1] = token0.toLowerCase() < token1.toLowerCase() From 74eb430c4c6bde56168bb87f42a4b157b1a9f672 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 23 Dec 2023 21:52:27 +0100 Subject: [PATCH 774/833] 2.42.30-camelotv2-pooldiscoveryfix.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 04c8fa5a6..218c3617e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.30-camelotv2-pooldiscoveryfix.1", + "version": "2.42.30-camelotv2-pooldiscoveryfix.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 8d15a6accadce74a0719d39c0ded25bfcf1d5685 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sat, 23 Dec 2023 23:05:19 +0100 Subject: [PATCH 775/833] 2.42.30 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 218c3617e..b1f04d9d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.30-camelotv2-pooldiscoveryfix.2", + "version": "2.42.30", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e33cd8c28906095519a3b8f35797712ce36544cd Mon Sep 17 00:00:00 2001 From: sandy-wombat <142200506+sandy-wombat@users.noreply.github.com> Date: Sun, 24 Dec 2023 15:04:38 +0800 Subject: [PATCH 776/833] implement wombat using event base approach --- src/abi/wombat/{pool.json => pool-v2.json} | 0 src/abi/wombat/pool-v3.json | 2013 ++++++++++++++++++++ src/dex/index.ts | 3 +- src/dex/wombat/utils.ts | 20 + src/dex/wombat/wombat-bmw.ts | 39 +- src/dex/wombat/wombat-e2e.test.ts | 14 +- src/dex/wombat/wombat-events.test.ts | 180 ++ src/dex/wombat/wombat-integration.test.ts | 212 +-- src/dex/wombat/wombat-pool.ts | 783 ++++++-- src/dex/wombat/wombat.ts | 36 +- tests/constants-e2e.ts | 12 +- 11 files changed, 2973 insertions(+), 339 deletions(-) rename src/abi/wombat/{pool.json => pool-v2.json} (100%) create mode 100644 src/abi/wombat/pool-v3.json create mode 100644 src/dex/wombat/wombat-events.test.ts diff --git a/src/abi/wombat/pool.json b/src/abi/wombat/pool-v2.json similarity index 100% rename from src/abi/wombat/pool.json rename to src/abi/wombat/pool-v2.json diff --git a/src/abi/wombat/pool-v3.json b/src/abi/wombat/pool-v3.json new file mode 100644 index 000000000..af288d33f --- /dev/null +++ b/src/abi/wombat/pool-v3.json @@ -0,0 +1,2013 @@ +[ + { + "inputs": [], + "name": "POOL__CREDIT_NOT_ENOUGH", + "type": "error" + }, + { + "inputs": [], + "name": "POOL__REACH_MAXIMUM_BURNED_CREDIT", + "type": "error" + }, + { + "inputs": [], + "name": "POOL__REACH_MAXIMUM_MINTED_CREDIT", + "type": "error" + }, + { + "inputs": [], + "name": "POOL__SWAP_CREDIT_FOR_TOKENS_DISABLED", + "type": "error" + }, + { + "inputs": [], + "name": "POOL__SWAP_TOKENS_FOR_CREDIT_DISABLED", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_AMOUNT_TOO_LOW", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ASSET_ALREADY_EXIST", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ASSET_ALREADY_PAUSED", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ASSET_NOT_EXISTS", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ASSET_NOT_PAUSED", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_CASH_NOT_ENOUGH", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_COV_RATIO_LIMIT_EXCEEDED", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_EXPIRED", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_FORBIDDEN", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_INVALID_VALUE", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_SAME_ADDRESS", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ZERO_ADDRESS", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ZERO_AMOUNT", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ZERO_CREDIT_AMOUNT", + "type": "error" + }, + { + "inputs": [], + "name": "WOMBAT_ZERO_LIQUIDITY", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "AssetAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "AssetRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FillPool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "creditAmount", + "type": "uint256" + } + ], + "name": "MintCredit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "PausedAsset", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SetAmpFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "SetDev", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "lpDividendRatio", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "retentionRatio", + "type": "uint256" + } + ], + "name": "SetFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "SetFeeTo", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SetHaircutRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "SetMasterWombat", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SetMintFeeThreshold", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SetWithdrawalHaircutRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "creditAmount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toTokenFee", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "SwapCreditForTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fromAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fromTokenFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "creditAmount", + "type": "uint256" + } + ], + "name": "SwapTokensForCredit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fromAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toTokenFee", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SwapV2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "TransferTipBucket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "UnpausedAsset", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "adaptor", + "outputs": [ + { + "internalType": "contract IAdaptor", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "addAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "addressOfAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ampFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fromAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumToAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "completeSwapCreditForTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "actualToAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "toTokenFee", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "creditBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "creditForTokensHaircut", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumLiquidity", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "shouldStake", + "type": "bool" + } + ], + "name": "deposit", + "outputs": [ + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "dev", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endCovRatio", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "exchangeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "xr", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "fillPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getTokens", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalEquilCovRatio", + "outputs": [ + { + "internalType": "int256", + "name": "equilCovRatio", + "type": "int256" + }, + { + "internalType": "int256", + "name": "invariant", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalEquilCovRatioWithCredit", + "outputs": [ + { + "internalType": "uint256", + "name": "equilCovRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "invariantInUint", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "haircutRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ampFactor_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "haircutRate_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lpDividendRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterWombat", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maximumInboundCredit", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maximumOutboundCredit", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "creditAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "mintCredit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "mintFee", + "outputs": [ + { + "internalType": "uint256", + "name": "feeCollected", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mintFeeThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "pauseAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "int256", + "name": "toAmount", + "type": "int256" + } + ], + "name": "quoteAmountIn", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "haircut", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "quotePotentialDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "int256", + "name": "fromAmount", + "type": "int256" + } + ], + "name": "quotePotentialSwap", + "outputs": [ + { + "internalType": "uint256", + "name": "potentialOutcome", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "haircut", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "name": "quotePotentialWithdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + } + ], + "name": "quotePotentialWithdrawFromOtherAsset", + "outputs": [ + { + "internalType": "uint256", + "name": "finalAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "withdrewAmount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fromCreditAmount", + "type": "uint256" + } + ], + "name": "quoteSwapCreditForTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "actualToAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "toTokenFee", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fromAmount", + "type": "uint256" + } + ], + "name": "quoteSwapTokensForCredit", + "outputs": [ + { + "internalType": "uint256", + "name": "creditAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fromTokenFee", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "removeAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "retentionRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IAdaptor", + "name": "_adaptor", + "type": "address" + } + ], + "name": "setAdaptorAddr", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ampFactor_", + "type": "uint256" + } + ], + "name": "setAmpFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "startCovRatio_", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "endCovRatio_", + "type": "uint128" + } + ], + "name": "setCovRatioFeeParam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "_tokensForCreditHaircut", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "_creditForTokensHaircut", + "type": "uint128" + } + ], + "name": "setCrossChainHaircut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dev_", + "type": "address" + } + ], + "name": "setDev", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "lpDividendRatio_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "retentionRatio_", + "type": "uint256" + } + ], + "name": "setFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "feeTo_", + "type": "address" + } + ], + "name": "setFeeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "haircutRate_", + "type": "uint256" + } + ], + "name": "setHaircutRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "masterWombat_", + "type": "address" + } + ], + "name": "setMasterWombat", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "_maximumInboundCredit", + "type": "uint128" + } + ], + "name": "setMaximumInboundCredit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint128", + "name": "_maximumOutboundCredit", + "type": "uint128" + } + ], + "name": "setMaximumOutboundCredit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "mintFeeThreshold_", + "type": "uint256" + } + ], + "name": "setMintFeeThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "setSwapCreditForTokensEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "setSwapTokensForCreditEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "withdrawalHaircutRate_", + "type": "uint256" + } + ], + "name": "setWithdrawalHaircutRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "startCovRatio", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fromAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumToAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "swap", + "outputs": [ + { + "internalType": "uint256", + "name": "actualToAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "haircut", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fromAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumToAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "swapCreditForTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "actualToAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "toTokenFee", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "toChain", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fromAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumToAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "receiverValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deliveryGasLimit", + "type": "uint256" + } + ], + "name": "swapCreditForTokensCrossChain", + "outputs": [ + { + "internalType": "uint256", + "name": "trackingId", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "swapCreditForTokensEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "swapTokensForCreditEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "toChain", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fromAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumCreditAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumToAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "receiverValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deliveryGasLimit", + "type": "uint256" + } + ], + "name": "swapTokensForTokensCrossChain", + "outputs": [ + { + "internalType": "uint256", + "name": "creditAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fromTokenFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sequence", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "tipBucketBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokensForCreditHaircut", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalCreditBurned", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalCreditMinted", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferTipBucket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unpauseAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromToken", + "type": "address" + }, + { + "internalType": "address", + "name": "toToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimumAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "withdrawFromOtherAsset", + "outputs": [ + { + "internalType": "uint256", + "name": "toAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawalHaircutRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/dex/index.ts b/src/dex/index.ts index 3c135f3ca..70ddb0c61 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -83,6 +83,7 @@ import { QuickPerps } from './quick-perps/quick-perps'; import { NomiswapV2 } from './uniswap-v2/nomiswap-v2'; import { Dexalot } from './dexalot/dexalot'; import { Smardex } from './smardex/smardex'; +import { Wombat } from './wombat/wombat'; const LegacyDexes = [ CurveV2, @@ -162,7 +163,7 @@ const Dexes = [ NomiswapV2, SolidlyV3, Smardex, - //Wombat, + Wombat, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< diff --git a/src/dex/wombat/utils.ts b/src/dex/wombat/utils.ts index cae5701a3..ef67d5de6 100644 --- a/src/dex/wombat/utils.ts +++ b/src/dex/wombat/utils.ts @@ -60,3 +60,23 @@ export const uint120ToBigInt = ( ): bigint => { return generalDecoder(result, ['uint120'], 0n, value => value[0].toBigInt()); }; + +export function convertUint256ToInt256(uint256Value: bigint): bigint { + const isNegative = + (uint256Value & + BigInt( + '0x8000000000000000000000000000000000000000000000000000000000000000', + )) !== + BigInt(0); + + if (isNegative) { + return ( + uint256Value - + BigInt( + '0x10000000000000000000000000000000000000000000000000000000000000000', + ) + ); + } else { + return uint256Value; + } +} diff --git a/src/dex/wombat/wombat-bmw.ts b/src/dex/wombat/wombat-bmw.ts index fcb41e4b9..cd63b212d 100644 --- a/src/dex/wombat/wombat-bmw.ts +++ b/src/dex/wombat/wombat-bmw.ts @@ -10,7 +10,7 @@ import { IDexHelper } from '../../dex-helper'; import { BmwState } from './types'; import BmwABI from '../../abi/wombat/bmw.json'; import AssetABI from '../../abi/wombat/asset.json'; -import PoolABI from '../../abi/wombat/pool.json'; +import PoolABI from '../../abi/wombat/pool-v2.json'; export class WombatBmw extends StatefulEventSubscriber { static readonly bmwInterface = new Interface(BmwABI); @@ -36,13 +36,12 @@ export class WombatBmw extends StatefulEventSubscriber { protected bmwAddress: Address, protected onAssetAdded: ( pool: Address, - asset2TokenMap: Map, blockNumber: number, ) => Promise, ) { super( - `${dexKey} ${name}`, - `${dexKey}-${network} ${name}`, + `${dexKey}-${name}`, + `${dexKey}-${network}-${name}`, dexHelper, logger, ); @@ -118,11 +117,6 @@ export class WombatBmw extends StatefulEventSubscriber { inputs = []; for (const lpToken of lpTokens) { - inputs.push({ - target: lpToken, - callData: - WombatBmw.assetInterface.encodeFunctionData('underlyingToken'), - }); inputs.push({ target: lpToken, callData: WombatBmw.assetInterface.encodeFunctionData('pool'), @@ -135,26 +129,20 @@ export class WombatBmw extends StatefulEventSubscriber { .call({}, blockNumber) ).returnData; - const pool2AssetInfo = new Map>(); + const poolAddressSet = new Set
(); let i = 0; for (const lpToken of lpTokens) { - const underlyingToken = WombatBmw.assetInterface - .decodeFunctionResult('underlyingToken', returnData[i++])[0] - .toLowerCase(); const pool = WombatBmw.assetInterface .decodeFunctionResult('pool', returnData[i++])[0] .toLowerCase(); - if (!pool2AssetInfo.has(pool)) { - pool2AssetInfo.set(pool, new Map()); - } - pool2AssetInfo.get(pool)!.set(lpToken, underlyingToken); + poolAddressSet.add(pool); } const promises: Promise[] = []; - pool2AssetInfo.forEach((asset2TokenMap, pool) => { + poolAddressSet.forEach(pool => { bmwState.pools.push(pool); - promises.push(this.onAssetAdded(pool, asset2TokenMap, blockNumber)); + promises.push(this.onAssetAdded(pool, blockNumber)); }); await Promise.all(promises); @@ -173,10 +161,6 @@ export class WombatBmw extends StatefulEventSubscriber { target: lpToken, callData: WombatBmw.assetInterface.encodeFunctionData('pool'), }); - multiCallInputs.push({ - target: lpToken, - callData: WombatBmw.assetInterface.encodeFunctionData('underlyingToken'), - }); const returnData = ( await this.dexHelper.multiContract.methods @@ -187,15 +171,8 @@ export class WombatBmw extends StatefulEventSubscriber { const pool = WombatBmw.assetInterface .decodeFunctionResult('pool', returnData[0])[0] .toLowerCase(); - const underlyingToken = WombatBmw.assetInterface - .decodeFunctionResult('underlyingToken', returnData[1])[0] - .toLowerCase(); - await this.onAssetAdded( - pool, - new Map().set(lpToken, underlyingToken), - log.blockNumber, - ); + await this.onAssetAdded(pool, log.blockNumber); if (!state.pools.includes(pool)) { return { pools: [...state.pools, pool], diff --git a/src/dex/wombat/wombat-e2e.test.ts b/src/dex/wombat/wombat-e2e.test.ts index 36968e240..91a447027 100644 --- a/src/dex/wombat/wombat-e2e.test.ts +++ b/src/dex/wombat/wombat-e2e.test.ts @@ -172,7 +172,7 @@ describe('Wombat E2E', () => { buyAmount: '1000000000000000000', }, { - name: 'wstETH', + name: 'frxETH', sellAmount: '1000000000000000000', buyAmount: '1000000000000000000', }, @@ -252,6 +252,18 @@ describe('Wombat E2E', () => { buyAmount: '100000000', }, ], + [ + { + name: 'ETH', + sellAmount: '100000000000000000', + buyAmount: '100000000000000000', + }, + { + name: 'frxETH', + sellAmount: '100000000000000000', + buyAmount: '100000000000000000', + }, + ], ]; testForNetwork(network, dexKey, pairs); diff --git a/src/dex/wombat/wombat-events.test.ts b/src/dex/wombat/wombat-events.test.ts new file mode 100644 index 000000000..7a50bafc5 --- /dev/null +++ b/src/dex/wombat/wombat-events.test.ts @@ -0,0 +1,180 @@ +import dotenv from 'dotenv'; + +dotenv.config(); + +import { DeepReadonly } from 'ts-essentials'; +import { WombatPool } from './wombat-pool'; +import { Network } from '../../constants'; +import { Address } from '../../types'; +import { DummyDexHelper } from '../../dex-helper'; +import { BmwState, PoolState } from './types'; +import { WombatConfig } from './config'; +import { Wombat } from './wombat'; +import { WombatBmw } from './wombat-bmw'; +import { testEventSubscriber } from '../../../tests/utils-events'; +/* + README + ====== + + This test script adds unit tests for Wombat event based + system. This is done by fetching the state on-chain before the + event block, manually pushing the block logs to the event-subscriber, + comparing the local state with on-chain state. + + Most of the logic for testing is abstracted by `testEventSubscriber`. + You need to do two things to make the tests work: + + 1. Fetch the block numbers where certain events were released. You + can modify the `./scripts/fetch-event-blocknumber.ts` to get the + block numbers for different events. Make sure to get sufficient + number of blockNumbers to cover all possible cases for the event + mutations. + + 2. Complete the implementation for fetchPoolState function. The + function should fetch the on-chain state of the event subscriber + using just the blocknumber. + + The template tests only include the test for a single event + subscriber. There can be cases where multiple event subscribers + exist for a single DEX. In such cases additional tests should be + added. + + You can run this individual test script by running: + `npx jest src/dex//-events.test.ts` + + (This comment should be removed from the final implementation) +*/ + +// npx jest src/dex/wombat/wombat-events.test.ts +jest.setTimeout(100 * 1000); + +async function fetchPoolState( + wombatPool: WombatPool, + blockNumber: number, +): Promise> { + return await wombatPool.generateState(blockNumber); +} + +async function fetchBmwState( + wombatBmw: WombatBmw, + blockNumber: number, +): Promise> { + return await wombatBmw.generateState(blockNumber); +} + +// eventName -> blockNumbers +type EventMappings = Record; + +describe('Wombat EventPool BSC', function () { + const dexKey = 'Wombat'; + const network = Network.BSC; + const dexHelper = new DummyDexHelper(network); + const logger = dexHelper.getLogger(dexKey); + const v2Pool = '0x9498563e47D7CFdFa22B818bb8112781036c201C'; // stable guild pool + const v3Pool = '0x1ee15673e07105Bcf360139fa8CafeBDd7754BeF'; // cross chain pool + const eventsToTest: Record = { + [v2Pool]: { + // topic0: 0xf5dd9317b9e63ac316ce44acc85f670b54b339cfa3e9076e1dd55065b922314b + ['Deposit']: [34556359, 34556365, 34558365], + // topic0: 0xfb80d861da582b723be2d19507ce3e03851820c464abea89156ec77e089b1ad9 + ['Withdraw']: [34208250, 34262795, 34549292], + // topic0: 0x54787c404bb33c88e86f4baf88183a3b0141d0a848e6a9f7a13b66ae3a9b73d1 + ['Swap']: [34588909, 34590323, 34593343, 34600568, 34602207], + ['SetAmpFactor']: [], + ['SetHaircutRate']: [], + // topic0: 0x0bb5715f0f217c2fe9a0c877ea87d474380c641102f3440ee2a4c8b9d9790918 + ['AssetAdded']: [28050075], + // topic0: 0x0fa1e4606af435f32f05b3804033d2933e691fab32ee74d2db6fa82d2741f1ea + ['AssetRemoved']: [34463362], + // topic0: 0x4941e18a2bcbb0f9fa0081238f26793a8ad8c202b913ae8bf5f7e523f68ff137 + ['FillPool']: [], + ['Paused']: [34342956], + // topic0: 0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa + ['Unpaused']: [34463362], + // topic0: 0xdcb65c0553aaa433aadd180404ff195259c48f78aa50f877ebcb4bb215129a4e + ['PausedAsset']: [34463362], + ['UnpausedAsset']: [], + }, + [v3Pool]: { + // topic0: 0xf5dd9317b9e63ac316ce44acc85f670b54b339cfa3e9076e1dd55065b922314b + ['Deposit']: [34558302, 34564573, 34597601], + // // topic0: 0xfb80d861da582b723be2d19507ce3e03851820c464abea89156ec77e089b1ad9 + ['Withdraw']: [34567962, 34569797, 34596990], + // // topic0: 0x7fa01e8d24e5a6ec56e00b4ff8ee7ed97e7650a7846ec494bbaa5d65f1be9ea4 + ['SwapV2']: [34609776, 34610336, 34610364, 34611146, 34611872], + // topic0: 0x0fa1e4606af435f32f05b3804033d2933e691fab32ee74d2db6fa82d2741f1ea + ['AssetRemoved']: [34463362], + }, + }; + + for (const [poolAddress, events] of Object.entries(eventsToTest)) { + describe(`Events for ${poolAddress}`, () => { + for (const [eventName, blockNumbers] of Object.entries(events)) { + describe(`${eventName}`, () => { + for (const blockNumber of blockNumbers) { + it(`State after ${blockNumber}`, async function () { + const wombatPool = new WombatPool( + dexKey, + poolAddress, + network, + dexHelper, + logger, + poolAddress.toLowerCase(), + ); + await wombatPool.initialize(blockNumber - 1); + + await testEventSubscriber( + wombatPool, + wombatPool.addressesSubscribed, + (_blockNumber: number) => + fetchPoolState(wombatPool, _blockNumber), + blockNumber, + `${dexKey}_${poolAddress}`, + dexHelper.provider, + ); + }); + } + }); + } + }); + } +}); +describe('Wombat BMW ARB', function () { + const dexKey = 'Wombat'; + const network = Network.ARBITRUM; + const dexHelper = new DummyDexHelper(network); + const bmwAddress = WombatConfig.Wombat[network].bmwAddress; + const eventsToTest: Record = { + [bmwAddress]: { + // topic0: 0xec85b1d1f037ff3a8722aaf5d4d8e7d93c7ff10c056430c18d76a9ec23aa397e + ['Add']: [158157042, 162173973], + }, + }; + + const wombat = new Wombat(network, dexKey, dexHelper); + + for (const [poolAddress, events] of Object.entries(eventsToTest)) { + describe(`Events for ${poolAddress}`, () => { + for (const [eventName, blockNumbers] of Object.entries(events)) { + describe(`${eventName}`, () => { + for (const blockNumber of blockNumbers) { + it(`State after ${blockNumber}`, async function () { + if (wombat.initializePricing) { + await wombat.initializePricing(blockNumber); + } + await testEventSubscriber( + wombat.bmw, + wombat.bmw.addressesSubscribed, + (_blockNumber: number) => + fetchBmwState(wombat.bmw, _blockNumber), + blockNumber, + `${dexKey}_${bmwAddress}`, + dexHelper.provider, + ); + }); + } + }); + } + }); + } +}); diff --git a/src/dex/wombat/wombat-integration.test.ts b/src/dex/wombat/wombat-integration.test.ts index aa9fa1f74..624fdd469 100644 --- a/src/dex/wombat/wombat-integration.test.ts +++ b/src/dex/wombat/wombat-integration.test.ts @@ -3,15 +3,11 @@ import dotenv from 'dotenv'; dotenv.config(); import { Interface, Result } from '@ethersproject/abi'; -import { DummyDexHelper } from '../../dex-helper/index'; +import { DummyDexHelper } from '../../dex-helper'; import { Network, SwapSide } from '../../constants'; import { BI_POWS } from '../../bigint-constants'; import { Wombat } from './wombat'; -import { - checkPoolPrices, - checkPoolsLiquidity, - checkConstantPoolPrices, -} from '../../../tests/utils'; +import { checkPoolPrices, checkConstantPoolPrices } from '../../../tests/utils'; import { Tokens } from '../../../tests/constants-e2e'; import { Token } from '../../types'; import { Address } from '@paraswap/core'; @@ -150,109 +146,103 @@ describe('Wombat', function () { let blockNumber: number; let wombat: Wombat; - // Object.keys(WombatConfig[dexKey]).forEach(key => { - // describe(`network ${key}`, () => { - // const network = Number(key) as Network; - // const dexHelper = new DummyDexHelper(network); - - // const tokens = Tokens[network]; - - // const srcTokenSymbol = 'USDC'; - // const destTokenSymbol = network == Network.BASE ? 'USDbC' : 'USDT'; - - // let amountsForSell = [ - // 0n, - // 1n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 2n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 3n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 4n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 5n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 6n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 7n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 8n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 9n * BI_POWS[tokens[srcTokenSymbol].decimals], - // 10n * BI_POWS[tokens[srcTokenSymbol].decimals], - // ]; - - // let amountsForBuy = [ - // 0n, - // 1n * BI_POWS[tokens[destTokenSymbol].decimals], - // 2n * BI_POWS[tokens[destTokenSymbol].decimals], - // 3n * BI_POWS[tokens[destTokenSymbol].decimals], - // 4n * BI_POWS[tokens[destTokenSymbol].decimals], - // 5n * BI_POWS[tokens[destTokenSymbol].decimals], - // 6n * BI_POWS[tokens[destTokenSymbol].decimals], - // 7n * BI_POWS[tokens[destTokenSymbol].decimals], - // 8n * BI_POWS[tokens[destTokenSymbol].decimals], - // 9n * BI_POWS[tokens[destTokenSymbol].decimals], - // 10n * BI_POWS[tokens[destTokenSymbol].decimals], - // ]; - - // // OPTIMISM has very low liquidity currently, so we have to use very small amounts - // // if (network === Network.OPTIMISM) { - // // amountsForSell = amountsForSell.map(a => a / 100n); - // // amountsForBuy = amountsForBuy.map(a => a / 100n); - // // } - - // beforeAll(async () => { - // blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); - // wombat = new Wombat(network, dexKey, dexHelper); - // }); - - // it('getTopPoolsForToken', async function () { - // // We have to check without calling initializePricing, because - // // pool-tracker is not calling that function - // if (wombat.updatePoolState) { - // await wombat.updatePoolState(); - // } - // const poolLiquidity = await wombat.getTopPoolsForToken( - // tokens[srcTokenSymbol].address, - // 10, - // ); - // console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); - - // if (!wombat.hasConstantPriceLargeAmounts) { - // checkPoolsLiquidity( - // poolLiquidity, - // Tokens[network][srcTokenSymbol].address, - // dexKey, - // ); - // } - // }); - - // it('getPoolIdentifiers and getPricesVolume SELL', async function () { - // if (wombat.initializePricing) { - // await wombat.initializePricing(blockNumber); - // } - // await testPricingOnNetwork( - // wombat, - // network, - // dexKey, - // blockNumber, - // srcTokenSymbol, - // destTokenSymbol, - // SwapSide.SELL, - // amountsForSell, - // 'quotePotentialSwap', - // ); - // }); - - // it('getPoolIdentifiers and getPricesVolume BUY', async function () { - // if (wombat.initializePricing) { - // await wombat.initializePricing(blockNumber); - // } - // await testPricingOnNetwork( - // wombat, - // network, - // dexKey, - // blockNumber, - // srcTokenSymbol, - // destTokenSymbol, - // SwapSide.BUY, - // amountsForBuy, - // 'quotePotentialSwap', - // ); - // }); - // }); - // }); + Object.keys(WombatConfig[dexKey]).forEach(key => { + describe(`network ${key}`, () => { + const network = Number(key) as Network; + const dexHelper = new DummyDexHelper(network); + + const tokens = Tokens[network]; + + const srcTokenSymbol = 'USDC'; + const destTokenSymbol = network == Network.BASE ? 'USDbC' : 'USDT'; + + let amountsForSell = [ + 0n, + 1n * BI_POWS[tokens[srcTokenSymbol].decimals], + 2n * BI_POWS[tokens[srcTokenSymbol].decimals], + 3n * BI_POWS[tokens[srcTokenSymbol].decimals], + 4n * BI_POWS[tokens[srcTokenSymbol].decimals], + 5n * BI_POWS[tokens[srcTokenSymbol].decimals], + 6n * BI_POWS[tokens[srcTokenSymbol].decimals], + 7n * BI_POWS[tokens[srcTokenSymbol].decimals], + 8n * BI_POWS[tokens[srcTokenSymbol].decimals], + 9n * BI_POWS[tokens[srcTokenSymbol].decimals], + 10n * BI_POWS[tokens[srcTokenSymbol].decimals], + ]; + + // let amountsForBuy = [ + // 0n, + // 1n * BI_POWS[tokens[destTokenSymbol].decimals], + // 2n * BI_POWS[tokens[destTokenSymbol].decimals], + // 3n * BI_POWS[tokens[destTokenSymbol].decimals], + // 4n * BI_POWS[tokens[destTokenSymbol].decimals], + // 5n * BI_POWS[tokens[destTokenSymbol].decimals], + // 6n * BI_POWS[tokens[destTokenSymbol].decimals], + // 7n * BI_POWS[tokens[destTokenSymbol].decimals], + // 8n * BI_POWS[tokens[destTokenSymbol].decimals], + // 9n * BI_POWS[tokens[destTokenSymbol].decimals], + // 10n * BI_POWS[tokens[destTokenSymbol].decimals], + // ]; + + beforeAll(async () => { + blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); + wombat = new Wombat(network, dexKey, dexHelper); + }); + + // it('getTopPoolsForToken', async function () { + // // We have to check without calling initializePricing, because + // // pool-tracker is not calling that function + // if (wombat.updatePoolState) { + // await wombat.updatePoolState(); + // } + // const poolLiquidity = await wombat.getTopPoolsForToken( + // tokens[srcTokenSymbol].address, + // 10, + // ); + // console.log(`${srcTokenSymbol} Top Pools:`, poolLiquidity); + // + // if (!wombat.hasConstantPriceLargeAmounts) { + // checkPoolsLiquidity( + // poolLiquidity, + // Tokens[network][srcTokenSymbol].address, + // dexKey, + // ); + // } + // }); + + it('getPoolIdentifiers and getPricesVolume SELL', async function () { + if (wombat.initializePricing) { + await wombat.initializePricing(blockNumber); + } + await testPricingOnNetwork( + wombat, + network, + dexKey, + blockNumber, + srcTokenSymbol, + destTokenSymbol, + SwapSide.SELL, + amountsForSell, + 'quotePotentialSwap', + ); + }); + + // it('getPoolIdentifiers and getPricesVolume BUY', async function () { + // if (wombat.initializePricing) { + // await wombat.initializePricing(blockNumber); + // } + // await testPricingOnNetwork( + // wombat, + // network, + // dexKey, + // blockNumber, + // srcTokenSymbol, + // destTokenSymbol, + // SwapSide.BUY, + // amountsForBuy, + // 'quotePotentialSwap', + // ); + // }); + }); + }); }); diff --git a/src/dex/wombat/wombat-pool.ts b/src/dex/wombat/wombat-pool.ts index c687b7467..12b876546 100644 --- a/src/dex/wombat/wombat-pool.ts +++ b/src/dex/wombat/wombat-pool.ts @@ -1,152 +1,250 @@ import { Interface } from '@ethersproject/abi'; -import { Address } from '@paraswap/core'; -import _ from 'lodash'; - -import { MultiCallParams, MultiResult } from '../../lib/multi-wrapper'; -import { IDexHelper } from '../../dex-helper'; -import { StatefulRpcPoller } from '../../lib/stateful-rpc-poller/stateful-rpc-poller'; -import { StatePollingManager } from '../../lib/stateful-rpc-poller/state-polling-manager'; -import { ObjWithUpdateInfo } from '../../lib/stateful-rpc-poller/types'; -import { pollingManagerCbExtractor } from '../../lib/stateful-rpc-poller/utils'; +import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; +import { + Address, + Log, + Logger, + MultiCallInput, + MultiCallOutput, +} from '../../types'; +import { catchParseLogError } from '../../utils'; import { - addressArrayDecode, - booleanDecode, - uint256ToBigInt, - uint8ToNumber, -} from '../../lib/decoders'; -import PoolABI from '../../abi/wombat/pool.json'; + InitializeStateOptions, + StatefulEventSubscriber, +} from '../../stateful-event-subscriber'; +import { IDexHelper } from '../../dex-helper'; +import PoolV2ABI from '../../abi/wombat/pool-v2.json'; +import PoolV3ABI from '../../abi/wombat/pool-v3.json'; import AssetABI from '../../abi/wombat/asset.json'; -import { uint120ToBigInt } from './utils'; -import { AssetState, MulticallResultOutputs, PoolState } from './types'; - -export class WombatPool extends StatefulRpcPoller< - PoolState, - MulticallResultOutputs -> { - static readonly poolInterface = new Interface(PoolABI); +import { convertUint256ToInt256, toWad, WAD, wdiv, wmul } from './utils'; +import { BlockHeader } from 'web3-eth'; +import { AssetState, PoolState } from './types'; + +export class WombatPool extends StatefulEventSubscriber { + static readonly poolV2Interface = new Interface(PoolV2ABI); + static readonly poolV3Interface = new Interface(PoolV3ABI); static readonly assetInterface = new Interface(AssetABI); + private handlers: { + [event: string]: ( + event: any, + state: DeepReadonly, + log: Readonly, + ) => AsyncOrSync | null>; + } = {}; + private poolInterface: Interface = WombatPool.poolV2Interface; + private eventRefetched: string[]; + + blankState: PoolState = { + asset: {}, + underlyingAddresses: [], + params: { + paused: false, + ampFactor: 0n, + haircutRate: 0n, + startCovRatio: 0n, + endCovRatio: 0n, + }, + }; + constructor( dexKey: string, - poolIdentifier: string, - dexHelper: IDexHelper, + name: string, + protected network: number, + protected dexHelper: IDexHelper, + logger: Logger, protected poolAddress: Address, - protected asset2TokenMap: Map, ) { - const callbacks = pollingManagerCbExtractor( - StatePollingManager.getInstance(dexHelper), + super( + `${dexKey}-${name}`, + `${dexKey}-${network}-${name}`, + dexHelper, + logger, + ); + + this.addressesSubscribed = [this.poolAddress]; + + // users-actions handlers + this.handlers['Swap'] = this.handleSwap.bind(this); + this.handlers['SwapV2'] = this.handleSwapV2.bind(this); + + // admin-actions handlers + this.handlers['SetAmpFactor'] = this.handleSetAmpFactor.bind(this); + this.handlers['SetHaircutRate'] = this.handleSetHaircutRate.bind(this); + this.handlers['AssetAdded'] = this.handleAssetAdded.bind(this); + this.handlers['AssetRemoved'] = this.handleAssetRemoved.bind(this); + this.handlers['FillPool'] = this.handleFillPool.bind(this); + this.handlers['Paused'] = this.handlePaused.bind(this); + this.handlers['Unpaused'] = this.handleUnpaused.bind(this); + this.handlers['PausedAsset'] = this.handlePausedAsset.bind(this); + this.handlers['UnpausedAsset'] = this.handleUnpausedAsset.bind(this); + + this.eventRefetched = ['Deposit', 'Withdraw']; + } + + async initialize( + blockNumber: number, + options?: InitializeStateOptions, + ) { + const poolContract = new this.dexHelper.web3Provider.eth.Contract( + PoolV3ABI as any, + this.poolAddress, ); + try { + await poolContract.methods.withdrawalHaircutRate().call({}, blockNumber); + this.poolInterface = WombatPool.poolV3Interface; + } catch (e) { + this.logger.info( + `no public variable withdrawalHaircutRate in pool ${this.poolAddress}, this is v2 pool`, + ); + } + await super.initialize(blockNumber, options); + } + + protected async processBlockLogs( + state: DeepReadonly, + logs: Readonly[], + blockHeader: Readonly, + ): Promise | null> { + let nextState: DeepReadonly | null = null; + for (const log of logs) { + try { + const event = this.poolInterface.parseLog(log); + if (this.eventRefetched.includes(event.name)) { + // if the state is refetched, no need to deal with the left logs in the block + if (!this.dexHelper.config.isSlave) { + return await this.generateState(log.blockNumber); + } + return null; + } + } catch (e) { + catchParseLogError(e, this.logger); + } - super(dexKey, poolIdentifier, dexHelper, 0, 0, false, callbacks); + const retState: DeepReadonly | null = await this.processLog( + nextState || state, + log, + blockHeader, + ); + + if (retState) { + nextState = retState; + } + } + return nextState; + } + + /** + * The function is called every time any of the subscribed + * addresses release log. The function accepts the current + * state, updates the state according to the log, and returns + * the updated state. + * @param state - Current state of event subscriber + * @param log - Log released by one of the subscribed addresses + * @param blockHeader + * @returns Updates state of the event subscriber after the log + */ + protected async processLog( + state: DeepReadonly, + log: Readonly, + blockHeader: Readonly, + ): Promise | null> { + try { + const event = this.poolInterface.parseLog(log); + if (event.name in this.handlers) { + return await this.handlers[event.name](event, state, log); + } + } catch (e) { + catchParseLogError(e, this.logger); + } + + return null; } - protected _getFetchStateMultiCalls(): MultiCallParams[] { - const params: MultiCallParams[] = []; + /** + * The function generates state using on-chain calls. This + * function is called to regenerate state if the event based + * system fails to fetch events and the local state is no + * more correct. + * @param blockNumber - Blocknumber for which the state should + * should be generated + * @returns state of the event subscriber at blocknumber + */ + async generateState(blockNumber: number): Promise> { + let multiCallInputs: MultiCallInput[] = []; - params.push({ + // 1.A generate pool params requests + // paused + multiCallInputs.push({ target: this.poolAddress, - callData: WombatPool.poolInterface.encodeFunctionData('paused'), - decodeFunction: booleanDecode, + callData: this.poolInterface.encodeFunctionData('paused'), }); - params.push({ + // ampFactor + multiCallInputs.push({ target: this.poolAddress, - callData: WombatPool.poolInterface.encodeFunctionData('ampFactor'), - decodeFunction: uint256ToBigInt, + callData: this.poolInterface.encodeFunctionData('ampFactor'), }); - params.push({ + // haircutRate + multiCallInputs.push({ target: this.poolAddress, - callData: WombatPool.poolInterface.encodeFunctionData('haircutRate'), - decodeFunction: uint256ToBigInt, + callData: this.poolInterface.encodeFunctionData('haircutRate'), }); - params.push({ + // startCovRatio + multiCallInputs.push({ target: this.poolAddress, - callData: WombatPool.poolInterface.encodeFunctionData('startCovRatio'), - decodeFunction: uint256ToBigInt, + callData: this.poolInterface.encodeFunctionData('startCovRatio'), }); - params.push({ + // endCovRatio + multiCallInputs.push({ target: this.poolAddress, - callData: WombatPool.poolInterface.encodeFunctionData('endCovRatio'), - decodeFunction: uint256ToBigInt, + callData: this.poolInterface.encodeFunctionData('endCovRatio'), }); - params.push({ + // tokens + multiCallInputs.push({ target: this.poolAddress, - callData: WombatPool.poolInterface.encodeFunctionData('getTokens'), - decodeFunction: addressArrayDecode, + callData: this.poolInterface.encodeFunctionData('getTokens'), }); - this.asset2TokenMap.forEach((token, asset) => { - params.push({ - target: this.poolAddress, - callData: WombatPool.poolInterface.encodeFunctionData('isPaused', [ - token, - ]), - decodeFunction: booleanDecode, - }); - params.push({ - target: asset, - callData: WombatPool.assetInterface.encodeFunctionData('cash'), - decodeFunction: uint120ToBigInt, - }); - params.push({ - target: asset, - callData: WombatPool.assetInterface.encodeFunctionData('liability'), - decodeFunction: uint120ToBigInt, - }); - params.push({ - target: asset, - callData: WombatPool.assetInterface.encodeFunctionData( - 'underlyingTokenDecimals', - ), - decodeFunction: uint8ToNumber, - }); - params.push({ - target: asset, - callData: - WombatPool.assetInterface.encodeFunctionData('getRelativePrice'), - decodeFunction: uint256ToBigInt, - }); - }); - - return params; - } - - protected _parseStateFromMultiResults( - multiOutputs: MulticallResultOutputs[], - ): PoolState { - const [ - paused, - ampFactor, - haircutRate, - startCovRatio, - endCovRatio, - tokens, - ...remained - ] = multiOutputs as [ - boolean, - bigint, - bigint, - bigint, - bigint, - Address[], - ...MulticallResultOutputs[], - ]; + // 1.B. invoke multicall + let returnData: MultiCallOutput[] = []; + if (multiCallInputs.length) { + returnData = ( + await this.dexHelper.multiContract.methods + .aggregate(multiCallInputs) + .call({}, blockNumber) + ).returnData; + } - const assetTokenArray = Array.from(this.asset2TokenMap.entries()); - const token2AssetStates = new Map(); - _.chunk(remained, 5).forEach((chunk, i) => { - const [paused, cash, liability, underlyingTokenDecimals, relativePrice] = - chunk as [boolean, bigint, bigint, number, bigint | undefined]; + let i = 0; + // 1.C. decode pool params + const paused = Boolean( + this.poolInterface.decodeFunctionResult('paused', returnData[i++])[0], + ); + const ampFactor = BigInt( + this.poolInterface.decodeFunctionResult('ampFactor', returnData[i++])[0], + ); + const haircutRate = BigInt( + this.poolInterface.decodeFunctionResult( + 'haircutRate', + returnData[i++], + )[0], + ); + const startCovRatio = BigInt( + this.poolInterface.decodeFunctionResult( + 'startCovRatio', + returnData[i++], + )[0], + ); + const endCovRatio = BigInt( + this.poolInterface.decodeFunctionResult( + 'endCovRatio', + returnData[i++], + )[0], + ); - const [asset, token] = assetTokenArray[i]; - token2AssetStates.set(token, { - address: asset, - paused, - cash, - liability, - underlyingTokenDecimals, - relativePrice, - }); - }); + const tokens = this.poolInterface + .decodeFunctionResult('getTokens', returnData[i++])[0] + .map((tokenAddress: Address) => tokenAddress.toLowerCase()); const poolState: PoolState = { params: { @@ -160,77 +258,420 @@ export class WombatPool extends StatefulRpcPoller< asset: {}, }; + // 2.A. generate requests for getting asset addresses + multiCallInputs = tokens.map((tokenAddress: Address) => ({ + target: this.poolAddress, + callData: this.poolInterface.encodeFunctionData('addressOfAsset', [ + tokenAddress, + ]), + })); + + // 2.B. invoke multicall + returnData = ( + await this.dexHelper.multiContract.methods + .aggregate(multiCallInputs) + .call({}, blockNumber) + ).returnData; + + // 2.C. decode asset addresses + const assets: Address[] = returnData.map(data => { + return this.poolInterface.decodeFunctionResult('addressOfAsset', data)[0]; + }); + + // 3. get asset states + const assetState = await this.getAssetState( + this.poolAddress, + assets.map(asset => asset.toLowerCase()), + tokens, + blockNumber, + ); const isMainPool = - Array.from(token2AssetStates.values()).filter( - assetState => assetState.relativePrice === undefined, - ).length > 0; - for (const token of poolState.underlyingAddresses) { - if (!token2AssetStates.has(token)) { - // this happens when asset has been added to pool but is not added to BMW yet - continue; - } - poolState.asset[token] = token2AssetStates.get(token)!; + assetState.filter(asset => asset.relativePrice === undefined).length > 0; + for (let j = 0; j < tokens.length; j++) { if (isMainPool) { - poolState.asset[token].relativePrice = undefined; + assetState[j].relativePrice = undefined; } + poolState.asset[tokens[j]] = assetState[j]; } return poolState; } - public async fetchLatestStateFromRpc(): Promise | null> { - const multiCalls = this.getFetchStateWithBlockInfoMultiCalls(); - try { - const lastUpdatedAtMs = Date.now(); - const aggregatedResults = (await this.dexHelper.multiWrapper.tryAggregate< - number | MulticallResultOutputs - >( - false, - multiCalls as MultiCallParams[], - undefined, - undefined, - // multiCalls includes calls asset.isPaused, asset.getRelativePrice - // some of the contracts don't have these methods, so prevent logging errors - false, - )) as [MultiResult, ...MultiResult[]]; - - return this.parseStateFromMultiResultsWithBlockInfo( - aggregatedResults, - lastUpdatedAtMs, + handleSwap( + event: any, + state: DeepReadonly, + log: Readonly, + ): AsyncOrSync | null> { + const fromTokenAddress = event.args.fromToken.toString().toLowerCase(); + const fromAmount = BigInt(event.args.fromAmount.toString()); + const toTokenAddress = event.args.toToken.toString().toLowerCase(); + const toAmount = BigInt(event.args.toAmount.toString()); + + if ( + !state.underlyingAddresses.includes(fromTokenAddress) || + !state.underlyingAddresses.includes(toTokenAddress) + ) { + return null; + } + + let idealToAmount; + const fromAmountInt256 = convertUint256ToInt256(fromAmount); + if (fromAmountInt256 > 0) { + idealToAmount = wdiv(toAmount, WAD - state.params.haircutRate); + } else { + this.logger.warn( + `pool ${this.poolAddress} swap from a negative amount ${fromAmountInt256} at block ${log.blockNumber} should not happen`, ); - } catch (e) { - this._logMessageWithSuppression('ERROR_FETCHING_STATE_FROM_RPC', e); + const haircut = wmul(-fromAmount, state.params.haircutRate); + idealToAmount = toAmount + haircut; } - return null; + const fromAmountInWad = toWad( + fromAmount, + BigInt(state.asset[fromTokenAddress].underlyingTokenDecimals), + ); + const toAmountInWad = toWad( + idealToAmount, + BigInt(state.asset[toTokenAddress].underlyingTokenDecimals), + ); + + return { + ...state, + asset: { + ...state.asset, + [fromTokenAddress]: { + ...state.asset[fromTokenAddress], + cash: state.asset[fromTokenAddress].cash + fromAmountInWad, + }, + [toTokenAddress]: { + ...state.asset[toTokenAddress], + cash: state.asset[toTokenAddress].cash - toAmountInWad, + }, + }, + }; } - public parseStateFromMultiResultsWithBlockInfo( - multiOutputs: [ - MultiResult, - ...MultiResult[], - ], - lastUpdatedAtMs: number, - ): ObjWithUpdateInfo { - const [blockNumber, ...outputsForAbstract] = multiOutputs.map((m, i) => { - return m.returnData; - }) as [number, ...MulticallResultOutputs[]]; + handleSwapV2( + event: any, + state: DeepReadonly, + _log: Readonly, + ): AsyncOrSync | null> { + const fromTokenAddress = event.args.fromToken.toString().toLowerCase(); + const fromAmount = BigInt(event.args.fromAmount.toString()); + const toTokenAddress = event.args.toToken.toString().toLowerCase(); + const toAmount = BigInt(event.args.toAmount.toString()); + const toTokenFee = BigInt(event.args.toTokenFee.toString()); + + if ( + !state.underlyingAddresses.includes(fromTokenAddress) || + !state.underlyingAddresses.includes(toTokenAddress) + ) { + return null; + } + + const fromAmountInWad = toWad( + fromAmount, + BigInt(state.asset[fromTokenAddress].underlyingTokenDecimals), + ); + const toAmountInWad = toWad( + toAmount + toTokenFee, + BigInt(state.asset[toTokenAddress].underlyingTokenDecimals), + ); return { - value: this._parseStateFromMultiResults(outputsForAbstract), - blockNumber, - lastUpdatedAtMs, + ...state, + asset: { + ...state.asset, + [fromTokenAddress]: { + ...state.asset[fromTokenAddress], + cash: state.asset[fromTokenAddress].cash + fromAmountInWad, + }, + [toTokenAddress]: { + ...state.asset[toTokenAddress], + cash: state.asset[toTokenAddress].cash - toAmountInWad, + }, + }, + }; + } + + handleSetAmpFactor( + event: any, + state: DeepReadonly, + _log: Readonly, + ): AsyncOrSync | null> { + const ampFactor = BigInt(event.args.value.toString()); + + return { + ...state, + params: { + ...state.params, + ampFactor, + }, + }; + } + + handleSetHaircutRate( + event: any, + state: DeepReadonly, + _log: Readonly, + ): AsyncOrSync | null> { + const haircutRate = BigInt(event.args.value.toString()); + + return { + ...state, + params: { + ...state.params, + haircutRate, + }, + }; + } + + async handleAssetAdded( + event: any, + state: DeepReadonly, + log: Readonly, + ): Promise | null> { + const token: Address = event.args.token.toString().toLowerCase(); + const asset: Address = event.args.asset.toString().toLowerCase(); + if (state.underlyingAddresses.includes(token)) { + return null; + } + + const assetState = await this.getAssetState( + this.poolAddress, + [asset], + [token], + log.blockNumber, + ); + const poolState = { + ...state, + underlyingAddresses: [...state.underlyingAddresses, token], + asset: { + ...state.asset, + [token]: assetState[0], + }, + }; + + const isMainPool = + Object.values(poolState.asset).filter( + asset => asset.relativePrice === undefined, + ).length > 0; + if (isMainPool) { + for (const underlyingAddress of poolState.underlyingAddresses) { + poolState.asset[underlyingAddress] = { + ...poolState.asset[underlyingAddress], + relativePrice: undefined, + }; + } + } + return poolState; + } + + async handleAssetRemoved( + event: any, + state: DeepReadonly, + _log: Readonly, + ): Promise | null> { + const token = event.args.token.toString().toLowerCase(); + if (!state.underlyingAddresses.includes(token)) { + return null; + } + + return { + ...state, + underlyingAddresses: state.underlyingAddresses.filter( + underlyingAddress => underlyingAddress !== token, + ), + asset: { + ...state.asset, + [token]: undefined, + }, + }; + } + + async handleFillPool( + event: any, + state: DeepReadonly, + _log: Readonly, + ): Promise | null> { + const token = event.args.token.toString().toLowerCase(); + const amount = BigInt(event.args.amount.toString()); + if (!state.underlyingAddresses.includes(token)) { + return null; + } + + return { + ...state, + asset: { + ...state.asset, + [token]: { + ...state.asset[token], + cash: state.asset[token].cash + amount, + }, + }, + }; + } + + async handlePaused( + event: any, + state: DeepReadonly, + _log: Readonly, + ): Promise | null> { + return { + ...state, + params: { + ...state.params, + paused: true, + }, + }; + } + + async handleUnpaused( + event: any, + state: DeepReadonly, + _log: Readonly, + ): Promise | null> { + return { + ...state, + params: { + ...state.params, + paused: false, + }, + }; + } + + async handlePausedAsset( + event: any, + state: DeepReadonly, + _log: Readonly, + ): Promise | null> { + const token = event.args.token.toString(); + if (!state.underlyingAddresses.includes(token)) { + return null; + } + + return { + ...state, + asset: { + ...state.asset, + [token]: { + ...state.asset[token], + paused: true, + }, + }, + }; + } + + async handleUnpausedAsset( + event: any, + state: DeepReadonly, + _log: Readonly, + ): Promise | null> { + const token = event.args.token.toString(); + if (!state.underlyingAddresses.includes(token)) { + return null; + } + + return { + ...state, + asset: { + ...state.asset, + [token]: { + ...state.asset[token], + paused: true, + }, + }, }; } - public addAssets(asset2TokenMap: Map) { - for (const [asset, token] of asset2TokenMap) { - if (this.asset2TokenMap.has(asset)) { - continue; + private async getAssetState( + pool: Address, + assets: Address[], + tokens: Address[], + blockNumber: number, + ): Promise { + const assetStates: AssetState[] = []; + const multiCallInputs: MultiCallInput[] = []; + + const methods = [ + 'cash', + 'liability', + 'underlyingTokenDecimals', + 'getRelativePrice', + ]; + + for (let i = 0; i < assets.length; i++) { + const asset = assets[i]; + const token = tokens[i]; + + multiCallInputs.push({ + target: pool, + callData: this.poolInterface.encodeFunctionData('isPaused', [token]), + }); + + for (const method of methods) { + multiCallInputs.push({ + target: asset, + callData: WombatPool.assetInterface.encodeFunctionData(method), + }); + } + } + + const returnData = await this.dexHelper.multiContract.methods + .tryAggregate(false, multiCallInputs) + .call({}, blockNumber); + + for ( + let i = 0; + i < assets.length * (methods.length + 1); + i += methods.length + 1 + ) { + const paused = returnData[i].success + ? Boolean( + this.poolInterface.decodeFunctionResult( + 'isPaused', + returnData[i].returnData, + )[0], + ) + : false; + const cash = BigInt( + WombatPool.assetInterface.decodeFunctionResult( + methods[0], + returnData[i + 1].returnData, + )[0], + ); + const liability = BigInt( + WombatPool.assetInterface.decodeFunctionResult( + methods[1], + returnData[i + 2].returnData, + )[0], + ); + const underlyingTokenDecimals = + WombatPool.assetInterface.decodeFunctionResult( + methods[2], + returnData[i + 3].returnData, + )[0]; + + let relativePrice: bigint | undefined; + if (returnData[i + 4].success) { + relativePrice = BigInt( + WombatPool.assetInterface.decodeFunctionResult( + methods[3], + returnData[i + 4].returnData, + )[0], + ); } - this.asset2TokenMap.set(asset, token); - this._cachedMultiCallData = undefined; + assetStates.push({ + address: assets[i / (methods.length + 1)], + paused, + cash, + liability, + underlyingTokenDecimals, + relativePrice, + }); } + + return assetStates; } } diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 17fabc2fe..42c70baad 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -14,7 +14,7 @@ import { } from '../../types'; import { Network } from '../../constants'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { getBigIntPow, getDexKeysWithNetwork, isETHAddress } from '../../utils'; +import { getBigIntPow, getDexKeysWithNetwork } from '../../utils'; import { IDex } from '../idex'; import { IDexHelper } from '../../dex-helper'; import { DexParams, PoolState, WombatData } from './types'; @@ -23,7 +23,7 @@ import { SimpleExchange, } from '../simple-exchange'; import { Adapters, WombatConfig } from './config'; -import PoolABI from '../../abi/wombat/pool.json'; +import PoolABI from '../../abi/wombat/pool-v2.json'; import AssetABI from '../../abi/wombat/asset.json'; import ERC20ABI from '../../abi/erc20.json'; import { WombatQuoter } from './wombat-quoter'; @@ -98,23 +98,17 @@ export class Wombat extends SimpleExchange implements IDex { } } - onAssetAdded = async ( - pool: Address, - asset2TokenMap: Map, - blockNumber: number, - ): Promise => { + onAssetAdded = async (pool: Address, blockNumber: number): Promise => { if (!this.pools[pool]) { this.pools[pool] = new WombatPool( this.dexKey, this.getPoolIdentifier(pool), + this.network, this.dexHelper, + this.logger, pool, - asset2TokenMap, ); - await this.pools[pool].getState('latest', true); - this.pollingManager.initializeAllPendingPools(); - } else { - this.pools[pool].addAssets(asset2TokenMap); + await this.pools[pool].initialize(blockNumber); } }; @@ -135,7 +129,6 @@ export class Wombat extends SimpleExchange implements IDex { blockNumber: number, ): Promise { if (side === SwapSide.BUY) return []; - await this.updatePoolState(); return ( await this.findPools( this.dexHelper.config.wrapETH(srcToken).address.toLowerCase(), @@ -195,7 +188,7 @@ export class Wombat extends SimpleExchange implements IDex { destTokenAddress, [getBigIntPow(srcToken.decimals), ...amounts], side, - state.value, + state, ); promises.push({ prices, @@ -240,15 +233,14 @@ export class Wombat extends SimpleExchange implements IDex { ): Promise { const pools: Address[] = []; for (const [poolAddress, pool] of Object.entries(this.pools)) { - let stateOj = await pool.getState(blockNumber); - if (!stateOj) { + const state = await pool.getState(blockNumber); + if (!state) { this.logger.warn( `State of pool ${poolAddress} is null in findPools, skipping...`, ); continue; } - const state = stateOj.value; if ( state && !state.params.paused && @@ -340,10 +332,10 @@ export class Wombat extends SimpleExchange implements IDex { const usdPromises = []; const poolStates: { [poolAddress: string]: DeepReadonly } = {}; const poolStateObjs = await Promise.all( - Object.values(this.pools).map(pool => pool.getState()), + Object.values(this.pools).map(pool => pool.getState(blockNumber)), ); - for (const [poolAddress, pool] of Object.entries(this.pools)) { + for (const [poolAddress, _] of Object.entries(this.pools)) { const index = Object.keys(this.pools).indexOf(poolAddress); let state = poolStateObjs[index]; if (!state) { @@ -352,10 +344,8 @@ export class Wombat extends SimpleExchange implements IDex { ); continue; } - poolStates[poolAddress] = state.value; - for (const [tokenAddress, assetState] of Object.entries( - state.value.asset, - )) { + poolStates[poolAddress] = state; + for (const [tokenAddress, assetState] of Object.entries(state.asset)) { usdPromises.push( this.dexHelper.getTokenUSDPrice( { diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index b4105fdd8..439068ef0 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -73,6 +73,10 @@ export const Tokens: { address: '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0', decimals: 18, }, + frxETH: { + address: '0x5E8422345238F34275888049021821E8E08CAa1f', + decimals: 18, + }, WETH: { address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', decimals: 18, @@ -936,6 +940,10 @@ export const Tokens: { address: '0x68f180fcCe6836688e9084f035309E29Bf0A2095', decimals: 8, }, + frxETH: { + address: '0x6806411765Af15Bddd26f8f544A34cC40cb9838B', + decimals: 18, + }, }, [Network.ZKEVM]: { ETH: { @@ -1068,6 +1076,7 @@ export const Holders: { MATIC: '0x7073783eee7e9b3e6e4ddac4d7f49dc46044dd9a', POL: '0x57B6Ad484ccdd902C4419424bA648ba6Ed45dc68', SDEX: '0xB0470cF15B22a6A32c49a7C20E3821B944A76058', + frxETH: '0x5964871e0F14564FDDAE54F5ff32f62E423731b1', }, [Network.ROPSTEN]: { ETH: '0x43262A12d8610AA70C15DbaeAC321d51613c9071', @@ -1228,6 +1237,7 @@ export const Holders: { wstETH: '0xf7626459234e9249808a06aa08dc6b67c8e0a2fc', rETH: '0x4c2e69e58b14de9afedfb94319519ce34e087283', WBTC: '0xb9c8f0d3254007ee4b98970b94544e473cd610ec', + frxETH: '0x4d4edf8291d169f975b99914b6ab3326abb45938', }, [Network.ZKEVM]: { ETH: '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9', @@ -1242,7 +1252,7 @@ export const Holders: { ETH: '0xdd9176ea3e7559d6b68b537ef555d3e89403f742', MAV: '0x7499785aa5d1bdf0a0ac862c1ef3698d3cba6568', USDC: '0xaac391f166f33cdaefaa4afa6616a3bea66b694d', - USDbC: '0xc68a33de9ceac7bdaed242ae1dc40d673ed4f643', + USDbC: '0xcc46564eb2063b60cd457da49d09dca9544dfeae', DAI: '0x20f03e26968b179025f65c1f4afadfd3959c8d03', BAL: '0x854b004700885a61107b458f11ecc169a019b764', GOLD: '0x1374c25b3710758c326ee0c70ec48b595d5ccf8c', From bee98063e59db6faa82a0debf5ad481d172be51a Mon Sep 17 00:00:00 2001 From: Danylo Kanievskyi Date: Sun, 24 Dec 2023 15:49:03 +0200 Subject: [PATCH 777/833] camelot: add pool discovery tests --- .../camelot/camelot-pool-discovery.test.ts | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 src/dex/camelot/camelot-pool-discovery.test.ts diff --git a/src/dex/camelot/camelot-pool-discovery.test.ts b/src/dex/camelot/camelot-pool-discovery.test.ts new file mode 100644 index 000000000..ee09eef11 --- /dev/null +++ b/src/dex/camelot/camelot-pool-discovery.test.ts @@ -0,0 +1,149 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { Network, SwapSide } from '../../constants'; +import { DummyDexHelper } from '../../dex-helper'; +import { BlockHeader } from 'web3-eth'; +import { Camelot } from './camelot'; +import { CamelotConfig } from './config'; +import { Log } from 'web3-core'; + +const network = Network.ARBITRUM; +const dexKey = 'Camelot'; + +interface Pool { + startBlockNumber: number; + endBlockNumber: number; + address: string; + srcToken: { address: string; decimals: number }; + destToken: { address: string; decimals: number }; +} + +const factoryAddress = CamelotConfig[dexKey][network].factoryAddress; +const blockHeaders: Record = {}; + +const pools: Pool[] = [ + { + address: '0x19d51dc52e52407656b40b197b1bbe14294b955b', + startBlockNumber: 162099096, + endBlockNumber: 162099098, + srcToken: { + address: `0x82aF49447D8a07e3bd95BD0d56f35241523fBab1`, + decimals: 18, + }, + destToken: { + address: '0x939727d85D99d0aC339bF1B76DfE30Ca27C19067', + decimals: 18, + }, + }, + { + address: '0x8b5c25d5f9be67dc6243e2fafcb36ec10ba54aa2', + startBlockNumber: 163124111, + endBlockNumber: 163124113, + srcToken: { + address: `0x82aF49447D8a07e3bd95BD0d56f35241523fBab1`, + decimals: 18, + }, + destToken: { + address: '0x38CC4c71425e9aB6B0A6Ec4240121598efE08398', + decimals: 18, + }, + }, +]; + +function groupAndSortLogsByBlockNumber(logsToDispatch: any[]): { + logsByBlockNumber: Record; + sortedBlocks: number[]; +} { + const logsByBlockNumber: Record = {}; + for (let log of logsToDispatch) { + if (!logsByBlockNumber[log.blockNumber]) { + logsByBlockNumber[log.blockNumber] = []; + } + logsByBlockNumber[log.blockNumber].push(log); + } + + const sortedBlocks = Object.keys(logsByBlockNumber) + .map(Number) + .sort((a, b) => Number(a) - Number(b)); + + return { logsByBlockNumber, sortedBlocks }; +} + +async function testPoolDiscovery(pool: Pool) { + const { startBlockNumber, endBlockNumber, srcToken, destToken, address } = + pool; + describe(`${address}: from ${startBlockNumber} to ${endBlockNumber}`, () => { + const dexHelper = new DummyDexHelper(network); + const camelot = new Camelot(network, dexKey, dexHelper); + + let logsByBlockNumber: Record = {}; + let sortedBlocks: number[] = []; + + it('should have pair created event', async () => { + const logsToDispatch = await dexHelper.provider.getLogs({ + fromBlock: startBlockNumber, + toBlock: endBlockNumber, + address: factoryAddress, + }); + + expect(logsToDispatch.length).toBe(1); + + const groupedLogs = groupAndSortLogsByBlockNumber(logsToDispatch); + logsByBlockNumber = groupedLogs.logsByBlockNumber; + sortedBlocks = groupedLogs.sortedBlocks; + }); + + it('prices before pool discovery should be empty', async () => { + // override default block to force camelot.factory.call() use block before pool was created + camelot.factory.defaultBlock = startBlockNumber; + const pricesBeforePoolDiscovery = await camelot.getPricesVolume( + srcToken, + destToken, + [10000000000000000000n, 10000000000000000000n], + SwapSide.SELL, + startBlockNumber, + ); + + // prices before pool created should not be available + expect(pricesBeforePoolDiscovery).toBe(null); + }); + + it('prices after pool discovery should not be empty', async () => { + // @ts-ignore + // initialize factory state + await camelot.factoryInst?.initialize(startBlockNumber); + + for (let blockNumber of sortedBlocks) { + if (!blockHeaders[blockNumber]) { + blockHeaders[blockNumber] = await dexHelper.web3Provider.eth.getBlock( + blockNumber, + ); + } + + // override default block to force camelot.factory.call() use specific block + camelot.factory.defaultBlock = blockNumber; + + // @ts-ignore + // emit PairCreated event for factory + await camelot.factoryInst?.update(logsByBlockNumber[blockNumber], { + [blockNumber]: blockHeaders[blockNumber], + }); + } + + const pricesAfterPoolDiscovery = await camelot.getPricesVolume( + srcToken, + destToken, + [10000000000000000000n, 10000000000000000000n], + SwapSide.SELL, + endBlockNumber, + ); + + expect(pricesAfterPoolDiscovery).not.toBe(null); + }); + }); +} + +describe(`Test ${dexKey} pool discovery`, () => { + pools.forEach(pool => testPoolDiscovery(pool)); +}); From 3475bc56892b2922fba0489bc6bf2b0516fd8b5b Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 27 Dec 2023 11:18:46 +0200 Subject: [PATCH 778/833] fix: generateState from all instances on certain events --- src/dex/wombat/wombat-pool.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/dex/wombat/wombat-pool.ts b/src/dex/wombat/wombat-pool.ts index 12b876546..c33eb4d85 100644 --- a/src/dex/wombat/wombat-pool.ts +++ b/src/dex/wombat/wombat-pool.ts @@ -112,10 +112,7 @@ export class WombatPool extends StatefulEventSubscriber { const event = this.poolInterface.parseLog(log); if (this.eventRefetched.includes(event.name)) { // if the state is refetched, no need to deal with the left logs in the block - if (!this.dexHelper.config.isSlave) { - return await this.generateState(log.blockNumber); - } - return null; + return await this.generateState(log.blockNumber); } } catch (e) { catchParseLogError(e, this.logger); From eb4f7f8b9606fbf50e27b72ad11d5bf034b91dfb Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 27 Dec 2023 11:56:27 +0200 Subject: [PATCH 779/833] fix: minor --- src/dex/wombat/wombat-pool.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/wombat/wombat-pool.ts b/src/dex/wombat/wombat-pool.ts index c33eb4d85..369b14ae5 100644 --- a/src/dex/wombat/wombat-pool.ts +++ b/src/dex/wombat/wombat-pool.ts @@ -56,8 +56,8 @@ export class WombatPool extends StatefulEventSubscriber { protected poolAddress: Address, ) { super( - `${dexKey}-${name}`, - `${dexKey}-${network}-${name}`, + `${dexKey}_${name}`, + `${dexKey}_${network}_${name}`, dexHelper, logger, ); From c92c097877296a1c1324775ccf37858081422cd3 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 27 Dec 2023 11:58:35 +0200 Subject: [PATCH 780/833] 2.42.29-wombat --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ac406f6d6..e9df4f1d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.29", + "version": "2.42.29-wombat", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 2bf6eeece4b6b8974d3ad4aa83e79156b84e06e4 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 28 Dec 2023 20:06:01 +0200 Subject: [PATCH 781/833] fix: implement throttling --- src/dex/wombat/types.ts | 5 +++++ src/dex/wombat/wombat-events.test.ts | 33 ---------------------------- src/dex/wombat/wombat-pool.ts | 15 +++++++++++-- tests/constants-e2e.ts | 2 +- 4 files changed, 19 insertions(+), 36 deletions(-) diff --git a/src/dex/wombat/types.ts b/src/dex/wombat/types.ts index 3bac57e66..b384eb536 100644 --- a/src/dex/wombat/types.ts +++ b/src/dex/wombat/types.ts @@ -1,3 +1,4 @@ +import { DeepReadonly } from 'ts-essentials'; import { Address } from '../../types'; // State-related types @@ -16,6 +17,10 @@ export type PoolState = { asset: { [underlyingAddress: string]: AssetState }; }; +export type StateGenerator = ( + blockNumber: number, +) => Promise>; + export type AssetState = { address: Address; paused: boolean; diff --git a/src/dex/wombat/wombat-events.test.ts b/src/dex/wombat/wombat-events.test.ts index 7a50bafc5..720f0cd0a 100644 --- a/src/dex/wombat/wombat-events.test.ts +++ b/src/dex/wombat/wombat-events.test.ts @@ -12,40 +12,7 @@ import { WombatConfig } from './config'; import { Wombat } from './wombat'; import { WombatBmw } from './wombat-bmw'; import { testEventSubscriber } from '../../../tests/utils-events'; -/* - README - ====== - This test script adds unit tests for Wombat event based - system. This is done by fetching the state on-chain before the - event block, manually pushing the block logs to the event-subscriber, - comparing the local state with on-chain state. - - Most of the logic for testing is abstracted by `testEventSubscriber`. - You need to do two things to make the tests work: - - 1. Fetch the block numbers where certain events were released. You - can modify the `./scripts/fetch-event-blocknumber.ts` to get the - block numbers for different events. Make sure to get sufficient - number of blockNumbers to cover all possible cases for the event - mutations. - - 2. Complete the implementation for fetchPoolState function. The - function should fetch the on-chain state of the event subscriber - using just the blocknumber. - - The template tests only include the test for a single event - subscriber. There can be cases where multiple event subscribers - exist for a single DEX. In such cases additional tests should be - added. - - You can run this individual test script by running: - `npx jest src/dex//-events.test.ts` - - (This comment should be removed from the final implementation) -*/ - -// npx jest src/dex/wombat/wombat-events.test.ts jest.setTimeout(100 * 1000); async function fetchPoolState( diff --git a/src/dex/wombat/wombat-pool.ts b/src/dex/wombat/wombat-pool.ts index 369b14ae5..cc325dd21 100644 --- a/src/dex/wombat/wombat-pool.ts +++ b/src/dex/wombat/wombat-pool.ts @@ -1,3 +1,4 @@ +import _ from 'lodash'; import { Interface } from '@ethersproject/abi'; import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; import { @@ -18,7 +19,10 @@ import PoolV3ABI from '../../abi/wombat/pool-v3.json'; import AssetABI from '../../abi/wombat/asset.json'; import { convertUint256ToInt256, toWad, WAD, wdiv, wmul } from './utils'; import { BlockHeader } from 'web3-eth'; -import { AssetState, PoolState } from './types'; +import { AssetState, PoolState, StateGenerator } from './types'; + +const GENERATE_STATE_THROTTLE = 1000 * 60 * 5; // 5 minutes +// const GENERATE_STATE_THROTTLE = 100; export class WombatPool extends StatefulEventSubscriber { static readonly poolV2Interface = new Interface(PoolV2ABI); @@ -35,6 +39,8 @@ export class WombatPool extends StatefulEventSubscriber { private poolInterface: Interface = WombatPool.poolV2Interface; private eventRefetched: string[]; + generateState: StateGenerator; + blankState: PoolState = { asset: {}, underlyingAddresses: [], @@ -80,6 +86,11 @@ export class WombatPool extends StatefulEventSubscriber { this.handlers['UnpausedAsset'] = this.handleUnpausedAsset.bind(this); this.eventRefetched = ['Deposit', 'Withdraw']; + + this.generateState = _.throttle( + this._generateState.bind(this), + GENERATE_STATE_THROTTLE, + ) as StateGenerator; } async initialize( @@ -167,7 +178,7 @@ export class WombatPool extends StatefulEventSubscriber { * should be generated * @returns state of the event subscriber at blocknumber */ - async generateState(blockNumber: number): Promise> { + async _generateState(blockNumber: number): Promise> { let multiCallInputs: MultiCallInput[] = []; // 1.A generate pool params requests diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 439068ef0..706cc50ba 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1076,7 +1076,7 @@ export const Holders: { MATIC: '0x7073783eee7e9b3e6e4ddac4d7f49dc46044dd9a', POL: '0x57B6Ad484ccdd902C4419424bA648ba6Ed45dc68', SDEX: '0xB0470cF15B22a6A32c49a7C20E3821B944A76058', - frxETH: '0x5964871e0F14564FDDAE54F5ff32f62E423731b1', + frxETH: '0x62aABd981fC0B1538e16FFB3D47ADa4feDa9e585', }, [Network.ROPSTEN]: { ETH: '0x43262A12d8610AA70C15DbaeAC321d51613c9071', From eb9e8d6ba0f21f94f9e1e7a01194c035034d4c16 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 28 Dec 2023 20:29:05 +0200 Subject: [PATCH 782/833] 2.42.29-wombat.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e9df4f1d6..fde314041 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.29-wombat", + "version": "2.42.29-wombat.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 07228de3d077eb021804516443d5201314b73dac Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 28 Dec 2023 22:29:47 +0200 Subject: [PATCH 783/833] fix: cleaning --- src/dex/wombat/wombat-integration.test.ts | 31 ----------------------- 1 file changed, 31 deletions(-) diff --git a/src/dex/wombat/wombat-integration.test.ts b/src/dex/wombat/wombat-integration.test.ts index 624fdd469..fd13aca1f 100644 --- a/src/dex/wombat/wombat-integration.test.ts +++ b/src/dex/wombat/wombat-integration.test.ts @@ -170,20 +170,6 @@ describe('Wombat', function () { 10n * BI_POWS[tokens[srcTokenSymbol].decimals], ]; - // let amountsForBuy = [ - // 0n, - // 1n * BI_POWS[tokens[destTokenSymbol].decimals], - // 2n * BI_POWS[tokens[destTokenSymbol].decimals], - // 3n * BI_POWS[tokens[destTokenSymbol].decimals], - // 4n * BI_POWS[tokens[destTokenSymbol].decimals], - // 5n * BI_POWS[tokens[destTokenSymbol].decimals], - // 6n * BI_POWS[tokens[destTokenSymbol].decimals], - // 7n * BI_POWS[tokens[destTokenSymbol].decimals], - // 8n * BI_POWS[tokens[destTokenSymbol].decimals], - // 9n * BI_POWS[tokens[destTokenSymbol].decimals], - // 10n * BI_POWS[tokens[destTokenSymbol].decimals], - // ]; - beforeAll(async () => { blockNumber = await dexHelper.web3Provider.eth.getBlockNumber(); wombat = new Wombat(network, dexKey, dexHelper); @@ -226,23 +212,6 @@ describe('Wombat', function () { 'quotePotentialSwap', ); }); - - // it('getPoolIdentifiers and getPricesVolume BUY', async function () { - // if (wombat.initializePricing) { - // await wombat.initializePricing(blockNumber); - // } - // await testPricingOnNetwork( - // wombat, - // network, - // dexKey, - // blockNumber, - // srcTokenSymbol, - // destTokenSymbol, - // SwapSide.BUY, - // amountsForBuy, - // 'quotePotentialSwap', - // ); - // }); }); }); }); From cd59f8f938dd174a639a983ae9a7cd291a5d5235 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 28 Dec 2023 23:02:09 +0200 Subject: [PATCH 784/833] fix: cleaning --- src/dex/wombat/wombat-pool.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dex/wombat/wombat-pool.ts b/src/dex/wombat/wombat-pool.ts index cc325dd21..daa804af5 100644 --- a/src/dex/wombat/wombat-pool.ts +++ b/src/dex/wombat/wombat-pool.ts @@ -22,7 +22,6 @@ import { BlockHeader } from 'web3-eth'; import { AssetState, PoolState, StateGenerator } from './types'; const GENERATE_STATE_THROTTLE = 1000 * 60 * 5; // 5 minutes -// const GENERATE_STATE_THROTTLE = 100; export class WombatPool extends StatefulEventSubscriber { static readonly poolV2Interface = new Interface(PoolV2ABI); From 7147011f6e4b0938d405118eb1315d210bbe0deb Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Thu, 28 Dec 2023 23:04:03 +0200 Subject: [PATCH 785/833] fix: cleaning 2 --- src/dex/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dex/index.ts b/src/dex/index.ts index 70ddb0c61..e7c71ebea 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -38,7 +38,6 @@ import { Excalibur } from './uniswap-v2/excalibur'; import { MakerPsm } from './maker-psm/maker-psm'; import { KyberDmm } from './kyberdmm/kyberdmm'; import { Platypus } from './platypus/platypus'; -//import { Wombat } from './wombat/wombat'; import { GMX } from './gmx/gmx'; import { WooFiV2 } from './woo-fi-v2/woo-fi-v2'; import { ParaSwapLimitOrders } from './paraswap-limit-orders/paraswap-limit-orders'; From e43b7be127222e8a63f2f76ca6384a2f378a5cc4 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 2 Jan 2024 20:30:46 +0200 Subject: [PATCH 786/833] fix: add logging for rpc calls --- src/dex/wombat/types.ts | 5 ----- src/dex/wombat/wombat-pool.ts | 29 +++++++++++++++++++---------- tests/constants-e2e.ts | 2 +- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/dex/wombat/types.ts b/src/dex/wombat/types.ts index b384eb536..3bac57e66 100644 --- a/src/dex/wombat/types.ts +++ b/src/dex/wombat/types.ts @@ -1,4 +1,3 @@ -import { DeepReadonly } from 'ts-essentials'; import { Address } from '../../types'; // State-related types @@ -17,10 +16,6 @@ export type PoolState = { asset: { [underlyingAddress: string]: AssetState }; }; -export type StateGenerator = ( - blockNumber: number, -) => Promise>; - export type AssetState = { address: Address; paused: boolean; diff --git a/src/dex/wombat/wombat-pool.ts b/src/dex/wombat/wombat-pool.ts index daa804af5..42dc775ac 100644 --- a/src/dex/wombat/wombat-pool.ts +++ b/src/dex/wombat/wombat-pool.ts @@ -1,4 +1,3 @@ -import _ from 'lodash'; import { Interface } from '@ethersproject/abi'; import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; import { @@ -19,15 +18,17 @@ import PoolV3ABI from '../../abi/wombat/pool-v3.json'; import AssetABI from '../../abi/wombat/asset.json'; import { convertUint256ToInt256, toWad, WAD, wdiv, wmul } from './utils'; import { BlockHeader } from 'web3-eth'; -import { AssetState, PoolState, StateGenerator } from './types'; +import { AssetState, PoolState } from './types'; -const GENERATE_STATE_THROTTLE = 1000 * 60 * 5; // 5 minutes +const CLEAR_RPC_CALL_COUNT_INTERVAL = 1000 * 60 * 5; // 5 minutes export class WombatPool extends StatefulEventSubscriber { static readonly poolV2Interface = new Interface(PoolV2ABI); static readonly poolV3Interface = new Interface(PoolV3ABI); static readonly assetInterface = new Interface(AssetABI); + private rpcCallCount = 0; + private handlers: { [event: string]: ( event: any, @@ -38,8 +39,6 @@ export class WombatPool extends StatefulEventSubscriber { private poolInterface: Interface = WombatPool.poolV2Interface; private eventRefetched: string[]; - generateState: StateGenerator; - blankState: PoolState = { asset: {}, underlyingAddresses: [], @@ -86,10 +85,9 @@ export class WombatPool extends StatefulEventSubscriber { this.eventRefetched = ['Deposit', 'Withdraw']; - this.generateState = _.throttle( - this._generateState.bind(this), - GENERATE_STATE_THROTTLE, - ) as StateGenerator; + setInterval(() => { + this.rpcCallCount = 0; + }, CLEAR_RPC_CALL_COUNT_INTERVAL); } async initialize( @@ -177,7 +175,18 @@ export class WombatPool extends StatefulEventSubscriber { * should be generated * @returns state of the event subscriber at blocknumber */ - async _generateState(blockNumber: number): Promise> { + async generateState(blockNumber: number): Promise> { + this.rpcCallCount++; + + if (this.rpcCallCount > 1) { + this.logger.warn( + `WombatPool generateState excessive RPC call. Name: ${ + this.name + }; pool: ${this.poolAddress}. Called ${ + this.rpcCallCount + 1 + } times during ${CLEAR_RPC_CALL_COUNT_INTERVAL / 1000} s interval`, + ); + } let multiCallInputs: MultiCallInput[] = []; // 1.A generate pool params requests diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 706cc50ba..8352a7e40 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -1076,7 +1076,7 @@ export const Holders: { MATIC: '0x7073783eee7e9b3e6e4ddac4d7f49dc46044dd9a', POL: '0x57B6Ad484ccdd902C4419424bA648ba6Ed45dc68', SDEX: '0xB0470cF15B22a6A32c49a7C20E3821B944A76058', - frxETH: '0x62aABd981fC0B1538e16FFB3D47ADa4feDa9e585', + frxETH: '0x9df2322bdAEC46627100C999E6dDdD27837fec6e', }, [Network.ROPSTEN]: { ETH: '0x43262A12d8610AA70C15DbaeAC321d51613c9071', From 4a098d402ecc54f547b591d2717300e424f709cb Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 2 Jan 2024 20:32:36 +0200 Subject: [PATCH 787/833] 2.42.29-wombat.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fde314041..0f5e6b1d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.29-wombat.2", + "version": "2.42.29-wombat.3", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From c0686fdc9e7b20deb1172e5ddb95f40b4342a78b Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 2 Jan 2024 22:59:08 +0200 Subject: [PATCH 788/833] fix: update logging --- src/dex/wombat/wombat-pool.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/dex/wombat/wombat-pool.ts b/src/dex/wombat/wombat-pool.ts index 42dc775ac..5ab5f91f1 100644 --- a/src/dex/wombat/wombat-pool.ts +++ b/src/dex/wombat/wombat-pool.ts @@ -59,12 +59,7 @@ export class WombatPool extends StatefulEventSubscriber { logger: Logger, protected poolAddress: Address, ) { - super( - `${dexKey}_${name}`, - `${dexKey}_${network}_${name}`, - dexHelper, - logger, - ); + super(dexKey, `${network}_${name}`, dexHelper, logger); this.addressesSubscribed = [this.poolAddress]; @@ -182,9 +177,9 @@ export class WombatPool extends StatefulEventSubscriber { this.logger.warn( `WombatPool generateState excessive RPC call. Name: ${ this.name - }; pool: ${this.poolAddress}. Called ${ - this.rpcCallCount + 1 - } times during ${CLEAR_RPC_CALL_COUNT_INTERVAL / 1000} s interval`, + }. Called ${this.rpcCallCount} times during ${ + CLEAR_RPC_CALL_COUNT_INTERVAL / 1000 + }s interval`, ); } let multiCallInputs: MultiCallInput[] = []; From 9f6c8997a268f9eeb80a5cf36e5005672c11e462 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Tue, 2 Jan 2024 23:00:05 +0200 Subject: [PATCH 789/833] 2.42.29-wombat.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f5e6b1d8..8736603af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.29-wombat.3", + "version": "2.42.29-wombat.4", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 0a47473ad88aa7cc931e3939fe768c8967820256 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 3 Jan 2024 19:12:25 +0200 Subject: [PATCH 790/833] 2.42.31 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b1f04d9d2..8da9359ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.30", + "version": "2.42.31", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 8fcbdf54fb46334daeabefd41e6de5c04e5e0441 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 3 Jan 2024 21:07:06 +0200 Subject: [PATCH 791/833] fix: remove excessive logging --- src/dex/wombat/wombat.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/dex/wombat/wombat.ts b/src/dex/wombat/wombat.ts index 42c70baad..a119b7c21 100644 --- a/src/dex/wombat/wombat.ts +++ b/src/dex/wombat/wombat.ts @@ -235,9 +235,6 @@ export class Wombat extends SimpleExchange implements IDex { for (const [poolAddress, pool] of Object.entries(this.pools)) { const state = await pool.getState(blockNumber); if (!state) { - this.logger.warn( - `State of pool ${poolAddress} is null in findPools, skipping...`, - ); continue; } From 407786212aeaffb569a8d6ec6013f5f3c987422e Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Wed, 3 Jan 2024 21:09:36 +0200 Subject: [PATCH 792/833] 2.42.32 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8da9359ed..136cd5c87 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.31", + "version": "2.42.32", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 4bc1c6736c23d3ebb5b2ec7e70000b445d5b40c8 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 15 Jan 2024 14:53:41 +0100 Subject: [PATCH 793/833] pass taker to rfq apis --- src/dex/generic-rfq/fetch-mm-api.ts | 5 +++++ src/dex/generic-rfq/generic-rfq.ts | 1 + src/dex/generic-rfq/rate-fetcher.ts | 3 +++ src/dex/generic-rfq/types.ts | 1 + src/dex/generic-rfq/utils.ts | 6 ++++++ 5 files changed, 16 insertions(+) diff --git a/src/dex/generic-rfq/fetch-mm-api.ts b/src/dex/generic-rfq/fetch-mm-api.ts index befc145db..1a5e01141 100644 --- a/src/dex/generic-rfq/fetch-mm-api.ts +++ b/src/dex/generic-rfq/fetch-mm-api.ts @@ -31,6 +31,10 @@ import { validateAndCast } from '../../lib/validators'; const network = 1; +const AgustusAddress = { + 1: '0xdef171fe48cf0115b1d80b88dc8eab59176fee57', +}; + const getEnv = (envName: string): string => { if (!process.env[envName]) { throw new Error(`Missing ${envName}`); @@ -269,6 +273,7 @@ const mainFirm = async () => { network, config.multicallV2Address, multiWrapper, + AgustusAddress[network], firmRateResp.order, ); diff --git a/src/dex/generic-rfq/generic-rfq.ts b/src/dex/generic-rfq/generic-rfq.ts index c6c1584b1..2fcbb5771 100644 --- a/src/dex/generic-rfq/generic-rfq.ts +++ b/src/dex/generic-rfq/generic-rfq.ts @@ -209,6 +209,7 @@ export class GenericRFQ extends ParaSwapLimitOrders { ? overOrder(optimalSwapExchange.srcAmount, OVERORDER_BPS) : overOrder(optimalSwapExchange.destAmount, 1), side, + this.augustusAddress, options.txOrigin, options.partner, ); diff --git a/src/dex/generic-rfq/rate-fetcher.ts b/src/dex/generic-rfq/rate-fetcher.ts index f5760c532..57ff5dc4d 100644 --- a/src/dex/generic-rfq/rate-fetcher.ts +++ b/src/dex/generic-rfq/rate-fetcher.ts @@ -375,6 +375,7 @@ export class RateFetcher { _destToken: Token, srcAmount: string, side: SwapSide, + takerAddress: Address, userAddress: Address, partner?: string, ): Promise { @@ -391,6 +392,7 @@ export class RateFetcher { makerAmount: side === SwapSide.BUY ? srcAmount : undefined, takerAmount: side === SwapSide.SELL ? srcAmount : undefined, userAddress, + takerAddress, partner, }; @@ -425,6 +427,7 @@ export class RateFetcher { this.dexHelper.config.data.network, this.dexHelper.config.data.augustusRFQAddress, this.dexHelper.multiWrapper, + takerAddress, firmRateResp.order, this.verifierContract, ); diff --git a/src/dex/generic-rfq/types.ts b/src/dex/generic-rfq/types.ts index dc2d3fcf2..cd7b834b7 100644 --- a/src/dex/generic-rfq/types.ts +++ b/src/dex/generic-rfq/types.ts @@ -84,6 +84,7 @@ export type RFQPayload = { makerAmount?: string; takerAmount?: string; userAddress: Address; + takerAddress: Address; partner?: string; }; diff --git a/src/dex/generic-rfq/utils.ts b/src/dex/generic-rfq/utils.ts index 520097f10..56b4947ad 100644 --- a/src/dex/generic-rfq/utils.ts +++ b/src/dex/generic-rfq/utils.ts @@ -16,9 +16,15 @@ export const checkOrder = async ( network: Network, augustusRFQAddress: Address, multiWrapper: MultiWrapper, + takerAddress: Address, order: AugustusOrderWithStringAndSignature, verifierContract?: ERC1271Contract, ) => { + if (order.taker.toLowerCase() !== takerAddress.toLowerCase()) { + throw new Error( + `Taker mismatch, expected ${takerAddress} but signed order got ${order.taker}`, + ); + } const hash = calculateOrderHash(network, order, augustusRFQAddress); if (verifierContract) { From 76c370e9eb6b294b780414ce32388e3bdf7b2663 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 15 Jan 2024 14:55:31 +0100 Subject: [PATCH 794/833] 2.42.33-back-1411-rfq-dynamic-taker.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 136cd5c87..45d4ea91e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.32", + "version": "2.42.33-back-1411-rfq-dynamic-taker.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 6ee872bda5c323115db472e2b78e608766b404b0 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 15 Jan 2024 19:57:37 +0100 Subject: [PATCH 795/833] rename --- src/dex/generic-rfq/fetch-mm-api.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/generic-rfq/fetch-mm-api.ts b/src/dex/generic-rfq/fetch-mm-api.ts index 1a5e01141..4359a1b32 100644 --- a/src/dex/generic-rfq/fetch-mm-api.ts +++ b/src/dex/generic-rfq/fetch-mm-api.ts @@ -31,7 +31,7 @@ import { validateAndCast } from '../../lib/validators'; const network = 1; -const AgustusAddress = { +const AugustusAddress = { 1: '0xdef171fe48cf0115b1d80b88dc8eab59176fee57', }; @@ -273,7 +273,7 @@ const mainFirm = async () => { network, config.multicallV2Address, multiWrapper, - AgustusAddress[network], + AugustusAddress[network], firmRateResp.order, ); From 6c28cf5a4d0181e4911b2c8d4f24fcbe6374beae Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 15 Jan 2024 19:59:29 +0100 Subject: [PATCH 796/833] generalise naming for allowed taker --- src/dex/generic-rfq/validators.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dex/generic-rfq/validators.ts b/src/dex/generic-rfq/validators.ts index 551c457cc..74ce67a95 100644 --- a/src/dex/generic-rfq/validators.ts +++ b/src/dex/generic-rfq/validators.ts @@ -149,7 +149,7 @@ const stringStartWithHex0x = ( return value; }; -const mustBeAugustusSwapper = ( +const mustBeAllowedTaker = ( value: string, helpers: CustomHelpers, ): string | ErrorReport => { @@ -168,7 +168,7 @@ export const orderWithSignatureValidator = joi nonceAndMeta: joi.string().custom(stringPositiveBigIntValidator), expiry: joi.number().min(0), maker: addressSchema.required(), - taker: addressSchema.required().custom(mustBeAugustusSwapper), + taker: addressSchema.required().custom(mustBeAllowedTaker), makerAsset: addressSchema.required(), takerAsset: addressSchema.required(), makerAmount: joi From fea6dad55e6d39d2592417377ada89f21254a5fb Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 15 Jan 2024 20:02:09 +0100 Subject: [PATCH 797/833] 2.42.33-back-1411-rfq-dynamic-taker.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 45d4ea91e..b27803660 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.33-back-1411-rfq-dynamic-taker.0", + "version": "2.42.33-back-1411-rfq-dynamic-taker.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 26ddfc5c502ca9dc0b485ffdce1e2f005308e00e Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Thu, 18 Jan 2024 17:12:59 +0100 Subject: [PATCH 798/833] 2.43.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b27803660..61b760299 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.42.33-back-1411-rfq-dynamic-taker.1", + "version": "2.43.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From ecae2ab06747c317a9fa28d8b016246a2dd1348e Mon Sep 17 00:00:00 2001 From: Danny Dalton Date: Tue, 12 Dec 2023 15:45:45 +0100 Subject: [PATCH 799/833] add abi for swETH and adapter for Swell --- src/abi/swETH.json | 1086 ++++++++++++++++++++++++++++++++++++++++++++ src/dex/swell.ts | 69 +++ 2 files changed, 1155 insertions(+) create mode 100644 src/abi/swETH.json create mode 100644 src/dex/swell.ts diff --git a/src/abi/swETH.json b/src/abi/swETH.json new file mode 100644 index 000000000..a8e5d31f0 --- /dev/null +++ b/src/abi/swETH.json @@ -0,0 +1,1086 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "AddressAlreadyInWhitelist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "AddressMissingFromWhitelist", + "type": "error" + }, + { + "inputs": [], + "name": "BotMethodsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "CannotBeZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "CannotReferSelf", + "type": "error" + }, + { + "inputs": [], + "name": "CannotRepriceWithZeroSwETHSupply", + "type": "error" + }, + { + "inputs": [], + "name": "CoreMethodsPaused", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidETHDeposit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidMethodCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPreRewardETHReserves", + "type": "error" + }, + { + "inputs": [], + "name": "NoActiveValidators", + "type": "error" + }, + { + "inputs": [], + "name": "NoTokensToWithdraw", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "remainingTime", + "type": "uint256" + } + ], + "name": "NotEnoughTimeElapsedForReprice", + "type": "error" + }, + { + "inputs": [], + "name": "NotInWhitelist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "x", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "y", + "type": "uint256" + } + ], + "name": "PRBMath_MulDiv18_Overflow", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "x", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "y", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "denominator", + "type": "uint256" + } + ], + "name": "PRBMath_MulDiv_Overflow", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "repriceDiff", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximumRepriceDiff", + "type": "uint256" + } + ], + "name": "RepriceDifferenceTooLarge", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "repriceswETHDiff", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximumswETHRepriceDiff", + "type": "uint256" + } + ], + "name": "RepriceswETHDifferenceTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "RewardPercentageTotalOverflow", + "type": "error" + }, + { + "inputs": [], + "name": "WhitelistAlreadyDisabled", + "type": "error" + }, + { + "inputs": [], + "name": "WhitelistAlreadyEnabled", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "AddedToWhitelist", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "swETHMinted", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalETHDeposited", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "referral", + "type": "address" + } + ], + "name": "ETHDepositReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "swETHBurned", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ethReturned", + "type": "uint256" + } + ], + "name": "ETHWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_oldMaximumRepriceDifferencePercentage", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newMaximumRepriceDifferencePercentage", + "type": "uint256" + } + ], + "name": "MaximumRepriceDifferencePercentageUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_oldMaximumRepriceswETHDifferencePercentage", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newMaximumRepriceswETHDifferencePercentage", + "type": "uint256" + } + ], + "name": "MaximumRepriceswETHDifferencePercentageUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_oldMinimumRepriceTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_newMinimumRepriceTime", + "type": "uint256" + } + ], + "name": "MinimumRepriceTimeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldPercentage", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPercentage", + "type": "uint256" + } + ], + "name": "NodeOperatorRewardPercentageUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "RemovedFromWhitelist", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newEthReserves", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSwETHToETHRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nodeOperatorRewards", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "swellTreasuryRewards", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalETHDeposited", + "type": "uint256" + } + ], + "name": "Reprice", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldPercentage", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPercentage", + "type": "uint256" + } + ], + "name": "SwellTreasuryRewardPercentageUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "WhitelistDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "WhitelistEnabled", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [], + "name": "AccessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "addToWhitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_addresses", + "type": "address[]" + } + ], + "name": "batchAddToWhitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_addresses", + "type": "address[]" + } + ], + "name": "batchRemoveFromWhitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "referral", + "type": "address" + } + ], + "name": "depositWithReferral", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "disableWhitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableWhitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "ethToSwETHRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IAccessControlManager", + "name": "_accessControlManager", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastRepriceETHReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRepriceUNIX", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maximumRepriceDifferencePercentage", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maximumRepriceswETHDifferencePercentage", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimumRepriceTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nodeOperatorRewardPercentage", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "removeFromWhitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_preRewardETHReserves", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_newETHRewards", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_swETHTotalSupply", + "type": "uint256" + } + ], + "name": "reprice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maximumRepriceDifferencePercentage", + "type": "uint256" + } + ], + "name": "setMaximumRepriceDifferencePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maximumRepriceswETHDifferencePercentage", + "type": "uint256" + } + ], + "name": "setMaximumRepriceswETHDifferencePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minimumRepriceTime", + "type": "uint256" + } + ], + "name": "setMinimumRepriceTime", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newNodeOperatorRewardPercentage", + "type": "uint256" + } + ], + "name": "setNodeOperatorRewardPercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newSwellTreasuryRewardPercentage", + "type": "uint256" + } + ], + "name": "setSwellTreasuryRewardPercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "swETHToETHRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "swellTreasuryRewardPercentage", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalETHDeposited", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "whitelistEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "whitelistedAddresses", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_token", + "type": "address" + } + ], + "name": "withdrawERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/dex/swell.ts b/src/dex/swell.ts new file mode 100644 index 000000000..cd9dc0a9e --- /dev/null +++ b/src/dex/swell.ts @@ -0,0 +1,69 @@ +import { Interface, JsonFragment } from '@ethersproject/abi'; +import { NumberAsString, SwapSide } from '@paraswap/core'; +import { AdapterExchangeParam, Address, SimpleExchangeParam } from '../types'; +import { IDexTxBuilder } from './idex'; +import SWETH_ABI from '../abi/swETH.json'; +import { NULL_ADDRESS } from '../constants'; +import Web3 from 'web3'; +import { IDexHelper } from '../dex-helper'; + +export const swETH: any = { + 1: '0xf951E335afb289353dc249e82926178EaC7DEd78', +}; + +export enum swETHFunctions { + deposit = 'deposit', +} + +export type SwellData = {}; + +export class Swell implements IDexTxBuilder { + static dexKeys = ['swell']; + swETHInterface: Interface; + + needWrapNative = false; + + private network: number; + + constructor(dexHelper: IDexHelper) { + this.network = dexHelper.config.data.network; + + this.swETHInterface = new Interface(SWETH_ABI as JsonFragment[]); + } + + getAdapterParam( + srcToken: Address, + destToken: Address, + srcAmount: NumberAsString, + destAmount: NumberAsString, + data: SwellData, + side: SwapSide, + ): AdapterExchangeParam { + return { + targetExchange: swETH[this.network], + payload: '0x', + networkFee: '0', + }; + } + + async getSimpleParam( + srcToken: Address, + destToken: Address, + srcAmount: NumberAsString, + destAmount: NumberAsString, + data: SwellData, + side: SwapSide, + ): Promise { + const swapData = this.swETHInterface.encodeFunctionData( + swETHFunctions.deposit, + [NULL_ADDRESS], + ); + + return { + callees: [swETH[this.network]], + calldata: [swapData], + values: [srcAmount], + networkFee: '0', + }; + } +} From 1b9ab207e49bd900760917d08b1ce9bfbcdbef24 Mon Sep 17 00:00:00 2001 From: Yevhen Shulha Date: Mon, 8 Jan 2024 15:31:20 +0200 Subject: [PATCH 800/833] fix: comment import --- src/dex/index.ts | 2 ++ src/dex/{ => swell}/swell.ts | 26 +++++++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) rename src/dex/{ => swell}/swell.ts (71%) diff --git a/src/dex/index.ts b/src/dex/index.ts index e7c71ebea..06ba02fd9 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -83,6 +83,7 @@ import { NomiswapV2 } from './uniswap-v2/nomiswap-v2'; import { Dexalot } from './dexalot/dexalot'; import { Smardex } from './smardex/smardex'; import { Wombat } from './wombat/wombat'; +// import { Swell } from './swell/swell'; const LegacyDexes = [ CurveV2, @@ -163,6 +164,7 @@ const Dexes = [ SolidlyV3, Smardex, Wombat, + // Swell, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< diff --git a/src/dex/swell.ts b/src/dex/swell/swell.ts similarity index 71% rename from src/dex/swell.ts rename to src/dex/swell/swell.ts index cd9dc0a9e..9af6cd6c3 100644 --- a/src/dex/swell.ts +++ b/src/dex/swell/swell.ts @@ -1,11 +1,19 @@ import { Interface, JsonFragment } from '@ethersproject/abi'; import { NumberAsString, SwapSide } from '@paraswap/core'; -import { AdapterExchangeParam, Address, SimpleExchangeParam } from '../types'; -import { IDexTxBuilder } from './idex'; -import SWETH_ABI from '../abi/swETH.json'; -import { NULL_ADDRESS } from '../constants'; +import { + AdapterExchangeParam, + Address, + SimpleExchangeParam, +} from '../../types'; +import { IDexTxBuilder } from '../idex'; +import SWETH_ABI from '../../abi/swETH.json'; +import { NULL_ADDRESS } from '../../constants'; import Web3 from 'web3'; -import { IDexHelper } from '../dex-helper'; +import { IDexHelper } from '../../dex-helper'; +import { SimpleExchange } from '../simple-exchange'; +import { BI_POWS } from '../../bigint-constants'; + +const unitPrice = BI_POWS[18]; export const swETH: any = { 1: '0xf951E335afb289353dc249e82926178EaC7DEd78', @@ -17,15 +25,19 @@ export enum swETHFunctions { export type SwellData = {}; -export class Swell implements IDexTxBuilder { +export class Swell + extends SimpleExchange + implements IDexTxBuilder +{ static dexKeys = ['swell']; swETHInterface: Interface; needWrapNative = false; - private network: number; + network: number; constructor(dexHelper: IDexHelper) { + super(dexHelper, 'swell'); this.network = dexHelper.config.data.network; this.swETHInterface = new Interface(SWETH_ABI as JsonFragment[]); From ea83a30337f9de3112fb4b62b89762e5d537276b Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Thu, 15 Feb 2024 18:41:57 +0100 Subject: [PATCH 801/833] swell: subscribe to reprice event change + implement pricing + swap params encoding --- src/dex/simple-exchange.ts | 9 +- src/dex/swell/config.ts | 14 +++ src/dex/swell/swell.ts | 190 +++++++++++++++++++++++++++++++++--- src/dex/swell/sweth-pool.ts | 58 +++++++++++ src/dex/swell/type.ts | 3 + src/dex/swell/utils.ts | 27 +++++ 6 files changed, 284 insertions(+), 17 deletions(-) create mode 100644 src/dex/swell/config.ts create mode 100644 src/dex/swell/sweth-pool.ts create mode 100644 src/dex/swell/type.ts create mode 100644 src/dex/swell/utils.ts diff --git a/src/dex/simple-exchange.ts b/src/dex/simple-exchange.ts index 4d6909988..282c58a67 100644 --- a/src/dex/simple-exchange.ts +++ b/src/dex/simple-exchange.ts @@ -44,7 +44,7 @@ export class SimpleExchange { readonly cacheStateKey: string; private readonly cacheApprovesKey: string; - constructor(dexHelper: IDexHelper, public dexKey: string) { + constructor(protected readonly dexHelper: IDexHelper, public dexKey: string) { this.simpleSwapHelper = new Interface(SimpleSwapHelperABI); this.erc20Interface = new Interface(ERC20ABI); this.erc20Contract = new dexHelper.web3Provider.eth.Contract( @@ -183,4 +183,11 @@ export class SimpleExchange { networkFee, }; } + + protected isWETH(tokenAddress: string) { + const weth = + this.dexHelper.config.data.wrappedNativeTokenAddress.toLowerCase(); + + return tokenAddress.toLowerCase() === weth; + } } diff --git a/src/dex/swell/config.ts b/src/dex/swell/config.ts new file mode 100644 index 000000000..8e6ef9067 --- /dev/null +++ b/src/dex/swell/config.ts @@ -0,0 +1,14 @@ +import { Network, SwapSide } from '../../constants'; + +export const Adapters: { + [chainId: number]: { [side: string]: { name: string; index: number }[] }; +} = { + [Network.MAINNET]: { + [SwapSide.SELL]: [ + { + name: 'Adapter04', // FIXME + index: 1, + }, + ], + }, +}; diff --git a/src/dex/swell/swell.ts b/src/dex/swell/swell.ts index 9af6cd6c3..4fc56097b 100644 --- a/src/dex/swell/swell.ts +++ b/src/dex/swell/swell.ts @@ -3,17 +3,27 @@ import { NumberAsString, SwapSide } from '@paraswap/core'; import { AdapterExchangeParam, Address, + ExchangePrices, + Logger, + PoolLiquidity, + PoolPrices, SimpleExchangeParam, + Token, + TransferFeeParams, } from '../../types'; -import { IDexTxBuilder } from '../idex'; +import { IDex } from '../idex'; import SWETH_ABI from '../../abi/swETH.json'; -import { NULL_ADDRESS } from '../../constants'; -import Web3 from 'web3'; +import { ETHER_ADDRESS } from '../../constants'; import { IDexHelper } from '../../dex-helper'; import { SimpleExchange } from '../simple-exchange'; import { BI_POWS } from '../../bigint-constants'; - -const unitPrice = BI_POWS[18]; +import { AsyncOrSync } from 'ts-essentials'; +import { getOnChainState } from './utils'; +import { SwethPool } from './sweth-pool'; +import { isETHAddress } from '../../utils'; +import { WethFunctions } from '../weth/types'; +import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; +import { Adapters } from '../jarvis-v6/config'; export const swETH: any = { 1: '0xf951E335afb289353dc249e82926178EaC7DEd78', @@ -24,23 +34,126 @@ export enum swETHFunctions { } export type SwellData = {}; +export type SwellParams = {}; export class Swell extends SimpleExchange - implements IDexTxBuilder + implements IDex { static dexKeys = ['swell']; swETHInterface: Interface; - needWrapNative = false; - + hasConstantPriceLargeAmounts: boolean = true; network: number; + swETHAddress: string; + eventPool: SwethPool; + logger: Logger; - constructor(dexHelper: IDexHelper) { + constructor(protected dexHelper: IDexHelper) { super(dexHelper, 'swell'); - this.network = dexHelper.config.data.network; + this.network = dexHelper.config.data.network; this.swETHInterface = new Interface(SWETH_ABI as JsonFragment[]); + this.swETHAddress = swETH[this.network]; + this.logger = dexHelper.getLogger(this.dexKey); + this.eventPool = new SwethPool( + this.dexKey, + dexHelper, + this.swETHAddress, + this.swETHInterface, + this.logger, + ); + } + + async initializePricing(blockNumber: number) { + const poolState = await getOnChainState( + this.dexHelper.multiContract, + this.swETHAddress, + this.swETHInterface, + blockNumber, + ); + + await this.eventPool.initialize(blockNumber, { + state: poolState, + }); + } + + getPoolIdentifierKey(): string { + return `${ETHER_ADDRESS}_${this.swETHAddress}`.toLowerCase(); + } + + isEligibleSwap( + srcToken: Token | string, + destToken: Token | string, + side: SwapSide, + ): boolean { + if (side === SwapSide.BUY) return false; + + const srcTokenAddress = ( + typeof srcToken === 'string' ? srcToken : srcToken.address + ).toLowerCase(); + const destTokenAddress = ( + typeof destToken === 'string' ? destToken : destToken.address + ).toLowerCase(); + + return ( + (isETHAddress(srcTokenAddress) || this.isWETH(srcTokenAddress)) && + destTokenAddress === this.swETHAddress.toLowerCase() + ); + } + + assertEligibility( + srcToken: Token | string, + destToken: Token | string, + side: SwapSide, + ) { + if (!this.isEligibleSwap(srcToken, destToken, side)) { + throw new Error('Only eth/weth -> swETH swaps are supported'); + } + } + + async getPoolIdentifiers( + srcToken: Token, + destToken: Token, + side: SwapSide, + blockNumber: number, + ): Promise { + return this.isEligibleSwap(srcToken, destToken, side) + ? [this.getPoolIdentifierKey()] + : []; + } + + async getPricesVolume( + srcToken: Token, + destToken: Token, + amountsIn: bigint[], + side: SwapSide, + blockNumber: number, + limitPools?: string[] | undefined, + transferFees?: TransferFeeParams | undefined, + isFirstSwap?: boolean | undefined, + ): Promise | null> { + this.assertEligibility(srcToken, destToken, side); + + if (this.eventPool.getState(blockNumber) === null) return null; + + const unitIn = BI_POWS[18]; + const unitOut = this.eventPool.getPrice(blockNumber, unitIn); + const amountsOut = amountsIn.map(amountIn => + this.eventPool.getPrice(blockNumber, amountIn), + ); + + return [ + { + prices: amountsOut, + unit: unitOut, + data: {}, + exchange: this.dexKey, + poolIdentifier: this.getPoolIdentifierKey(), + gasCost: 120_000, + poolAddresses: [this.swETHAddress], + }, + ]; } getAdapterParam( @@ -51,9 +164,20 @@ export class Swell data: SwellData, side: SwapSide, ): AdapterExchangeParam { + this.assertEligibility(srcToken, destToken, side); + + const payload = this.abiCoder.encodeParameter( + { + ParentStruct: { + shouldWithdraw: 'bool', + }, + }, + { shouldWithdraw: this.isWETH(srcToken) }, + ); + return { - targetExchange: swETH[this.network], - payload: '0x', + targetExchange: this.swETHAddress, + payload, networkFee: '0', }; } @@ -66,16 +190,50 @@ export class Swell data: SwellData, side: SwapSide, ): Promise { + this.assertEligibility(srcToken, destToken, side); + + const callees = []; + const calldata = []; + const values = []; + + if (this.isWETH(srcToken)) { + // note: apparently ERC20 ABI contains wETH fns (deposit() and withdraw()) + const wethUnwrapData = this.erc20Interface.encodeFunctionData( + WethFunctions.withdraw, + [srcAmount], + ); + callees.push(this.dexHelper.config.data.wrappedNativeTokenAddress); + calldata.push(wethUnwrapData); + values.push('0'); + } + const swapData = this.swETHInterface.encodeFunctionData( swETHFunctions.deposit, - [NULL_ADDRESS], + [], ); + callees.push(this.swETHAddress); + calldata.push(swapData); + values.push(srcAmount); + return { - callees: [swETH[this.network]], - calldata: [swapData], - values: [srcAmount], + callees, + calldata, + values, networkFee: '0', }; } + + getCalldataGasCost(poolPrices: PoolPrices): number | number[] { + return CALLDATA_GAS_COST.DEX_OVERHEAD + CALLDATA_GAS_COST.LENGTH_SMALL; + } + getAdapters(side: SwapSide): { name: string; index: number }[] | null { + return Adapters[this.network][side] || null; + } + getTopPoolsForToken( + tokenAddress: string, + limit: number, + ): AsyncOrSync { + return []; + } } diff --git a/src/dex/swell/sweth-pool.ts b/src/dex/swell/sweth-pool.ts new file mode 100644 index 000000000..b708919df --- /dev/null +++ b/src/dex/swell/sweth-pool.ts @@ -0,0 +1,58 @@ +import { Interface } from '@ethersproject/abi'; +import { IDexHelper } from '../../dex-helper'; +import { StatefulEventSubscriber } from '../../stateful-event-subscriber'; +import { Address, Log, Logger } from '../../types'; +import { AsyncOrSync, DeepReadonly } from 'ts-essentials'; +import { SWETHPoolState } from './type'; +import { getOnChainState } from './utils'; +import { BI_POWS } from '../../bigint-constants'; + +export class SwethPool extends StatefulEventSubscriber { + decoder = (log: Log) => this.poolInterface.parseLog(log); + + constructor( + parentName: string, + protected dexHelper: IDexHelper, + private poolAddress: Address, + private poolInterface: Interface, + logger: Logger, + ) { + super(parentName, 'sweth', dexHelper, logger); + this.addressesSubscribed = [poolAddress]; + } + + protected processLog( + state: DeepReadonly, + log: Readonly, + ): AsyncOrSync | null> { + const event = this.decoder(log); + if (event.name === 'Reprice') + return { + swETHToETHRateFixed: BigInt(event.args.newSwETHToETHRate), + }; + + return null; + } + + async generateState( + blockNumber: number | 'latest' = 'latest', + ): Promise> { + const state = await getOnChainState( + this.dexHelper.multiContract, + this.poolAddress, + this.poolInterface, + blockNumber, + ); + + return state; + } + + getPrice(blockNumber: number, ethAmount: bigint): bigint { + const state = this.getState(blockNumber); + if (!state) throw new Error('Cannot compute price'); + const { swETHToETHRateFixed } = state; + + // calculation in contract are made with UD60x18 precision + return (ethAmount * BI_POWS[18]) / swETHToETHRateFixed; + } +} diff --git a/src/dex/swell/type.ts b/src/dex/swell/type.ts new file mode 100644 index 000000000..481ddcd83 --- /dev/null +++ b/src/dex/swell/type.ts @@ -0,0 +1,3 @@ +export type SWETHPoolState = { + swETHToETHRateFixed: bigint; +}; diff --git a/src/dex/swell/utils.ts b/src/dex/swell/utils.ts new file mode 100644 index 000000000..17e5f4ba1 --- /dev/null +++ b/src/dex/swell/utils.ts @@ -0,0 +1,27 @@ +import { Contract } from 'web3-eth-contract'; +import { SWETHPoolState } from './type'; +import { Interface, AbiCoder } from '@ethersproject/abi'; + +const coder = new AbiCoder(); + +export async function getOnChainState( + multiContract: Contract, + poolAddress: string, + poolInterface: Interface, + blockNumber: number | 'latest', +): Promise { + const data: { returnData: any[] } = await multiContract.methods + .aggregate({ + to: poolAddress, + data: poolInterface.encodeFunctionData('swETHToETHRate', []), + }) + .call({}, blockNumber); + + const decodedData = coder.decode(['uint256'], data.returnData); + + const swETHToETHRateFixed = BigInt(decodedData[0].toString()); + + return { + swETHToETHRateFixed, + }; +} From 1d055fe1de7a336e17d1d75291c6ddc3df5ac8bf Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Thu, 15 Feb 2024 19:27:25 +0100 Subject: [PATCH 802/833] swell: reactivate integration - move address to config --- src/dex/index.ts | 4 ++-- src/dex/swell/config.ts | 13 +++++++++++++ src/dex/swell/swell.ts | 36 ++++++++++++++++++++---------------- src/dex/swell/utils.ts | 12 +++++++----- 4 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/dex/index.ts b/src/dex/index.ts index 06ba02fd9..13124d3ab 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -83,7 +83,7 @@ import { NomiswapV2 } from './uniswap-v2/nomiswap-v2'; import { Dexalot } from './dexalot/dexalot'; import { Smardex } from './smardex/smardex'; import { Wombat } from './wombat/wombat'; -// import { Swell } from './swell/swell'; +import { Swell } from './swell/swell'; const LegacyDexes = [ CurveV2, @@ -164,7 +164,7 @@ const Dexes = [ SolidlyV3, Smardex, Wombat, - // Swell, + Swell, ]; export type LegacyDexConstructor = new (dexHelper: IDexHelper) => IDexTxBuilder< diff --git a/src/dex/swell/config.ts b/src/dex/swell/config.ts index 8e6ef9067..a3ba291f8 100644 --- a/src/dex/swell/config.ts +++ b/src/dex/swell/config.ts @@ -1,4 +1,17 @@ import { Network, SwapSide } from '../../constants'; +import { DexConfigMap } from '../../types'; + +type DexParams = { + swETH: string; +}; + +export const SwellConfig: DexConfigMap = { + Swell: { + [Network.MAINNET]: { + swETH: '0xf951E335afb289353dc249e82926178EaC7DEd78', + }, + }, +}; export const Adapters: { [chainId: number]: { [side: string]: { name: string; index: number }[] }; diff --git a/src/dex/swell/swell.ts b/src/dex/swell/swell.ts index 4fc56097b..bb846c9e3 100644 --- a/src/dex/swell/swell.ts +++ b/src/dex/swell/swell.ts @@ -13,21 +13,18 @@ import { } from '../../types'; import { IDex } from '../idex'; import SWETH_ABI from '../../abi/swETH.json'; -import { ETHER_ADDRESS } from '../../constants'; +import { ETHER_ADDRESS, Network } from '../../constants'; import { IDexHelper } from '../../dex-helper'; import { SimpleExchange } from '../simple-exchange'; import { BI_POWS } from '../../bigint-constants'; import { AsyncOrSync } from 'ts-essentials'; import { getOnChainState } from './utils'; import { SwethPool } from './sweth-pool'; -import { isETHAddress } from '../../utils'; +import { getDexKeysWithNetwork, isETHAddress } from '../../utils'; import { WethFunctions } from '../weth/types'; import * as CALLDATA_GAS_COST from '../../calldata-gas-cost'; -import { Adapters } from '../jarvis-v6/config'; - -export const swETH: any = { - 1: '0xf951E335afb289353dc249e82926178EaC7DEd78', -}; +import _ from 'lodash'; +import { SwellConfig, Adapters } from './config'; export enum swETHFunctions { deposit = 'deposit', @@ -40,21 +37,29 @@ export class Swell extends SimpleExchange implements IDex { - static dexKeys = ['swell']; + static dexKeys = ['Swell']; swETHInterface: Interface; needWrapNative = false; hasConstantPriceLargeAmounts: boolean = true; - network: number; swETHAddress: string; eventPool: SwethPool; logger: Logger; - constructor(protected dexHelper: IDexHelper) { - super(dexHelper, 'swell'); + public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = + getDexKeysWithNetwork(_.pick(SwellConfig, ['Swell'])); + + constructor( + protected network: Network, + dexKey: string, + protected dexHelper: IDexHelper, + protected config = SwellConfig[dexKey][network], + protected adapters = Adapters[network], + ) { + super(dexHelper, 'Swell'); this.network = dexHelper.config.data.network; this.swETHInterface = new Interface(SWETH_ABI as JsonFragment[]); - this.swETHAddress = swETH[this.network]; + this.swETHAddress = this.config.swETH.toLowerCase(); this.logger = dexHelper.getLogger(this.dexKey); this.eventPool = new SwethPool( this.dexKey, @@ -98,7 +103,7 @@ export class Swell return ( (isETHAddress(srcTokenAddress) || this.isWETH(srcTokenAddress)) && - destTokenAddress === this.swETHAddress.toLowerCase() + destTokenAddress === this.swETHAddress ); } @@ -133,8 +138,7 @@ export class Swell transferFees?: TransferFeeParams | undefined, isFirstSwap?: boolean | undefined, ): Promise | null> { - this.assertEligibility(srcToken, destToken, side); - + if (!this.isEligibleSwap(srcToken, destToken, side)) return null; if (this.eventPool.getState(blockNumber) === null) return null; const unitIn = BI_POWS[18]; @@ -228,7 +232,7 @@ export class Swell return CALLDATA_GAS_COST.DEX_OVERHEAD + CALLDATA_GAS_COST.LENGTH_SMALL; } getAdapters(side: SwapSide): { name: string; index: number }[] | null { - return Adapters[this.network][side] || null; + return this.adapters?.[side] || null; } getTopPoolsForToken( tokenAddress: string, diff --git a/src/dex/swell/utils.ts b/src/dex/swell/utils.ts index 17e5f4ba1..23c1345ba 100644 --- a/src/dex/swell/utils.ts +++ b/src/dex/swell/utils.ts @@ -11,13 +11,15 @@ export async function getOnChainState( blockNumber: number | 'latest', ): Promise { const data: { returnData: any[] } = await multiContract.methods - .aggregate({ - to: poolAddress, - data: poolInterface.encodeFunctionData('swETHToETHRate', []), - }) + .aggregate([ + { + target: poolAddress, + callData: poolInterface.encodeFunctionData('swETHToETHRate', []), + }, + ]) .call({}, blockNumber); - const decodedData = coder.decode(['uint256'], data.returnData); + const decodedData = coder.decode(['uint256'], data.returnData[0]); const swETHToETHRateFixed = BigInt(decodedData[0].toString()); From 179aa625999011e0031ff5715b252a92b8d1dbb6 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 16 Feb 2024 16:02:39 +0100 Subject: [PATCH 803/833] fix adapter --- src/config.ts | 1 + src/dex/swell/config.ts | 2 +- src/dex/swell/swell.ts | 13 ++----------- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/config.ts b/src/config.ts index c02f6d306..57bf3a19c 100644 --- a/src/config.ts +++ b/src/config.ts @@ -54,6 +54,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { Adapter02: '0xFC2Ba6E830a04C25e207B8214b26d8C713F6881F', Adapter03: '0xBAEeb4540f59d30E567a5B563CC0c4587eDd9366', Adapter04: '0x369A2FDb910d432f0a07381a5E3d27572c876713', + Adapter05: '0x221cf6d7569b35726e73e5f329bad2ee3836c4fc', BuyAdapter: '0x84bEF12C9931cE12662cc9F2366b6a5029E4BD29', BuyAdapter02: '0xe53d24CD81cC81bbf271AD7B02D0d67f851D727c', }, diff --git a/src/dex/swell/config.ts b/src/dex/swell/config.ts index a3ba291f8..869eebc4f 100644 --- a/src/dex/swell/config.ts +++ b/src/dex/swell/config.ts @@ -19,7 +19,7 @@ export const Adapters: { [Network.MAINNET]: { [SwapSide.SELL]: [ { - name: 'Adapter04', // FIXME + name: 'Adapter05', index: 1, }, ], diff --git a/src/dex/swell/swell.ts b/src/dex/swell/swell.ts index bb846c9e3..76915a220 100644 --- a/src/dex/swell/swell.ts +++ b/src/dex/swell/swell.ts @@ -170,18 +170,9 @@ export class Swell ): AdapterExchangeParam { this.assertEligibility(srcToken, destToken, side); - const payload = this.abiCoder.encodeParameter( - { - ParentStruct: { - shouldWithdraw: 'bool', - }, - }, - { shouldWithdraw: this.isWETH(srcToken) }, - ); - return { - targetExchange: this.swETHAddress, - payload, + targetExchange: this.swETHAddress, // not used contract side + payload: '0x', networkFee: '0', }; } From b67d069c2a9f759f9d6a68bbcf005a4370820b73 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 16 Feb 2024 16:04:40 +0100 Subject: [PATCH 804/833] 2.44.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 61b760299..3c1ec3025 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.43.0", + "version": "2.44.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From e47bb2b029b9451fa5238fbeb24074e615c7d637 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 16 Feb 2024 17:20:24 +0100 Subject: [PATCH 805/833] upate adapter05 --- src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index 57bf3a19c..c62234fc9 100644 --- a/src/config.ts +++ b/src/config.ts @@ -54,7 +54,7 @@ const baseConfigs: { [network: number]: BaseConfig } = { Adapter02: '0xFC2Ba6E830a04C25e207B8214b26d8C713F6881F', Adapter03: '0xBAEeb4540f59d30E567a5B563CC0c4587eDd9366', Adapter04: '0x369A2FDb910d432f0a07381a5E3d27572c876713', - Adapter05: '0x221cf6d7569b35726e73e5f329bad2ee3836c4fc', + Adapter05: '0x3329dfa55A40B450952FBE0203167Ae6908E656d', BuyAdapter: '0x84bEF12C9931cE12662cc9F2366b6a5029E4BD29', BuyAdapter02: '0xe53d24CD81cC81bbf271AD7B02D0d67f851D727c', }, From f6630a0e56fffc8d12f28c905f1c949bd1ea4043 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 19 Feb 2024 13:27:56 +0100 Subject: [PATCH 806/833] add test for swell --- src/dex/swell/swell-e2e.test.ts | 53 +++++++++++++++++++++++++++++++++ tests/constants-e2e.ts | 4 +++ 2 files changed, 57 insertions(+) create mode 100644 src/dex/swell/swell-e2e.test.ts diff --git a/src/dex/swell/swell-e2e.test.ts b/src/dex/swell/swell-e2e.test.ts new file mode 100644 index 000000000..7f4e83ee1 --- /dev/null +++ b/src/dex/swell/swell-e2e.test.ts @@ -0,0 +1,53 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +import { testE2E } from '../../../tests/utils-e2e'; +import { Tokens, Holders } from '../../../tests/constants-e2e'; +import { Network, ContractMethod, SwapSide } from '../../constants'; +import { StaticJsonRpcProvider } from '@ethersproject/providers'; +import { generateConfig } from '../../config'; + +describe('Swell', () => { + const network = Network.MAINNET; + const tokens = Tokens[network]; + const holders = Holders[network]; + const provider = new StaticJsonRpcProvider( + generateConfig(network).privateHttpProvider, + network, + ); + const dexKey = 'Swell'; + + [ + ContractMethod.simpleSwap, + ContractMethod.multiSwap, + ContractMethod.megaSwap, + ].forEach(contractMethod => { + it(`${contractMethod} - ETH -> SWETH`, async () => { + await testE2E( + tokens.ETH, + tokens.SWETH, + holders.ETH, + '1000000000000000000', + SwapSide.SELL, + dexKey, + contractMethod, + network, + provider, + ); + }); + + it(`${contractMethod} - WETH -> SWETH`, async () => { + await testE2E( + tokens.WETH, + tokens.SWETH, + holders.WETH, + '1000000000000000000', + SwapSide.SELL, + dexKey, + contractMethod, + network, + provider, + ); + }); + }); +}); diff --git a/tests/constants-e2e.ts b/tests/constants-e2e.ts index 8352a7e40..321ed7cf2 100644 --- a/tests/constants-e2e.ts +++ b/tests/constants-e2e.ts @@ -23,6 +23,10 @@ export const Tokens: { address: ETHER_ADDRESS, decimals: 18, }, + SWETH: { + address: '0xf951e335afb289353dc249e82926178eac7ded78', + decimals: 18, + }, REQ: { address: '0x8f8221aFbB33998d8584A2B05749bA73c37a938a', decimals: 18, From 3c40f8056dae41a2bc61890f1f3dc034c04debd3 Mon Sep 17 00:00:00 2001 From: sakulstra Date: Mon, 19 Feb 2024 22:06:37 +0100 Subject: [PATCH 807/833] feat: use aave address book --- package.json | 1 + src/dex/aave-v2/aave-v2.ts | 17 +++++++----- src/dex/aave-v3/config.ts | 53 +++++++++++++++++++++++++++++--------- yarn.lock | 5 ++++ 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 3c1ec3025..5bf995365 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ }, "dependencies": { "@0x/utils": "^4.5.2", + "@bgd-labs/aave-address-book": "^2.20.0", "@ethersproject/abi": "^5.7.0", "@hashflow/sdk": "1.2.4", "@hashflow/taker-js": "0.3.4", diff --git a/src/dex/aave-v2/aave-v2.ts b/src/dex/aave-v2/aave-v2.ts index 43e591df9..6a2c7b626 100644 --- a/src/dex/aave-v2/aave-v2.ts +++ b/src/dex/aave-v2/aave-v2.ts @@ -25,17 +25,22 @@ import { IDexHelper } from '../../dex-helper/idex-helper'; import { SimpleExchange } from '../simple-exchange'; import { AaveV2Config, Adapters } from './config'; import { isAaveV2Pair } from './tokens'; +import { + AaveV2Avalanche, + AaveV2Ethereum, + AaveV2Polygon, +} from '@bgd-labs/aave-address-book'; const aaveLendingPool: { [network: string]: string } = { - [Network.MAINNET]: '0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9', - [Network.POLYGON]: '0x8dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcf', - [Network.AVALANCHE]: '0x4F01AeD16D97E3aB5ab2B501154DC9bb0F1A5A2C', + [Network.MAINNET]: AaveV2Ethereum.POOL, + [Network.POLYGON]: AaveV2Polygon.POOL, + [Network.AVALANCHE]: AaveV2Avalanche.POOL, }; const WETH_GATEWAY: any = { - [Network.MAINNET]: '0xDcD33426BA191383f1c9B431A342498fdac73488', - [Network.POLYGON]: '0xbEadf48d62aCC944a06EEaE0A9054A90E5A7dc97', - [Network.AVALANCHE]: '0x8a47F74d1eE0e2edEB4F3A7e64EF3bD8e11D27C8', + [Network.MAINNET]: AaveV2Ethereum.WETH_GATEWAY, + [Network.POLYGON]: AaveV2Polygon.WETH_GATEWAY, + [Network.AVALANCHE]: AaveV2Avalanche.WETH_GATEWAY, }; const WETH_GATEWAY_ABI: any = { diff --git a/src/dex/aave-v3/config.ts b/src/dex/aave-v3/config.ts index d365c4f19..f1659657f 100644 --- a/src/dex/aave-v3/config.ts +++ b/src/dex/aave-v3/config.ts @@ -1,6 +1,17 @@ import { DexConfigMap } from '../../types'; import { Network, SwapSide } from '../../constants'; import { DexParam } from './types'; +import { + AaveV3Arbitrum, + AaveV3Avalanche, + AaveV3BNB, + AaveV3Base, + AaveV3Ethereum, + AaveV3Fantom, + AaveV3Optimism, + AaveV3Polygon, + AaveV3PolygonZkEvm, +} from '@bgd-labs/aave-address-book'; // TODO: find vals for V3 export const Config: DexConfigMap = { @@ -8,38 +19,56 @@ export const Config: DexConfigMap = { [Network.FANTOM]: { ethGasCost: 246 * 100, lendingGasCost: 328 * 1000, - poolAddress: '0x794a61358D6845594F94dc1DB02A252b5b4814aD', - wethGatewayAddress: '0x17d013C19FE25cf4D911CE85eD5f40FE8880F46f', + poolAddress: AaveV3Fantom.POOL, + wethGatewayAddress: AaveV3Fantom.WETH_GATEWAY, }, [Network.POLYGON]: { ethGasCost: 246 * 100, lendingGasCost: 328 * 1000, - poolAddress: '0x794a61358D6845594F94dc1DB02A252b5b4814aD', - wethGatewayAddress: '0x9bdb5fcc80a49640c7872ac089cc0e00a98451b6', + poolAddress: AaveV3Polygon.POOL, + wethGatewayAddress: AaveV3Polygon.WETH_GATEWAY, }, [Network.AVALANCHE]: { ethGasCost: 246 * 100, lendingGasCost: 328 * 1000, - poolAddress: '0x794a61358D6845594F94dc1DB02A252b5b4814aD', - wethGatewayAddress: '0xa938d8536aEed1Bd48f548380394Ab30Aa11B00E', + poolAddress: AaveV3Avalanche.POOL, + wethGatewayAddress: AaveV3Avalanche.WETH_GATEWAY, }, [Network.ARBITRUM]: { ethGasCost: 246 * 100, lendingGasCost: 328 * 1000, - poolAddress: '0x794a61358D6845594F94dc1DB02A252b5b4814aD', - wethGatewayAddress: '0xC09e69E79106861dF5d289dA88349f10e2dc6b5C', + poolAddress: AaveV3Arbitrum.POOL, + wethGatewayAddress: AaveV3Arbitrum.WETH_GATEWAY, }, [Network.OPTIMISM]: { ethGasCost: 246 * 100, lendingGasCost: 328 * 1000, - poolAddress: '0x794a61358D6845594F94dc1DB02A252b5b4814aD', - wethGatewayAddress: '0x86b4D2636EC473AC4A5dD83Fc2BEDa98845249A7', + poolAddress: AaveV3Optimism.POOL, + wethGatewayAddress: AaveV3Optimism.WETH_GATEWAY, }, [Network.MAINNET]: { ethGasCost: 246 * 100, lendingGasCost: 328 * 1000, - poolAddress: '0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2', - wethGatewayAddress: '0xD322A49006FC828F9B5B37Ab215F99B4E5caB19C', + poolAddress: AaveV3Ethereum.POOL, + wethGatewayAddress: AaveV3Ethereum.WETH_GATEWAY, + }, + [Network.BASE]: { + ethGasCost: 246 * 100, + lendingGasCost: 328 * 1000, + poolAddress: AaveV3Base.POOL, + wethGatewayAddress: AaveV3Base.WETH_GATEWAY, + }, + [Network.BSC]: { + ethGasCost: 246 * 100, + lendingGasCost: 328 * 1000, + poolAddress: AaveV3BNB.POOL, + wethGatewayAddress: AaveV3BNB.WETH_GATEWAY, + }, + [Network.ZKEVM]: { + ethGasCost: 246 * 100, + lendingGasCost: 328 * 1000, + poolAddress: AaveV3PolygonZkEvm.POOL, + wethGatewayAddress: AaveV3PolygonZkEvm.WETH_GATEWAY, }, }, }; diff --git a/yarn.lock b/yarn.lock index cf26f6f93..dbb531726 100644 --- a/yarn.lock +++ b/yarn.lock @@ -341,6 +341,11 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@bgd-labs/aave-address-book@^2.20.0": + version "2.20.0" + resolved "https://registry.yarnpkg.com/@bgd-labs/aave-address-book/-/aave-address-book-2.20.0.tgz#787a28e87ffc4d9a4c1c9cabc47e965d97234e73" + integrity sha512-XRXqrR3NrZAJISSAPAWdDukiaXeXcTgRdLv7tgsHRg5k8f7BB9pND6yVA91HGMpmghAsB0bm5W9Lo26ZB9tRYg== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" From 9cd1458ab5281865adb63bc42ae723df6842d181 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 20 Feb 2024 14:39:59 +0100 Subject: [PATCH 808/833] fix missing exclusion of Aerodrome in main implem --- src/dex/solidly/solidly.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dex/solidly/solidly.ts b/src/dex/solidly/solidly.ts index fa380c425..ff96dd475 100644 --- a/src/dex/solidly/solidly.ts +++ b/src/dex/solidly/solidly.ts @@ -67,6 +67,7 @@ export class Solidly extends UniswapV2 { _.omit(SolidlyConfig, [ 'Velodrome', 'VelodromeV2', + 'Aerodrome', 'SpiritSwapV2', 'Cone', 'SolidlyV2', From 30205c91170a9d3942d58b140ecb8022f192ce5f Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 20 Feb 2024 14:42:00 +0100 Subject: [PATCH 809/833] dedup dexKeys --- src/dex/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dex/index.ts b/src/dex/index.ts index 13124d3ab..b285b3201 100644 --- a/src/dex/index.ts +++ b/src/dex/index.ts @@ -1,3 +1,4 @@ +import _ from 'lodash'; import { UnoptimizedRate } from '../types'; import { CurveV2 } from './curve-v2'; import { IDexTxBuilder, DexContructor, IDex, IRouteOptimizer } from './idex'; @@ -294,7 +295,7 @@ export class DexAdapterService { } getAllDexKeys() { - return this.dexKeys; + return _.uniq(this.dexKeys); } getDexByKey(key: string): IDex { From 55e4069834d9f2bcf7af25bf54022e07d966ad05 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Tue, 20 Feb 2024 14:43:40 +0100 Subject: [PATCH 810/833] 2.44.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3c1ec3025..ff7600c0d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.44.0", + "version": "2.44.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 1e42a4b15e8bb885ebca17be974046e08ce9f959 Mon Sep 17 00:00:00 2001 From: sakulstra Date: Wed, 21 Feb 2024 11:34:01 +0100 Subject: [PATCH 811/833] fix: use tokenlist for v2 --- .env.example | 7 + package.json | 2 +- src/dex/aave-v2/aave-v2.ts | 24 +--- src/dex/aave-v2/config.ts | 17 +++ src/dex/aave-v2/tokens-avalanche.json | 44 ------ src/dex/aave-v2/tokens-mainnet.json | 188 -------------------------- src/dex/aave-v2/tokens-polygon.json | 44 ------ src/dex/aave-v2/tokens.ts | 27 +++- yarn.lock | 8 +- 9 files changed, 56 insertions(+), 305 deletions(-) create mode 100644 .env.example delete mode 100644 src/dex/aave-v2/tokens-avalanche.json delete mode 100644 src/dex/aave-v2/tokens-mainnet.json delete mode 100644 src/dex/aave-v2/tokens-polygon.json diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..cc27ae949 --- /dev/null +++ b/.env.example @@ -0,0 +1,7 @@ +HTTP_PROVIDER_1= +HTTP_PROVIDER_137= +HTTP_PROVIDER_43114= + +TENDERLY_TOKEN= +TENDERLY_ACCOUNT_ID= +TENDERLY_PROJECT= \ No newline at end of file diff --git a/package.json b/package.json index 5bf995365..d135d05ec 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ }, "dependencies": { "@0x/utils": "^4.5.2", - "@bgd-labs/aave-address-book": "^2.20.0", + "@bgd-labs/aave-address-book": "2.21.1-be0c0c2323752df82e6faeaadaccd99a239e6e60.0", "@ethersproject/abi": "^5.7.0", "@hashflow/sdk": "1.2.4", "@hashflow/taker-js": "0.3.4", diff --git a/src/dex/aave-v2/aave-v2.ts b/src/dex/aave-v2/aave-v2.ts index 6a2c7b626..a60480aef 100644 --- a/src/dex/aave-v2/aave-v2.ts +++ b/src/dex/aave-v2/aave-v2.ts @@ -23,25 +23,13 @@ import { IDex } from '../../dex/idex'; import { IDexHelper } from '../../dex-helper/idex-helper'; import { SimpleExchange } from '../simple-exchange'; -import { AaveV2Config, Adapters } from './config'; -import { isAaveV2Pair } from './tokens'; import { - AaveV2Avalanche, - AaveV2Ethereum, - AaveV2Polygon, -} from '@bgd-labs/aave-address-book'; - -const aaveLendingPool: { [network: string]: string } = { - [Network.MAINNET]: AaveV2Ethereum.POOL, - [Network.POLYGON]: AaveV2Polygon.POOL, - [Network.AVALANCHE]: AaveV2Avalanche.POOL, -}; - -const WETH_GATEWAY: any = { - [Network.MAINNET]: AaveV2Ethereum.WETH_GATEWAY, - [Network.POLYGON]: AaveV2Polygon.WETH_GATEWAY, - [Network.AVALANCHE]: AaveV2Avalanche.WETH_GATEWAY, -}; + AaveV2Config, + Adapters, + WETH_GATEWAY, + aaveLendingPool, +} from './config'; +import { isAaveV2Pair } from './tokens'; const WETH_GATEWAY_ABI: any = { [Network.MAINNET]: WETH_GATEWAY_ABI_MAINNET, diff --git a/src/dex/aave-v2/config.ts b/src/dex/aave-v2/config.ts index 13265f716..6fef2160f 100644 --- a/src/dex/aave-v2/config.ts +++ b/src/dex/aave-v2/config.ts @@ -1,5 +1,22 @@ import { DexConfigMap } from '../../types'; import { Network, SwapSide } from '../../constants'; +import { + AaveV2Avalanche, + AaveV2Ethereum, + AaveV2Polygon, +} from '@bgd-labs/aave-address-book'; + +export const aaveLendingPool: { [network: string]: string } = { + [Network.MAINNET]: AaveV2Ethereum.POOL, + [Network.POLYGON]: AaveV2Polygon.POOL, + [Network.AVALANCHE]: AaveV2Avalanche.POOL, +}; + +export const WETH_GATEWAY: any = { + [Network.MAINNET]: AaveV2Ethereum.WETH_GATEWAY, + [Network.POLYGON]: AaveV2Polygon.WETH_GATEWAY, + [Network.AVALANCHE]: AaveV2Avalanche.WETH_GATEWAY, +}; export const AaveV2Config: DexConfigMap = { AaveV2: { diff --git a/src/dex/aave-v2/tokens-avalanche.json b/src/dex/aave-v2/tokens-avalanche.json deleted file mode 100644 index dcc55363b..000000000 --- a/src/dex/aave-v2/tokens-avalanche.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "aSymbol": "avWETH", - "aAddress": "0x53f7c5869a859f0aec3d334ee8b4cf01e3492f21", - "address": "0x49d5c2bdffac6ce2bfdb6640f4f80f226bc10bab", - "decimals": 18 - }, - { - "aSymbol": "avDAI", - "aAddress": "0x47afa96cdc9fab46904a55a6ad4bf6660b53c38a", - "address": "0xd586e7f844cea2f87f50152665bcbc2c279d8d70", - "decimals": 18 - }, - { - "aSymbol": "avUSDT", - "aAddress": "0x532e6537fea298397212f09a61e03311686f548e", - "address": "0xc7198437980c041c805a1edcba50c1ce5db95118", - "decimals": 6 - }, - { - "aSymbol": "avUSDC", - "aAddress": "0x46a51127c3ce23fb7ab1de06226147f446e4a857", - "address": "0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664", - "decimals": 6 - }, - { - "aSymbol": "avAAVE", - "aAddress": "0xd45b7c061016102f9fa220502908f2c0f1add1d7", - "address": "0x63a72806098bd3d9520cc43356dd78afe5d386d9", - "decimals": 18 - }, - { - "aSymbol": "avWBTC", - "aAddress": "0x686bef2417b6dc32c50a3cbfbcc3bb60e1e9a15d", - "address": "0x50b7545627a5162f82a992c33b87adc75187b218", - "decimals": 8 - }, - { - "aSymbol": "avWAVAX", - "aAddress": "0xdfe521292ece2a4f44242efbcd66bc594ca9714b", - "address": "0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7", - "decimals": 18 - } -] diff --git a/src/dex/aave-v2/tokens-mainnet.json b/src/dex/aave-v2/tokens-mainnet.json deleted file mode 100644 index 6758530c5..000000000 --- a/src/dex/aave-v2/tokens-mainnet.json +++ /dev/null @@ -1,188 +0,0 @@ -[ - { - "aSymbol": "aUSDT", - "aAddress": "0x3ed3b47dd13ec9a98b44e6204a523e766b225811", - "address": "0xdac17f958d2ee523a2206206994597c13d831ec7", - "decimals": 6 - }, - { - "aSymbol": "aWBTC", - "aAddress": "0x9ff58f4ffb29fa2266ab25e75e2a8b3503311656", - "address": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", - "decimals": 8 - }, - { - "aSymbol": "aWETH", - "aAddress": "0x030ba81f1c18d280636f32af80b9aad02cf0854e", - "address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", - "decimals": 18 - }, - { - "aSymbol": "aYFI", - "aAddress": "0x5165d24277cd063f5ac44efd447b27025e888f37", - "address": "0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e", - "decimals": 18 - }, - { - "aSymbol": "aZRX", - "aAddress": "0xdf7ff54aacacbff42dfe29dd6144a69b629f8c9e", - "address": "0xe41d2489571d322189246dafa5ebde1f4699f498", - "decimals": 18 - }, - { - "aSymbol": "aUNI", - "aAddress": "0xb9d7cb55f463405cdfbe4e90a6d2df01c2b92bf1", - "address": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984", - "decimals": 18 - }, - { - "aSymbol": "aAAVE", - "aAddress": "0xffc97d72e13e01096502cb8eb52dee56f74dad7b", - "address": "0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9", - "decimals": 18 - }, - { - "aSymbol": "aBAT", - "aAddress": "0x05ec93c0365baaeabf7aeffb0972ea7ecdd39cf1", - "address": "0x0d8775f648430679a709e98d2b0cb6250d2887ef", - "decimals": 18 - }, - { - "aSymbol": "aBUSD", - "aAddress": "0xa361718326c15715591c299427c62086f69923d9", - "address": "0x4fabb145d64652a948d72533023f6e7a623c7c53", - "decimals": 18 - }, - { - "aSymbol": "aDAI", - "aAddress": "0x028171bca77440897b824ca71d1c56cac55b68a3", - "address": "0x6b175474e89094c44da98b954eedeac495271d0f", - "decimals": 18 - }, - { - "aSymbol": "aENJ", - "aAddress": "0xac6df26a590f08dcc95d5a4705ae8abbc88509ef", - "address": "0xf629cbd94d3791c9250152bd8dfbdf380e2a3b9c", - "decimals": 18 - }, - { - "aSymbol": "aKNC", - "aAddress": "0x39c6b3e42d6a679d7d776778fe880bc9487c2eda", - "address": "0xdd974d5c2e2928dea5f71b9825b8b646686bd200", - "decimals": 18 - }, - { - "aSymbol": "aLINK", - "aAddress": "0xa06bc25b5805d5f8d82847d191cb4af5a3e873e0", - "address": "0x514910771af9ca656af840dff83e8264ecf986ca", - "decimals": 18 - }, - { - "aSymbol": "aMANA", - "aAddress": "0xa685a61171bb30d4072b338c80cb7b2c865c873e", - "address": "0x0f5d2fb29fb7d3cfee444a200298f468908cc942", - "decimals": 18 - }, - { - "aSymbol": "aMKR", - "aAddress": "0xc713e5e149d5d0715dcd1c156a020976e7e56b88", - "address": "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2", - "decimals": 18 - }, - { - "aSymbol": "aREN", - "aAddress": "0xcc12abe4ff81c9378d670de1b57f8e0dd228d77a", - "address": "0x408e41876cccdc0f92210600ef50372656052a38", - "decimals": 18 - }, - { - "aSymbol": "aSNX", - "aAddress": "0x35f6b052c598d933d69a4eec4d04c73a191fe6c2", - "address": "0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f", - "decimals": 18 - }, - { - "aSymbol": "aSUSD", - "aAddress": "0x6c5024cd4f8a59110119c56f8933403a539555eb", - "address": "0x57ab1ec28d129707052df4df418d58a2d46d5f51", - "decimals": 18 - }, - { - "aSymbol": "aTUSD", - "aAddress": "0x101cc05f4a51c0319f570d5e146a8c625198e636", - "address": "0x0000000000085d4780b73119b644ae5ecd22b376", - "decimals": 18 - }, - { - "aSymbol": "aUSDC", - "aAddress": "0xbcca60bb61934080951369a648fb03df4f96263c", - "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", - "decimals": 6 - }, - { - "aSymbol": "aCRV", - "aAddress": "0x8dae6cb04688c62d939ed9b68d32bc62e49970b1", - "address": "0xd533a949740bb3306d119cc777fa900ba034cd52", - "decimals": 18 - }, - { - "aSymbol": "aGUSD", - "aAddress": "0xd37ee7e4f452c6638c96536e68090de8cbcdb583", - "address": "0x056fd409e1d7a124bd7017459dfea2f387b6d5cd", - "decimals": 2 - }, - { - "aSymbol": "aBAL", - "aAddress": "0x272f97b7a56a387ae942350bbc7df5700f8a4576", - "address": "0xba100000625a3754423978a60c9317c58a424e3d", - "decimals": 18 - }, - { - "aSymbol": "aXSUSHI", - "aAddress": "0xf256cc7847e919fac9b808cc216cac87ccf2f47a", - "address": "0x8798249c2e607446efb7ad49ec89dd1865ff4272", - "decimals": 18 - }, - { - "aSymbol": "aRENFIL", - "aAddress": "0x514cd6756ccbe28772d4cb81bc3156ba9d1744aa", - "address": "0xd5147bc8e386d91cc5dbe72099dac6c9b99276f5", - "decimals": 18 - }, - { - "aSymbol": "aRAI", - "aAddress": "0xc9bc48c72154ef3e5425641a3c747242112a46af", - "address": "0x03ab458634910aad20ef5f1c8ee96f1d6ac54919", - "decimals": 18 - }, - { - "aSymbol": "aAMPL", - "aAddress": "0x1e6bb68acec8fefbd87d192be09bb274170a0548", - "address": "0xd46ba6d942050d489dbd938a2c909a5d5039a161", - "decimals": 9 - }, - { - "aSymbol": "aUSDP", - "aAddress": "0x2e8f4bdbe3d47d7d7de490437aea9915d930f1a3", - "address": "0x8e870d67f660d95d5be530380d0ec0bd388289e1", - "decimals": 18 - }, - { - "aSymbol": "aDPI", - "aAddress": "0x6f634c6135d2ebd550000ac92f494f9cb8183dae", - "address": "0x1494ca1f11d487c2bbe4543e90080aeba4ba3c2b", - "decimals": 18 - }, - { - "aSymbol": "aFRAX", - "aAddress": "0xd4937682df3c8aef4fe912a96a74121c0829e664", - "address": "0x853d955acef822db058eb8505911ed77f175b99e", - "decimals": 18 - }, - { - "aSymbol": "aFEI", - "aAddress": "0x683923db55fead99a79fa01a27eec3cb19679cc3", - "address": "0x956f47f50a910163d8bf957cf5846d573e7f87ca", - "decimals": 18 - } -] diff --git a/src/dex/aave-v2/tokens-polygon.json b/src/dex/aave-v2/tokens-polygon.json deleted file mode 100644 index fd047ba77..000000000 --- a/src/dex/aave-v2/tokens-polygon.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "aSymbol": "amAAVE", - "aAddress": "0x1d2a0E5EC8E5bBDCA5CB219e649B565d8e5c3360", - "address": "0xd6df932a45c0f255f85145f286ea0b292b21c90b", - "decimals": 18 - }, - { - "aSymbol": "amDAI", - "aAddress": "0x27f8d03b3a2196956ed754badc28d73be8830a6e", - "address": "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063", - "decimals": 18 - }, - { - "aSymbol": "amUSDC", - "aAddress": "0x1a13f4ca1d028320a707d99520abfefca3998b7f", - "address": "0x2791bca1f2de4661ed88a30c99a7a9449aa84174", - "decimals": 6 - }, - { - "aSymbol": "amUSDT", - "aAddress": "0x60d55f02a771d515e077c9c2403a1ef324885cec", - "address": "0xc2132d05d31c914a87c6611c10748aeb04b58e8f", - "decimals": 6 - }, - { - "aSymbol": "amWBTC", - "aAddress": "0x5c2ed810328349100a66b82b78a1791b101c9d61", - "address": "0x1bfd67037b42cf73acf2047067bd4f2c47d9bfd6", - "decimals": 8 - }, - { - "aSymbol": "amWETH", - "aAddress": "0x28424507fefb6f7f8e9d3860f56504e4e5f5f390", - "address": "0x7ceb23fd6bc0add59e62ac25578270cff1b9f619", - "decimals": 18 - }, - { - "aSymbol": "amWMATIC", - "aAddress": "0x8df3aad3a84da6b69a4da8aec3ea40d9091b2ac4", - "address": "0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270", - "decimals": 18 - } -] diff --git a/src/dex/aave-v2/tokens.ts b/src/dex/aave-v2/tokens.ts index 40c7e0ae8..095a3aac1 100644 --- a/src/dex/aave-v2/tokens.ts +++ b/src/dex/aave-v2/tokens.ts @@ -1,18 +1,33 @@ import { aToken, Token } from '../../types'; import { Network } from '../../constants'; +import { tokenlist } from '@bgd-labs/aave-address-book'; +import { aaveLendingPool } from './config'; -import tokensMainnet from './tokens-mainnet.json'; -import tokensPolygon from './tokens-polygon.json'; -import tokensAvalanche from './tokens-avalanche.json'; +function getTokensForPool(pool: string): aToken[] { + return tokenlist.tokens + .filter( + token => + token.extensions?.pool && + token.extensions?.pool.toLowerCase() === pool.toLowerCase() && + token.tags.includes('aTokenV2'), + ) + .map(token => ({ + aSymbol: token.symbol, + aAddress: token.address.toLowerCase(), + // the type is a bit imprecise, when tag is aTokenV2, underlying will exist + address: token.extensions!.underlying.toLowerCase(), + decimals: token.decimals, + })); +} export const Tokens: { [network: number]: { [symbol: string]: aToken } } = {}; const TokensByAddress: { [network: number]: { [address: string]: aToken } } = {}; const tokensByNetwork: { [network: number]: any } = { - [Network.MAINNET]: tokensMainnet, - [Network.POLYGON]: tokensPolygon, - [Network.AVALANCHE]: tokensAvalanche, + [Network.MAINNET]: getTokensForPool(aaveLendingPool[Network.MAINNET]), + [Network.POLYGON]: getTokensForPool(aaveLendingPool[Network.POLYGON]), + [Network.AVALANCHE]: getTokensForPool(aaveLendingPool[Network.AVALANCHE]), }; for (const [key, tokens] of Object.entries(tokensByNetwork)) { diff --git a/yarn.lock b/yarn.lock index dbb531726..6fb6f5921 100644 --- a/yarn.lock +++ b/yarn.lock @@ -341,10 +341,10 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@bgd-labs/aave-address-book@^2.20.0": - version "2.20.0" - resolved "https://registry.yarnpkg.com/@bgd-labs/aave-address-book/-/aave-address-book-2.20.0.tgz#787a28e87ffc4d9a4c1c9cabc47e965d97234e73" - integrity sha512-XRXqrR3NrZAJISSAPAWdDukiaXeXcTgRdLv7tgsHRg5k8f7BB9pND6yVA91HGMpmghAsB0bm5W9Lo26ZB9tRYg== +"@bgd-labs/aave-address-book@2.21.1-be0c0c2323752df82e6faeaadaccd99a239e6e60.0": + version "2.21.1-be0c0c2323752df82e6faeaadaccd99a239e6e60.0" + resolved "https://registry.yarnpkg.com/@bgd-labs/aave-address-book/-/aave-address-book-2.21.1-be0c0c2323752df82e6faeaadaccd99a239e6e60.0.tgz#d0feb66424d6158057968f6f630c28992b28c0be" + integrity sha512-enoNRLuWLhTscoAPRktD3s47E8JknbkI8UesjXforpIIndQc3lEngTATBpNUtIBdTkE+k/Z1kSV4zTOFxL3Msg== "@cspotcode/source-map-support@^0.8.0": version "0.8.1" From 132c0cb9fc65c31c575c4b0d793d2d476c80fa6d Mon Sep 17 00:00:00 2001 From: sakulstra Date: Wed, 21 Feb 2024 11:42:03 +0100 Subject: [PATCH 812/833] chore: use stable version --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d135d05ec..d80c26655 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ }, "dependencies": { "@0x/utils": "^4.5.2", - "@bgd-labs/aave-address-book": "2.21.1-be0c0c2323752df82e6faeaadaccd99a239e6e60.0", + "@bgd-labs/aave-address-book": "2.21.1", "@ethersproject/abi": "^5.7.0", "@hashflow/sdk": "1.2.4", "@hashflow/taker-js": "0.3.4", diff --git a/yarn.lock b/yarn.lock index 6fb6f5921..1cc969dce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -341,10 +341,10 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@bgd-labs/aave-address-book@2.21.1-be0c0c2323752df82e6faeaadaccd99a239e6e60.0": - version "2.21.1-be0c0c2323752df82e6faeaadaccd99a239e6e60.0" - resolved "https://registry.yarnpkg.com/@bgd-labs/aave-address-book/-/aave-address-book-2.21.1-be0c0c2323752df82e6faeaadaccd99a239e6e60.0.tgz#d0feb66424d6158057968f6f630c28992b28c0be" - integrity sha512-enoNRLuWLhTscoAPRktD3s47E8JknbkI8UesjXforpIIndQc3lEngTATBpNUtIBdTkE+k/Z1kSV4zTOFxL3Msg== +"@bgd-labs/aave-address-book@2.21.1": + version "2.21.1" + resolved "https://registry.yarnpkg.com/@bgd-labs/aave-address-book/-/aave-address-book-2.21.1.tgz#004aa244d715d785079029f6b61d5ece6bcff563" + integrity sha512-q22AThlSRgEgRkwWiK1ts13oO3epZkARmdJzhezv6Fv3PNa5M95uoqABjNldWmpUyadhy2UtujGzXdOQ6MSS9Q== "@cspotcode/source-map-support@^0.8.0": version "0.8.1" From e991c97627ed8643ccc979cfef033e5ca857dd39 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 1 Mar 2024 17:45:40 +0100 Subject: [PATCH 813/833] 2.44.2-aave-updates.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 47a0e8626..d8d8cf307 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.44.1", + "version": "2.44.2-aave-updates.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 95387843d582197e4240a96e8066295e4652b0ab Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 4 Mar 2024 16:18:09 +0100 Subject: [PATCH 814/833] aaveV3: add new chains adapters --- src/dex/aave-v3/config.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/dex/aave-v3/config.ts b/src/dex/aave-v3/config.ts index f1659657f..c0d058bff 100644 --- a/src/dex/aave-v3/config.ts +++ b/src/dex/aave-v3/config.ts @@ -124,4 +124,28 @@ export const Adapters: { }, ], }, + [Network.BASE]: { + [SwapSide.SELL]: [ + { + name: 'BaseAdapter01', + index: 9, + }, + ], + }, + [Network.BSC]: { + [SwapSide.SELL]: [ + { + name: 'BscAdapter02', + index: 9, + }, + ], + }, + [Network.ZKEVM]: { + [SwapSide.SELL]: [ + { + name: 'PolygonZkEvmAdapter02', + index: 1, + }, + ], + }, }; From 9917a3f1db759e5c63f385cf4aede61de2ac9b82 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 4 Mar 2024 16:19:32 +0100 Subject: [PATCH 815/833] 2.44.2-aave-updates.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d8d8cf307..f5eef5925 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.44.2-aave-updates.0", + "version": "2.44.2-aave-updates.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 4d3dea11637f5afc00b12135dc145674c4ee9f8b Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 4 Mar 2024 18:02:57 +0100 Subject: [PATCH 816/833] 2.45.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f5eef5925..4f3e71e79 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.44.2-aave-updates.1", + "version": "2.45.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 95e0c3a982d564b15c9f9184f753ea27c48c8df6 Mon Sep 17 00:00:00 2001 From: 0xSokka Date: Mon, 18 Mar 2024 13:02:04 -0300 Subject: [PATCH 817/833] chore: readme updates --- README.md | 325 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 315 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 723826186..7b10150fe 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **DexLib** is a library used by ParaSwap backend to integrate with decentralized exchanges. This library enables external DEX developers to integrate their DEX with ParaSwap by creating pull requests to this repository. -### Steps to add new exchange to DexLib +## How to add your DEX to ParaSwap 1. Fork [paraswap-dex-lib](https://github.com/paraswap/paraswap-dex-lib) to your organization or personal account. 2. Clone the repository locally and create a branch with appropriate name (eg: `feature/super-dex`) @@ -18,11 +18,11 @@ yarn install yarn init-integration ``` -You can find template code for newly integrated Dex in `src/dex/` +You can find template code for newly integrated DEX in `src/dex/` 5. Complete the template code by filling the functions implementations. Template code is highly documented which should help you build the implementation. You should look into existing DEX implementation in `src/dex/` to understand the interfaces. Please refer below for detailed explanations and good practices. -6. Add `` to `Dexes` list in `src/dex/index.ts` +6. Add `` to `dexes` list in `src/dex/index.ts` 7. Complete the test templates (All files with `src/dex//*.test.ts`). Each DEX implementation should have thorough testing. We have multiple kinds of tests each dex must have. You can refer to [Writing Tests](#writing-testing) for detailed explanation. You can run all the tests using @@ -32,26 +32,331 @@ yarn test-integration 8. Create a PR(pull-request) from your feature branch to DexLib master. The PR must contain brief explanation about the DEX background, pricing logic, links to existing documentation, important contract addresses, and anything you think could help us review your code faster. -### Understanding the event based pricing approach +## DEX Integration Walkthrough (5 Steps) -One of the most important features of ParaSwap is to serve prices efficiently and quickly. As the number of requests grow, and blockchain get faster, it's not feasible to perform fullnode rpc calls to hundreds of pools for every pricing request. To solve this issue ParaSwap uses a novel event based pricing approach which allows to create pricing without performing the fullnode calls every time. `Event` are triggers released by the smart contract when certain changes happen. External services can easily subscribe to these events by websocket connection to a fullnode rpc. +ParaSwap optimizes price serving through an innovative event-based approach, bypassing the need for frequent fullnode RPC calls by utilizing smart contract events and in-memory state for pricing. +This method, abstracted for ease of implementation, requires DEXs to initially fetch on-chain state, subscribe to updates via events, and use the updated in-memory state for efficient pricing. -To follow ParaSwap's event based approach DEX should fetch the required on chain state to do pricing once, subscribe to events, update state when events are released, and on price request only use in memory state to create prices. To make the whole event based approach easy to implement and optimized on backend, most of the implementation logic is abstracted and developers have to only obey a simple interface. +Additionally, ParaSwap's main router, known as Augustus, is ingeniously crafted to only necessitate canonical (offchain) hints for navigating swaps across different DEXs. This design enables the seamless execution of sophisticated trading strategies that involve multiple DEXs and various layers of token swaps. This design also means that any liquidity source can be added without any contract change in most of the cases. -TODO: explain the blockmanager and stateful event subscriber +### Step 1/5: Initializing your DEX's pools state -### Good Practices for DEX integration +Typically, the first step of an integration would be to initialize its pools' state. + +This can be done either + +- greedily, initialise on starting the backend services, by overriding the `initializePricing` function in your DEX + or +- lazily, initialise on receiving a first price request involving an asset that your DEX can handle, as part of `getPricesVolume` function + +The latter is the most preferred option. + +```ts +async initializePricing(blockNumber: number) { + const poolState = await getOnChainState( + this.dexHelper.multiContract, + this.swETHAddress, + this.swETHInterface, + blockNumber, + ); + + await this.eventPool.initialize(blockNumber, { + state: poolState, + }); +} +``` + +The example above shows how the current state of the [`swETH`](https://etherscan.io/address/0xdda46bf18eeb3e06e2f12975a3a184e40581a72f#code) contract is, in this case the `swETHToEthRate`. The `getOnChainState` call is executing a Multicall contract call to the `swETHAddress` (using the swETH ABI). + +```ts +export async function getOnChainState( + multiContract: Contract, + poolAddress: string, + poolInterface: Interface, + blockNumber: number | 'latest', +): Promise { + const data: { returnData: any[] } = await multiContract.methods + .aggregate([ + { + target: poolAddress, + callData: poolInterface.encodeFunctionData('swETHToETHRate', []), + }, + ]) + .call({}, blockNumber); + + const decodedData = coder.decode(['uint256'], data.returnData[0]); + + const swETHToETHRateFixed = BigInt(decodedData[0].toString()); + + return { + swETHToETHRateFixed, + }; +} +``` + +When interacting with smart-contracts on any blockchain, you should try to be mindful of the cost of RPC calls, thus, the best approach is to use Multicall. the Multicall contract can be accessed via `this.dexHelper.multiContract` from your DEX. + +### Step 2/5: Keeping your DEX's pools state in sync + +The `initializePricing` call will take care of setting the initial state of the pool (at the time of the DEX initializing). To ensure correct pricing, you can leverage the Stateful Event Subscriber. + +Following the previous example, we can now implement a listener for the `Reprice` event, which is emitted by the `swETH` pool when the `swETH -> ETH` rate changes, which is what our DEX needs to be aware of. To do this, we can override the `processLog` method in the `StatefulEventSubscriber` declared by our DEX. This method is called when an event which the subscriber is listening to is emitted. The state will be modified after the function is called, only if a state is returned. Returning `null` will be ignored and the state will not be altered. + +```ts +decoder = (log: Log) => this.poolInterface.parseLog(log); + +protected processLog( + state: DeepReadonly, + log: Readonly, + ): AsyncOrSync | null> { + const event = this.decoder(log); + if (event.name === 'Reprice') + return { + swETHToETHRateFixed: BigInt(event.args.newSwETHToETHRate), + }; + + return null; +} +``` + +Some other DEX pools which could come in handy when implementing your own DEX pool listener. + +1. [Uniswap V3](https://github.com/paraswap/paraswap-dex-lib/blob/master/src/dex/uniswap-v3/uniswap-v3-pool.ts#L139) +2. [Nerve](https://github.com/paraswap/paraswap-dex-lib/blob/master/src/dex/nerve/nerve-pool.ts#L109) +3. [Curve V1 (Complex)](https://github.com/paraswap/paraswap-dex-lib/blob/master/src/dex/curve-v1/pools/curve-pool.ts#L81) - has multiple pools (eg 3pool, EURSPool, etc). + +### Step 3/5: Calculating your DEX's rates for a token pair and specific amount ranges + +Now that we can guarantee an up-to-date state of our pool, we need to ensure that we always provide correct pricing and rates when constructing a transaction. + +To do this, the best approach is to replicate the contract's behaviour and calculations, any mistake in the number manipulation (mathematical operations, bit shifting, etc) can lead to wrong prices and result in various scenarios, for example: + +- If the price difference is positive, it can lead to Paraswap taking the surplus and the gas fees being higher than simulated/expected. +- If the price difference is negative, it can cause transactions to fail or revert. + +Given [swETH Contract](https://etherscan.io/address/0x2d3b4bb82bdf0a3593bcf098b5c5b6f7570211a7#code) we can check how it prices the out value to the `deposit` function, and implement the counterpart on our DEX to make sure pricing is correct. + +```solidity +uint256 swETHAmount = wrap(msg.value).mul(_ethToSwETHRate()).unwrap(); +``` + +This line is taking the ETH value (`msg.value`) of the `deposit` function and multiplying it to the current `ethToSwETHRate`, since the pool keeps track of the opposite rate (`swETH -> ETH`), we need to reverse this logic. + +```ts +getPrice(blockNumber: number, ethAmount: bigint): bigint { + const state = this.getState(blockNumber); + if (!state) throw new Error('Cannot compute price'); + const { swETHToETHRateFixed } = state; + + return (ethAmount * BI_POWS[18]) / swETHToETHRateFixed; + } +``` + +### Step 4/5: Allow Augustus to swap through your DEX + +When a user wants to swap, we need to compute Augustus's calldata, this involves computing the necessary data to swap through your DEX. +Concretely, you need to abi-encode a swap through your DEX for a given placeholder amount and extra metadata about your DEX in order to allow to perform complex swaps. + +For instance, let's take the `swell` DEX integration and the `getDexParam` implementation to see how this encoding is achieved. Keep in mind that the following example was stripped down for simplicity. + +```ts +getDexParam( + srcToken: Address, + destToken: Address, + srcAmount: NumberAsString, + destAmount: NumberAsString, + recipient: Address, + data: SwellData, + side: SwapSide, + ): DexExchangeParam { + const swapData = this.swETHInterface.encodeFunctionData( + swETHFunctions.deposit, + [], + ); + + return { + needWrapNative: this.needWrapNative, + dexFuncHasRecipient: false, + exchangeData: swapData, + targetExchange: this.swETHAddress, + }; + } +``` + +
+A more advanced getDexParam example. + +```ts + getDexParam( + srcToken: Address, + destToken: Address, + srcAmount: NumberAsString, + destAmount: NumberAsString, + recipient: Address, + data: WooFiV2Data, + side: SwapSide, + ): DexExchangeParam { + if (side === SwapSide.BUY) throw new Error(`Buy not supported`); + + const _srcToken = srcToken.toLowerCase(); + const _destToken = destToken.toLowerCase(); + + const swapData = ifaces.PPV2.encodeFunctionData('swap', [ + _srcToken, + _destToken, + srcAmount, + MIN_CONVERSION_RATE, + recipient, + rebateTo, + ]); + + return { + needWrapNative: this.needWrapNative, + dexFuncHasRecipient: true, + exchangeData: swapData, + targetExchange: this.config.wooPPV2Address, + transferSrcTokenBeforeSwap: this.config.wooPPV2Address, + }; + } + +``` + +
+ +A considerable amount of abstraction is incorporated into the DEX library's upper encoding logic and Augustus to precisely set the swap amount (especially if your DEX follows another swap affected by slippage in any direction). Moreover, it ensures the successful execution of the swap by managing all necessary prerequisites, including token approvals, wrapping/unwrapping of WETH, transfers, and more. + +In order to ensure correctness of encoding please make use of these parameters: + +- `needWrapNative`: if true, tells if the DEX only deals with wrapped native tokens (eg. on Ethereum it only executes trades with wETH, not native ETH). +- `dexFuncHasRecipient`: if true, tells if the DEX can swap and transfer to an arbitrary address (`recipient`) else we would append a transfer call +- `exchangeData`: the call data required by the DEX, and typically requires targetting the contract's interface to encode data. +- `transferSrcTokenBeforeSwap`: if your DEX requires a transfer before the swap happens, rather than encoding it within the `exchangeData` +- `targetExchange`: the contract against which we swap +- `spender`: a contract that we need to approve in order to swap against `targetExchange`. If not set, then the spender will be `targetExchange` + +To verify the validity of the encoding, we recommend looking at [this link](#writing-testing) and using Tenderly to validate transactions. If the encoding is done incorrectly at the Interface level, you will see errors in your testing logs. + +### Step 5/5: Signal the most liquid tokens of your DEX + +When the ParaSwap aggregator is searching for the best connector between two or more tokens, it needs to be able to access this data in a fast and reliable manner. + +These data aggregations can be very time-consuming, include undesired data, and for FIAT calculations, result in invalid prices and such mistakes. To do this, certain DEXes implement the `getTopPoolsForToken` method, which calls specific Subgraphs (on The Graph), [eg. Uniswap V2](https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2) subgraph. + +This method will return an array of the following type: + +```ts +export type PoolLiquidity = { + exchange: string; + address: Address; + connectorTokens: Token[]; + liquidityUSD: number; +}; +``` + +We can look at the Solidly V3 implementation below, to see how the DEX interacts with a subgraph to compute the `PoolLiquidity[]`. + +
+Solidly V3 getTopPoolsForToken + +```ts + async getTopPoolsForToken( + tokenAddress: Address, + limit: number, + ): Promise { + const _tokenAddress = tokenAddress.toLowerCase(); + + const res = await this._querySubgraph( + `query ($token: Bytes!, $count: Int) { + pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token, liquidity_gt: "0"}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token, liquidity_gt: "0"}) { + id + token0 { + id + decimals + } + token1 { + id + decimals + } + totalValueLockedUSD + } + }`, + { + token: _tokenAddress, + count: limit, + }, + ); + + if (!(res && res.pools0 && res.pools1)) { + this.logger.error( + `Error_${this.dexKey}_Subgraph: couldn't fetch the pools from the subgraph`, + ); + return []; + } + + const pools0 = _.map(res.pools0, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token1.id.toLowerCase(), + decimals: parseInt(pool.token1.decimals), + }, + ], + liquidityUSD: + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + })); + + const pools1 = _.map(res.pools1, pool => ({ + exchange: this.dexKey, + address: pool.id.toLowerCase(), + connectorTokens: [ + { + address: pool.token0.id.toLowerCase(), + decimals: parseInt(pool.token0.decimals), + }, + ], + liquidityUSD: + parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, + })); + + const pools = _.slice( + _.sortBy(_.concat(pools0, pools1), [pool => -1 * pool.liquidityUSD]), + 0, + limit, + ); + return pools; + } + +``` + +
+ +#### Good Practices for DEX integration - Fullnode calls are expensive. An integration should minimize the number of fullnode rpc calls by following [Event based Pricing](#Understanding-the-event-based-pricing-approach) - Use Multicall. Instead of performing each RPC calls individually they should be batched together into multicalls. - Contract & Interface instances should be reused. There will be cases when you would be lured to create Contract/Interface objects for every dex pool to perform on-chain calls. This can lead to memory leaks in DEXes like UniswapV2 where there can be arbitrarily many pools. In such cases all the pools with the same abi should reuse the same Contract/Interface object. -### Writing Testing +## Writing Testing -- Integration Tests (`-integration.test.ts`): Tests the basic validity of the integration like prices are valid, obeys the limit pools, etc. +- Integration Tests (`-integration.test.ts`): Tests the basic validity of the integration like if prices are valid, obeys the limit pools, etc. - Events Unit Tests (`-events.test.ts`): Unit tests the event based system. This is done by fetching the state on-chain before the event, manually pushing the block logs to the event subscriber, comparing the local state with on-chain state. - E2E Tests (`-e2e.test.ts`): End to end test the integration which involves pricing, transaction building and simulating the transaction on chain using tenderly fork simulations. E2E tests use the Tenderly fork api. Please add the following to your .env file: +In order to run tests, you will need to use Tenderly and so have .env file with this environment variables + ```bash TENDERLY_TOKEN=Find this under Account>Settings>Authorization. TENDERLY_ACCOUNT_ID=Your Tenderly account name. From fdb08532fc7f88de71b64e0598a6d2585328181f Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Mon, 18 Mar 2024 17:28:53 +0100 Subject: [PATCH 818/833] Revert "Merge pull request #629 from paraswap/chore/readme-updates" This reverts commit 993101d6654799599fc4fe6ee51ab6442427cb4b, reversing changes made to cdc95769cd494e305f4c7216a4af85349a245709. --- README.md | 325 ++---------------------------------------------------- 1 file changed, 10 insertions(+), 315 deletions(-) diff --git a/README.md b/README.md index 7b10150fe..723826186 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **DexLib** is a library used by ParaSwap backend to integrate with decentralized exchanges. This library enables external DEX developers to integrate their DEX with ParaSwap by creating pull requests to this repository. -## How to add your DEX to ParaSwap +### Steps to add new exchange to DexLib 1. Fork [paraswap-dex-lib](https://github.com/paraswap/paraswap-dex-lib) to your organization or personal account. 2. Clone the repository locally and create a branch with appropriate name (eg: `feature/super-dex`) @@ -18,11 +18,11 @@ yarn install yarn init-integration ``` -You can find template code for newly integrated DEX in `src/dex/` +You can find template code for newly integrated Dex in `src/dex/` 5. Complete the template code by filling the functions implementations. Template code is highly documented which should help you build the implementation. You should look into existing DEX implementation in `src/dex/` to understand the interfaces. Please refer below for detailed explanations and good practices. -6. Add `` to `dexes` list in `src/dex/index.ts` +6. Add `` to `Dexes` list in `src/dex/index.ts` 7. Complete the test templates (All files with `src/dex//*.test.ts`). Each DEX implementation should have thorough testing. We have multiple kinds of tests each dex must have. You can refer to [Writing Tests](#writing-testing) for detailed explanation. You can run all the tests using @@ -32,331 +32,26 @@ yarn test-integration 8. Create a PR(pull-request) from your feature branch to DexLib master. The PR must contain brief explanation about the DEX background, pricing logic, links to existing documentation, important contract addresses, and anything you think could help us review your code faster. -## DEX Integration Walkthrough (5 Steps) +### Understanding the event based pricing approach -ParaSwap optimizes price serving through an innovative event-based approach, bypassing the need for frequent fullnode RPC calls by utilizing smart contract events and in-memory state for pricing. -This method, abstracted for ease of implementation, requires DEXs to initially fetch on-chain state, subscribe to updates via events, and use the updated in-memory state for efficient pricing. +One of the most important features of ParaSwap is to serve prices efficiently and quickly. As the number of requests grow, and blockchain get faster, it's not feasible to perform fullnode rpc calls to hundreds of pools for every pricing request. To solve this issue ParaSwap uses a novel event based pricing approach which allows to create pricing without performing the fullnode calls every time. `Event` are triggers released by the smart contract when certain changes happen. External services can easily subscribe to these events by websocket connection to a fullnode rpc. -Additionally, ParaSwap's main router, known as Augustus, is ingeniously crafted to only necessitate canonical (offchain) hints for navigating swaps across different DEXs. This design enables the seamless execution of sophisticated trading strategies that involve multiple DEXs and various layers of token swaps. This design also means that any liquidity source can be added without any contract change in most of the cases. +To follow ParaSwap's event based approach DEX should fetch the required on chain state to do pricing once, subscribe to events, update state when events are released, and on price request only use in memory state to create prices. To make the whole event based approach easy to implement and optimized on backend, most of the implementation logic is abstracted and developers have to only obey a simple interface. -### Step 1/5: Initializing your DEX's pools state +TODO: explain the blockmanager and stateful event subscriber -Typically, the first step of an integration would be to initialize its pools' state. - -This can be done either - -- greedily, initialise on starting the backend services, by overriding the `initializePricing` function in your DEX - or -- lazily, initialise on receiving a first price request involving an asset that your DEX can handle, as part of `getPricesVolume` function - -The latter is the most preferred option. - -```ts -async initializePricing(blockNumber: number) { - const poolState = await getOnChainState( - this.dexHelper.multiContract, - this.swETHAddress, - this.swETHInterface, - blockNumber, - ); - - await this.eventPool.initialize(blockNumber, { - state: poolState, - }); -} -``` - -The example above shows how the current state of the [`swETH`](https://etherscan.io/address/0xdda46bf18eeb3e06e2f12975a3a184e40581a72f#code) contract is, in this case the `swETHToEthRate`. The `getOnChainState` call is executing a Multicall contract call to the `swETHAddress` (using the swETH ABI). - -```ts -export async function getOnChainState( - multiContract: Contract, - poolAddress: string, - poolInterface: Interface, - blockNumber: number | 'latest', -): Promise { - const data: { returnData: any[] } = await multiContract.methods - .aggregate([ - { - target: poolAddress, - callData: poolInterface.encodeFunctionData('swETHToETHRate', []), - }, - ]) - .call({}, blockNumber); - - const decodedData = coder.decode(['uint256'], data.returnData[0]); - - const swETHToETHRateFixed = BigInt(decodedData[0].toString()); - - return { - swETHToETHRateFixed, - }; -} -``` - -When interacting with smart-contracts on any blockchain, you should try to be mindful of the cost of RPC calls, thus, the best approach is to use Multicall. the Multicall contract can be accessed via `this.dexHelper.multiContract` from your DEX. - -### Step 2/5: Keeping your DEX's pools state in sync - -The `initializePricing` call will take care of setting the initial state of the pool (at the time of the DEX initializing). To ensure correct pricing, you can leverage the Stateful Event Subscriber. - -Following the previous example, we can now implement a listener for the `Reprice` event, which is emitted by the `swETH` pool when the `swETH -> ETH` rate changes, which is what our DEX needs to be aware of. To do this, we can override the `processLog` method in the `StatefulEventSubscriber` declared by our DEX. This method is called when an event which the subscriber is listening to is emitted. The state will be modified after the function is called, only if a state is returned. Returning `null` will be ignored and the state will not be altered. - -```ts -decoder = (log: Log) => this.poolInterface.parseLog(log); - -protected processLog( - state: DeepReadonly, - log: Readonly, - ): AsyncOrSync | null> { - const event = this.decoder(log); - if (event.name === 'Reprice') - return { - swETHToETHRateFixed: BigInt(event.args.newSwETHToETHRate), - }; - - return null; -} -``` - -Some other DEX pools which could come in handy when implementing your own DEX pool listener. - -1. [Uniswap V3](https://github.com/paraswap/paraswap-dex-lib/blob/master/src/dex/uniswap-v3/uniswap-v3-pool.ts#L139) -2. [Nerve](https://github.com/paraswap/paraswap-dex-lib/blob/master/src/dex/nerve/nerve-pool.ts#L109) -3. [Curve V1 (Complex)](https://github.com/paraswap/paraswap-dex-lib/blob/master/src/dex/curve-v1/pools/curve-pool.ts#L81) - has multiple pools (eg 3pool, EURSPool, etc). - -### Step 3/5: Calculating your DEX's rates for a token pair and specific amount ranges - -Now that we can guarantee an up-to-date state of our pool, we need to ensure that we always provide correct pricing and rates when constructing a transaction. - -To do this, the best approach is to replicate the contract's behaviour and calculations, any mistake in the number manipulation (mathematical operations, bit shifting, etc) can lead to wrong prices and result in various scenarios, for example: - -- If the price difference is positive, it can lead to Paraswap taking the surplus and the gas fees being higher than simulated/expected. -- If the price difference is negative, it can cause transactions to fail or revert. - -Given [swETH Contract](https://etherscan.io/address/0x2d3b4bb82bdf0a3593bcf098b5c5b6f7570211a7#code) we can check how it prices the out value to the `deposit` function, and implement the counterpart on our DEX to make sure pricing is correct. - -```solidity -uint256 swETHAmount = wrap(msg.value).mul(_ethToSwETHRate()).unwrap(); -``` - -This line is taking the ETH value (`msg.value`) of the `deposit` function and multiplying it to the current `ethToSwETHRate`, since the pool keeps track of the opposite rate (`swETH -> ETH`), we need to reverse this logic. - -```ts -getPrice(blockNumber: number, ethAmount: bigint): bigint { - const state = this.getState(blockNumber); - if (!state) throw new Error('Cannot compute price'); - const { swETHToETHRateFixed } = state; - - return (ethAmount * BI_POWS[18]) / swETHToETHRateFixed; - } -``` - -### Step 4/5: Allow Augustus to swap through your DEX - -When a user wants to swap, we need to compute Augustus's calldata, this involves computing the necessary data to swap through your DEX. -Concretely, you need to abi-encode a swap through your DEX for a given placeholder amount and extra metadata about your DEX in order to allow to perform complex swaps. - -For instance, let's take the `swell` DEX integration and the `getDexParam` implementation to see how this encoding is achieved. Keep in mind that the following example was stripped down for simplicity. - -```ts -getDexParam( - srcToken: Address, - destToken: Address, - srcAmount: NumberAsString, - destAmount: NumberAsString, - recipient: Address, - data: SwellData, - side: SwapSide, - ): DexExchangeParam { - const swapData = this.swETHInterface.encodeFunctionData( - swETHFunctions.deposit, - [], - ); - - return { - needWrapNative: this.needWrapNative, - dexFuncHasRecipient: false, - exchangeData: swapData, - targetExchange: this.swETHAddress, - }; - } -``` - -
-A more advanced getDexParam example. - -```ts - getDexParam( - srcToken: Address, - destToken: Address, - srcAmount: NumberAsString, - destAmount: NumberAsString, - recipient: Address, - data: WooFiV2Data, - side: SwapSide, - ): DexExchangeParam { - if (side === SwapSide.BUY) throw new Error(`Buy not supported`); - - const _srcToken = srcToken.toLowerCase(); - const _destToken = destToken.toLowerCase(); - - const swapData = ifaces.PPV2.encodeFunctionData('swap', [ - _srcToken, - _destToken, - srcAmount, - MIN_CONVERSION_RATE, - recipient, - rebateTo, - ]); - - return { - needWrapNative: this.needWrapNative, - dexFuncHasRecipient: true, - exchangeData: swapData, - targetExchange: this.config.wooPPV2Address, - transferSrcTokenBeforeSwap: this.config.wooPPV2Address, - }; - } - -``` - -
- -A considerable amount of abstraction is incorporated into the DEX library's upper encoding logic and Augustus to precisely set the swap amount (especially if your DEX follows another swap affected by slippage in any direction). Moreover, it ensures the successful execution of the swap by managing all necessary prerequisites, including token approvals, wrapping/unwrapping of WETH, transfers, and more. - -In order to ensure correctness of encoding please make use of these parameters: - -- `needWrapNative`: if true, tells if the DEX only deals with wrapped native tokens (eg. on Ethereum it only executes trades with wETH, not native ETH). -- `dexFuncHasRecipient`: if true, tells if the DEX can swap and transfer to an arbitrary address (`recipient`) else we would append a transfer call -- `exchangeData`: the call data required by the DEX, and typically requires targetting the contract's interface to encode data. -- `transferSrcTokenBeforeSwap`: if your DEX requires a transfer before the swap happens, rather than encoding it within the `exchangeData` -- `targetExchange`: the contract against which we swap -- `spender`: a contract that we need to approve in order to swap against `targetExchange`. If not set, then the spender will be `targetExchange` - -To verify the validity of the encoding, we recommend looking at [this link](#writing-testing) and using Tenderly to validate transactions. If the encoding is done incorrectly at the Interface level, you will see errors in your testing logs. - -### Step 5/5: Signal the most liquid tokens of your DEX - -When the ParaSwap aggregator is searching for the best connector between two or more tokens, it needs to be able to access this data in a fast and reliable manner. - -These data aggregations can be very time-consuming, include undesired data, and for FIAT calculations, result in invalid prices and such mistakes. To do this, certain DEXes implement the `getTopPoolsForToken` method, which calls specific Subgraphs (on The Graph), [eg. Uniswap V2](https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2) subgraph. - -This method will return an array of the following type: - -```ts -export type PoolLiquidity = { - exchange: string; - address: Address; - connectorTokens: Token[]; - liquidityUSD: number; -}; -``` - -We can look at the Solidly V3 implementation below, to see how the DEX interacts with a subgraph to compute the `PoolLiquidity[]`. - -
-Solidly V3 getTopPoolsForToken - -```ts - async getTopPoolsForToken( - tokenAddress: Address, - limit: number, - ): Promise { - const _tokenAddress = tokenAddress.toLowerCase(); - - const res = await this._querySubgraph( - `query ($token: Bytes!, $count: Int) { - pools0: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token0: $token, liquidity_gt: "0"}) { - id - token0 { - id - decimals - } - token1 { - id - decimals - } - totalValueLockedUSD - } - pools1: pools(first: $count, orderBy: totalValueLockedUSD, orderDirection: desc, where: {token1: $token, liquidity_gt: "0"}) { - id - token0 { - id - decimals - } - token1 { - id - decimals - } - totalValueLockedUSD - } - }`, - { - token: _tokenAddress, - count: limit, - }, - ); - - if (!(res && res.pools0 && res.pools1)) { - this.logger.error( - `Error_${this.dexKey}_Subgraph: couldn't fetch the pools from the subgraph`, - ); - return []; - } - - const pools0 = _.map(res.pools0, pool => ({ - exchange: this.dexKey, - address: pool.id.toLowerCase(), - connectorTokens: [ - { - address: pool.token1.id.toLowerCase(), - decimals: parseInt(pool.token1.decimals), - }, - ], - liquidityUSD: - parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, - })); - - const pools1 = _.map(res.pools1, pool => ({ - exchange: this.dexKey, - address: pool.id.toLowerCase(), - connectorTokens: [ - { - address: pool.token0.id.toLowerCase(), - decimals: parseInt(pool.token0.decimals), - }, - ], - liquidityUSD: - parseFloat(pool.totalValueLockedUSD) * UNISWAPV3_EFFICIENCY_FACTOR, - })); - - const pools = _.slice( - _.sortBy(_.concat(pools0, pools1), [pool => -1 * pool.liquidityUSD]), - 0, - limit, - ); - return pools; - } - -``` - -
- -#### Good Practices for DEX integration +### Good Practices for DEX integration - Fullnode calls are expensive. An integration should minimize the number of fullnode rpc calls by following [Event based Pricing](#Understanding-the-event-based-pricing-approach) - Use Multicall. Instead of performing each RPC calls individually they should be batched together into multicalls. - Contract & Interface instances should be reused. There will be cases when you would be lured to create Contract/Interface objects for every dex pool to perform on-chain calls. This can lead to memory leaks in DEXes like UniswapV2 where there can be arbitrarily many pools. In such cases all the pools with the same abi should reuse the same Contract/Interface object. -## Writing Testing +### Writing Testing -- Integration Tests (`-integration.test.ts`): Tests the basic validity of the integration like if prices are valid, obeys the limit pools, etc. +- Integration Tests (`-integration.test.ts`): Tests the basic validity of the integration like prices are valid, obeys the limit pools, etc. - Events Unit Tests (`-events.test.ts`): Unit tests the event based system. This is done by fetching the state on-chain before the event, manually pushing the block logs to the event subscriber, comparing the local state with on-chain state. - E2E Tests (`-e2e.test.ts`): End to end test the integration which involves pricing, transaction building and simulating the transaction on chain using tenderly fork simulations. E2E tests use the Tenderly fork api. Please add the following to your .env file: -In order to run tests, you will need to use Tenderly and so have .env file with this environment variables - ```bash TENDERLY_TOKEN=Find this under Account>Settings>Authorization. TENDERLY_ACCOUNT_ID=Your Tenderly account name. From 1db27da4d1d8c27469f8c5c603470ce8845a761d Mon Sep 17 00:00:00 2001 From: Jaimi Patel Date: Fri, 22 Mar 2024 18:53:51 +0000 Subject: [PATCH 819/833] chore: add executor address to dexalot firm quote --- src/dex/dexalot/dexalot.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dex/dexalot/dexalot.ts b/src/dex/dexalot/dexalot.ts index 06ba02634..014831349 100644 --- a/src/dex/dexalot/dexalot.ts +++ b/src/dex/dexalot/dexalot.ts @@ -597,6 +597,7 @@ export class Dexalot extends SimpleExchange implements IDex { takerAmount: isSell ? optimalSwapExchange.srcAmount : undefined, userAddress: options.txOrigin, chainid: this.network, + executor: this.augustusAddress, partner: options.partner, slippage: slippageBps, }; From d74c3e7dc59fae8d2728c5f2b278554905cfc9b6 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Mon, 25 Mar 2024 12:58:56 +0300 Subject: [PATCH 820/833] 2.45.1-dexalot-executor-address.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4f3e71e79..538bfcd59 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.45.0", + "version": "2.45.1-dexalot-executor-address.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From c6e23623d9a69e1d45db4fe36b405d3e81a56467 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 2 Apr 2024 13:51:06 +0300 Subject: [PATCH 821/833] bump @paraswap/core@2.0.0 --- package.json | 2 +- src/implementations/local-paraswap-sdk.ts | 2 ++ yarn.lock | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 4f3e71e79..d9e1012df 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "@ethersproject/abi": "^5.7.0", "@hashflow/sdk": "1.2.4", "@hashflow/taker-js": "0.3.4", - "@paraswap/core": "1.1.0", + "@paraswap/core": "2.0.0", "async": "^3.2.4", "axios": "0.26.0", "bignumber.js": "9.1.0", diff --git a/src/implementations/local-paraswap-sdk.ts b/src/implementations/local-paraswap-sdk.ts index d1b573beb..46e1770a9 100644 --- a/src/implementations/local-paraswap-sdk.ts +++ b/src/implementations/local-paraswap-sdk.ts @@ -19,6 +19,7 @@ import { SwapSide, NULL_ADDRESS, ContractMethod } from '../constants'; import { LimitOrderExchange } from '../dex/limit-order-exchange'; import { v4 as uuid } from 'uuid'; import { DirectContractMethods } from '@paraswap/core/build/constants'; +import { ParaSwapVersion } from '@paraswap/core'; export interface IParaSwapSDK { getPrices( @@ -177,6 +178,7 @@ export class LocalParaswapSDK implements IParaSwapSDK { gasCost: '0', others: [], side, + version: ParaSwapVersion.V5, tokenTransferProxy: this.dexHelper.config.data.tokenTransferProxyAddress, contractAddress: this.dexHelper.config.data.augustusAddress, }; diff --git a/yarn.lock b/yarn.lock index 1cc969dce..6bef98c33 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1466,6 +1466,11 @@ resolved "https://registry.yarnpkg.com/@paraswap/core/-/core-1.1.0.tgz#5ec7415be69dc657a9d82b0fde4e20f632cca1b6" integrity sha512-ecnX8ezlhYWFwolZxYEz+K+RfLr8xaxQqiJKlxJ8Yf00tXTGxDGn6/Acy00t4+9Kv0apewd7++J33eJt9yNfwg== +"@paraswap/core@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@paraswap/core/-/core-2.0.0.tgz#be62161abec67db3cef22498a1631b12aa2d81e1" + integrity sha512-zhXSjX2dbYaRxYZt9LhzOCW/qeP0CLyvaFU7e8MkWahu/IAhyvKc/45/STDgNgTjPw1MHjNHbmi5a5pVqXyXBg== + "@paraswap/sdk@6.2.1": version "6.2.1" resolved "https://registry.yarnpkg.com/@paraswap/sdk/-/sdk-6.2.1.tgz#cbac091ae1a8f080edd64234465ef127fdbd21f6" From 2dafe74ddc968b1bd5df8387edab004ab54a09db Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Tue, 2 Apr 2024 13:51:59 +0300 Subject: [PATCH 822/833] 2.45.1-core.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d9e1012df..2b6711df0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.45.0", + "version": "2.45.1-core.2.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 3a9e021981abd982ad8fe8e1c1fd5bb61fca5087 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 3 Apr 2024 13:48:58 +0300 Subject: [PATCH 823/833] 2.46.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2b6711df0..c12e0cf1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.45.1-core.2.0", + "version": "2.46.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From d1d33d37fa5ce24047b39cd67c490c3e34c0ecfb Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 3 Apr 2024 14:16:29 +0300 Subject: [PATCH 824/833] 2.46.1-dexalot-executor-address.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 538bfcd59..ea484ea11 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.45.1-dexalot-executor-address.0", + "version": "2.46.1-dexalot-executor-address.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From cc4373b0bbc308a61f1ecb99174f924f61aea12a Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 3 Apr 2024 14:28:49 +0300 Subject: [PATCH 825/833] fix for incorrectly solved conflict --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ea484ea11..85b119ee3 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "@ethersproject/abi": "^5.7.0", "@hashflow/sdk": "1.2.4", "@hashflow/taker-js": "0.3.4", - "@paraswap/core": "1.1.0", + "@paraswap/core": "2.0.0", "async": "^3.2.4", "axios": "0.26.0", "bignumber.js": "9.1.0", From 6725c8d34069374777c8b2522ecff10142f98c61 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Wed, 3 Apr 2024 14:29:52 +0300 Subject: [PATCH 826/833] 2.46.1-dexalot-executor-address.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 85b119ee3..aae376308 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.46.1-dexalot-executor-address.0", + "version": "2.46.1-dexalot-executor-address.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From d51d6a32ea7be53bba5ac89cb470baa59c137f30 Mon Sep 17 00:00:00 2001 From: Alexander Burkut Date: Thu, 4 Apr 2024 12:09:20 +0300 Subject: [PATCH 827/833] 2.46.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index aae376308..726f543a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.46.1-dexalot-executor-address.1", + "version": "2.46.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From c00012ab1e036390d1a3f19bf5546ecf98de80c9 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 5 Apr 2024 20:50:31 +0200 Subject: [PATCH 828/833] uniswapV2: add missing chains --- src/dex/uniswap-v2/config.ts | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/dex/uniswap-v2/config.ts b/src/dex/uniswap-v2/config.ts index 9845fc2ec..2749cdeac 100644 --- a/src/dex/uniswap-v2/config.ts +++ b/src/dex/uniswap-v2/config.ts @@ -150,6 +150,48 @@ export const UniswapV2Config: DexConfigMap = { poolGasCost: 80 * 1000, feeCode: 30, }, + [Network.ARBITRUM]: { + factoryAddress: '0xf1D7CC64Fb4452F05c498126312eBE29f30Fbcf9', + initCode: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + poolGasCost: 80 * 1000, + feeCode: 30, + }, + [Network.AVALANCHE]: { + factoryAddress: '0x9e5A52f57b3038F1B8EeE45F28b3C1967e22799C', + initCode: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + poolGasCost: 80 * 1000, + feeCode: 30, + }, + [Network.BSC]: { + factoryAddress: '0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6', + initCode: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + poolGasCost: 80 * 1000, + feeCode: 30, + }, + [Network.BASE]: { + factoryAddress: '0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6', + initCode: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + poolGasCost: 80 * 1000, + feeCode: 30, + }, + [Network.OPTIMISM]: { + factoryAddress: '0x0c3c1c532F1e39EdF36BE9Fe0bE1410313E074Bf', + initCode: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + poolGasCost: 80 * 1000, + feeCode: 30, + }, + [Network.POLYGON]: { + factoryAddress: '0x9e5A52f57b3038F1B8EeE45F28b3C1967e22799C', + initCode: + '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f', + poolGasCost: 80 * 1000, + feeCode: 30, + }, }, ApeSwap: { [Network.BSC]: { From fad623870e54568b0b838d342c62834233fe17dc Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 5 Apr 2024 20:51:15 +0200 Subject: [PATCH 829/833] 2.47.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 726f543a0..4c8600abd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.46.1", + "version": "2.47.0", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From 4b3f55ab6d6fd962c15af2528c4598db4e4cd5b4 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 5 Apr 2024 21:02:19 +0200 Subject: [PATCH 830/833] fix uniswapV2 alias to be always univ2 --- src/dex/uniswap-v2/constants.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/dex/uniswap-v2/constants.ts b/src/dex/uniswap-v2/constants.ts index 80c5d890a..6a654568c 100644 --- a/src/dex/uniswap-v2/constants.ts +++ b/src/dex/uniswap-v2/constants.ts @@ -48,10 +48,13 @@ export const UniswapForksWithNetwork = transformToNetworkMap({ export const UniswapV2Alias: { [network: number]: string } = { [Network.MAINNET]: 'uniswapv2', [Network.ROPSTEN]: 'uniswapv2', - [Network.BSC]: 'pancakeswap', - [Network.POLYGON]: 'quickswap', - [Network.AVALANCHE]: 'pangolinswap', + [Network.BSC]: 'uniswapv2', + [Network.POLYGON]: 'uniswapv2', + [Network.AVALANCHE]: 'uniswapv2', + [Network.ARBITRUM]: 'uniswapv2', + [Network.OPTIMISM]: 'uniswapv2', + [Network.BASE]: 'uniswapv2', + + // use only to handle UniswapForkOptimized build with this dex [Network.FANTOM]: 'spookyswap', - [Network.ARBITRUM]: 'sushiswap', - [Network.OPTIMISM]: 'zipswap', }; From 4091e7fb8634457c1cc06bf47fdfca4e8403ecfe Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Fri, 5 Apr 2024 21:02:58 +0200 Subject: [PATCH 831/833] 2.47.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4c8600abd..6881620fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.47.0", + "version": "2.47.1", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib", From f620a0570fd3c2e6fcb55f9a5c62ba79a9bc7124 Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sun, 7 Apr 2024 11:53:20 +0200 Subject: [PATCH 832/833] balancer-v2: disable investment pool --- src/dex/balancer-v2/balancer-v2.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dex/balancer-v2/balancer-v2.ts b/src/dex/balancer-v2/balancer-v2.ts index d6c34b3bf..f71de9e44 100644 --- a/src/dex/balancer-v2/balancer-v2.ts +++ b/src/dex/balancer-v2/balancer-v2.ts @@ -111,6 +111,7 @@ const disabledPoolIds = [ '0x8a6b25e33b12d1bb6929a8793961076bd1f9d3eb0002000000000000000003e8', '0x959216bb492b2efa72b15b7aacea5b5c984c3cca000200000000000000000472', '0x9b692f571b256140a39a34676bffa30634c586e100000000000000000000059d', + '0xe7b1d394f3b40abeaa0b64a545dbcf89da1ecb3f00010000000000000000009a', // polygon '0xb3d658d5b95bf04e2932370dd1ff976fe18dd66a000000000000000000000ace', From 03d15616452f75334fbae371e672ac79c5fbc8ae Mon Sep 17 00:00:00 2001 From: Mohamed Hassen Mami Date: Sun, 7 Apr 2024 11:53:58 +0200 Subject: [PATCH 833/833] 2.47.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6881620fd..aafb6f781 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@paraswap/dex-lib", - "version": "2.47.1", + "version": "2.47.2", "main": "build/index.js", "types": "build/index.d.ts", "repository": "https://github.com/paraswap/paraswap-dex-lib",