mirror of
https://github.com/orionprotocol/sdk.git
synced 2026-03-14 14:12:35 +03:00
Strictest / tests / minor improvements
This commit is contained in:
@@ -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",
|
||||
{
|
||||
|
||||
36
package-lock.json
generated
36
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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<Record<string, Record<'exchange' | 'wallet', BigNumber>>>,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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<z.infer<typeof orderSchema>>
|
||||
}
|
||||
|
||||
type PoolSwap = {
|
||||
through: 'orion_pool'
|
||||
txHash: string
|
||||
wait: (confirmations?: number | undefined) => Promise<ethers.providers.TransactionReceipt>
|
||||
}
|
||||
|
||||
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<z.infer<typeof orderSchema>>((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,
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// import { ethers } from 'ethers';
|
||||
import Orion from '../Orion';
|
||||
import OrionAnalytics from '../services/OrionAnalytics';
|
||||
import { ReferralSystem } from '../services/ReferralSystem';
|
||||
|
||||
39
src/__tests__/exchangeContract.test.ts
Normal file
39
src/__tests__/exchangeContract.test.ts
Normal file
@@ -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,
|
||||
});
|
||||
});
|
||||
});
|
||||
39
src/__tests__/pools.test.ts
Normal file
39
src/__tests__/pools.test.ts
Normal file
@@ -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,
|
||||
});
|
||||
});
|
||||
});
|
||||
103
src/__tests__/trading.test.ts
Normal file
103
src/__tests__/trading.test.ts
Normal file
@@ -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();
|
||||
});
|
||||
});
|
||||
@@ -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',
|
||||
|
||||
@@ -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<T>(obj: Record<string, T | undefined>) {
|
||||
const newObj: Partial<Record<string, T>> = {};
|
||||
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,
|
||||
});
|
||||
|
||||
|
||||
@@ -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(
|
||||
[
|
||||
|
||||
@@ -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(
|
||||
[
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ethers } from 'ethers';
|
||||
import { type CFDOrder } from '../types';
|
||||
import type { CFDOrder } from '../types';
|
||||
|
||||
const { arrayify, joinSignature, splitSignature } = ethers.utils;
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ethers } from 'ethers';
|
||||
import { type Order } from '../types';
|
||||
import type { Order } from '../types';
|
||||
|
||||
const { arrayify, joinSignature, splitSignature } = ethers.utils;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { type Schema, type z } from 'zod';
|
||||
import type { Schema, z } from 'zod';
|
||||
import fetch from 'isomorphic-unfetch';
|
||||
|
||||
import {
|
||||
|
||||
@@ -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,
|
||||
|
||||
101
src/services/OrionAggregator/schemas/orderSchema.ts
Normal file
101
src/services/OrionAggregator/schemas/orderSchema.ts
Normal file
@@ -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;
|
||||
@@ -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(),
|
||||
});
|
||||
|
||||
|
||||
@@ -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<typeof orderUpdateSchema> | z.infer<typeof fullOrderSchema>
|
||||
order?: z.infer<typeof orderUpdateSchema> | z.infer<typeof fullOrderSchema> | undefined
|
||||
}
|
||||
|
||||
type AddressUpdateInitial = {
|
||||
kind: 'initial'
|
||||
balances: Partial<
|
||||
Record<
|
||||
string,
|
||||
Balance
|
||||
Record<
|
||||
string,
|
||||
Balance
|
||||
>
|
||||
>
|
||||
>
|
||||
orders?: Array<z.infer<typeof fullOrderSchema>> // The field is not defined if the user has no orders
|
||||
orders?: Array<z.infer<typeof fullOrderSchema>> | undefined // The field is not defined if the user has no orders
|
||||
}
|
||||
|
||||
type CfdAddressUpdateUpdate = {
|
||||
kind: 'update'
|
||||
balances?: CFDBalance[]
|
||||
order?: z.infer<typeof orderUpdateSchema> | z.infer<typeof fullOrderSchema>
|
||||
balances?: CFDBalance[] | undefined
|
||||
order?: z.infer<typeof orderUpdateSchema> | z.infer<typeof fullOrderSchema> | undefined
|
||||
}
|
||||
|
||||
type CfdAddressUpdateInitial = {
|
||||
kind: 'initial'
|
||||
balances: CFDBalance[]
|
||||
orders?: Array<z.infer<typeof fullOrderSchema>> // The field is not defined if the user has no orders
|
||||
orders?: Array<z.infer<typeof fullOrderSchema>> | 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<Record<string, Subscription[K]>>
|
||||
}> = {};
|
||||
|
||||
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<Record<string, unknown>> = {};
|
||||
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:
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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
|
||||
|
||||
30
src/types.ts
30
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<Record<string, string>>
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
// "extends": "@tsconfig/strictest/tsconfig.json",
|
||||
"extends": "@tsconfig/strictest/tsconfig.json",
|
||||
"files": [
|
||||
"./src/index.ts"
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user