From 92d7e2028ea6a2dc19756e2b695bbb1160ce1473 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Fri, 27 Oct 2023 15:41:22 +0400 Subject: [PATCH 01/11] export generateCalldata function without unit param --- package.json | 2 +- src/Unit/Exchange/generateSwapCalldata.ts | 57 ++++++++++++++++++++--- src/Unit/Exchange/index.ts | 4 +- src/index.ts | 1 + src/utils/addressLikeToString.ts | 9 ++++ 5 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 src/utils/addressLikeToString.ts diff --git a/package.json b/package.json index 51a3ce5..67bd4d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.20.10", + "version": "0.20.10-rc0", "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 da40ee6..c28c02f 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -12,10 +12,12 @@ import { exchangeToNativeDecimals, generateCalls, pathCallWithBalance } from './ import { generateApproveCall, generateTransferCall } from './callGenerators/erc20.js'; import { generateCurveStableSwapCall } from './callGenerators/curve.js'; import type { SingleSwap } from '../../types.js'; +import type { AddressLike } from 'ethers'; +import { addressLikeToString } from '../../utils/addressLikeToString.js'; export type Factory = "UniswapV2" | "UniswapV3" | "Curve" | "OrionV2" | "OrionV3" -export type GenerateSwapCalldataParams = { +export type GenerateSwapCalldataWithUnitParams = { amount: BigNumberish minReturnAmount: BigNumberish receiverAddress: string @@ -23,13 +25,25 @@ export type GenerateSwapCalldataParams = { unit: Unit } -export default async function generateSwapCalldata({ +export type GenerateSwapCalldataParams = { + amount: BigNumberish + minReturnAmount: BigNumberish + receiverAddress: string + path: ArrayLike + wethAddress: AddressLike, + curveRegistryAddress: AddressLike, + swapExecutorContractAddress: AddressLike, + exchangeContractAddress: AddressLike, + provider: JsonRpcProvider +} + +export async function generateSwapCalldataWithUnit({ amount, minReturnAmount, receiverAddress, path: arrayLikePath, unit -}: GenerateSwapCalldataParams +}: GenerateSwapCalldataWithUnitParams ): Promise<{ calldata: string, swapDescription: LibValidator.SwapDescriptionStruct }> { if (arrayLikePath == undefined || arrayLikePath.length == 0) { throw new Error('Empty path'); @@ -43,6 +57,36 @@ export default async function generateSwapCalldata({ return swapInfo; }) + return generateSwapCalldata({ + amount, + minReturnAmount, + receiverAddress, + path, + wethAddress, + curveRegistryAddress, + swapExecutorContractAddress, + exchangeContractAddress, + provider: unit.provider + }) +} + +export async function generateSwapCalldata({ + amount, + minReturnAmount, + receiverAddress, + path: arrayLikePath, + wethAddress: wethAddressLike, + curveRegistryAddress: curveRegistryAddressLike, + swapExecutorContractAddress: swapExecutorContractAddressLike, + exchangeContractAddress: exchangeContractAddressLike, + provider, +}: GenerateSwapCalldataParams) { + const wethAddress = await addressLikeToString(wethAddressLike) + const curveRegistryAddress = await addressLikeToString(curveRegistryAddressLike) + const swapExecutorContractAddress = await addressLikeToString(swapExecutorContractAddressLike) + const exchangeContractAddress = await addressLikeToString(exchangeContractAddressLike) + let path = SafeArray.from(arrayLikePath) + const { factory, assetIn: srcToken } = path.first() const dstToken = path.last().assetOut @@ -55,13 +99,14 @@ export default async function generateSwapCalldata({ minReturnAmount, flags: 0 } - const amountNativeDecimals = await exchangeToNativeDecimals(srcToken, amount, unit.provider); + const amountNativeDecimals = await exchangeToNativeDecimals(srcToken, amount, provider); path = SafeArray.from(arrayLikePath).map((singleSwap) => { if (singleSwap.assetIn == ethers.ZeroAddress) singleSwap.assetIn = wethAddress if (singleSwap.assetOut == ethers.ZeroAddress) singleSwap.assetOut = wethAddress return singleSwap; }); + const isSingleFactorySwap = path.every(singleSwap => singleSwap.factory === factory) let calldata: BytesLike if (isSingleFactorySwap) { @@ -73,7 +118,7 @@ export default async function generateSwapCalldata({ amountNativeDecimals, swapExecutorContractAddress, curveRegistryAddress, - unit.provider + provider )) } else { ({ swapDescription, calldata } = await processMultiFactorySwaps( @@ -83,7 +128,7 @@ export default async function generateSwapCalldata({ amountNativeDecimals, swapExecutorContractAddress, curveRegistryAddress, - unit.provider + provider )) } diff --git a/src/Unit/Exchange/index.ts b/src/Unit/Exchange/index.ts index f6b75a3..c25b7b9 100644 --- a/src/Unit/Exchange/index.ts +++ b/src/Unit/Exchange/index.ts @@ -1,7 +1,7 @@ import type Unit from '../index.js'; import deposit, { type DepositParams } from './deposit.js'; import getSwapInfo, { type GetSwapInfoParams } from './getSwapInfo.js'; -import generateSwapCalldata, { type GenerateSwapCalldataParams } from './generateSwapCalldata.js'; +import {generateSwapCalldataWithUnit, type GenerateSwapCalldataParams } from './generateSwapCalldata.js'; import withdraw, { type WithdrawParams } from './withdraw.js'; type PureDepositParams = Omit @@ -39,7 +39,7 @@ export default class Exchange { } public generateSwapCalldata(params: PureGenerateSwapCalldataParams) { - return generateSwapCalldata({ + return generateSwapCalldataWithUnit({ ...params, unit: this.unit }) diff --git a/src/index.ts b/src/index.ts index a23d913..7b72aa7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,7 @@ BigNumber.config({ EXPONENTIAL_AT: 1e+9 }); export * as config from './config/index.js'; export { default as Unit } from './Unit/index.js'; export { default as Orion } from './Orion/index.js'; +export {generateSwapCalldata} from './Unit/Exchange/generateSwapCalldata.js'; export { default as factories} from './constants/factories.js'; export * as utils from './utils/index.js'; export * as services from './services/index.js'; diff --git a/src/utils/addressLikeToString.ts b/src/utils/addressLikeToString.ts new file mode 100644 index 0000000..974c505 --- /dev/null +++ b/src/utils/addressLikeToString.ts @@ -0,0 +1,9 @@ +import type { AddressLike } from "ethers"; + +export async function addressLikeToString(address: AddressLike): Promise { + address = await address + if (typeof address !== 'string') { + address = await address.getAddress() + } + return address +} \ No newline at end of file From b3ed38890cb8b78214f18ca7887ae22494295da8 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Fri, 27 Oct 2023 15:48:19 +0400 Subject: [PATCH 02/11] bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 67bd4d9..8da21a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.20.10-rc0", + "version": "0.20.10-rc101", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", From cdc3a78eb91a5f6d2d2b7ad547f84c59a3714754 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Mon, 30 Oct 2023 19:54:47 +0400 Subject: [PATCH 03/11] Change final transfer location. Add wrap/unwrap functionality --- package-lock.json | 18 +- package.json | 4 +- src/Unit/Exchange/callGenerators/curve.ts | 52 ++-- src/Unit/Exchange/callGenerators/uniswapV2.ts | 4 +- src/Unit/Exchange/callGenerators/uniswapV3.ts | 8 +- src/Unit/Exchange/callGenerators/weth.ts | 32 ++ src/Unit/Exchange/generateSwapCalldata.ts | 273 +++++++++--------- 7 files changed, 213 insertions(+), 178 deletions(-) create mode 100644 src/Unit/Exchange/callGenerators/weth.ts diff --git a/package-lock.json b/package-lock.json index b77e8ec..9e5ad1d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,19 @@ { "name": "@orionprotocol/sdk", - "version": "0.20.10", + "version": "0.20.10-rc101", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@orionprotocol/sdk", - "version": "0.20.10", + "version": "0.20.10-rc101", "hasInstallScript": true, "license": "ISC", "dependencies": { "@babel/runtime": "^7.21.0", "@ethersproject/abstract-signer": "^5.7.0", "@ethersproject/providers": "^5.7.2", - "@orionprotocol/contracts": "1.19.5", + "@orionprotocol/contracts": "1.22.1", "bignumber.js": "^9.1.1", "bson-objectid": "^2.0.4", "buffer": "^6.0.3", @@ -2419,9 +2419,9 @@ } }, "node_modules/@orionprotocol/contracts": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-1.19.5.tgz", - "integrity": "sha512-z8oWz+BswG+kN2dZCgjmQJwNc52S3aAnchZX0JRMe8+l/4WHIYDJQ3W9pEClzvg/86LO41DAHmS73rHNrGAARw==" + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-1.22.1.tgz", + "integrity": "sha512-DrIyAmZ+LK3Eflv/gk6Uq3shpTLjeG4wV6PoKVxJKoqk05qL35cJs5V/2it16s5NolcQliFrtJ54G3xI78gTwA==" }, "node_modules/@sinclair/typebox": { "version": "0.27.8", @@ -13460,9 +13460,9 @@ } }, "@orionprotocol/contracts": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-1.19.5.tgz", - "integrity": "sha512-z8oWz+BswG+kN2dZCgjmQJwNc52S3aAnchZX0JRMe8+l/4WHIYDJQ3W9pEClzvg/86LO41DAHmS73rHNrGAARw==" + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-1.22.1.tgz", + "integrity": "sha512-DrIyAmZ+LK3Eflv/gk6Uq3shpTLjeG4wV6PoKVxJKoqk05qL35cJs5V/2it16s5NolcQliFrtJ54G3xI78gTwA==" }, "@sinclair/typebox": { "version": "0.27.8", diff --git a/package.json b/package.json index 8da21a6..18ea5e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.20.10-rc101", + "version": "0.20.10-rc102", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", @@ -88,7 +88,7 @@ "@babel/runtime": "^7.21.0", "@ethersproject/abstract-signer": "^5.7.0", "@ethersproject/providers": "^5.7.2", - "@orionprotocol/contracts": "1.19.5", + "@orionprotocol/contracts": "1.22.1", "bignumber.js": "^9.1.1", "bson-objectid": "^2.0.4", "buffer": "^6.0.3", diff --git a/src/Unit/Exchange/callGenerators/curve.ts b/src/Unit/Exchange/callGenerators/curve.ts index 7fc54d3..eb9d29e 100644 --- a/src/Unit/Exchange/callGenerators/curve.ts +++ b/src/Unit/Exchange/callGenerators/curve.ts @@ -1,28 +1,44 @@ -import { SwapExecutor__factory, CurveRegistry__factory } from "@orionprotocol/contracts/lib/ethers-v6/index.js" -import type { BigNumberish, JsonRpcProvider } from "ethers" -import { addCallParams } from "./utils.js" -import type { SingleSwap } from "../../../types.js" +import { + SwapExecutor__factory, + CurveRegistry__factory, + ERC20__factory, +} from "@orionprotocol/contracts/lib/ethers-v6/index.js"; +import { MaxUint256, type BigNumberish, type JsonRpcProvider } from "ethers"; +import { addCallParams } from "./utils.js"; +import type { SingleSwap } from "../../../types.js"; +import { generateApproveCall } from "./erc20.js"; +import type { BytesLike } from "ethers"; export async function generateCurveStableSwapCall( amount: BigNumberish, to: string, swap: SingleSwap, provider: JsonRpcProvider, + swapExecutorContractAddress: string, curveRegistry: string ) { - const executorInterface = SwapExecutor__factory.createInterface() - const registry = CurveRegistry__factory.connect(curveRegistry, provider) - const { pool, assetIn, assetOut } = swap - const [i, j,] = await registry.get_coin_indices(pool, assetIn, assetOut) + const executorInterface = SwapExecutor__factory.createInterface(); + const registry = CurveRegistry__factory.connect(curveRegistry, provider); + const { pool, assetIn, assetOut } = swap; + const firstToken = ERC20__factory.connect(assetIn, provider) + const executorAllowance = await firstToken.allowance(swapExecutorContractAddress, pool) - let calldata = executorInterface.encodeFunctionData('curveSwapStableAmountIn', [ - pool, - assetOut, - i, - j, - to, - amount, - ]) + const calls: BytesLike[] = [] + if (executorAllowance <= BigInt(amount)) { + const approveCall = await generateApproveCall( + assetIn, + pool, + MaxUint256 + ); + calls.push(approveCall); + } - return addCallParams(calldata) -} \ No newline at end of file + const [i, j] = await registry.get_coin_indices(pool, assetIn, assetOut); + let calldata = executorInterface.encodeFunctionData( + "curveSwapStableAmountIn", + [pool, assetOut, i, j, to, amount] + ); + calls.push(addCallParams(calldata)) + + return calls +} diff --git a/src/Unit/Exchange/callGenerators/uniswapV2.ts b/src/Unit/Exchange/callGenerators/uniswapV2.ts index 6d34820..19b86b0 100644 --- a/src/Unit/Exchange/callGenerators/uniswapV2.ts +++ b/src/Unit/Exchange/callGenerators/uniswapV2.ts @@ -1,7 +1,7 @@ import { SwapExecutor__factory } from "@orionprotocol/contracts/lib/ethers-v6/index.js" import { SafeArray } from "../../../utils/safeGetters.js" import { type BytesLike, type BigNumberish, concat, ethers, toBeHex } from "ethers" -import { addCallParams, generateCalls } from "./utils.js" +import { addCallParams } from "./utils.js" import type { SingleSwap } from "../../../types.js" export async function generateUni2Calls( @@ -33,7 +33,7 @@ export async function generateUni2Calls( ]) calls.push(addCallParams(calldata)) - return generateCalls(calls) + return calls } export async function generateUni2Call( diff --git a/src/Unit/Exchange/callGenerators/uniswapV3.ts b/src/Unit/Exchange/callGenerators/uniswapV3.ts index 2ef3f04..67bfcec 100644 --- a/src/Unit/Exchange/callGenerators/uniswapV3.ts +++ b/src/Unit/Exchange/callGenerators/uniswapV3.ts @@ -1,7 +1,7 @@ import { SwapExecutor__factory, UniswapV3Pool__factory } from "@orionprotocol/contracts/lib/ethers-v6/index.js" -import { type BigNumberish , type BytesLike, ethers, JsonRpcProvider } from "ethers" +import { type BigNumberish , ethers, JsonRpcProvider } from "ethers" import { SafeArray } from "../../../utils/safeGetters.js" -import { addCallParams, generateCalls } from "./utils.js" +import { addCallParams } from "./utils.js" import type { SingleSwap } from "../../../types.js" export async function generateUni3Call( @@ -49,7 +49,7 @@ export async function generateUni3Calls( let calldata = executorInterface.encodeFunctionData('uniswapV3SwapTo', [encodedPools, recipient, amount]) calldata = addCallParams(calldata) - return generateCalls([calldata]) + return [calldata] } export async function generateOrion3Calls( @@ -67,7 +67,7 @@ export async function generateOrion3Calls( let calldata = executorInterface.encodeFunctionData('orionV3SwapTo', [encodedPools, recipient, amount]) calldata = addCallParams(calldata) - return generateCalls([calldata]) + return [calldata] } export async function encodePoolV3( diff --git a/src/Unit/Exchange/callGenerators/weth.ts b/src/Unit/Exchange/callGenerators/weth.ts new file mode 100644 index 0000000..7aaf566 --- /dev/null +++ b/src/Unit/Exchange/callGenerators/weth.ts @@ -0,0 +1,32 @@ +import { SwapExecutor__factory } from "@orionprotocol/contracts/lib/ethers-v6/index.js" +import type { BigNumberish } from "ethers" +import { type CallParams, addCallParams } from "./utils.js" +import type { AddressLike } from "ethers" + +export function generateWrapAndTransferCall( + target: AddressLike, + callParams?: CallParams +) { + + const executorInterface = SwapExecutor__factory.createInterface() + const calldata = executorInterface.encodeFunctionData('wrapAndTransfer', [ + target, + ]) + + return addCallParams(calldata, callParams) +} + +export function generateUnwrapAndTransferCall( + target: AddressLike, + amount: BigNumberish, + callParams?: CallParams +) { + + const executorInterface = SwapExecutor__factory.createInterface() + const calldata = executorInterface.encodeFunctionData('unwrapAndTransfer', [ + target, + amount + ]) + + return addCallParams(calldata, callParams) +} \ No newline at end of file diff --git a/src/Unit/Exchange/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts index c28c02f..cef0f02 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -1,61 +1,65 @@ -import type { LibValidator } from '@orionprotocol/contracts/lib/ethers-v6/Exchange.js'; +import type { LibValidator } from "@orionprotocol/contracts/lib/ethers-v6/Exchange.js"; +import { ethers, type BigNumberish, type BytesLike, JsonRpcProvider, ZeroAddress } from "ethers"; +import { safeGet, SafeArray } from "../../utils/safeGetters.js"; +import { simpleFetch } from "simple-typed-fetch"; +import type Unit from "../index.js"; +import { generateUni2Calls, generateUni2Call } from "./callGenerators/uniswapV2.js"; import { - ERC20__factory -} from '@orionprotocol/contracts/lib/ethers-v6/index.js'; -import { ethers, type BigNumberish, type BytesLike, JsonRpcProvider } from 'ethers'; -import { safeGet, SafeArray } from '../../utils/safeGetters.js'; -import { simpleFetch } from 'simple-typed-fetch'; -import type Unit from '../index.js'; -import { generateUni2Calls, generateUni2Call } from './callGenerators/uniswapV2.js'; -import { generateUni3Calls, generateOrion3Calls, generateUni3Call, generateOrion3Call } from './callGenerators/uniswapV3.js'; -import { exchangeToNativeDecimals, generateCalls, pathCallWithBalance } from './callGenerators/utils.js'; -import { generateApproveCall, generateTransferCall } from './callGenerators/erc20.js'; -import { generateCurveStableSwapCall } from './callGenerators/curve.js'; -import type { SingleSwap } from '../../types.js'; -import type { AddressLike } from 'ethers'; -import { addressLikeToString } from '../../utils/addressLikeToString.js'; + generateUni3Calls, + generateOrion3Calls, + generateUni3Call, + generateOrion3Call, +} from "./callGenerators/uniswapV3.js"; +import { exchangeToNativeDecimals, generateCalls, pathCallWithBalance } from "./callGenerators/utils.js"; +import { generateTransferCall } from "./callGenerators/erc20.js"; +import { generateCurveStableSwapCall } from "./callGenerators/curve.js"; +import type { SingleSwap } from "../../types.js"; +import type { AddressLike } from "ethers"; +import { addressLikeToString } from "../../utils/addressLikeToString.js"; +import { generateUnwrapAndTransferCall, generateWrapAndTransferCall } from "./callGenerators/weth.js"; -export type Factory = "UniswapV2" | "UniswapV3" | "Curve" | "OrionV2" | "OrionV3" +export type Factory = "UniswapV2" | "UniswapV3" | "Curve" | "OrionV2" | "OrionV3"; export type GenerateSwapCalldataWithUnitParams = { - amount: BigNumberish - minReturnAmount: BigNumberish - receiverAddress: string - path: ArrayLike - unit: Unit -} + amount: BigNumberish; + minReturnAmount: BigNumberish; + receiverAddress: string; + path: ArrayLike; + unit: Unit; +}; export type GenerateSwapCalldataParams = { - amount: BigNumberish - minReturnAmount: BigNumberish - receiverAddress: string - path: ArrayLike - wethAddress: AddressLike, - curveRegistryAddress: AddressLike, - swapExecutorContractAddress: AddressLike, - exchangeContractAddress: AddressLike, - provider: JsonRpcProvider -} + amount: BigNumberish; + minReturnAmount: BigNumberish; + receiverAddress: string; + path: ArrayLike; + wethAddress: AddressLike; + curveRegistryAddress: AddressLike; + swapExecutorContractAddress: AddressLike; + provider: JsonRpcProvider; +}; export async function generateSwapCalldataWithUnit({ amount, minReturnAmount, receiverAddress, path: arrayLikePath, - unit -}: GenerateSwapCalldataWithUnitParams -): Promise<{ calldata: string, swapDescription: LibValidator.SwapDescriptionStruct }> { + unit, +}: GenerateSwapCalldataWithUnitParams): Promise<{ + calldata: string; + swapDescription: LibValidator.SwapDescriptionStruct; +}> { if (arrayLikePath == undefined || arrayLikePath.length == 0) { - throw new Error('Empty path'); + 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 wethAddress = safeGet(unit.contracts, "WETH"); + const curveRegistryAddress = safeGet(unit.contracts, "curveRegistry"); + const { assetToAddress, swapExecutorContractAddress } = await simpleFetch(unit.blockchainService.getInfo)(); let path = SafeArray.from(arrayLikePath).map((swapInfo) => { swapInfo.assetIn = assetToAddress[swapInfo.assetIn] ?? swapInfo.assetIn.toLowerCase(); swapInfo.assetOut = assetToAddress[swapInfo.assetOut] ?? swapInfo.assetOut.toLowerCase(); return swapInfo; - }) + }); return generateSwapCalldata({ amount, @@ -65,9 +69,8 @@ export async function generateSwapCalldataWithUnit({ wethAddress, curveRegistryAddress, swapExecutorContractAddress, - exchangeContractAddress, - provider: unit.provider - }) + provider: unit.provider, + }); } export async function generateSwapCalldata({ @@ -78,198 +81,182 @@ export async function generateSwapCalldata({ wethAddress: wethAddressLike, curveRegistryAddress: curveRegistryAddressLike, swapExecutorContractAddress: swapExecutorContractAddressLike, - exchangeContractAddress: exchangeContractAddressLike, provider, }: GenerateSwapCalldataParams) { - const wethAddress = await addressLikeToString(wethAddressLike) - const curveRegistryAddress = await addressLikeToString(curveRegistryAddressLike) - const swapExecutorContractAddress = await addressLikeToString(swapExecutorContractAddressLike) - const exchangeContractAddress = await addressLikeToString(exchangeContractAddressLike) - let path = SafeArray.from(arrayLikePath) + const wethAddress = await addressLikeToString(wethAddressLike); + const curveRegistryAddress = await addressLikeToString(curveRegistryAddressLike); + const swapExecutorContractAddress = await addressLikeToString(swapExecutorContractAddressLike); + let path = SafeArray.from(arrayLikePath); - const { factory, assetIn: srcToken } = path.first() - const dstToken = path.last().assetOut + const { factory, assetIn: srcToken } = path.first(); + const dstToken = path.last().assetOut; + const amountNativeDecimals = await exchangeToNativeDecimals(srcToken, amount, provider); + const minReturnAmountNativeDecimals = await exchangeToNativeDecimals(dstToken, minReturnAmount, provider); let swapDescription: LibValidator.SwapDescriptionStruct = { srcToken: srcToken, dstToken: dstToken, srcReceiver: swapExecutorContractAddress, dstReceiver: receiverAddress, - amount, - minReturnAmount, - flags: 0 - } - const amountNativeDecimals = await exchangeToNativeDecimals(srcToken, amount, provider); + amount: amountNativeDecimals, + minReturnAmount: minReturnAmountNativeDecimals, + flags: 0, + }; path = SafeArray.from(arrayLikePath).map((singleSwap) => { - if (singleSwap.assetIn == ethers.ZeroAddress) singleSwap.assetIn = wethAddress - if (singleSwap.assetOut == ethers.ZeroAddress) singleSwap.assetOut = wethAddress + if (singleSwap.assetIn == ethers.ZeroAddress) singleSwap.assetIn = wethAddress; + if (singleSwap.assetOut == ethers.ZeroAddress) singleSwap.assetOut = wethAddress; return singleSwap; }); - - const isSingleFactorySwap = path.every(singleSwap => singleSwap.factory === factory) - let calldata: BytesLike + + const isSingleFactorySwap = path.every((singleSwap) => singleSwap.factory === factory); + let calls: BytesLike[]; if (isSingleFactorySwap) { - ({ swapDescription, calldata } = await processSingleFactorySwaps( + ({ swapDescription, calls } = await processSingleFactorySwaps( factory, swapDescription, path, - exchangeContractAddress, amountNativeDecimals, swapExecutorContractAddress, curveRegistryAddress, provider - )) + )); } else { - ({ swapDescription, calldata } = await processMultiFactorySwaps( + ({ swapDescription, calls } = await processMultiFactorySwaps( swapDescription, path, - exchangeContractAddress, amountNativeDecimals, swapExecutorContractAddress, curveRegistryAddress, provider - )) + )); } - return { swapDescription, calldata } + calls = wrapOrUnwrapIfNeeded(swapDescription, calls); + const calldata = generateCalls(calls); + return { swapDescription, calldata }; } async function processSingleFactorySwaps( factory: Factory, swapDescription: LibValidator.SwapDescriptionStruct, path: SafeArray, - recipient: string, amount: BigNumberish, swapExecutorContractAddress: string, curveRegistryAddress: string, provider: JsonRpcProvider ) { - let calldata: BytesLike + let calls: BytesLike[] = []; switch (factory) { - case 'OrionV2': { - swapDescription.srcReceiver = path.first().pool - calldata = await generateUni2Calls(path, recipient); + case "OrionV2": { + swapDescription.srcReceiver = path.first().pool; + calls = await generateUni2Calls(path, swapExecutorContractAddress); break; } - case 'UniswapV2': { - swapDescription.srcReceiver = path.first().pool - calldata = await generateUni2Calls(path, recipient); + case "UniswapV2": { + swapDescription.srcReceiver = path.first().pool; + calls = await generateUni2Calls(path, swapExecutorContractAddress); break; } - case 'UniswapV3': { - calldata = await generateUni3Calls(path, amount, recipient, provider) + case "UniswapV3": { + calls = await generateUni3Calls(path, amount, swapExecutorContractAddress, provider); break; } - case 'OrionV3': { - calldata = await generateOrion3Calls(path, amount, recipient, provider) + case "OrionV3": { + calls = await generateOrion3Calls(path, amount, swapExecutorContractAddress, provider); break; } - case 'Curve': { + case "Curve": { if (path.length > 1) { - throw new Error('Supporting only single stable swap on curve') + throw new Error("Supporting only single stable swap on curve"); } - const { pool, assetIn } = path.first() - const firstToken = ERC20__factory.connect(assetIn, provider) - const executorAllowance = await firstToken.allowance(swapExecutorContractAddress, pool) - const calls: BytesLike[] = [] - if (executorAllowance <= BigInt(amount)) { - const approveCall = await generateApproveCall( - assetIn, - pool, - ethers.MaxUint256 - ) - calls.push(approveCall) - } - let curveCall = await generateCurveStableSwapCall( + calls = await generateCurveStableSwapCall( amount, - recipient, + swapExecutorContractAddress, path.first(), provider, + swapExecutorContractAddress, curveRegistryAddress ); - calls.push(curveCall) - calldata = await generateCalls(calls) break; } default: { - throw new Error(`Factory ${factory} is not supported`) + throw new Error(`Factory ${factory} is not supported`); } } - return { swapDescription, calldata } + return { swapDescription, calls }; } async function processMultiFactorySwaps( swapDescription: LibValidator.SwapDescriptionStruct, path: SafeArray, - recipient: string, amount: BigNumberish, swapExecutorContractAddress: string, curveRegistryAddress: string, provider: JsonRpcProvider ) { - let calls: BytesLike[] = [] + let calls: BytesLike[] = []; + if (swapDescription.srcToken === ZeroAddress) { + const wrapCall = await generateWrapAndTransferCall(swapExecutorContractAddress, { value: amount }); + calls.push(wrapCall); + } for (const swap of path) { switch (swap.factory) { - case 'OrionV2': { - let transferCall = await generateTransferCall(swap.assetIn, swap.pool, 0) - transferCall = pathCallWithBalance(transferCall, swap.assetIn) - const uni2Call = await generateUni2Call(swap.pool, swap.assetIn, swap.assetOut, swapExecutorContractAddress) - calls = calls.concat([transferCall, uni2Call]) + case "OrionV2": { + let transferCall = await generateTransferCall(swap.assetIn, swap.pool, 0); + transferCall = pathCallWithBalance(transferCall, swap.assetIn); + const uni2Call = await generateUni2Call(swap.pool, swap.assetIn, swap.assetOut, swapExecutorContractAddress); + calls.push(transferCall, uni2Call); break; } - case 'UniswapV2': { - let transferCall = await generateTransferCall(swap.assetIn, swap.pool, 0) - transferCall = pathCallWithBalance(transferCall, swap.assetIn) - const uni2Call = await generateUni2Call(swap.pool, swap.assetIn, swap.assetOut, swapExecutorContractAddress) - calls = calls.concat([transferCall, uni2Call]) + case "UniswapV2": { + let transferCall = await generateTransferCall(swap.assetIn, swap.pool, 0); + transferCall = pathCallWithBalance(transferCall, swap.assetIn); + const uni2Call = await generateUni2Call(swap.pool, swap.assetIn, swap.assetOut, swapExecutorContractAddress); + calls.push(transferCall, uni2Call); break; } - case 'UniswapV3': { - let uni3Call = await generateUni3Call(swap, 0, swapExecutorContractAddress, provider) - uni3Call = pathCallWithBalance(uni3Call, swap.assetIn) - calls.push(uni3Call) + case "UniswapV3": { + let uni3Call = await generateUni3Call(swap, 0, swapExecutorContractAddress, provider); + uni3Call = pathCallWithBalance(uni3Call, swap.assetIn); + calls.push(uni3Call); break; } - case 'OrionV3': { - let orion3Call = await generateOrion3Call(swap, 0, swapExecutorContractAddress, provider) - orion3Call = pathCallWithBalance(orion3Call, swap.assetIn) - calls.push(orion3Call) + case "OrionV3": { + let orion3Call = await generateOrion3Call(swap, 0, swapExecutorContractAddress, provider); + orion3Call = pathCallWithBalance(orion3Call, swap.assetIn); + calls.push(orion3Call); break; } - case 'Curve': { - const { pool, assetIn } = swap - const firstToken = ERC20__factory.connect(assetIn, provider) - const executorAllowance = await firstToken.allowance(swapExecutorContractAddress, pool) - if (executorAllowance <= BigInt(amount)) { - const approveCall = await generateApproveCall( - assetIn, - pool, - ethers.MaxUint256 - ) - calls.push(approveCall) - } - let curveCall = await generateCurveStableSwapCall( + case "Curve": { + let curveCalls = await generateCurveStableSwapCall( amount, swapExecutorContractAddress, swap, provider, + swapExecutorContractAddress, curveRegistryAddress ); - curveCall = pathCallWithBalance(curveCall, swap.assetIn) - calls.push(curveCall) + calls.push(...curveCalls); break; } default: { - throw new Error(`Factory ${swap.factory} is not supported`) + throw new Error(`Factory ${swap.factory} is not supported`); } } } - const dstToken = swapDescription.dstToken - let finalTransferCall = await generateTransferCall(dstToken, recipient, 0) - finalTransferCall = pathCallWithBalance(finalTransferCall, dstToken) - calls.push(finalTransferCall) - const calldata = generateCalls(calls) - - return { swapDescription, calldata } + return { swapDescription, calls }; +} + +function wrapOrUnwrapIfNeeded(swapDescription: LibValidator.SwapDescriptionStruct, calls: BytesLike[]): BytesLike[] { + if (swapDescription.srcToken === ZeroAddress) { + const wrapCall = generateWrapAndTransferCall(swapDescription.dstReceiver, { value: swapDescription.amount }); + calls = ([wrapCall] as BytesLike[]).concat(calls); + } + if (swapDescription.dstToken === ZeroAddress) { + let unwrapCall = generateUnwrapAndTransferCall(swapDescription.dstReceiver, 0); + unwrapCall = pathCallWithBalance(unwrapCall, swapDescription.dstToken); + calls.push(unwrapCall); + } + return calls; } From 31efda9969721403558d6a1a4b9497568ecddb8a Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Mon, 30 Oct 2023 20:07:06 +0400 Subject: [PATCH 04/11] Return exchange precision in swapDescription --- package.json | 2 +- src/Unit/Exchange/generateSwapCalldata.ts | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 18ea5e3..ea50977 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.20.10-rc102", + "version": "0.20.10-rc103", "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 cef0f02..2a90444 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -91,18 +91,17 @@ export async function generateSwapCalldata({ const { factory, assetIn: srcToken } = path.first(); const dstToken = path.last().assetOut; - const amountNativeDecimals = await exchangeToNativeDecimals(srcToken, amount, provider); - const minReturnAmountNativeDecimals = await exchangeToNativeDecimals(dstToken, minReturnAmount, provider); let swapDescription: LibValidator.SwapDescriptionStruct = { srcToken: srcToken, dstToken: dstToken, srcReceiver: swapExecutorContractAddress, dstReceiver: receiverAddress, - amount: amountNativeDecimals, - minReturnAmount: minReturnAmountNativeDecimals, + amount, + minReturnAmount, flags: 0, }; - + const amountNativeDecimals = await exchangeToNativeDecimals(srcToken, amount, provider); + path = SafeArray.from(arrayLikePath).map((singleSwap) => { if (singleSwap.assetIn == ethers.ZeroAddress) singleSwap.assetIn = wethAddress; if (singleSwap.assetOut == ethers.ZeroAddress) singleSwap.assetOut = wethAddress; @@ -132,7 +131,7 @@ export async function generateSwapCalldata({ )); } - calls = wrapOrUnwrapIfNeeded(swapDescription, calls); + calls = wrapOrUnwrapIfNeeded(amountNativeDecimals, swapDescription, calls); const calldata = generateCalls(calls); return { swapDescription, calldata }; } @@ -248,7 +247,7 @@ async function processMultiFactorySwaps( return { swapDescription, calls }; } -function wrapOrUnwrapIfNeeded(swapDescription: LibValidator.SwapDescriptionStruct, calls: BytesLike[]): BytesLike[] { +function wrapOrUnwrapIfNeeded(amount: BigNumberish, swapDescription: LibValidator.SwapDescriptionStruct, calls: BytesLike[]): BytesLike[] { if (swapDescription.srcToken === ZeroAddress) { const wrapCall = generateWrapAndTransferCall(swapDescription.dstReceiver, { value: swapDescription.amount }); calls = ([wrapCall] as BytesLike[]).concat(calls); From 43e0fa0abef7443372255bafca694a8b786cf5cf Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Mon, 30 Oct 2023 20:10:50 +0400 Subject: [PATCH 05/11] fix build --- src/Unit/Exchange/generateSwapCalldata.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Unit/Exchange/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts index 2a90444..449c5b0 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -249,7 +249,7 @@ async function processMultiFactorySwaps( function wrapOrUnwrapIfNeeded(amount: BigNumberish, swapDescription: LibValidator.SwapDescriptionStruct, calls: BytesLike[]): BytesLike[] { if (swapDescription.srcToken === ZeroAddress) { - const wrapCall = generateWrapAndTransferCall(swapDescription.dstReceiver, { value: swapDescription.amount }); + const wrapCall = generateWrapAndTransferCall(swapDescription.dstReceiver, { value: amount }); calls = ([wrapCall] as BytesLike[]).concat(calls); } if (swapDescription.dstToken === ZeroAddress) { From 4d9f09bc211e6b4a51e537fe7913782646ceda4d Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Mon, 30 Oct 2023 20:24:58 +0400 Subject: [PATCH 06/11] Add final transfer from executor in any case --- package.json | 2 +- src/Unit/Exchange/generateSwapCalldata.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index ea50977..122bdbe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.20.10-rc103", + "version": "0.20.10-rc104", "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 449c5b0..bfdf259 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -131,7 +131,7 @@ export async function generateSwapCalldata({ )); } - calls = wrapOrUnwrapIfNeeded(amountNativeDecimals, swapDescription, calls); + calls = await wrapOrUnwrapIfNeeded(amountNativeDecimals, swapDescription, calls); const calldata = generateCalls(calls); return { swapDescription, calldata }; } @@ -247,7 +247,7 @@ async function processMultiFactorySwaps( return { swapDescription, calls }; } -function wrapOrUnwrapIfNeeded(amount: BigNumberish, swapDescription: LibValidator.SwapDescriptionStruct, calls: BytesLike[]): BytesLike[] { +async function wrapOrUnwrapIfNeeded(amount: BigNumberish, swapDescription: LibValidator.SwapDescriptionStruct, calls: BytesLike[]): Promise { if (swapDescription.srcToken === ZeroAddress) { const wrapCall = generateWrapAndTransferCall(swapDescription.dstReceiver, { value: amount }); calls = ([wrapCall] as BytesLike[]).concat(calls); @@ -256,6 +256,10 @@ function wrapOrUnwrapIfNeeded(amount: BigNumberish, swapDescription: LibValidato let unwrapCall = generateUnwrapAndTransferCall(swapDescription.dstReceiver, 0); unwrapCall = pathCallWithBalance(unwrapCall, swapDescription.dstToken); calls.push(unwrapCall); + } else { + let transferCall = await generateTransferCall(swapDescription.dstToken, swapDescription.dstReceiver, 0); + transferCall = pathCallWithBalance(transferCall, swapDescription.dstToken); + calls.push(transferCall); } return calls; } From 83f4a54ef8c65ac0103762daf4b6a64efc5b7e15 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Mon, 30 Oct 2023 20:43:39 +0400 Subject: [PATCH 07/11] Fix single factory srcReceiver bug --- package.json | 2 +- src/Unit/Exchange/generateSwapCalldata.ts | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 122bdbe..9c10b83 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.20.10-rc104", + "version": "0.20.10-rc105", "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 bfdf259..d38df4e 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -101,7 +101,7 @@ export async function generateSwapCalldata({ flags: 0, }; const amountNativeDecimals = await exchangeToNativeDecimals(srcToken, amount, provider); - + path = SafeArray.from(arrayLikePath).map((singleSwap) => { if (singleSwap.assetIn == ethers.ZeroAddress) singleSwap.assetIn = wethAddress; if (singleSwap.assetOut == ethers.ZeroAddress) singleSwap.assetOut = wethAddress; @@ -131,7 +131,7 @@ export async function generateSwapCalldata({ )); } - calls = await wrapOrUnwrapIfNeeded(amountNativeDecimals, swapDescription, calls); + ({ swapDescription, calls } = await wrapOrUnwrapIfNeeded(amountNativeDecimals, swapDescription, calls, swapExecutorContractAddress)); const calldata = generateCalls(calls); return { swapDescription, calldata }; } @@ -247,9 +247,15 @@ async function processMultiFactorySwaps( return { swapDescription, calls }; } -async function wrapOrUnwrapIfNeeded(amount: BigNumberish, swapDescription: LibValidator.SwapDescriptionStruct, calls: BytesLike[]): Promise { +async function wrapOrUnwrapIfNeeded( + amount: BigNumberish, + swapDescription: LibValidator.SwapDescriptionStruct, + calls: BytesLike[], + swapExecutorContractAddress: string +) { if (swapDescription.srcToken === ZeroAddress) { - const wrapCall = generateWrapAndTransferCall(swapDescription.dstReceiver, { value: amount }); + const wrapCall = generateWrapAndTransferCall(swapDescription.srcReceiver, { value: amount }); + swapDescription.srcReceiver = swapExecutorContractAddress calls = ([wrapCall] as BytesLike[]).concat(calls); } if (swapDescription.dstToken === ZeroAddress) { @@ -261,5 +267,5 @@ async function wrapOrUnwrapIfNeeded(amount: BigNumberish, swapDescription: LibVa transferCall = pathCallWithBalance(transferCall, swapDescription.dstToken); calls.push(transferCall); } - return calls; + return { swapDescription, calls }; } From fa5863b42cd0b1b59b2589bac588836411d730f0 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Tue, 31 Oct 2023 10:44:23 +0400 Subject: [PATCH 08/11] Fix patching with eth balance --- src/Unit/Exchange/generateSwapCalldata.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Unit/Exchange/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts index d38df4e..4aa3e18 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -131,7 +131,7 @@ export async function generateSwapCalldata({ )); } - ({ swapDescription, calls } = await wrapOrUnwrapIfNeeded(amountNativeDecimals, swapDescription, calls, swapExecutorContractAddress)); + ({ swapDescription, calls } = await wrapOrUnwrapIfNeeded(amountNativeDecimals, swapDescription, calls, swapExecutorContractAddress, wethAddress)); const calldata = generateCalls(calls); return { swapDescription, calldata }; } @@ -251,16 +251,17 @@ async function wrapOrUnwrapIfNeeded( amount: BigNumberish, swapDescription: LibValidator.SwapDescriptionStruct, calls: BytesLike[], - swapExecutorContractAddress: string + swapExecutorContractAddress: string, + wethAddress: string ) { if (swapDescription.srcToken === ZeroAddress) { const wrapCall = generateWrapAndTransferCall(swapDescription.srcReceiver, { value: amount }); swapDescription.srcReceiver = swapExecutorContractAddress calls = ([wrapCall] as BytesLike[]).concat(calls); - } + } if (swapDescription.dstToken === ZeroAddress) { let unwrapCall = generateUnwrapAndTransferCall(swapDescription.dstReceiver, 0); - unwrapCall = pathCallWithBalance(unwrapCall, swapDescription.dstToken); + unwrapCall = pathCallWithBalance(unwrapCall, wethAddress); calls.push(unwrapCall); } else { let transferCall = await generateTransferCall(swapDescription.dstToken, swapDescription.dstReceiver, 0); From d2982e9265abd93fd906beaa419759e30bcc6442 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Tue, 31 Oct 2023 10:52:36 +0400 Subject: [PATCH 09/11] bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9c10b83..77d6642 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.20.10-rc105", + "version": "0.20.10-rc106", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", From 935412724eeaee4989899ba3e795215e218d503e Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Tue, 31 Oct 2023 20:56:25 +0400 Subject: [PATCH 10/11] fix: correct swapDescription.flags initialization to enable contract balance for swaps --- src/Unit/Exchange/generateSwapCalldata.ts | 39 ++++++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/Unit/Exchange/generateSwapCalldata.ts b/src/Unit/Exchange/generateSwapCalldata.ts index 4aa3e18..e792a27 100644 --- a/src/Unit/Exchange/generateSwapCalldata.ts +++ b/src/Unit/Exchange/generateSwapCalldata.ts @@ -17,6 +17,8 @@ import type { SingleSwap } from "../../types.js"; import type { AddressLike } from "ethers"; import { addressLikeToString } from "../../utils/addressLikeToString.js"; import { generateUnwrapAndTransferCall, generateWrapAndTransferCall } from "./callGenerators/weth.js"; +import { Exchange__factory } from "@orionprotocol/contracts/lib/ethers-v6/index.js"; +import getBalance from "../../utils/getBalance.js"; export type Factory = "UniswapV2" | "UniswapV3" | "Curve" | "OrionV2" | "OrionV3"; @@ -32,6 +34,7 @@ export type GenerateSwapCalldataParams = { amount: BigNumberish; minReturnAmount: BigNumberish; receiverAddress: string; + useContractBalance: boolean; path: ArrayLike; wethAddress: AddressLike; curveRegistryAddress: AddressLike; @@ -54,8 +57,21 @@ export async function generateSwapCalldataWithUnit({ } const wethAddress = safeGet(unit.contracts, "WETH"); const curveRegistryAddress = safeGet(unit.contracts, "curveRegistry"); - const { assetToAddress, swapExecutorContractAddress } = await simpleFetch(unit.blockchainService.getInfo)(); - let path = SafeArray.from(arrayLikePath).map((swapInfo) => { + const { assetToAddress, swapExecutorContractAddress, exchangeContractAddress } = await simpleFetch( + unit.blockchainService.getInfo + )(); + + let path = SafeArray.from(arrayLikePath); + const { wallet } = await getBalance( + unit.aggregator, + path.first().assetIn, + safeGet(assetToAddress, path.first().assetIn), + receiverAddress, + Exchange__factory.connect(exchangeContractAddress, unit.provider), + unit.provider + ); + + path = SafeArray.from(arrayLikePath).map((swapInfo) => { swapInfo.assetIn = assetToAddress[swapInfo.assetIn] ?? swapInfo.assetIn.toLowerCase(); swapInfo.assetOut = assetToAddress[swapInfo.assetOut] ?? swapInfo.assetOut.toLowerCase(); return swapInfo; @@ -65,6 +81,7 @@ export async function generateSwapCalldataWithUnit({ amount, minReturnAmount, receiverAddress, + useContractBalance: BigInt(wallet.toString()) < BigInt(amount), path, wethAddress, curveRegistryAddress, @@ -77,6 +94,7 @@ export async function generateSwapCalldata({ amount, minReturnAmount, receiverAddress, + useContractBalance, path: arrayLikePath, wethAddress: wethAddressLike, curveRegistryAddress: curveRegistryAddressLike, @@ -131,8 +149,19 @@ export async function generateSwapCalldata({ )); } - ({ swapDescription, calls } = await wrapOrUnwrapIfNeeded(amountNativeDecimals, swapDescription, calls, swapExecutorContractAddress, wethAddress)); + ({ swapDescription, calls } = await wrapOrUnwrapIfNeeded( + amountNativeDecimals, + swapDescription, + calls, + swapExecutorContractAddress, + wethAddress + )); const calldata = generateCalls(calls); + + if (useContractBalance) { + swapDescription.flags = 1n << 255n; + } + return { swapDescription, calldata }; } @@ -256,9 +285,9 @@ async function wrapOrUnwrapIfNeeded( ) { if (swapDescription.srcToken === ZeroAddress) { const wrapCall = generateWrapAndTransferCall(swapDescription.srcReceiver, { value: amount }); - swapDescription.srcReceiver = swapExecutorContractAddress + swapDescription.srcReceiver = swapExecutorContractAddress; calls = ([wrapCall] as BytesLike[]).concat(calls); - } + } if (swapDescription.dstToken === ZeroAddress) { let unwrapCall = generateUnwrapAndTransferCall(swapDescription.dstReceiver, 0); unwrapCall = pathCallWithBalance(unwrapCall, wethAddress); From 0b74c695a12bdf7e963cb9ef47de6080cb030057 Mon Sep 17 00:00:00 2001 From: lomonoshka Date: Tue, 31 Oct 2023 20:56:38 +0400 Subject: [PATCH 11/11] bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 77d6642..68d26fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.20.10-rc106", + "version": "0.20.10-rc107", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js",