From 2c24f714531c87a80dc4da2330b2a44ca08574f2 Mon Sep 17 00:00:00 2001 From: Aleksandr Kraiz Date: Fri, 17 Feb 2023 17:31:35 +0400 Subject: [PATCH] Strictest / tests / minor improvements --- .eslintrc.js | 7 ++ package-lock.json | 36 +++++- package.json | 5 +- src/BalanceGuard.ts | 2 +- src/Orion/index.ts | 6 +- src/OrionUnit/Exchange/deposit.ts | 21 ++-- src/OrionUnit/Exchange/getSwapInfo.ts | 4 +- src/OrionUnit/Exchange/swapMarket.ts | 25 +++++ src/OrionUnit/Exchange/withdraw.ts | 17 ++- src/OrionUnit/index.ts | 56 +++++++--- src/__tests__/basic.test.ts | 1 - src/__tests__/exchangeContract.test.ts | 39 +++++++ src/__tests__/pools.test.ts | 39 +++++++ src/__tests__/trading.test.ts | 103 ++++++++++++++++++ src/constants/exchanges.ts | 1 + src/crypt/getDomainData.ts | 14 ++- src/crypt/hashCFDOrder.ts | 2 +- src/crypt/hashOrder.ts | 2 +- src/crypt/signCFDOrder.ts | 6 +- src/crypt/signCFDOrderPersonal.ts | 2 +- src/crypt/signCancelOrder.ts | 6 +- src/crypt/signCancelOrderPersonal.ts | 2 +- src/crypt/signOrder.ts | 6 +- src/crypt/signOrderPersonal.ts | 2 +- src/fetchWithValidation.ts | 2 +- src/services/OrionAggregator/index.ts | 36 +++++- .../OrionAggregator/schemas/orderSchema.ts | 101 +++++++++++++++++ .../OrionAggregator/schemas/swapInfoSchema.ts | 24 ++-- src/services/OrionAggregator/ws/index.ts | 58 +++++----- .../ws/schemas/swapInfoSchema.ts | 19 ++-- src/services/OrionBlockchain/index.ts | 2 +- src/services/PriceFeed/index.ts | 2 +- src/simpleFetch.ts | 2 +- src/types.ts | 30 ++--- src/utils/denormalizeNumber.ts | 2 +- src/utils/getAvailableFundsSources.ts | 2 +- src/utils/getBalance.ts | 2 +- src/utils/getBalances.ts | 6 +- tsconfig.json | 2 +- 39 files changed, 566 insertions(+), 128 deletions(-) create mode 100644 src/__tests__/exchangeContract.test.ts create mode 100644 src/__tests__/pools.test.ts create mode 100644 src/__tests__/trading.test.ts create mode 100644 src/services/OrionAggregator/schemas/orderSchema.ts diff --git a/.eslintrc.js b/.eslintrc.js index e718c7f..b9e7312 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -28,6 +28,13 @@ module.exports = { '@typescript-eslint', ], rules: { + "@typescript-eslint/consistent-type-imports": [ + "error", + { + "fixStyle": "separate-type-imports", + "disallowTypeAnnotations": true + } + ], "@typescript-eslint/strict-boolean-expressions": [ "error", { diff --git a/package-lock.json b/package-lock.json index 11068f8..6b2c9c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { "name": "@orionprotocol/sdk", - "version": "0.17.7-rc.1", + "version": "0.17.11", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@orionprotocol/sdk", - "version": "0.17.7-rc.1", + "version": "0.17.11", "license": "ISC", "dependencies": { + "@babel/runtime": "^7.20.13", "@ethersproject/abstract-signer": "^5.7.0", "@ethersproject/providers": "^5.7.2", "@lukeed/csprng": "^1.0.1", @@ -515,6 +516,22 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", + "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, "node_modules/@babel/template": { "version": "7.18.10", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", @@ -11637,6 +11654,21 @@ "@babel/helper-plugin-utils": "^7.19.0" } }, + "@babel/runtime": { + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", + "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==", + "requires": { + "regenerator-runtime": "^0.13.11" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + } + } + }, "@babel/template": { "version": "7.18.10", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", diff --git a/package.json b/package.json index cb565ba..65f40a2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.17.11", + "version": "0.17.12", "description": "Orion Protocol SDK", "main": "./lib/esm/index.js", "module": "./lib/esm/index.js", @@ -19,7 +19,7 @@ "lint:eslint:fix": "eslint ./src --ext .ts,.js,.tsx,.jsx --fix", "postpublish": "npm run publish-npm", "publish-npm": "npm publish --access public --ignore-scripts --@orionprotocol:registry='https://registry.npmjs.org'", - "test": "jest", + "test": "dotenv jest", "test:coverage": "jest --coverage", "test:watch": "jest --watch" }, @@ -70,6 +70,7 @@ "webpack-cli": "^5.0.1" }, "dependencies": { + "@babel/runtime": "^7.20.13", "@ethersproject/abstract-signer": "^5.7.0", "@ethersproject/providers": "^5.7.2", "@lukeed/csprng": "^1.0.1", diff --git a/src/BalanceGuard.ts b/src/BalanceGuard.ts index ce7d1ff..94d10a0 100644 --- a/src/BalanceGuard.ts +++ b/src/BalanceGuard.ts @@ -28,7 +28,7 @@ export default class BalanceGuard { private readonly signer: ethers.Signer; - private readonly logger?: (message: string) => void; + private readonly logger?: ((message: string) => void) | undefined constructor( balances: Partial>>, diff --git a/src/Orion/index.ts b/src/Orion/index.ts index c02c8b2..87370bb 100644 --- a/src/Orion/index.ts +++ b/src/Orion/index.ts @@ -1,11 +1,11 @@ import { merge } from 'merge-anything'; import { chains, envs } from '../config'; -import { type networkCodes } from '../constants'; +import type { networkCodes } from '../constants'; import OrionUnit from '../OrionUnit'; import OrionAnalytics from '../services/OrionAnalytics'; import { ReferralSystem } from '../services/ReferralSystem'; import simpleFetch from '../simpleFetch'; -import { type SupportedChainId, type DeepPartial, type VerboseOrionUnitConfig } from '../types'; +import type { SupportedChainId, DeepPartial, VerboseOrionUnitConfig, KnownEnv } from '../types'; import { isValidChainId } from '../utils'; type EnvConfig = { @@ -29,8 +29,6 @@ type AggregatedAssets = Partial< > >; -type KnownEnv = 'testing' | 'staging' | 'production'; - export default class Orion { public readonly env?: string; diff --git a/src/OrionUnit/Exchange/deposit.ts b/src/OrionUnit/Exchange/deposit.ts index c4c3734..ed1c1db 100644 --- a/src/OrionUnit/Exchange/deposit.ts +++ b/src/OrionUnit/Exchange/deposit.ts @@ -116,12 +116,19 @@ export default async function deposit({ unsignedTx.nonce = nonce; const signedTx = await signer.signTransaction(unsignedTx); - const txResponse = await provider.sendTransaction(signedTx); - console.log(`Deposit tx sent: ${txResponse.hash}. Waiting for confirmation...`); - const txReceipt = await txResponse.wait(); - if (txReceipt.status !== undefined) { - console.log('Deposit tx confirmed'); - } else { - console.log('Deposit tx failed'); + try { + const txResponse = await provider.sendTransaction(signedTx); + console.log(`Deposit tx sent: ${txResponse.hash}. Waiting for confirmation...`); + const txReceipt = await txResponse.wait(); + if (txReceipt.status !== undefined) { + console.log('Deposit tx confirmed'); + } else { + console.log('Deposit tx failed'); + } + } catch (e) { + if (!(e instanceof Error)) throw new Error('e is not an Error'); + console.error(`Deposit tx failed: ${e.message}`, { + unsignedTx, + }); } } diff --git a/src/OrionUnit/Exchange/getSwapInfo.ts b/src/OrionUnit/Exchange/getSwapInfo.ts index 232bc8a..0d1e13f 100644 --- a/src/OrionUnit/Exchange/getSwapInfo.ts +++ b/src/OrionUnit/Exchange/getSwapInfo.ts @@ -1,8 +1,8 @@ import BigNumber from 'bignumber.js'; import { ethers } from 'ethers'; import { NATIVE_CURRENCY_PRECISION, SWAP_THROUGH_ORION_POOL_GAS_LIMIT } from '../../constants'; -import { type OrionAggregator } from '../../services/OrionAggregator'; -import { type OrionBlockchain } from '../../services/OrionBlockchain'; +import type { OrionAggregator } from '../../services/OrionAggregator'; +import type { OrionBlockchain } from '../../services/OrionBlockchain'; import simpleFetch from '../../simpleFetch'; import { calculateFeeInFeeAsset, denormalizeNumber, getNativeCryptocurrency } from '../../utils'; diff --git a/src/OrionUnit/Exchange/swapMarket.ts b/src/OrionUnit/Exchange/swapMarket.ts index 5639e96..fc4608f 100644 --- a/src/OrionUnit/Exchange/swapMarket.ts +++ b/src/OrionUnit/Exchange/swapMarket.ts @@ -10,6 +10,8 @@ import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency'; import simpleFetch from '../../simpleFetch'; import { calculateFeeInFeeAsset, denormalizeNumber, normalizeNumber } from '../../utils'; import { signOrder } from '../../crypt'; +import type orderSchema from '../../services/OrionAggregator/schemas/orderSchema'; +import type { z } from 'zod'; export type SwapMarketParams = { type: 'exactSpend' | 'exactReceive' @@ -34,11 +36,13 @@ export type SwapMarketParams = { type AggregatorOrder = { through: 'aggregator' id: string + wait: () => Promise> } type PoolSwap = { through: 'orion_pool' txHash: string + wait: (confirmations?: number | undefined) => Promise } export type Swap = AggregatorOrder | PoolSwap; @@ -293,6 +297,7 @@ export default async function swapMarket({ const swapThroughOrionPoolTxResponse = await signer.sendTransaction(unsignedSwapThroughOrionPoolTx); options?.logger?.(`Transaction sent. Tx hash: ${swapThroughOrionPoolTxResponse.hash}`); return { + wait: swapThroughOrionPoolTxResponse.wait, through: 'orion_pool', txHash: swapThroughOrionPoolTxResponse.hash, }; @@ -408,6 +413,26 @@ export default async function swapMarket({ options?.logger?.(`Order placed. Order id: ${orderId}`); return { + wait: () => new Promise>((resolve, reject) => { + const timeout = setTimeout(() => { + reject(new Error('Timeout')) + }, 60000); + const interval = setInterval(() => { + simpleFetch(orionAggregator.getOrder)(orderId).then((data) => { + if (data.order.status === 'SETTLED') { + options?.logger?.(`Order ${orderId} settled`); + clearTimeout(timeout); + clearInterval(interval); + resolve(data); + } else { + options?.logger?.(`Order ${orderId} status: ${data.order.status}`); + } + }).catch((e) => { + if (!(e instanceof Error)) throw new Error('Not an error'); + options?.logger?.(`Error while getting order status: ${e.message}`); + }); + }, 1000); + }), through: 'aggregator', id: orderId, }; diff --git a/src/OrionUnit/Exchange/withdraw.ts b/src/OrionUnit/Exchange/withdraw.ts index fd73f7d..014ff65 100644 --- a/src/OrionUnit/Exchange/withdraw.ts +++ b/src/OrionUnit/Exchange/withdraw.ts @@ -109,10 +109,17 @@ export default async function withdraw({ const signedTx = await signer.signTransaction(unsignedTx); const txResponse = await provider.sendTransaction(signedTx); console.log(`Withdraw tx sent: ${txResponse.hash}. Waiting for confirmation...`); - const txReceipt = await txResponse.wait(); - if (txReceipt.status !== undefined) { - console.log('Withdraw tx confirmed'); - } else { - console.log('Withdraw tx failed'); + try { + const txReceipt = await txResponse.wait(); + if (txReceipt.status !== undefined) { + console.log('Withdraw tx confirmed'); + } else { + console.log('Withdraw tx failed'); + } + } catch (e) { + if (!(e instanceof Error)) throw new Error('e is not an Error'); + console.error(`Deposit tx failed: ${e.message}`, { + unsignedTx, + }); } } diff --git a/src/OrionUnit/index.ts b/src/OrionUnit/index.ts index d18bdc8..444bd6d 100644 --- a/src/OrionUnit/index.ts +++ b/src/OrionUnit/index.ts @@ -2,16 +2,16 @@ import { ethers } from 'ethers'; import { OrionAggregator } from '../services/OrionAggregator'; import { OrionBlockchain } from '../services/OrionBlockchain'; import { PriceFeed } from '../services/PriceFeed'; -import type { SupportedChainId, VerboseOrionUnitConfig } from '../types'; +import type { KnownEnv, SupportedChainId, VerboseOrionUnitConfig } from '../types'; import Exchange from './Exchange'; import FarmingManager from './FarmingManager'; -import { chains } from '../config'; -import { type networkCodes } from '../constants'; +import { chains, envs } from '../config'; +import type { networkCodes } from '../constants'; -// type KnownConfig = { -// env: string; -// chainId: SupportedChainId; -// } +type KnownConfig = { + env: KnownEnv + chainId: SupportedChainId +} // type OrionUnitConfig = KnownConfig | VerboseOrionUnitConfig; @@ -39,8 +39,36 @@ export default class OrionUnit { // constructor(config: KnownConfig); // constructor(config: VerboseConfig); - constructor(config: VerboseOrionUnitConfig) { - this.config = config; + constructor(config: KnownConfig | VerboseOrionUnitConfig) { + if ('env' in config) { + const staticConfig = envs[config.env]; + if (!staticConfig) throw new Error(`Invalid environment: ${config.env}. Available environments: ${Object.keys(envs).join(', ')}`); + + const chainConfig = chains[config.chainId]; + if (!chainConfig) throw new Error(`Invalid chainId: ${config.chainId}. Available chainIds: ${Object.keys(chains).join(', ')}`); + + 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, + services: { + orionBlockchain: { + http: networkConfig.api + networkConfig.services.blockchain.http, + }, + orionAggregator: { + http: networkConfig.api + networkConfig.services.aggregator.http, + ws: networkConfig.api + networkConfig.services.aggregator.ws, + }, + priceFeed: { + api: networkConfig.api + networkConfig.services.priceFeed.all, + }, + }, + } + } else { + this.config = config; + } const chainInfo = chains[config.chainId]; if (!chainInfo) throw new Error('Chain info is required'); @@ -48,14 +76,14 @@ export default class OrionUnit { // this.env = config.env; this.chainId = config.chainId; this.networkCode = chainInfo.code; - this.provider = new ethers.providers.StaticJsonRpcProvider(config.nodeJsonRpc); + this.provider = new ethers.providers.StaticJsonRpcProvider(this.config.nodeJsonRpc); - this.orionBlockchain = new OrionBlockchain(config.services.orionBlockchain.http); + this.orionBlockchain = new OrionBlockchain(this.config.services.orionBlockchain.http); this.orionAggregator = new OrionAggregator( - config.services.orionAggregator.http, - config.services.orionAggregator.ws, + this.config.services.orionAggregator.http, + this.config.services.orionAggregator.ws, ); - this.priceFeed = new PriceFeed(config.services.priceFeed.api); + this.priceFeed = new PriceFeed(this.config.services.priceFeed.api); this.exchange = new Exchange(this); this.farmingManager = new FarmingManager(this); } diff --git a/src/__tests__/basic.test.ts b/src/__tests__/basic.test.ts index aabb327..4201b25 100644 --- a/src/__tests__/basic.test.ts +++ b/src/__tests__/basic.test.ts @@ -1,4 +1,3 @@ -// import { ethers } from 'ethers'; import Orion from '../Orion'; import OrionAnalytics from '../services/OrionAnalytics'; import { ReferralSystem } from '../services/ReferralSystem'; diff --git a/src/__tests__/exchangeContract.test.ts b/src/__tests__/exchangeContract.test.ts new file mode 100644 index 0000000..b52d048 --- /dev/null +++ b/src/__tests__/exchangeContract.test.ts @@ -0,0 +1,39 @@ +import { ethers } from 'ethers'; +import Orion from '../Orion'; + +const privateKey = process.env['PRIVATE_KEY']; +if (privateKey === undefined) throw new Error('Private key is required'); + +jest.setTimeout(30000); + +describe('Transfers', () => { + test('Deposit ORN', async () => { + const orion = new Orion('testing'); + const bscUnit = orion.getUnit('bsc'); + const wallet = new ethers.Wallet( + privateKey, + bscUnit.provider + ); + + await bscUnit.exchange.deposit({ + asset: 'ORN', + amount: 20, + signer: wallet, + }); + }); + + test('Withdraw ORN', async () => { + const orion = new Orion('testing'); + const bscUnit = orion.getUnit('bsc'); + const wallet = new ethers.Wallet( + privateKey, + bscUnit.provider + ); + + await bscUnit.exchange.withdraw({ + asset: 'ORN', + amount: 20, + signer: wallet, + }); + }); +}); diff --git a/src/__tests__/pools.test.ts b/src/__tests__/pools.test.ts new file mode 100644 index 0000000..9bffd5e --- /dev/null +++ b/src/__tests__/pools.test.ts @@ -0,0 +1,39 @@ +import { ethers } from 'ethers'; +import Orion from '../Orion'; + +const privateKey = process.env['PRIVATE_KEY'] +if (privateKey === undefined) throw new Error('Private key is required'); + +jest.setTimeout(30000); + +describe('Pools', () => { + test('Add liquidity ORN', async () => { + const orion = new Orion('testing'); + const bscUnit = orion.getUnit('bsc'); + const wallet = new ethers.Wallet( + privateKey, + bscUnit.provider + ); + + await bscUnit.farmingManager.addLiquidity({ + amountAsset: 'ORN', + poolName: 'ORN-USDT', + amount: 20, + signer: wallet, + }); + }); + + test('Remove liquidity ORN', async () => { + const orion = new Orion('testing'); + const bscUnit = orion.getUnit('bsc'); + const wallet = new ethers.Wallet( + privateKey, + bscUnit.provider + ); + + await bscUnit.farmingManager.removeAllLiquidity({ + poolName: 'ORN-USDT', + signer: wallet, + }); + }); +}); diff --git a/src/__tests__/trading.test.ts b/src/__tests__/trading.test.ts new file mode 100644 index 0000000..11c0823 --- /dev/null +++ b/src/__tests__/trading.test.ts @@ -0,0 +1,103 @@ +import { ethers } from 'ethers'; +import Orion from '../Orion'; +import swapMarket from '../OrionUnit/Exchange/swapMarket'; + +const privateKey = process.env['PRIVATE_KEY'] +if (privateKey === undefined) throw new Error('Private key is required'); + +jest.setTimeout(240000); + +describe('Spot trading', () => { + test('Sell. Simple', async () => { + const orion = new Orion('testing'); + const bscUnit = orion.getUnit('bsc'); + const wallet = new ethers.Wallet( + privateKey, + bscUnit.provider + ); + + const result = await swapMarket({ + assetIn: 'ORN', + assetOut: 'USDT', + amount: 20, + type: 'exactSpend', + signer: wallet, + feeAsset: 'USDT', + orionUnit: bscUnit, + slippagePercent: 1, + // options: { + // logger: console.log + // } + }) + await result.wait(); + }); + + test('Buy. Simple', async () => { + const orion = new Orion('testing'); + const bscUnit = orion.getUnit('bsc'); + const wallet = new ethers.Wallet( + privateKey, + bscUnit.provider + ); + + const result = await bscUnit.exchange.swapMarket({ + assetIn: 'USDT', + assetOut: 'ORN', + amount: 20, + type: 'exactReceive', + signer: wallet, + feeAsset: 'USDT', + slippagePercent: 1, + // options: { + // logger: console.log + // } + }) + await result.wait(); + }); + + test('Buy. Complex', async () => { + const orion = new Orion('testing'); + const bscUnit = orion.getUnit('bsc'); + const wallet = new ethers.Wallet( + privateKey, + bscUnit.provider + ); + + const result = await bscUnit.exchange.swapMarket({ + assetIn: 'USDT', + assetOut: 'BNB', + amount: 40, + type: 'exactSpend', + signer: wallet, + feeAsset: 'USDT', + slippagePercent: 1, + // options: { + // logger: console.log + // } + }) + await result.wait(); + }); + + test('Sell. Complex', async () => { + const orion = new Orion('testing'); + const bscUnit = orion.getUnit('bsc'); + const wallet = new ethers.Wallet( + privateKey, + bscUnit.provider + ); + + const result = await bscUnit.exchange.swapMarket({ + assetIn: 'BNB', + assetOut: 'ETH', + amount: 0.01, + type: 'exactReceive', + signer: wallet, + feeAsset: 'USDT', + slippagePercent: 1, + // options: { + // logger: console.log + // } + }); + await result.wait(); + }); +}); diff --git a/src/constants/exchanges.ts b/src/constants/exchanges.ts index 5c646f6..53d1a5d 100644 --- a/src/constants/exchanges.ts +++ b/src/constants/exchanges.ts @@ -1,3 +1,4 @@ +// https://github.com/orionprotocol/orion-aggregator/blob/11a7847af958726c65ae5f7b14ee6463c75ea14b/src/main/java/io/orionprotocol/aggregator/model/Exchange.java export default [ // CEXes 'ASCENDEX', diff --git a/src/crypt/getDomainData.ts b/src/crypt/getDomainData.ts index d43c75e..cd84ce6 100644 --- a/src/crypt/getDomainData.ts +++ b/src/crypt/getDomainData.ts @@ -1,14 +1,24 @@ -import { type SupportedChainId } from '../types'; +import type { SupportedChainId } from '../types'; import eip712DomainData from '../config/eip712DomainData.json'; import eip712DomainSchema from '../config/schemas/eip712DomainSchema'; const EIP712Domain = eip712DomainSchema.parse(eip712DomainData); +function removeUndefined(obj: Record) { + const newObj: Partial> = {}; + for (const [key, value] of Object.entries(obj)) { + if (value !== undefined) { + newObj[key] = value; + } + } + return newObj; +} + /** * See {@link https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator} */ const getDomainData = (chainId: SupportedChainId) => ({ - ...EIP712Domain, + ...removeUndefined(EIP712Domain), chainId, }); diff --git a/src/crypt/hashCFDOrder.ts b/src/crypt/hashCFDOrder.ts index 099d217..ca63c77 100644 --- a/src/crypt/hashCFDOrder.ts +++ b/src/crypt/hashCFDOrder.ts @@ -1,5 +1,5 @@ import { ethers } from 'ethers'; -import { type CFDOrder } from '../types'; +import type { CFDOrder } from '../types'; const hashCFDOrder = (order: CFDOrder) => ethers.utils.solidityKeccak256( [ diff --git a/src/crypt/hashOrder.ts b/src/crypt/hashOrder.ts index 7d6cdeb..aca6ed8 100644 --- a/src/crypt/hashOrder.ts +++ b/src/crypt/hashOrder.ts @@ -1,5 +1,5 @@ import { ethers } from 'ethers'; -import { type Order } from '../types'; +import type { Order } from '../types'; const hashOrder = (order: Order) => ethers.utils.solidityKeccak256( [ diff --git a/src/crypt/signCFDOrder.ts b/src/crypt/signCFDOrder.ts index 554ee39..358d4be 100644 --- a/src/crypt/signCFDOrder.ts +++ b/src/crypt/signCFDOrder.ts @@ -1,9 +1,9 @@ -import { type TypedDataSigner } from '@ethersproject/abstract-signer'; +import type { TypedDataSigner } from '@ethersproject/abstract-signer'; import BigNumber from 'bignumber.js'; -import { type ethers } from 'ethers'; +import type { ethers } from 'ethers'; import { joinSignature, splitSignature } from 'ethers/lib/utils'; import { INTERNAL_ORION_PRECISION } from '../constants'; -import { type CFDOrder, type SignedCFDOrder, type SupportedChainId } from '../types'; +import type { CFDOrder, SignedCFDOrder, SupportedChainId } from '../types'; import normalizeNumber from '../utils/normalizeNumber'; import getDomainData from './getDomainData'; import signCFDOrderPersonal from './signCFDOrderPersonal'; diff --git a/src/crypt/signCFDOrderPersonal.ts b/src/crypt/signCFDOrderPersonal.ts index d47889a..60366ca 100644 --- a/src/crypt/signCFDOrderPersonal.ts +++ b/src/crypt/signCFDOrderPersonal.ts @@ -1,5 +1,5 @@ import { ethers } from 'ethers'; -import { type CFDOrder } from '../types'; +import type { CFDOrder } from '../types'; const { arrayify, joinSignature, splitSignature } = ethers.utils; diff --git a/src/crypt/signCancelOrder.ts b/src/crypt/signCancelOrder.ts index 10cb6a6..e48bdb0 100644 --- a/src/crypt/signCancelOrder.ts +++ b/src/crypt/signCancelOrder.ts @@ -1,8 +1,8 @@ -import { type TypedDataSigner } from '@ethersproject/abstract-signer'; -import { type ethers } from 'ethers'; +import type { TypedDataSigner } from '@ethersproject/abstract-signer'; +import type { ethers } from 'ethers'; import { joinSignature, splitSignature } from 'ethers/lib/utils'; import CANCEL_ORDER_TYPES from '../constants/cancelOrderTypes'; -import { type CancelOrderRequest, type SignedCancelOrderRequest, type SupportedChainId } from '../types'; +import type { CancelOrderRequest, SignedCancelOrderRequest, SupportedChainId } from '../types'; import getDomainData from './getDomainData'; import signCancelOrderPersonal from './signCancelOrderPersonal'; diff --git a/src/crypt/signCancelOrderPersonal.ts b/src/crypt/signCancelOrderPersonal.ts index f3b3855..25c544d 100644 --- a/src/crypt/signCancelOrderPersonal.ts +++ b/src/crypt/signCancelOrderPersonal.ts @@ -1,6 +1,6 @@ import { ethers } from 'ethers'; import { arrayify, joinSignature, splitSignature } from 'ethers/lib/utils'; -import { type CancelOrderRequest } from '../types'; +import type { CancelOrderRequest } from '../types'; const signCancelOrderPersonal = async ( cancelOrderRequest: CancelOrderRequest, diff --git a/src/crypt/signOrder.ts b/src/crypt/signOrder.ts index 983e480..afe3aa8 100644 --- a/src/crypt/signOrder.ts +++ b/src/crypt/signOrder.ts @@ -1,10 +1,10 @@ -import { type TypedDataSigner } from '@ethersproject/abstract-signer'; +import type { TypedDataSigner } from '@ethersproject/abstract-signer'; import BigNumber from 'bignumber.js'; -import { type ethers } from 'ethers'; +import type { ethers } from 'ethers'; import { joinSignature, splitSignature } from 'ethers/lib/utils'; import { INTERNAL_ORION_PRECISION } from '../constants'; import ORDER_TYPES from '../constants/orderTypes'; -import { type Order, type SignedOrder, type SupportedChainId } from '../types'; +import type { Order, SignedOrder, SupportedChainId } from '../types'; import normalizeNumber from '../utils/normalizeNumber'; import getDomainData from './getDomainData'; import hashOrder from './hashOrder'; diff --git a/src/crypt/signOrderPersonal.ts b/src/crypt/signOrderPersonal.ts index 35efe4c..e791b28 100644 --- a/src/crypt/signOrderPersonal.ts +++ b/src/crypt/signOrderPersonal.ts @@ -1,5 +1,5 @@ import { ethers } from 'ethers'; -import { type Order } from '../types'; +import type { Order } from '../types'; const { arrayify, joinSignature, splitSignature } = ethers.utils; diff --git a/src/fetchWithValidation.ts b/src/fetchWithValidation.ts index 8a68030..f0b227b 100644 --- a/src/fetchWithValidation.ts +++ b/src/fetchWithValidation.ts @@ -1,4 +1,4 @@ -import { type Schema, type z } from 'zod'; +import type { Schema, z } from 'zod'; import fetch from 'isomorphic-unfetch'; import { diff --git a/src/services/OrionAggregator/index.ts b/src/services/OrionAggregator/index.ts index 97c8f86..97416a5 100644 --- a/src/services/OrionAggregator/index.ts +++ b/src/services/OrionAggregator/index.ts @@ -9,7 +9,7 @@ import errorSchema from './schemas/errorSchema'; import placeAtomicSwapSchema from './schemas/placeAtomicSwapSchema'; import { OrionAggregatorWS } from './ws'; import { atomicSwapHistorySchema } from './schemas/atomicSwapHistorySchema'; -import { type Exchange, type SignedCancelOrderRequest, type SignedCFDOrder, type SignedOrder } from '../../types'; +import type { Exchange, SignedCancelOrderRequest, SignedCFDOrder, SignedOrder } from '../../types'; import { pairConfigSchema } from './schemas'; import { aggregatedOrderbookSchema, exchangeOrderbookSchema, poolReservesSchema, @@ -17,6 +17,8 @@ import { import type networkCodes from '../../constants/networkCodes'; import toUpperCase from '../../utils/toUpperCase'; import httpToWS from '../../utils/httpToWS'; +import { ethers } from 'ethers'; +import orderSchema from './schemas/orderSchema'; class OrionAggregator { private readonly apiUrl: string; @@ -55,6 +57,27 @@ class OrionAggregator { this.getAggregatedOrderbook = this.getAggregatedOrderbook.bind(this); this.getExchangeOrderbook = this.getExchangeOrderbook.bind(this); this.getPoolReserves = this.getPoolReserves.bind(this); + this.getVersion = this.getVersion.bind(this); + } + + getOrder = (orderId: string, owner?: string) => { + if (!ethers.utils.isHexString(orderId)) { + throw new Error(`Invalid order id: ${orderId}. Must be a hex string`); + } + const url = new URL(`${this.apiUrl}/api/v1/order`); + url.searchParams.append('orderId', orderId); + if (owner !== undefined) { + if (!ethers.utils.isAddress(owner)) { + throw new Error(`Invalid owner address: ${owner}`); + } + url.searchParams.append('owner', owner); + } + return fetchWithValidation( + url.toString(), + orderSchema, + undefined, + errorSchema, + ); } getPairsList = (market: 'spot' | 'futures') => { @@ -124,6 +147,17 @@ class OrionAggregator { ); }; + getVersion = () => fetchWithValidation( + `${this.apiUrl}/api/v1/version`, + z.object({ + serviceName: z.string(), + version: z.string(), + apiVersion: z.string(), + }), + undefined, + errorSchema, + ); + getPairConfig = (assetPair: string) => fetchWithValidation( `${this.apiUrl}/api/v1/pairs/exchangeInfo/${assetPair}`, pairConfigSchema, diff --git a/src/services/OrionAggregator/schemas/orderSchema.ts b/src/services/OrionAggregator/schemas/orderSchema.ts new file mode 100644 index 0000000..e8f0a6a --- /dev/null +++ b/src/services/OrionAggregator/schemas/orderSchema.ts @@ -0,0 +1,101 @@ +import { ethers } from 'ethers'; +import { z } from 'zod'; +import { exchanges, orderStatuses, subOrderStatuses } from '../../../constants'; + +const blockchainOrderSchema = z.object({ + id: z.string().refine(ethers.utils.isHexString, (value) => ({ + message: `blockchainOrder.id must be a hex string, got ${value}`, + })), + senderAddress: z.string().refine(ethers.utils.isAddress, (value) => ({ + message: `blockchainOrder.senderAddress must be an address, got ${value}`, + })), + matcherAddress: z.string().refine(ethers.utils.isAddress, (value) => ({ + message: `blockchainOrder.matcherAddress must be an address, got ${value}`, + })), + baseAsset: z.string().refine(ethers.utils.isAddress, (value) => ({ + message: `blockchainOrder.baseAsset must be an address, got ${value}`, + })), + quoteAsset: z.string().refine(ethers.utils.isAddress, (value) => ({ + message: `blockchainOrder.quoteAsset must be an address, got ${value}`, + })), + matcherFeeAsset: z.string().refine(ethers.utils.isAddress, (value) => ({ + message: `blockchainOrder.matcherFeeAsset must be an address, got ${value}`, + })), + amount: z.number().int().nonnegative(), + price: z.number().int().nonnegative(), + matcherFee: z.number().int().nonnegative(), + nonce: z.number(), + expiration: z.number(), + buySide: z.union([z.literal(1), z.literal(0)]), + signature: z.string().refine(ethers.utils.isHexString, (value) => ({ + message: `blockchainOrder.signature must be a hex string, got ${value}`, + })), + isPersonalSign: z.boolean(), + needWithdraw: z.boolean(), +}); + +const tradeInfoSchema = z.object({ + tradeId: z.string().uuid(), + tradeStatus: z.enum(['NEW', 'PENDING', 'OK', 'FAIL', 'TEMP_ERROR', 'REJECTED']), + filledAmount: z.number().nonnegative(), + price: z.number().nonnegative(), + creationTime: z.number(), + updateTime: z.number(), + matchedBlockchainOrder: blockchainOrderSchema, + matchedSubOrderId: z.number().int().nonnegative(), + exchangeTradeInfo: z.boolean(), + poolTradeInfo: z.boolean(), +}); + +const baseOrderSchema = z.object({ + assetPair: z.string(), + side: z.enum(['BUY', 'SELL']), + amount: z.number().nonnegative(), + remainingAmount: z.number().nonnegative(), + price: z.number().nonnegative(), + sender: z.string().refine(ethers.utils.isAddress, (value) => ({ + message: `order.sender must be an address, got ${value}`, + })), + filledAmount: z.number().nonnegative(), + internalOnly: z.boolean(), +}) + +const subOrderSchema = baseOrderSchema.extend({ + price: z.number(), + id: z.number(), + parentOrderId: z.string().refine(ethers.utils.isHexString, (value) => ({ + message: `subOrder.parentOrderId must be a hex string, got ${value}`, + })), + exchange: z.enum(exchanges), + brokerAddress: + z.literal('ORION_BROKER').or(z.string().refine(ethers.utils.isAddress, (value) => ({ + message: `subOrder.subOrders.[n].brokerAddress must be an address, got ${value}`, + }))), + tradesInfo: z.record( + z.string().uuid(), + tradeInfoSchema + ), + status: z.enum(subOrderStatuses), + complexSwap: z.boolean(), +}); + +const orderSchema = z.object({ + orderId: z.string().refine(ethers.utils.isHexString, (value) => ({ + message: `orderId must be a hex string, got ${value}`, + })), + order: baseOrderSchema.extend({ + id: z.string().refine(ethers.utils.isHexString, (value) => ({ + message: `order.id must be a hex string, got ${value}`, + })), + fee: z.number().nonnegative(), + feeAsset: z.string(), + creationTime: z.number(), + blockchainOrder: blockchainOrderSchema, + subOrders: z.record(subOrderSchema), + updateTime: z.number(), + status: z.enum(orderStatuses), + settledAmount: z.number().nonnegative(), + }) +}); + +export default orderSchema; diff --git a/src/services/OrionAggregator/schemas/swapInfoSchema.ts b/src/services/OrionAggregator/schemas/swapInfoSchema.ts index 649b57a..53a5a93 100644 --- a/src/services/OrionAggregator/schemas/swapInfoSchema.ts +++ b/src/services/OrionAggregator/schemas/swapInfoSchema.ts @@ -1,6 +1,13 @@ import { z } from 'zod'; import { exchanges } from '../../../constants'; +const orderInfoSchema = z.object({ + assetPair: z.string(), + side: z.enum(['BUY', 'SELL']), + amount: z.number(), + safePrice: z.number(), +}).nullable(); + const swapInfoBase = z.object({ id: z.string(), amountIn: z.number(), @@ -10,12 +17,7 @@ const swapInfoBase = z.object({ path: z.array(z.string()), // isThroughPoolOptimal: z.boolean(), // deprecated executionInfo: z.string(), - orderInfo: z.object({ - assetPair: z.string(), - side: z.enum(['BUY', 'SELL']), - amount: z.number(), - safePrice: z.number(), - }).nullable(), + orderInfo: orderInfoSchema, exchanges: z.array(z.enum(exchanges)), price: z.number().nullable(), // spending asset price minAmountOut: z.number(), @@ -29,11 +31,13 @@ const swapInfoBase = z.object({ action: z.string(), }).array(), }), - marketAmountOut: z.number().optional(), - marketAmountIn: z.number().optional(), + marketAmountOut: z.number().nullable(), + marketAmountIn: z.number().nullable(), marketPrice: z.number(), - availableAmountIn: z.number().optional(), - availableAmountOut: z.number().optional(), + availableAmountIn: z.number().nullable(), + availableAmountOut: z.number().nullable(), + orderInfo: orderInfoSchema, + isThroughPoolOrCurve: z.boolean(), }).array(), }); diff --git a/src/services/OrionAggregator/ws/index.ts b/src/services/OrionAggregator/ws/index.ts index ebcdbb0..ba0683f 100644 --- a/src/services/OrionAggregator/ws/index.ts +++ b/src/services/OrionAggregator/ws/index.ts @@ -9,13 +9,13 @@ import { assetPairsConfigSchema, addressUpdateSchema, swapInfoSchema, } from './schemas'; import UnsubscriptionType from './UnsubscriptionType'; -import { - type SwapInfoBase, type AssetPairUpdate, type OrderbookItem, - type Balance, type Exchange, type CFDBalance, type FuturesTradeInfo, type SwapInfo, +import type { + SwapInfoBase, AssetPairUpdate, OrderbookItem, + Balance, Exchange, CFDBalance, FuturesTradeInfo, SwapInfo, } from '../../../types'; import unsubscriptionDoneSchema from './schemas/unsubscriptionDoneSchema'; import assetPairConfigSchema from './schemas/assetPairConfigSchema'; -import { type fullOrderSchema, type orderUpdateSchema } from './schemas/addressUpdateSchema'; +import type { fullOrderSchema, orderUpdateSchema } from './schemas/addressUpdateSchema'; import cfdAddressUpdateSchema from './schemas/cfdAddressUpdateSchema'; import futuresTradeInfoSchema from './schemas/futuresTradeInfoSchema'; // import errorSchema from './schemas/errorSchema'; @@ -79,35 +79,35 @@ type FuturesTradeInfoSubscription = { type AddressUpdateUpdate = { kind: 'update' balances: Partial< - Record< - string, - Balance + Record< + string, + Balance + > > - > - order?: z.infer | z.infer + order?: z.infer | z.infer | undefined } type AddressUpdateInitial = { kind: 'initial' balances: Partial< - Record< - string, - Balance + Record< + string, + Balance + > > - > - orders?: Array> // The field is not defined if the user has no orders + orders?: Array> | undefined // The field is not defined if the user has no orders } type CfdAddressUpdateUpdate = { kind: 'update' - balances?: CFDBalance[] - order?: z.infer | z.infer + balances?: CFDBalance[] | undefined + order?: z.infer | z.infer | undefined } type CfdAddressUpdateInitial = { kind: 'initial' balances: CFDBalance[] - orders?: Array> // The field is not defined if the user has no orders + orders?: Array> | undefined // The field is not defined if the user has no orders } type AddressUpdateSubscription = { @@ -156,7 +156,7 @@ type BufferLike = const isSubType = (subType: string): subType is keyof Subscription => Object.values(SubscriptionType).some((t) => t === subType); class OrionAggregatorWS { - private ws: WebSocket | undefined; + private ws?: WebSocket | undefined; // is used to make sure we do not need to renew ws subscription // we can not be sure that onclose event will recieve our code when we do `ws.close(4000)` @@ -168,11 +168,11 @@ class OrionAggregatorWS { [K in keyof Subscription]: Partial> }> = {}; - public onInit?: () => void; + public onInit: (() => void) | undefined - public onError?: (err: string) => void; + public onError: ((err: string) => void) | undefined - public logger?: (message: string) => void; + public logger: ((message: string) => void) | undefined private readonly wsUrl: string; @@ -229,15 +229,15 @@ class OrionAggregatorWS { ? ((subscription as any).payload as string) // TODO: Refactor!!! : uuidv4(); const subRequest: Partial> = {}; - subRequest.T = type; - subRequest.id = id; + subRequest['T'] = type; + subRequest['id'] = id; // TODO Refactor this if ('payload' in subscription) { if (typeof subscription.payload === 'string') { - subRequest.S = subscription.payload; + subRequest['S'] = subscription.payload; } else { - subRequest.S = { + subRequest['S'] = { d: id, ...subscription.payload, }; @@ -296,9 +296,9 @@ class OrionAggregatorWS { } } } else if (subscription === UnsubscriptionType.ASSET_PAIRS_CONFIG_UPDATES_UNSUBSCRIBE) { - delete this.subscriptions[SubscriptionType.ASSET_PAIRS_CONFIG_UPDATES_SUBSCRIBE]?.default; + delete this.subscriptions[SubscriptionType.ASSET_PAIRS_CONFIG_UPDATES_SUBSCRIBE]?.['default']; } else if (subscription === UnsubscriptionType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_UNSUBSCRIBE) { - delete this.subscriptions[SubscriptionType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_SUBSCRIBE]?.default; + delete this.subscriptions[SubscriptionType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_SUBSCRIBE]?.['default']; } } @@ -503,7 +503,7 @@ class OrionAggregatorWS { this.subscriptions[ SubscriptionType.ASSET_PAIRS_CONFIG_UPDATES_SUBSCRIBE - ]?.default?.callback({ + ]?.['default']?.callback({ kind: json.k === 'i' ? 'initial' : 'update', data: priceUpdates, }); @@ -612,7 +612,7 @@ class OrionAggregatorWS { this.subscriptions[ SubscriptionType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_SUBSCRIBE - ]?.default?.callback(brokerBalances); + ]?.['default']?.callback(brokerBalances); } break; default: diff --git a/src/services/OrionAggregator/ws/schemas/swapInfoSchema.ts b/src/services/OrionAggregator/ws/schemas/swapInfoSchema.ts index 4a4088f..cd692ef 100644 --- a/src/services/OrionAggregator/ws/schemas/swapInfoSchema.ts +++ b/src/services/OrionAggregator/ws/schemas/swapInfoSchema.ts @@ -3,6 +3,15 @@ import exchanges from '../../../../constants/exchanges'; import MessageType from '../MessageType'; import baseMessageSchema from './baseMessageSchema'; +const alternativeSchema = z.object({ // execution alternatives + e: z.enum(exchanges).array(), // exchanges + ps: z.string().array(), // path + mo: z.number().optional(), // market amount out + mi: z.number().optional(), // market amount in + mp: z.number(), // market price + aa: z.number().optional(), // available amount in + aao: z.number().optional(), // available amount out +}); const swapInfoSchemaBase = baseMessageSchema.extend({ T: z.literal(MessageType.SWAP_INFO), S: z.string(), // swap request id @@ -23,15 +32,7 @@ const swapInfoSchemaBase = baseMessageSchema.extend({ a: z.number(), // amount sp: z.number(), // safe price (with safe deviation but without slippage) }).optional(), - as: z.object({ // execution alternatives - e: z.enum(exchanges).array(), // exchanges - ps: z.string().array(), // path - mo: z.number().optional(), // market amount out - mi: z.number().optional(), // market amount in - mp: z.number(), // market price - aa: z.number().optional(), // available amount in - aao: z.number().optional(), // available amount out - }).array(), + as: alternativeSchema.array(), }); const swapInfoSchemaByAmountIn = swapInfoSchemaBase.extend({ diff --git a/src/services/OrionBlockchain/index.ts b/src/services/OrionBlockchain/index.ts index 3343f2a..eee1b11 100644 --- a/src/services/OrionBlockchain/index.ts +++ b/src/services/OrionBlockchain/index.ts @@ -16,7 +16,7 @@ import { import type redeemOrderSchema from '../OrionAggregator/schemas/redeemOrderSchema'; import { sourceAtomicHistorySchema, targetAtomicHistorySchema } from './schemas/atomicHistorySchema'; import { makePartial } from '../../utils'; -import { type networkCodes } from '../../constants'; +import type { networkCodes } from '../../constants'; type IAdminAuthHeaders = { auth: string diff --git a/src/services/PriceFeed/index.ts b/src/services/PriceFeed/index.ts index 2a0e5bd..a382906 100644 --- a/src/services/PriceFeed/index.ts +++ b/src/services/PriceFeed/index.ts @@ -1,5 +1,5 @@ import fetchWithValidation from '../../fetchWithValidation'; -import { type Exchange } from '../../types'; +import type { Exchange } from '../../types'; import { statisticsOverviewSchema, topPairsStatisticsSchema } from './schemas'; import candlesSchema from './schemas/candlesSchema'; import { PriceFeedWS } from './ws'; diff --git a/src/simpleFetch.ts b/src/simpleFetch.ts index ef36606..aa63e01 100644 --- a/src/simpleFetch.ts +++ b/src/simpleFetch.ts @@ -1,4 +1,4 @@ -import { type Schema, type z } from 'zod'; +import type { Schema, z } from 'zod'; import fetchWithValidation from './fetchWithValidation'; // https://stackoverflow.com/a/64919133 diff --git a/src/types.ts b/src/types.ts index 2bd53fa..7d10f25 100644 --- a/src/types.ts +++ b/src/types.ts @@ -143,13 +143,13 @@ export type BalanceRequirement = { readonly asset: Asset readonly amount: string readonly sources: Source[] - readonly spenderAddress?: string + readonly spenderAddress?: string | undefined } export type AggregatedBalanceRequirement = { readonly asset: Asset readonly sources: Source[] - readonly spenderAddress?: string + readonly spenderAddress?: string | undefined items: Partial> } @@ -189,11 +189,11 @@ export type OrderbookItem = { export type SwapInfoAlternative = { exchanges: Exchange[] path: string[] - marketAmountOut?: number - marketAmountIn?: number + marketAmountOut?: number | undefined + marketAmountIn?: number | undefined marketPrice: number - availableAmountIn?: number - availableAmountOut?: number + availableAmountIn?: number | undefined + availableAmountOut?: number | undefined } export type SwapInfoBase = { @@ -206,30 +206,30 @@ export type SwapInfoBase = { minAmountOut: number path: string[] - exchanges?: Exchange[] + exchanges?: Exchange[] | undefined poolOptimal: boolean - price?: number - marketPrice?: number + price?: number | undefined + marketPrice?: number | undefined orderInfo?: { pair: string side: 'BUY' | 'SELL' amount: number safePrice: number - } + } | undefined alternatives: SwapInfoAlternative[] } export type SwapInfoByAmountIn = SwapInfoBase & { kind: 'exactSpend' - availableAmountIn?: number - marketAmountOut?: number + availableAmountIn?: number | undefined + marketAmountOut?: number | undefined } export type SwapInfoByAmountOut = SwapInfoBase & { kind: 'exactReceive' - marketAmountIn?: number - availableAmountOut?: number + marketAmountIn?: number | undefined + availableAmountOut?: number | undefined } export type SwapInfo = SwapInfoByAmountIn | SwapInfoByAmountOut; @@ -282,3 +282,5 @@ export type VerboseOrionUnitConfig = { } } } + +export type KnownEnv = 'testing' | 'staging' | 'production'; diff --git a/src/utils/denormalizeNumber.ts b/src/utils/denormalizeNumber.ts index dbdda29..f7e3852 100644 --- a/src/utils/denormalizeNumber.ts +++ b/src/utils/denormalizeNumber.ts @@ -1,5 +1,5 @@ import BigNumber from 'bignumber.js'; -import { type ethers } from 'ethers'; +import type { ethers } from 'ethers'; /** * Converts normalized blockchain ("machine-readable") number to denormalized ("human-readable") number. diff --git a/src/utils/getAvailableFundsSources.ts b/src/utils/getAvailableFundsSources.ts index 982ec42..4a11576 100644 --- a/src/utils/getAvailableFundsSources.ts +++ b/src/utils/getAvailableFundsSources.ts @@ -1,5 +1,5 @@ import { ethers } from 'ethers'; -import { type Source } from '../types'; +import type { Source } from '../types'; export default function getAvailableFundsSources( expenseType: 'amount' | 'network_fee' | 'orion_fee', diff --git a/src/utils/getBalance.ts b/src/utils/getBalance.ts index b1a2469..5cdcd2f 100644 --- a/src/utils/getBalance.ts +++ b/src/utils/getBalance.ts @@ -3,7 +3,7 @@ import { ERC20__factory, type Exchange } from '@orionprotocol/contracts'; import type BigNumber from 'bignumber.js'; import { ethers } from 'ethers'; import { INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION } from '../constants'; -import { type OrionAggregator } from '../services/OrionAggregator'; +import type { OrionAggregator } from '../services/OrionAggregator'; import denormalizeNumber from './denormalizeNumber'; export default async function getBalance( diff --git a/src/utils/getBalances.ts b/src/utils/getBalances.ts index 0294070..d9904b4 100644 --- a/src/utils/getBalances.ts +++ b/src/utils/getBalances.ts @@ -1,7 +1,7 @@ -import { type Exchange } from '@orionprotocol/contracts'; +import type { Exchange } from '@orionprotocol/contracts'; import type BigNumber from 'bignumber.js'; -import { type ethers } from 'ethers'; -import { type OrionAggregator } from '../services/OrionAggregator'; +import type { ethers } from 'ethers'; +import type { OrionAggregator } from '../services/OrionAggregator'; import getBalance from './getBalance'; export default async ( diff --git a/tsconfig.json b/tsconfig.json index a785243..02ef5dc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,5 @@ { - // "extends": "@tsconfig/strictest/tsconfig.json", + "extends": "@tsconfig/strictest/tsconfig.json", "files": [ "./src/index.ts" ],