From 7ae44c930cad7d477b9d1edf5ae483686fee8c99 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Fri, 4 Aug 2023 13:21:54 +0300 Subject: [PATCH 01/24] Added support for single factory swaps in utils --- package.json | 2 +- src/utils/arrayHelpers.ts | 29 +++ src/utils/generateSwapCalldata.ts | 293 ++++++++++++++++++++++++++++++ 3 files changed, 323 insertions(+), 1 deletion(-) create mode 100644 src/utils/arrayHelpers.ts create mode 100644 src/utils/generateSwapCalldata.ts diff --git a/package.json b/package.json index 501882e..793e234 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "@babel/runtime": "^7.21.0", "@ethersproject/abstract-signer": "^5.7.0", "@ethersproject/providers": "^5.7.2", - "@orionprotocol/contracts": "1.9.0", + "@orionprotocol/contracts": "1.16.1", "bignumber.js": "^9.1.1", "bson-objectid": "^2.0.4", "buffer": "^6.0.3", diff --git a/src/utils/arrayHelpers.ts b/src/utils/arrayHelpers.ts new file mode 100644 index 0000000..fc583e2 --- /dev/null +++ b/src/utils/arrayHelpers.ts @@ -0,0 +1,29 @@ +declare global { + interface Array { + get(index: number): T; + last(): T + first(): T + } +} + +if (!Array.prototype.get) { + Array.prototype.get = function (this: T[], index: number): T { + const value = this.at(index); + if (value === undefined) { + throw new Error(`Element at index ${index} is undefined. Array: ${this}`) + } + return value + } +} + +if (!Array.prototype.last) { + Array.prototype.last = function (this: T[]): T { + return this.get(this.length - 1) + } +} + +if (!Array.prototype.first) { + Array.prototype.first = function (this: T[]): T { + return this.get(0) + } +} \ No newline at end of file diff --git a/src/utils/generateSwapCalldata.ts b/src/utils/generateSwapCalldata.ts new file mode 100644 index 0000000..b6ba623 --- /dev/null +++ b/src/utils/generateSwapCalldata.ts @@ -0,0 +1,293 @@ +import type { ExchangeWithGenericSwap } from '@orionprotocol/contracts/lib/ethers-v5/Exchange.js'; +import { UniswapV3Pool__factory, ERC20__factory, SwapExecutor__factory, CurveRegistry__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js'; +import { BigNumber, ethers } from 'ethers'; +import { concat, defaultAbiCoder, type BytesLike } from 'ethers/lib/utils.js'; + +type Factory = "UniswapV2" | "UniswapV3" | "Curve" | "OrionV2" | "OrionV3" + +export type SwapInfo = { + pool: string, + assetIn: string, + assetOut: string, + factory: Factory +} + +type CallParams = { + isMandatory?: boolean, + target?: string, + gaslimit?: BigNumber, + value?: BigNumber +} + +export default async function generateSwapCalldata( + amount: string, + minReturnAmount: string, + receiverAddress: string, + exchangeAddress: string, + executorAddress: string, + path: SwapInfo[], + weth: string, + curveRegistry: string, + provider: ethers.providers.JsonRpcProvider +): Promise<{ calldata: string, swapDescription: ExchangeWithGenericSwap.SwapDescriptionStruct }> { + if (path == undefined || path.length == 0) { + throw new Error(`Empty path`); + } + const factory = path.first().factory + + if (!path.every(e => e.factory === factory)) { + throw new Error(`Supporting only swaps with single factory`); + } + + const swapDescription: ExchangeWithGenericSwap.SwapDescriptionStruct = { + srcToken: path.first().assetIn, + dstToken: path.last().assetOut, + srcReceiver: executorAddress, + dstReceiver: receiverAddress, + amount: amount, + minReturnAmount: minReturnAmount, + flags: 0 + } + let calldata: string + switch (factory) { + case "OrionV2": { + swapDescription.srcReceiver = path.first().pool + calldata = await generateUni2Calls(exchangeAddress, path); + break; + } + case "UniswapV2": { + swapDescription.srcReceiver = path.first().pool + calldata = await generateUni2Calls(exchangeAddress, path); + break; + } + case "UniswapV3": { + calldata = await generateUni3Calls(amount, exchangeAddress, weth, path, provider) + break; + } + case "OrionV3": { + calldata = await generateOrion3Calls(amount, exchangeAddress, weth, path, provider) + break; + } + case "Curve": { + calldata = await generateCurveStableSwapCalls(amount, exchangeAddress, executorAddress, path, provider, curveRegistry); + break; + } + default: { + throw new Error(`Factory ${factory} is not supported`) + } + } + return { swapDescription, calldata } +} + + + +export async function generateUni2Calls( + exchangeAddress: string, + path: SwapInfo[] +) { + const executorInterface = SwapExecutor__factory.createInterface() + const calls: BytesLike[] = [] + if (path.length > 1) { + for (let i = 0; i < path.length - 1; ++i) { + const currentSwap = path.get(i) + const nextSwap = path.get(i + 1) + + const calldata = executorInterface.encodeFunctionData("swapUniV2", [ + currentSwap.pool, + currentSwap.assetIn, + currentSwap.assetOut, + defaultAbiCoder.encode(["uint256"], [concat(["0x03", nextSwap.pool])]), + ] + ) + calls.push(addCallParams(calldata)) + } + } + const lastSwap = path.last(); + const calldata = executorInterface.encodeFunctionData("swapUniV2", [ + lastSwap.pool, + lastSwap.assetIn, + lastSwap.assetOut, + defaultAbiCoder.encode(["uint256"], [concat(["0x03", exchangeAddress])]), + ]) + calls.push(addCallParams(calldata)) + + return generateCalls(calls) +} + +export async function generateUni3Calls( + amount: string, + exchangeAddress: string, + weth: string, + path: SwapInfo[], + provider: ethers.providers.JsonRpcProvider +) { + const encodedPools: BytesLike[] = [] + for (const swap of path) { + const pool = UniswapV3Pool__factory.connect(swap.pool, provider) + const token0 = await pool.token0() + const zeroForOne = token0 === swap.assetIn + const unwrapWETH = swap.assetOut === ethers.constants.AddressZero + if (unwrapWETH) { + swap.assetOut = weth + } + + let encodedPool = ethers.utils.solidityPack(["uint256"], [pool.address]) + encodedPool = ethers.utils.hexDataSlice(encodedPool, 1) + let firstByte = 0 + if (unwrapWETH) firstByte += 32 + if (!zeroForOne) firstByte += 128 + const encodedFirstByte = ethers.utils.solidityPack(["uint8"], [firstByte]) + encodedPool = ethers.utils.hexlify(ethers.utils.concat([encodedFirstByte, encodedPool])) + encodedPools.push(encodedPool) + } + const executorInterface = SwapExecutor__factory.createInterface() + let calldata = executorInterface.encodeFunctionData("uniswapV3SwapTo", [encodedPools, exchangeAddress, amount]) + calldata = addCallParams(calldata) + + return generateCalls([calldata]) +} + +export async function generateOrion3Calls( + amount: string, + exchangeAddress: string, + weth: string, + path: SwapInfo[], + provider: ethers.providers.JsonRpcProvider +) { + const encodedPools: BytesLike[] = [] + for (const swap of path) { + const pool = UniswapV3Pool__factory.connect(swap.pool, provider) + const token0 = await pool.token0() + const zeroForOne = token0 === swap.assetIn + const unwrapWETH = swap.assetOut === ethers.constants.AddressZero + if (unwrapWETH) { + swap.assetOut = weth + } + + let encodedPool = ethers.utils.solidityPack(["uint256"], [pool.address]) + encodedPool = ethers.utils.hexDataSlice(encodedPool, 1) + let firstByte = 0 + if (unwrapWETH) firstByte += 32 + if (!zeroForOne) firstByte += 128 + const encodedFirstByte = ethers.utils.solidityPack(["uint8"], [firstByte]) + encodedPool = ethers.utils.hexlify(ethers.utils.concat([encodedFirstByte, encodedPool])) + encodedPools.push(encodedPool) + } + const executorInterface = SwapExecutor__factory.createInterface() + let calldata = executorInterface.encodeFunctionData("orionV3SwapTo", [encodedPools, exchangeAddress, amount]) + calldata = addCallParams(calldata) + + return generateCalls([calldata]) +} + +export async function generateCurveStableSwapCalls( + amount: string, + exchangeAddress: string, + executorAddress: string, + path: SwapInfo[], + provider: ethers.providers.JsonRpcProvider, + curveRegistry: string +) { + if (path.length > 1) { + throw new Error("Supporting only single stable swap on curve") + } + const executorInterface = SwapExecutor__factory.createInterface() + const registry = CurveRegistry__factory.connect(curveRegistry, provider) + + const swap = path.first() + const firstToken = ERC20__factory.connect(swap.assetIn, provider) + const { pool, assetIn, assetOut } = swap + const [i, j,] = await registry.get_coin_indices(pool, assetIn, assetOut) + + const executorAllowance = await firstToken.allowance(executorAddress, swap.pool) + const calls: BytesLike[] = [] + if (executorAllowance.lt(amount)) { + const calldata = addCallParams( + executorInterface.encodeFunctionData("safeApprove", [ + swap.assetIn, + swap.pool, + ethers.constants.MaxUint256 + ]) + ) + calls.push(calldata) + } + let calldata = executorInterface.encodeFunctionData("curveSwapStableAmountIn", [ + pool, + assetOut, + i, + j, + amount, + 0, + exchangeAddress + ]) + + calldata = addCallParams(calldata) + calls.push(calldata) + + return generateCalls(calls) +} + +export function addCallParams( + calldata: BytesLike, + callParams?: CallParams +) { + let firstByte = 0 + if (callParams) { + if (callParams.value !== undefined) { + firstByte += 16 + const encodedValue = ethers.utils.solidityPack(["uint128"], [callParams.value]) + calldata = ethers.utils.hexlify(ethers.utils.concat([encodedValue, calldata])) + } + if (callParams.target !== undefined) { + firstByte += 32 + const encodedAddress = ethers.utils.solidityPack(["address"], [callParams.target]) + calldata = ethers.utils.hexlify(ethers.utils.concat([encodedAddress, calldata])) + } + if (callParams.gaslimit !== undefined) { + firstByte += 64 + const encodedGaslimit = ethers.utils.solidityPack(["uint32"], [callParams.gaslimit]) + calldata = ethers.utils.hexlify(ethers.utils.concat([encodedGaslimit, calldata])) + } + if (callParams.isMandatory !== undefined) firstByte += 128 + } + + const encodedFirstByte = ethers.utils.solidityPack(["uint8"], [firstByte]) + calldata = ethers.utils.hexlify(ethers.utils.concat([encodedFirstByte, calldata])) + return calldata +} + + +export async function generateCalls(calls: BytesLike[]) { + const executorInterface = SwapExecutor__factory.createInterface() + return "0x" + executorInterface.encodeFunctionData("func_70LYiww", [ethers.constants.AddressZero, calls]).slice(74) +} + +declare global { + interface Array { + get(index: number): T; + last(): T + first(): T + } +} + +if (!Array.prototype.get) { + Array.prototype.get = function (this: T[], index: number): T { + const value = this.at(index); + if (value === undefined) { + throw new Error(`Element at index ${index} is undefined. Array: ${this}`) + } + return value + } +} + +if (!Array.prototype.last) { + Array.prototype.last = function (this: T[]): T { + return this.get(this.length - 1) + } +} + +if (!Array.prototype.first) { + Array.prototype.first = function (this: T[]): T { + return this.get(0) + } +} \ No newline at end of file From 232fae6631262956601600ad967a55e718bc0bf8 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Fri, 4 Aug 2023 13:27:45 +0300 Subject: [PATCH 02/24] Updated package-lock.json --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index da8adff..3a2bd24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,18 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.34", + "version": "0.19.41", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@orionprotocol/sdk", - "version": "0.19.34", + "version": "0.19.41", "license": "ISC", "dependencies": { "@babel/runtime": "^7.21.0", "@ethersproject/abstract-signer": "^5.7.0", "@ethersproject/providers": "^5.7.2", - "@orionprotocol/contracts": "1.9.0", + "@orionprotocol/contracts": "1.16.1", "bignumber.js": "^9.1.1", "bson-objectid": "^2.0.4", "buffer": "^6.0.3", @@ -2330,9 +2330,9 @@ } }, "node_modules/@orionprotocol/contracts": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-1.9.0.tgz", - "integrity": "sha512-nYShitqtgVoz5BiXPapZ0Fi+IaW4ufBLGFeHki7ZRV6oXgwDuXoCbD0kLGdOUZDeDjzuMqGRolbrI3PAoI3Lpg==" + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-1.16.1.tgz", + "integrity": "sha512-2Y7oubSfjP5Xn+1ldAY051DrvF2LLoLewGyFbwf1bKlUzbhDNGF2noBO0mWU5sQNQf7eCC913YCob3lvd3AvyQ==" }, "node_modules/@sinclair/typebox": { "version": "0.25.23", From 98bac7f86d04d4d451ded1b55d4a2c5d4c8f82f5 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Sat, 5 Aug 2023 16:42:51 +0300 Subject: [PATCH 03/24] Created array subclass with safeGetter --- src/utils/arrayHelpers.ts | 29 ------------------------ src/utils/safeGetters.ts | 47 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 29 deletions(-) delete mode 100644 src/utils/arrayHelpers.ts create mode 100644 src/utils/safeGetters.ts diff --git a/src/utils/arrayHelpers.ts b/src/utils/arrayHelpers.ts deleted file mode 100644 index fc583e2..0000000 --- a/src/utils/arrayHelpers.ts +++ /dev/null @@ -1,29 +0,0 @@ -declare global { - interface Array { - get(index: number): T; - last(): T - first(): T - } -} - -if (!Array.prototype.get) { - Array.prototype.get = function (this: T[], index: number): T { - const value = this.at(index); - if (value === undefined) { - throw new Error(`Element at index ${index} is undefined. Array: ${this}`) - } - return value - } -} - -if (!Array.prototype.last) { - Array.prototype.last = function (this: T[]): T { - return this.get(this.length - 1) - } -} - -if (!Array.prototype.first) { - Array.prototype.first = function (this: T[]): T { - return this.get(0) - } -} \ No newline at end of file diff --git a/src/utils/safeGetters.ts b/src/utils/safeGetters.ts new file mode 100644 index 0000000..944f498 --- /dev/null +++ b/src/utils/safeGetters.ts @@ -0,0 +1,47 @@ +export class SafeArray extends Array { + + public static override from(array: T[]): SafeArray { + return new SafeArray(array); + } + + constructor(array: T[]) { + super(array.length); + array.forEach((element, index) => { + this[index] = element; + }) + } + + public toArray(): T[] { + return [...this]; + } + + public override map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): SafeArray { + return new SafeArray(super.map(callbackfn, thisArg)); + } + + public override filter(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): SafeArray { + return new SafeArray(super.filter(callbackfn, thisArg)); + } + + public get(this: SafeArray, index: number): T { + const value = this.at(index); + if (value === undefined) { + throw new Error(`Element at index ${index} is undefined. Array: ${this}`) + } + return value + } + + public last(this: SafeArray): T { + return this.get(this.length - 1) + } + + public first(this: SafeArray): T { + return this.get(0) + } +} + +export function safeGet(obj: Partial>, key: string, errorMessage?: string) { + const value = obj[key]; + if (value === undefined) throw new Error(`Key '${key.toString()}' not found in object. Available keys: ${Object.keys(obj).join(', ')}.${errorMessage ? ` ${errorMessage}` : ''}`); + return value; +} \ No newline at end of file From d9ca7cba1ad857451bef71a062a3ae181047e6c6 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Sat, 5 Aug 2023 16:43:58 +0300 Subject: [PATCH 04/24] moved generateSwapCalldata to Exchange unit --- .../Exchange}/generateSwapCalldata.ts | 113 ++++++++---------- src/Unit/Exchange/index.ts | 12 +- src/Unit/index.ts | 6 +- 3 files changed, 65 insertions(+), 66 deletions(-) rename src/{utils => Unit/Exchange}/generateSwapCalldata.ts (78%) diff --git a/src/utils/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts similarity index 78% rename from src/utils/generateSwapCalldata.ts rename to src/Unit/Exchange/generateSwapCalldata.ts index b6ba623..9c86866 100644 --- a/src/utils/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -2,8 +2,11 @@ import type { ExchangeWithGenericSwap } from '@orionprotocol/contracts/lib/ether import { UniswapV3Pool__factory, ERC20__factory, SwapExecutor__factory, CurveRegistry__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js'; import { BigNumber, ethers } from 'ethers'; import { concat, defaultAbiCoder, type BytesLike } from 'ethers/lib/utils.js'; +import { safeGet, type SafeArray } from '../../utils/safeGetters.js'; +import type Unit from '../index.js'; +import { simpleFetch } from 'simple-typed-fetch'; -type Factory = "UniswapV2" | "UniswapV3" | "Curve" | "OrionV2" | "OrionV3" +export type Factory = "UniswapV2" | "UniswapV3" | "Curve" | "OrionV2" | "OrionV3" export type SwapInfo = { pool: string, @@ -12,24 +15,33 @@ export type SwapInfo = { factory: Factory } -type CallParams = { +export type CallParams = { isMandatory?: boolean, target?: string, gaslimit?: BigNumber, value?: BigNumber } -export default async function generateSwapCalldata( +export type GenerateSwapCalldataParams = { amount: string, minReturnAmount: string, receiverAddress: string, - exchangeAddress: string, - executorAddress: string, - path: SwapInfo[], - weth: string, - curveRegistry: string, - provider: ethers.providers.JsonRpcProvider + path: SafeArray, + unit: Unit +} + +export default async function generateSwapCalldata({ + amount, + minReturnAmount, + receiverAddress, + path, + unit +}: GenerateSwapCalldataParams ): Promise<{ calldata: string, swapDescription: ExchangeWithGenericSwap.SwapDescriptionStruct }> { + const wethAddress = safeGet(unit.contracts, "WETH") + const curveRegistryAddress = safeGet(unit.contracts, "curveRegistry") + const { exchangeContractAddress, swapExecutorContractAddress } = await simpleFetch(unit.blockchainService.getInfo)(); + if (path == undefined || path.length == 0) { throw new Error(`Empty path`); } @@ -42,34 +54,42 @@ export default async function generateSwapCalldata( const swapDescription: ExchangeWithGenericSwap.SwapDescriptionStruct = { srcToken: path.first().assetIn, dstToken: path.last().assetOut, - srcReceiver: executorAddress, + srcReceiver: swapExecutorContractAddress, dstReceiver: receiverAddress, amount: amount, minReturnAmount: minReturnAmount, flags: 0 } + let calldata: string switch (factory) { case "OrionV2": { swapDescription.srcReceiver = path.first().pool - calldata = await generateUni2Calls(exchangeAddress, path); + calldata = await generateUni2Calls(exchangeContractAddress, path); break; } case "UniswapV2": { swapDescription.srcReceiver = path.first().pool - calldata = await generateUni2Calls(exchangeAddress, path); + calldata = await generateUni2Calls(exchangeContractAddress, path); break; } case "UniswapV3": { - calldata = await generateUni3Calls(amount, exchangeAddress, weth, path, provider) + calldata = await generateUni3Calls(amount, exchangeContractAddress, wethAddress, path, unit.provider) break; } case "OrionV3": { - calldata = await generateOrion3Calls(amount, exchangeAddress, weth, path, provider) + calldata = await generateOrion3Calls(amount, exchangeContractAddress, wethAddress, path, unit.provider) break; } case "Curve": { - calldata = await generateCurveStableSwapCalls(amount, exchangeAddress, executorAddress, path, provider, curveRegistry); + calldata = await generateCurveStableSwapCalls( + amount, + exchangeContractAddress, + swapExecutorContractAddress, + path, + unit.provider, + curveRegistryAddress + ); break; } default: { @@ -83,7 +103,7 @@ export default async function generateSwapCalldata( export async function generateUni2Calls( exchangeAddress: string, - path: SwapInfo[] + path: SafeArray ) { const executorInterface = SwapExecutor__factory.createInterface() const calls: BytesLike[] = [] @@ -114,11 +134,11 @@ export async function generateUni2Calls( return generateCalls(calls) } -export async function generateUni3Calls( +async function generateUni3Calls( amount: string, - exchangeAddress: string, + exchangeContractAddress: string, weth: string, - path: SwapInfo[], + path: SafeArray, provider: ethers.providers.JsonRpcProvider ) { const encodedPools: BytesLike[] = [] @@ -141,17 +161,17 @@ export async function generateUni3Calls( encodedPools.push(encodedPool) } const executorInterface = SwapExecutor__factory.createInterface() - let calldata = executorInterface.encodeFunctionData("uniswapV3SwapTo", [encodedPools, exchangeAddress, amount]) + let calldata = executorInterface.encodeFunctionData("uniswapV3SwapTo", [encodedPools, exchangeContractAddress, amount]) calldata = addCallParams(calldata) return generateCalls([calldata]) } -export async function generateOrion3Calls( +async function generateOrion3Calls( amount: string, - exchangeAddress: string, + exchangeContractAddress: string, weth: string, - path: SwapInfo[], + path: SafeArray, provider: ethers.providers.JsonRpcProvider ) { const encodedPools: BytesLike[] = [] @@ -174,17 +194,17 @@ export async function generateOrion3Calls( encodedPools.push(encodedPool) } const executorInterface = SwapExecutor__factory.createInterface() - let calldata = executorInterface.encodeFunctionData("orionV3SwapTo", [encodedPools, exchangeAddress, amount]) + let calldata = executorInterface.encodeFunctionData("orionV3SwapTo", [encodedPools, exchangeContractAddress, amount]) calldata = addCallParams(calldata) return generateCalls([calldata]) } -export async function generateCurveStableSwapCalls( +async function generateCurveStableSwapCalls( amount: string, - exchangeAddress: string, + exchangeContractAddress: string, executorAddress: string, - path: SwapInfo[], + path: SafeArray, provider: ethers.providers.JsonRpcProvider, curveRegistry: string ) { @@ -204,7 +224,7 @@ export async function generateCurveStableSwapCalls( if (executorAllowance.lt(amount)) { const calldata = addCallParams( executorInterface.encodeFunctionData("safeApprove", [ - swap.assetIn, + swap.assetIn, swap.pool, ethers.constants.MaxUint256 ]) @@ -218,8 +238,7 @@ export async function generateCurveStableSwapCalls( j, amount, 0, - exchangeAddress - ]) + exchangeContractAddress]) calldata = addCallParams(calldata) calls.push(calldata) @@ -227,7 +246,7 @@ export async function generateCurveStableSwapCalls( return generateCalls(calls) } -export function addCallParams( +function addCallParams( calldata: BytesLike, callParams?: CallParams ) { @@ -257,37 +276,7 @@ export function addCallParams( } -export async function generateCalls(calls: BytesLike[]) { +async function generateCalls(calls: BytesLike[]) { const executorInterface = SwapExecutor__factory.createInterface() return "0x" + executorInterface.encodeFunctionData("func_70LYiww", [ethers.constants.AddressZero, calls]).slice(74) -} - -declare global { - interface Array { - get(index: number): T; - last(): T - first(): T - } -} - -if (!Array.prototype.get) { - Array.prototype.get = function (this: T[], index: number): T { - const value = this.at(index); - if (value === undefined) { - throw new Error(`Element at index ${index} is undefined. Array: ${this}`) - } - return value - } -} - -if (!Array.prototype.last) { - Array.prototype.last = function (this: T[]): T { - return this.get(this.length - 1) - } -} - -if (!Array.prototype.first) { - Array.prototype.first = function (this: T[]): T { - return this.get(0) - } } \ No newline at end of file diff --git a/src/Unit/Exchange/index.ts b/src/Unit/Exchange/index.ts index c5d36cc..2c90119 100644 --- a/src/Unit/Exchange/index.ts +++ b/src/Unit/Exchange/index.ts @@ -1,8 +1,8 @@ import type Unit from '../index.js'; import deposit, { type DepositParams } from './deposit.js'; import getSwapInfo, { type GetSwapInfoParams } from './getSwapInfo.js'; -import type { SwapLimitParams } from './swapLimit.js'; -import swapLimit from './swapLimit.js'; +import generateSwapCalldata, { type GenerateSwapCalldataParams } from './generateSwapCalldata.js'; +import swapLimit, {type SwapLimitParams} from './swapLimit.js'; import swapMarket, { type SwapMarketParams } from './swapMarket.js'; import withdraw, { type WithdrawParams } from './withdraw.js'; @@ -11,6 +11,7 @@ type PureSwapLimitParams = Omit type PureDepositParams = Omit type PureWithdrawParams = Omit type PureGetSwapMarketInfoParams = Omit +type PureGenerateSwapCalldataParams = Omit export default class Exchange { private readonly unit: Unit; @@ -54,4 +55,11 @@ export default class Exchange { unit: this.unit, }); } + + public generateSwapCalldata(params: PureGenerateSwapCalldataParams) { + return generateSwapCalldata({ + ...params, + unit: this.unit + }) + } } diff --git a/src/Unit/index.ts b/src/Unit/index.ts index b9fb66c..c8b4462 100644 --- a/src/Unit/index.ts +++ b/src/Unit/index.ts @@ -32,6 +32,8 @@ export default class Unit { public readonly config: VerboseUnitConfig; + public readonly contracts: Record; + constructor(config: KnownConfig | VerboseUnitConfig) { if ('env' in config) { const staticConfig = envs[config.env]; @@ -42,7 +44,6 @@ export default class Unit { const networkConfig = staticConfig.networks[config.chainId]; if (!networkConfig) throw new Error(`Invalid chainId: ${config.chainId}. Available chainIds: ${Object.keys(staticConfig.networks).join(', ')}`); - this.config = { chainId: config.chainId, nodeJsonRpc: networkConfig.rpc ?? chainConfig.rpc, @@ -64,9 +65,10 @@ export default class Unit { } const chainInfo = chains[config.chainId]; if (!chainInfo) throw new Error('Chain info is required'); - + this.chainId = config.chainId; this.networkCode = chainInfo.code; + this.contracts = chainInfo.contracts const intNetwork = parseInt(this.chainId, 10); if (Number.isNaN(intNetwork)) throw new Error('Invalid chainId (not a number)' + this.chainId); this.provider = new ethers.providers.StaticJsonRpcProvider(this.config.nodeJsonRpc, intNetwork); From 03056563f26009b99f8ce646200b9c8292a86446 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Sat, 5 Aug 2023 16:44:36 +0300 Subject: [PATCH 05/24] Update schemas due to generateSwapCalldata method --- src/config/chains.json | 80 +++++++++++++++---- src/config/schemas/pureChainSchema.ts | 1 + .../BlockchainService/schemas/infoSchema.ts | 1 + 3 files changed, 68 insertions(+), 14 deletions(-) diff --git a/src/config/chains.json b/src/config/chains.json index d5de68c..f4b4d29 100644 --- a/src/config/chains.json +++ b/src/config/chains.json @@ -6,7 +6,11 @@ "shortName": "ETH", "code": "eth", "rpc": "https://trade.orionprotocol.io/rpc", - "baseCurrencyName": "ETH" + "baseCurrencyName": "ETH", + "contracts": { + "WETH": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "curveRegistry": "0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5" + } }, "56": { "chainId": "56", @@ -15,7 +19,11 @@ "shortName": "BSC", "code": "bsc", "rpc": "https://bsc-dataseed.binance.org/", - "baseCurrencyName": "BNB" + "baseCurrencyName": "BNB", + "contracts": { + "WETH": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", + "curveRegistry": "" + } }, "97": { "chainId": "97", @@ -24,7 +32,11 @@ "shortName": "BSC-Testnet", "code": "bsc", "rpc": "https://bsc-stage.node.orionprotocol.io/", - "baseCurrencyName": "BNB" + "baseCurrencyName": "BNB", + "contracts": { + "WETH": "0x23eE96bEaAB62abE126AA192e677c52bB7d274F0", + "curveRegistry": "0x8845b36C3DE93379F468590FFa102D4aF8C49A6c" + } }, "3": { "chainId": "3", @@ -33,7 +45,11 @@ "shortName": "ETH-Ropsten", "code": "eth", "rpc": "https://testing.orionprotocol.io/eth-ropsten/rpc", - "baseCurrencyName": "ETH" + "baseCurrencyName": "ETH", + "contracts": { + "WETH": "", + "curveRegistry": "" + } }, "5": { "chainId": "5", @@ -42,7 +58,11 @@ "shortName": "ETH-Goerli", "code": "eth", "rpc": "https://testing.orionprotocol.io/eth-goerli/rpc", - "baseCurrencyName": "ETH" + "baseCurrencyName": "ETH", + "contracts": { + "WETH": "", + "curveRegistry": "" + } }, "421613": { "chainId": "421613", @@ -51,7 +71,11 @@ "shortName": "Arbitrum Goerli", "code": "arb", "rpc": "https://goerli-rollup.arbitrum.io/rpc", - "baseCurrencyName": "ETH" + "baseCurrencyName": "ETH", + "contracts": { + "WETH": "", + "curveRegistry": "" + } }, "4002": { "chainId": "4002", @@ -60,7 +84,11 @@ "shortName": "FTM-Testnet", "code": "ftm", "rpc": "https://testing.orionprotocol.io/ftm-testnet/rpc", - "baseCurrencyName": "FTM" + "baseCurrencyName": "FTM", + "contracts": { + "WETH": "", + "curveRegistry": "" + } }, "250": { "chainId": "250", @@ -69,7 +97,11 @@ "shortName": "FTM", "code": "ftm", "rpc": "https://rpcapi.fantom.network/", - "baseCurrencyName": "FTM" + "baseCurrencyName": "FTM", + "contracts": { + "WETH": "", + "curveRegistry": "" + } }, "137": { "chainId": "137", @@ -78,7 +110,11 @@ "code": "polygon", "baseCurrencyName": "MATIC", "rpc": "https://polygon-rpc.com/", - "explorer": "https://polygonscan.com/" + "explorer": "https://polygonscan.com/", + "contracts": { + "WETH": "", + "curveRegistry": "" + } }, "80001": { "chainId": "80001", @@ -87,7 +123,11 @@ "code": "polygon", "baseCurrencyName": "MATIC", "rpc": "https://rpc-mumbai.matic.today", - "explorer": "https://mumbai.polygonscan.com/" + "explorer": "https://mumbai.polygonscan.com/", + "contracts": { + "WETH": "", + "curveRegistry": "" + } }, "66": { "chainId": "66", @@ -96,7 +136,11 @@ "shortName": "OKC", "code": "okc", "rpc": "https://exchainrpc.okex.org/", - "baseCurrencyName": "OKT" + "baseCurrencyName": "OKT", + "contracts": { + "WETH": "", + "curveRegistry": "" + } }, "65": { "chainId": "65", @@ -105,7 +149,11 @@ "shortName": "OKC-Testnet", "code": "okc", "rpc": "https://exchaintestrpc.okex.org/", - "baseCurrencyName": "OKT" + "baseCurrencyName": "OKT", + "contracts": { + "WETH": "", + "curveRegistry": "" + } }, "56303": { "chainId": "56303", @@ -114,6 +162,10 @@ "code": "drip", "baseCurrencyName": "DRIP", "rpc": "testnet.1d.rip", - "explorer": "https://explorer-testnet.1d.rip/" + "explorer": "https://explorer-testnet.1d.rip/", + "contracts": { + "WETH": "", + "curveRegistry": "" + } } -} +} \ No newline at end of file diff --git a/src/config/schemas/pureChainSchema.ts b/src/config/schemas/pureChainSchema.ts index abc224b..9c45941 100644 --- a/src/config/schemas/pureChainSchema.ts +++ b/src/config/schemas/pureChainSchema.ts @@ -10,6 +10,7 @@ export const pureChainInfoPayloadSchema = z.object({ explorer: z.string(), rpc: z.string(), baseCurrencyName: z.string(), + contracts: z.record(z.string(), z.string()) }); export const pureChainInfoSchema = z.record( diff --git a/src/services/BlockchainService/schemas/infoSchema.ts b/src/services/BlockchainService/schemas/infoSchema.ts index 326f18e..472a895 100644 --- a/src/services/BlockchainService/schemas/infoSchema.ts +++ b/src/services/BlockchainService/schemas/infoSchema.ts @@ -11,6 +11,7 @@ const infoSchema = z.object({ chainId: z.number(), chainName: z.string(), exchangeContractAddress: z.string(), + swapExecutorContractAddress: z.string(), oracleContractAddress: z.string(), matcherAddress: z.string(), orderFeePercent: z.number(), From 9fcccdcfd67ad25766b2c158f6ede5592f5c2569 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Sun, 6 Aug 2023 13:16:39 +0300 Subject: [PATCH 06/24] update version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 793e234..56ad85e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.41", + "version": "0.19.42", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", From 8bac672bfdd813ce2e79ff50873ded8632c5ec84 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Sun, 6 Aug 2023 13:18:14 +0300 Subject: [PATCH 07/24] SafeArray from Arraylike --- src/Unit/Exchange/generateSwapCalldata.ts | 5 ++--- src/utils/safeGetters.ts | 16 ++++++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Unit/Exchange/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts index 9c86866..2bfeefa 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -2,7 +2,7 @@ import type { ExchangeWithGenericSwap } from '@orionprotocol/contracts/lib/ether import { UniswapV3Pool__factory, ERC20__factory, SwapExecutor__factory, CurveRegistry__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js'; import { BigNumber, ethers } from 'ethers'; import { concat, defaultAbiCoder, type BytesLike } from 'ethers/lib/utils.js'; -import { safeGet, type SafeArray } from '../../utils/safeGetters.js'; +import { safeGet, SafeArray } from '../../utils/safeGetters.js'; import type Unit from '../index.js'; import { simpleFetch } from 'simple-typed-fetch'; @@ -46,7 +46,6 @@ export default async function generateSwapCalldata({ throw new Error(`Empty path`); } const factory = path.first().factory - if (!path.every(e => e.factory === factory)) { throw new Error(`Supporting only swaps with single factory`); } @@ -60,7 +59,7 @@ export default async function generateSwapCalldata({ minReturnAmount: minReturnAmount, flags: 0 } - + let calldata: string switch (factory) { case "OrionV2": { diff --git a/src/utils/safeGetters.ts b/src/utils/safeGetters.ts index 944f498..3bf4336 100644 --- a/src/utils/safeGetters.ts +++ b/src/utils/safeGetters.ts @@ -1,14 +1,18 @@ export class SafeArray extends Array { - public static override from(array: T[]): SafeArray { + public static override from(array: ArrayLike): SafeArray { return new SafeArray(array); } - constructor(array: T[]) { + constructor(array: ArrayLike) { super(array.length); - array.forEach((element, index) => { - this[index] = element; - }) + for (const index in array) { + const value = array[index] + if (value === undefined) { + throw new Error("Array passed to constructor has undefined values") + } + this[index] = value + } } public toArray(): T[] { @@ -26,7 +30,7 @@ export class SafeArray extends Array { public get(this: SafeArray, index: number): T { const value = this.at(index); if (value === undefined) { - throw new Error(`Element at index ${index} is undefined. Array: ${this}`) + throw new Error(`Element at index ${index} is undefined.`) } return value } From e9d908445d74dfa024c976306b0d57f3d5b355ee Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Sun, 6 Aug 2023 13:21:50 +0300 Subject: [PATCH 08/24] update version once again --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 56ad85e..686d15d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.42", + "version": "0.19.46", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", From e205ebeb970f1a48f71e264c5e143235e0cf349e Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Mon, 7 Aug 2023 10:30:52 +0300 Subject: [PATCH 09/24] minor fixes --- src/Unit/Exchange/generateSwapCalldata.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Unit/Exchange/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts index 2bfeefa..ed32ea9 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -6,6 +6,8 @@ import { safeGet, SafeArray } from '../../utils/safeGetters.js'; import type Unit from '../index.js'; import { simpleFetch } from 'simple-typed-fetch'; +const EXECUTOR_SWAP_FUNCTION = "func_70LYiww" + export type Factory = "UniswapV2" | "UniswapV3" | "Curve" | "OrionV2" | "OrionV3" export type SwapInfo = { @@ -26,7 +28,7 @@ export type GenerateSwapCalldataParams = { amount: string, minReturnAmount: string, receiverAddress: string, - path: SafeArray, + path: ArrayLike, unit: Unit } @@ -34,13 +36,14 @@ export default async function generateSwapCalldata({ amount, minReturnAmount, receiverAddress, - path, + path: path_, unit }: GenerateSwapCalldataParams ): Promise<{ calldata: string, swapDescription: ExchangeWithGenericSwap.SwapDescriptionStruct }> { const wethAddress = safeGet(unit.contracts, "WETH") const curveRegistryAddress = safeGet(unit.contracts, "curveRegistry") const { exchangeContractAddress, swapExecutorContractAddress } = await simpleFetch(unit.blockchainService.getInfo)(); + const path = SafeArray.from(path_) if (path == undefined || path.length == 0) { throw new Error(`Empty path`); @@ -245,28 +248,29 @@ async function generateCurveStableSwapCalls( return generateCalls(calls) } +// Adds additional byte to single swap with settings function addCallParams( calldata: BytesLike, callParams?: CallParams ) { let firstByte = 0 if (callParams) { - if (callParams.value !== undefined) { - firstByte += 16 + if (callParams.value !== undefined) { + firstByte += 16 // 00000010 const encodedValue = ethers.utils.solidityPack(["uint128"], [callParams.value]) calldata = ethers.utils.hexlify(ethers.utils.concat([encodedValue, calldata])) } if (callParams.target !== undefined) { - firstByte += 32 + firstByte += 32 // 00000100 const encodedAddress = ethers.utils.solidityPack(["address"], [callParams.target]) calldata = ethers.utils.hexlify(ethers.utils.concat([encodedAddress, calldata])) } if (callParams.gaslimit !== undefined) { - firstByte += 64 + firstByte += 64 // 00000100 const encodedGaslimit = ethers.utils.solidityPack(["uint32"], [callParams.gaslimit]) calldata = ethers.utils.hexlify(ethers.utils.concat([encodedGaslimit, calldata])) } - if (callParams.isMandatory !== undefined) firstByte += 128 + if (callParams.isMandatory !== undefined) firstByte += 128 // 00001000 } const encodedFirstByte = ethers.utils.solidityPack(["uint8"], [firstByte]) @@ -277,5 +281,5 @@ function addCallParams( async function generateCalls(calls: BytesLike[]) { const executorInterface = SwapExecutor__factory.createInterface() - return "0x" + executorInterface.encodeFunctionData("func_70LYiww", [ethers.constants.AddressZero, calls]).slice(74) + return "0x" + executorInterface.encodeFunctionData(EXECUTOR_SWAP_FUNCTION, [ethers.constants.AddressZero, calls]).slice(74) } \ No newline at end of file From 994d76639106f9dc9174232da89344f5222d9eac Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Mon, 7 Aug 2023 12:10:55 +0300 Subject: [PATCH 10/24] Add conditional paremeters --- src/Unit/Exchange/generateSwapCalldata.ts | 15 +++++++++++++-- src/utils/safeGetters.ts | 9 +++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Unit/Exchange/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts index ed32ea9..f3fd6f4 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -2,7 +2,7 @@ import type { ExchangeWithGenericSwap } from '@orionprotocol/contracts/lib/ether import { UniswapV3Pool__factory, ERC20__factory, SwapExecutor__factory, CurveRegistry__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js'; import { BigNumber, ethers } from 'ethers'; import { concat, defaultAbiCoder, type BytesLike } from 'ethers/lib/utils.js'; -import { safeGet, SafeArray } from '../../utils/safeGetters.js'; +import must, { safeGet, SafeArray } from '../../utils/safeGetters.js'; import type Unit from '../index.js'; import { simpleFetch } from 'simple-typed-fetch'; @@ -29,6 +29,8 @@ export type GenerateSwapCalldataParams = { minReturnAmount: string, receiverAddress: string, path: ArrayLike, + exchangeContractAddress?: string, + swapExecutorContractAddress?: string, unit: Unit } @@ -37,12 +39,21 @@ export default async function generateSwapCalldata({ minReturnAmount, receiverAddress, path: path_, + exchangeContractAddress, + swapExecutorContractAddress, unit }: GenerateSwapCalldataParams ): Promise<{ calldata: string, swapDescription: ExchangeWithGenericSwap.SwapDescriptionStruct }> { const wethAddress = safeGet(unit.contracts, "WETH") const curveRegistryAddress = safeGet(unit.contracts, "curveRegistry") - const { exchangeContractAddress, swapExecutorContractAddress } = await simpleFetch(unit.blockchainService.getInfo)(); + if (swapExecutorContractAddress === undefined || swapExecutorContractAddress === undefined) { + const info = await simpleFetch(unit.blockchainService.getInfo)(); + if (swapExecutorContractAddress === undefined) swapExecutorContractAddress = info.swapExecutorContractAddress + if (exchangeContractAddress === undefined) exchangeContractAddress = info.exchangeContractAddress + } + must(swapExecutorContractAddress !== undefined) + must(exchangeContractAddress !== undefined) + const path = SafeArray.from(path_) if (path == undefined || path.length == 0) { diff --git a/src/utils/safeGetters.ts b/src/utils/safeGetters.ts index 3bf4336..17f273f 100644 --- a/src/utils/safeGetters.ts +++ b/src/utils/safeGetters.ts @@ -48,4 +48,13 @@ export function safeGet(obj: Partial>, key: string, errorMe const value = obj[key]; if (value === undefined) throw new Error(`Key '${key.toString()}' not found in object. Available keys: ${Object.keys(obj).join(', ')}.${errorMessage ? ` ${errorMessage}` : ''}`); return value; +} + +const prefix = 'Requirement not met'; + +export default function must(condition: unknown, message?: string | (() => string)): asserts condition { + if (condition) return; + const provided = typeof message === 'function' ? message() : message; + const value = provided ? `${prefix}: ${provided}` : prefix; + throw new Error(value); } \ No newline at end of file From f64738ec6ad9071d7f4546bfc8669776c653736d Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Wed, 9 Aug 2023 13:19:05 +0300 Subject: [PATCH 11/24] Removed conditional params, added exchange->factory record --- package-lock.json | 4 +- src/Unit/Exchange/generateSwapCalldata.ts | 56 ++++++++++++++--------- src/utils/safeGetters.ts | 2 +- 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3a2bd24..281bb66 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.41", + "version": "0.19.46", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@orionprotocol/sdk", - "version": "0.19.41", + "version": "0.19.46", "license": "ISC", "dependencies": { "@babel/runtime": "^7.21.0", diff --git a/src/Unit/Exchange/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts index f3fd6f4..1679376 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -2,19 +2,38 @@ import type { ExchangeWithGenericSwap } from '@orionprotocol/contracts/lib/ether import { UniswapV3Pool__factory, ERC20__factory, SwapExecutor__factory, CurveRegistry__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js'; import { BigNumber, ethers } from 'ethers'; import { concat, defaultAbiCoder, type BytesLike } from 'ethers/lib/utils.js'; -import must, { safeGet, SafeArray } from '../../utils/safeGetters.js'; +import { safeGet, SafeArray } from '../../utils/safeGetters.js'; import type Unit from '../index.js'; import { simpleFetch } from 'simple-typed-fetch'; +import type { Exchange } from '../../types.js'; const EXECUTOR_SWAP_FUNCTION = "func_70LYiww" export type Factory = "UniswapV2" | "UniswapV3" | "Curve" | "OrionV2" | "OrionV3" +const exchangeToType: Partial> = { + 'SPOOKYSWAP': 'UniswapV2', + 'PANCAKESWAP': 'UniswapV2', + 'UNISWAP': 'UniswapV2', + 'QUICKSWAP': 'UniswapV2', + 'ORION_POOL': 'UniswapV2', + 'CHERRYSWAP': 'UniswapV2', + 'OKXSWAP': 'UniswapV2', + 'INTERNAL_POOL_V2': 'UniswapV2', + 'INTERNAL_POOL_V3': "OrionV3", + 'INTERNAL_POOL_V3_0_01': "OrionV3", + 'INTERNAL_POOL_V3_0_05': "OrionV3", + 'INTERNAL_POOL_V3_0_3': "OrionV3", + 'INTERNAL_POOL_V3_1_0': "OrionV3", + 'CURVE': "Curve", + 'CURVE_FACTORY': "Curve", +} + export type SwapInfo = { pool: string, assetIn: string, assetOut: string, - factory: Factory + factory: Exchange } export type CallParams = { @@ -29,8 +48,6 @@ export type GenerateSwapCalldataParams = { minReturnAmount: string, receiverAddress: string, path: ArrayLike, - exchangeContractAddress?: string, - swapExecutorContractAddress?: string, unit: Unit } @@ -39,28 +56,25 @@ export default async function generateSwapCalldata({ minReturnAmount, receiverAddress, path: path_, - exchangeContractAddress, - swapExecutorContractAddress, unit }: GenerateSwapCalldataParams ): Promise<{ calldata: string, swapDescription: ExchangeWithGenericSwap.SwapDescriptionStruct }> { - const wethAddress = safeGet(unit.contracts, "WETH") - const curveRegistryAddress = safeGet(unit.contracts, "curveRegistry") - if (swapExecutorContractAddress === undefined || swapExecutorContractAddress === undefined) { - const info = await simpleFetch(unit.blockchainService.getInfo)(); - if (swapExecutorContractAddress === undefined) swapExecutorContractAddress = info.swapExecutorContractAddress - if (exchangeContractAddress === undefined) exchangeContractAddress = info.exchangeContractAddress - } - must(swapExecutorContractAddress !== undefined) - must(exchangeContractAddress !== undefined) - - const path = SafeArray.from(path_) - - if (path == undefined || path.length == 0) { + if (path_ == undefined || path_.length == 0) { throw new Error(`Empty path`); } + const wethAddress = safeGet(unit.contracts, "WETH") + const curveRegistryAddress = safeGet(unit.contracts, "curveRegistry") + const {assetToAddress, swapExecutorContractAddress, exchangeContractAddress} = await simpleFetch(unit.blockchainService.getInfo)(); + + const path = SafeArray.from(path_).map((swapInfo) => { + const swapInfoWithAddresses: SwapInfo = swapInfo + swapInfoWithAddresses.assetIn = safeGet(assetToAddress, swapInfo.assetIn); + swapInfoWithAddresses.assetOut = safeGet(assetToAddress, swapInfo.assetOut); + return swapInfoWithAddresses; + }); + const factory = path.first().factory - if (!path.every(e => e.factory === factory)) { + if (!path.every(swapInfo => swapInfo.factory === factory)) { throw new Error(`Supporting only swaps with single factory`); } @@ -75,7 +89,7 @@ export default async function generateSwapCalldata({ } let calldata: string - switch (factory) { + switch (exchangeToType[factory]) { case "OrionV2": { swapDescription.srcReceiver = path.first().pool calldata = await generateUni2Calls(exchangeContractAddress, path); diff --git a/src/utils/safeGetters.ts b/src/utils/safeGetters.ts index 17f273f..0da1797 100644 --- a/src/utils/safeGetters.ts +++ b/src/utils/safeGetters.ts @@ -52,7 +52,7 @@ export function safeGet(obj: Partial>, key: string, errorMe const prefix = 'Requirement not met'; -export default function must(condition: unknown, message?: string | (() => string)): asserts condition { +export function must(condition: unknown, message?: string | (() => string)): asserts condition { if (condition) return; const provided = typeof message === 'function' ? message() : message; const value = provided ? `${prefix}: ${provided}` : prefix; From b92ba570f825a04a8d6f19242424c4368a2b62ef Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Wed, 9 Aug 2023 13:24:47 +0300 Subject: [PATCH 12/24] Upd version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 686d15d..8994810 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.46", + "version": "0.19.48-dev.1", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", From 452da5ad875a27f70e0fd4f4a6e79c6fed4cf887 Mon Sep 17 00:00:00 2001 From: Dmitriy Pavlov Date: Thu, 10 Aug 2023 14:19:04 +0300 Subject: [PATCH 13/24] add eps field to swap --- package-lock.json | 4 ++-- package.json | 2 +- src/services/Aggregator/ws/schemas/swapInfoSchema.ts | 6 ++++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 281bb66..20d7a15 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.46", + "version": "0.19.48-dev.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@orionprotocol/sdk", - "version": "0.19.46", + "version": "0.19.48-dev.1", "license": "ISC", "dependencies": { "@babel/runtime": "^7.21.0", diff --git a/package.json b/package.json index 8994810..bd43adb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.48-dev.1", + "version": "0.19.48-dev.1-rc-0", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", diff --git a/src/services/Aggregator/ws/schemas/swapInfoSchema.ts b/src/services/Aggregator/ws/schemas/swapInfoSchema.ts index 7cc8e35..9c383e6 100644 --- a/src/services/Aggregator/ws/schemas/swapInfoSchema.ts +++ b/src/services/Aggregator/ws/schemas/swapInfoSchema.ts @@ -34,6 +34,12 @@ const swapInfoSchemaBase = baseMessageSchema.extend({ }).optional(), as: alternativeSchema.array(), anm: z.record(z.string()).optional(), // address to ERC20 names + eps: z.array(z.object({ + p: z.string(), + ai: z.string().toUpperCase(), + ao: z.string().toUpperCase(), + f: z.string().toUpperCase(), + })) }); const swapInfoSchemaByAmountIn = swapInfoSchemaBase.extend({ From 4af3da4bf58f307c2a5bf4371a778706a11a2f9b Mon Sep 17 00:00:00 2001 From: Dmitriy Pavlov Date: Thu, 10 Aug 2023 14:34:24 +0300 Subject: [PATCH 14/24] add field comments --- src/services/Aggregator/ws/schemas/swapInfoSchema.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/services/Aggregator/ws/schemas/swapInfoSchema.ts b/src/services/Aggregator/ws/schemas/swapInfoSchema.ts index 9c383e6..9607cb2 100644 --- a/src/services/Aggregator/ws/schemas/swapInfoSchema.ts +++ b/src/services/Aggregator/ws/schemas/swapInfoSchema.ts @@ -35,10 +35,10 @@ const swapInfoSchemaBase = baseMessageSchema.extend({ as: alternativeSchema.array(), anm: z.record(z.string()).optional(), // address to ERC20 names eps: z.array(z.object({ - p: z.string(), - ai: z.string().toUpperCase(), - ao: z.string().toUpperCase(), - f: z.string().toUpperCase(), + p: z.string(), // pool address + ai: z.string().toUpperCase(), // asset in + ao: z.string().toUpperCase(), // asset out + f: z.string().toUpperCase(), // factory })) }); From a886c343d370157c76ea952db2d4e36d2935f98e Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Thu, 10 Aug 2023 15:26:12 +0300 Subject: [PATCH 15/24] Removed Exchange type --- src/Unit/Exchange/generateSwapCalldata.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Unit/Exchange/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts index 1679376..15f7399 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -5,13 +5,12 @@ import { concat, defaultAbiCoder, type BytesLike } from 'ethers/lib/utils.js'; import { safeGet, SafeArray } from '../../utils/safeGetters.js'; import type Unit from '../index.js'; import { simpleFetch } from 'simple-typed-fetch'; -import type { Exchange } from '../../types.js'; const EXECUTOR_SWAP_FUNCTION = "func_70LYiww" export type Factory = "UniswapV2" | "UniswapV3" | "Curve" | "OrionV2" | "OrionV3" -const exchangeToType: Partial> = { +const exchangeToType: Partial> = { 'SPOOKYSWAP': 'UniswapV2', 'PANCAKESWAP': 'UniswapV2', 'UNISWAP': 'UniswapV2', @@ -33,7 +32,7 @@ export type SwapInfo = { pool: string, assetIn: string, assetOut: string, - factory: Exchange + factory: string } export type CallParams = { From 8ea9cdfbd49db5caf3e9a04d8f685162810d1142 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Thu, 10 Aug 2023 15:29:22 +0300 Subject: [PATCH 16/24] upd version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b95422..187a515 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.48-dev.1", + "version": "0.19.48-dev.2", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", From df38bfdc2cf3cdd89e6f34f060c19b4d9937bcd8 Mon Sep 17 00:00:00 2001 From: Dmitriy Pavlov Date: Thu, 10 Aug 2023 18:46:10 +0300 Subject: [PATCH 17/24] add eps types to services --- package.json | 2 +- src/Unit/Exchange/generateSwapCalldata.ts | 4 +--- src/services/Aggregator/ws/index.ts | 6 ++++++ src/types.ts | 8 ++++++++ 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 1f69f76..8cc0e0a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.48-dev.2-rc-0", + "version": "0.19.48-dev.2-rc-1", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", diff --git a/src/Unit/Exchange/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts index 15f7399..b525e12 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -125,8 +125,6 @@ export default async function generateSwapCalldata({ return { swapDescription, calldata } } - - export async function generateUni2Calls( exchangeAddress: string, path: SafeArray @@ -306,4 +304,4 @@ function addCallParams( async function generateCalls(calls: BytesLike[]) { const executorInterface = SwapExecutor__factory.createInterface() return "0x" + executorInterface.encodeFunctionData(EXECUTOR_SWAP_FUNCTION, [ethers.constants.AddressZero, calls]).slice(74) -} \ No newline at end of file +} diff --git a/src/services/Aggregator/ws/index.ts b/src/services/Aggregator/ws/index.ts index c014e6c..9aed556 100644 --- a/src/services/Aggregator/ws/index.ts +++ b/src/services/Aggregator/ws/index.ts @@ -500,6 +500,12 @@ class AggregatorWS { minAmountIn: json.ma, path: json.ps, exchanges: json.e, + exchangeContractPath: json.eps.map((path) => ({ + poolAddress: path.p, + assetIn: path.ai, + assetOut: path.ao, + factory: path.f, + })), poolOptimal: json.po, ...(json.oi) && { orderInfo: { diff --git a/src/types.ts b/src/types.ts index 0c19b6c..3d8e434 100644 --- a/src/types.ts +++ b/src/types.ts @@ -164,6 +164,13 @@ export type SwapInfoAlternative = { availableAmountOut?: number | undefined } +type ExchangeContractPath = { + poolAddress: string + assetIn: string + assetOut: string + factory: string +} + export type SwapInfoBase = { swapRequestId: string assetIn: string @@ -174,6 +181,7 @@ export type SwapInfoBase = { minAmountOut: number path: string[] + exchangeContractPath: ExchangeContractPath[] exchanges?: string[] | undefined poolOptimal: boolean From 12bd1bc069a77d3989e41f86f81aead967c10e51 Mon Sep 17 00:00:00 2001 From: Dmitriy Pavlov Date: Thu, 10 Aug 2023 19:05:40 +0300 Subject: [PATCH 18/24] change type names --- package.json | 2 +- src/services/Aggregator/ws/index.ts | 2 +- src/types.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 8cc0e0a..1303923 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.48-dev.2-rc-1", + "version": "0.19.48-dev.2-rc-2", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", diff --git a/src/services/Aggregator/ws/index.ts b/src/services/Aggregator/ws/index.ts index 9aed556..f6e6729 100644 --- a/src/services/Aggregator/ws/index.ts +++ b/src/services/Aggregator/ws/index.ts @@ -501,7 +501,7 @@ class AggregatorWS { path: json.ps, exchanges: json.e, exchangeContractPath: json.eps.map((path) => ({ - poolAddress: path.p, + pool: path.p, assetIn: path.ai, assetOut: path.ao, factory: path.f, diff --git a/src/types.ts b/src/types.ts index 3d8e434..78c6f8b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -165,7 +165,7 @@ export type SwapInfoAlternative = { } type ExchangeContractPath = { - poolAddress: string + pool: string assetIn: string assetOut: string factory: string From c118230818c60e4768673ac750f1c0ae95bc6394 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Mon, 21 Aug 2023 09:15:29 +0300 Subject: [PATCH 19/24] Convert ZeroAddress to WETH in path --- package.json | 2 +- src/Unit/Exchange/generateSwapCalldata.ts | 31 ++++++++++------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 187a515..4c48708 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.48-dev.2", + "version": "0.19.48-dev.3", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", diff --git a/src/Unit/Exchange/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts index 15f7399..2d866c8 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -64,14 +64,11 @@ export default async function generateSwapCalldata({ const wethAddress = safeGet(unit.contracts, "WETH") const curveRegistryAddress = safeGet(unit.contracts, "curveRegistry") const {assetToAddress, swapExecutorContractAddress, exchangeContractAddress} = await simpleFetch(unit.blockchainService.getInfo)(); - - const path = SafeArray.from(path_).map((swapInfo) => { - const swapInfoWithAddresses: SwapInfo = swapInfo - swapInfoWithAddresses.assetIn = safeGet(assetToAddress, swapInfo.assetIn); - swapInfoWithAddresses.assetOut = safeGet(assetToAddress, swapInfo.assetOut); - return swapInfoWithAddresses; - }); - + let path = SafeArray.from(path_).map((swapInfo) => { + swapInfo.assetIn = safeGet(assetToAddress, swapInfo.assetIn); + swapInfo.assetOut = safeGet(assetToAddress, swapInfo.assetOut); + return swapInfo; + }) const factory = path.first().factory if (!path.every(swapInfo => swapInfo.factory === factory)) { throw new Error(`Supporting only swaps with single factory`); @@ -86,6 +83,12 @@ export default async function generateSwapCalldata({ minReturnAmount: minReturnAmount, flags: 0 } + path = SafeArray.from(path_).map((swapInfo) => { + if (swapInfo.assetIn == ethers.constants.AddressZero) swapInfo.assetIn = wethAddress + if (swapInfo.assetOut == ethers.constants.AddressZero) swapInfo.assetOut = wethAddress + return swapInfo; + }); + let calldata: string switch (exchangeToType[factory]) { @@ -100,11 +103,11 @@ export default async function generateSwapCalldata({ break; } case "UniswapV3": { - calldata = await generateUni3Calls(amount, exchangeContractAddress, wethAddress, path, unit.provider) + calldata = await generateUni3Calls(amount, exchangeContractAddress, path, unit.provider) break; } case "OrionV3": { - calldata = await generateOrion3Calls(amount, exchangeContractAddress, wethAddress, path, unit.provider) + calldata = await generateOrion3Calls(amount, exchangeContractAddress, path, unit.provider) break; } case "Curve": { @@ -163,7 +166,6 @@ export async function generateUni2Calls( async function generateUni3Calls( amount: string, exchangeContractAddress: string, - weth: string, path: SafeArray, provider: ethers.providers.JsonRpcProvider ) { @@ -173,9 +175,6 @@ async function generateUni3Calls( const token0 = await pool.token0() const zeroForOne = token0 === swap.assetIn const unwrapWETH = swap.assetOut === ethers.constants.AddressZero - if (unwrapWETH) { - swap.assetOut = weth - } let encodedPool = ethers.utils.solidityPack(["uint256"], [pool.address]) encodedPool = ethers.utils.hexDataSlice(encodedPool, 1) @@ -196,7 +195,6 @@ async function generateUni3Calls( async function generateOrion3Calls( amount: string, exchangeContractAddress: string, - weth: string, path: SafeArray, provider: ethers.providers.JsonRpcProvider ) { @@ -206,9 +204,6 @@ async function generateOrion3Calls( const token0 = await pool.token0() const zeroForOne = token0 === swap.assetIn const unwrapWETH = swap.assetOut === ethers.constants.AddressZero - if (unwrapWETH) { - swap.assetOut = weth - } let encodedPool = ethers.utils.solidityPack(["uint256"], [pool.address]) encodedPool = ethers.utils.hexDataSlice(encodedPool, 1) From 7416a6cfbfc86d433f142fd905744edfba2494bd Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Wed, 23 Aug 2023 22:06:44 +0300 Subject: [PATCH 20/24] Correct exchange precision --- package.json | 2 +- src/Unit/Exchange/generateSwapCalldata.ts | 33 ++++++++++++++++------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index d74e240..e5727c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.48-dev.4", + "version": "0.19.48-dev.5", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", diff --git a/src/Unit/Exchange/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts index 2d866c8..5f64878 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -1,10 +1,11 @@ import type { ExchangeWithGenericSwap } from '@orionprotocol/contracts/lib/ethers-v5/Exchange.js'; import { UniswapV3Pool__factory, ERC20__factory, SwapExecutor__factory, CurveRegistry__factory } from '@orionprotocol/contracts/lib/ethers-v5/index.js'; -import { BigNumber, ethers } from 'ethers'; +import { BigNumber, ethers, type BigNumberish } from 'ethers'; import { concat, defaultAbiCoder, type BytesLike } from 'ethers/lib/utils.js'; import { safeGet, SafeArray } from '../../utils/safeGetters.js'; import type Unit from '../index.js'; import { simpleFetch } from 'simple-typed-fetch'; +import type { PromiseOrValue } from '@orionprotocol/contracts/lib/ethers-v5/common.js'; const EXECUTOR_SWAP_FUNCTION = "func_70LYiww" @@ -43,8 +44,8 @@ export type CallParams = { } export type GenerateSwapCalldataParams = { - amount: string, - minReturnAmount: string, + amount: BigNumberish, + minReturnAmount: BigNumberish, receiverAddress: string, path: ArrayLike, unit: Unit @@ -73,7 +74,7 @@ export default async function generateSwapCalldata({ if (!path.every(swapInfo => swapInfo.factory === factory)) { throw new Error(`Supporting only swaps with single factory`); } - + const swapDescription: ExchangeWithGenericSwap.SwapDescriptionStruct = { srcToken: path.first().assetIn, dstToken: path.last().assetOut, @@ -83,6 +84,18 @@ export default async function generateSwapCalldata({ minReturnAmount: minReturnAmount, flags: 0 } + + const exchangeToNativeDecimals = async (token: PromiseOrValue) => { + token = await token + let decimals = 18 + if (token !== ethers.constants.AddressZero) { + const contract = ERC20__factory.connect(token, unit.provider) + decimals = await contract.decimals() + } + return BigNumber.from(amount).mul(BigNumber.from(10).pow(decimals)).div(BigNumber.from(10).pow(8)) + } + const amountNativeDecimals = await exchangeToNativeDecimals(swapDescription.srcToken); + path = SafeArray.from(path_).map((swapInfo) => { if (swapInfo.assetIn == ethers.constants.AddressZero) swapInfo.assetIn = wethAddress if (swapInfo.assetOut == ethers.constants.AddressZero) swapInfo.assetOut = wethAddress @@ -103,16 +116,16 @@ export default async function generateSwapCalldata({ break; } case "UniswapV3": { - calldata = await generateUni3Calls(amount, exchangeContractAddress, path, unit.provider) + calldata = await generateUni3Calls(amountNativeDecimals, exchangeContractAddress, path, unit.provider) break; } case "OrionV3": { - calldata = await generateOrion3Calls(amount, exchangeContractAddress, path, unit.provider) + calldata = await generateOrion3Calls(amountNativeDecimals, exchangeContractAddress, path, unit.provider) break; } case "Curve": { calldata = await generateCurveStableSwapCalls( - amount, + amountNativeDecimals, exchangeContractAddress, swapExecutorContractAddress, path, @@ -164,7 +177,7 @@ export async function generateUni2Calls( } async function generateUni3Calls( - amount: string, + amount: BigNumberish, exchangeContractAddress: string, path: SafeArray, provider: ethers.providers.JsonRpcProvider @@ -193,7 +206,7 @@ async function generateUni3Calls( } async function generateOrion3Calls( - amount: string, + amount: BigNumberish, exchangeContractAddress: string, path: SafeArray, provider: ethers.providers.JsonRpcProvider @@ -222,7 +235,7 @@ async function generateOrion3Calls( } async function generateCurveStableSwapCalls( - amount: string, + amount: BigNumberish, exchangeContractAddress: string, executorAddress: string, path: SafeArray, From 64b61db6a96486b0689f911f225b65db9b40ebbc Mon Sep 17 00:00:00 2001 From: Dmitriy Pavlov Date: Thu, 24 Aug 2023 10:36:48 +0300 Subject: [PATCH 21/24] update deps --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index bba9579..ccf76bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.48-dev.5-rc0", + "version": "0.19.48-dev.6-rc-0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@orionprotocol/sdk", - "version": "0.19.48-dev.5-rc0", + "version": "0.19.48-dev.6-rc-0", "hasInstallScript": true, "license": "ISC", "dependencies": { From 7671c41013ff524e671681302d295d81f4f8adbd Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Thu, 24 Aug 2023 12:33:37 +0300 Subject: [PATCH 22/24] case insensitive address compare --- src/Unit/Exchange/generateSwapCalldata.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Unit/Exchange/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts index 5f64878..39b14c0 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -186,7 +186,7 @@ async function generateUni3Calls( for (const swap of path) { const pool = UniswapV3Pool__factory.connect(swap.pool, provider) const token0 = await pool.token0() - const zeroForOne = token0 === swap.assetIn + const zeroForOne = token0.toLowerCase() === swap.assetIn.toLowerCase() const unwrapWETH = swap.assetOut === ethers.constants.AddressZero let encodedPool = ethers.utils.solidityPack(["uint256"], [pool.address]) @@ -215,7 +215,7 @@ async function generateOrion3Calls( for (const swap of path) { const pool = UniswapV3Pool__factory.connect(swap.pool, provider) const token0 = await pool.token0() - const zeroForOne = token0 === swap.assetIn + const zeroForOne = token0.toLowerCase() === swap.assetIn.toLowerCase() const unwrapWETH = swap.assetOut === ethers.constants.AddressZero let encodedPool = ethers.utils.solidityPack(["uint256"], [pool.address]) @@ -288,21 +288,21 @@ function addCallParams( let firstByte = 0 if (callParams) { if (callParams.value !== undefined) { - firstByte += 16 // 00000010 + firstByte += 16 // 00010000 const encodedValue = ethers.utils.solidityPack(["uint128"], [callParams.value]) calldata = ethers.utils.hexlify(ethers.utils.concat([encodedValue, calldata])) } if (callParams.target !== undefined) { - firstByte += 32 // 00000100 + firstByte += 32 // 00100000 const encodedAddress = ethers.utils.solidityPack(["address"], [callParams.target]) calldata = ethers.utils.hexlify(ethers.utils.concat([encodedAddress, calldata])) } if (callParams.gaslimit !== undefined) { - firstByte += 64 // 00000100 + firstByte += 64 // 01000000 const encodedGaslimit = ethers.utils.solidityPack(["uint32"], [callParams.gaslimit]) calldata = ethers.utils.hexlify(ethers.utils.concat([encodedGaslimit, calldata])) } - if (callParams.isMandatory !== undefined) firstByte += 128 // 00001000 + if (callParams.isMandatory !== undefined) firstByte += 128 // 10000000 } const encodedFirstByte = ethers.utils.solidityPack(["uint8"], [firstByte]) From d9a08eabb3098f7d6cd728955c7c37eca8b93142 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Thu, 24 Aug 2023 12:39:18 +0300 Subject: [PATCH 23/24] version update --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 702a92c..b84bfcd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.48-dev.6-rc-0", + "version": "0.19.48-dev.6-rc-1", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", From 295e390cbdddc6de8f34fdf7329a806a4d639d1f Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Thu, 24 Aug 2023 15:01:29 +0300 Subject: [PATCH 24/24] update version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9f3ba4d..16358d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.48-dev.6", + "version": "v0.19.69", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js",