mirror of
https://github.com/orionprotocol/sdk.git
synced 2026-03-13 21:52:36 +03:00
Exchanges / more error messages
This commit is contained in:
18
package-lock.json
generated
18
package-lock.json
generated
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"name": "@orionprotocol/sdk",
|
||||
"version": "0.12.4",
|
||||
"version": "0.12.12",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@orionprotocol/sdk",
|
||||
"version": "0.12.4",
|
||||
"version": "0.12.12",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@ethersproject/abstract-signer": "^5.6.0",
|
||||
"@ethersproject/providers": "^5.6.2",
|
||||
"@lukeed/csprng": "^1.0.1",
|
||||
"@orionprotocol/contracts": "0.0.8",
|
||||
"@orionprotocol/contracts": "0.0.9",
|
||||
"bignumber.js": "^9.0.2",
|
||||
"buffer": "^6.0.3",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
@@ -2485,9 +2485,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@orionprotocol/contracts": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-0.0.8.tgz",
|
||||
"integrity": "sha512-dgfowYXTf2nu/o9wcQbnLZg+kF7mJusP62unGSxhRKjquVrF1qids+lpSyjvbA9KT/XYKbXg61tXOZ9pOdrBTw=="
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-0.0.9.tgz",
|
||||
"integrity": "sha512-mMnds/0clCcGDr7+LW6SyTKzrxm1o6Hkksi6m6XBeIXkMGjnfMTApoC3b+/sniHuXTgplkb08ecSyz6VPgII2g=="
|
||||
},
|
||||
"node_modules/@sinonjs/commons": {
|
||||
"version": "1.8.3",
|
||||
@@ -12131,9 +12131,9 @@
|
||||
}
|
||||
},
|
||||
"@orionprotocol/contracts": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-0.0.8.tgz",
|
||||
"integrity": "sha512-dgfowYXTf2nu/o9wcQbnLZg+kF7mJusP62unGSxhRKjquVrF1qids+lpSyjvbA9KT/XYKbXg61tXOZ9pOdrBTw=="
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@orionprotocol/contracts/-/contracts-0.0.9.tgz",
|
||||
"integrity": "sha512-mMnds/0clCcGDr7+LW6SyTKzrxm1o6Hkksi6m6XBeIXkMGjnfMTApoC3b+/sniHuXTgplkb08ecSyz6VPgII2g=="
|
||||
},
|
||||
"@sinonjs/commons": {
|
||||
"version": "1.8.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@orionprotocol/sdk",
|
||||
"version": "0.12.12",
|
||||
"version": "0.12.13",
|
||||
"description": "Orion Protocol SDK",
|
||||
"main": "./lib/esm/index.js",
|
||||
"module": "./lib/esm/index.js",
|
||||
@@ -60,7 +60,7 @@
|
||||
"@ethersproject/abstract-signer": "^5.6.0",
|
||||
"@ethersproject/providers": "^5.6.2",
|
||||
"@lukeed/csprng": "^1.0.1",
|
||||
"@orionprotocol/contracts": "0.0.8",
|
||||
"@orionprotocol/contracts": "0.0.9",
|
||||
"bignumber.js": "^9.0.2",
|
||||
"buffer": "^6.0.3",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
|
||||
@@ -94,6 +94,7 @@ export default async function getSwapMarketFeeInfo({
|
||||
}
|
||||
|
||||
const [baseAssetName] = swapInfo.orderInfo.assetPair.split('-');
|
||||
if (baseAssetName === undefined) throw new Error('Base asset name is undefined');
|
||||
const baseAssetAddress = assetToAddress[baseAssetName];
|
||||
if (!baseAssetAddress) throw new Error(`No asset address for ${baseAssetName}`);
|
||||
|
||||
|
||||
@@ -86,6 +86,8 @@ export default async function swapMarket({
|
||||
const feeAssets = await simpleFetch(orionBlockchain.getTokensFee)();
|
||||
const pricesInOrn = await simpleFetch(orionBlockchain.getPrices)();
|
||||
const gasPriceWei = await simpleFetch(orionBlockchain.getGasPriceWei)();
|
||||
const { factories } = await simpleFetch(orionBlockchain.getPoolsConfig)();
|
||||
const poolExchangesList = factories !== undefined ? Object.keys(factories) : [];
|
||||
|
||||
const gasPriceGwei = ethers.utils.formatUnits(gasPriceWei, 'gwei').toString();
|
||||
|
||||
@@ -125,6 +127,12 @@ export default async function swapMarket({
|
||||
options?.poolOnly ? ['ORION_POOL'] : undefined,
|
||||
);
|
||||
|
||||
const { exchanges: swapExchanges } = swapInfo;
|
||||
|
||||
const firstSwapExchange = swapExchanges?.[0];
|
||||
|
||||
if (swapExchanges) options?.logger?.(`Swap exchanges: ${swapExchanges.join(', ')}`);
|
||||
|
||||
if (swapInfo.orderInfo !== null && options?.poolOnly === true && options.poolOnly !== swapInfo.isThroughPoolOptimal) {
|
||||
throw new Error(`Unexpected Orion Aggregator response. Please, contact support. Report swap request id: ${swapInfo.id}`);
|
||||
}
|
||||
@@ -139,16 +147,49 @@ export default async function swapMarket({
|
||||
|
||||
if (swapInfo.orderInfo === null) throw new Error(swapInfo.executionInfo);
|
||||
|
||||
const [baseAssetName, quoteAssetName] = swapInfo.orderInfo.assetPair.split('-');
|
||||
if (baseAssetName === undefined) throw new Error('Base asset name is undefined');
|
||||
if (quoteAssetName === undefined) throw new Error('Quote asset name is undefined');
|
||||
|
||||
const pairConfig = await simpleFetch(orionAggregator.getPairConfig)(`${baseAssetName}-${quoteAssetName}`);
|
||||
if (!pairConfig) throw new Error(`Pair config ${baseAssetName}-${quoteAssetName} not found`);
|
||||
|
||||
const qtyPrecisionBN = new BigNumber(pairConfig.qtyPrecision);
|
||||
const qtyDecimalPlaces = amountBN.dp();
|
||||
|
||||
if (qtyPrecisionBN.lt(qtyDecimalPlaces)) throw new Error(`Actual amount decimal places (${qtyDecimalPlaces}) is greater than max allowed decimal places (${qtyPrecisionBN.toString()}) on pair ${baseAssetName}-${quoteAssetName}`);
|
||||
|
||||
const percent = new BigNumber(slippagePercent).div(100);
|
||||
|
||||
let isThroughPoolOptimal: boolean;
|
||||
|
||||
if (options?.developer?.route !== undefined) {
|
||||
isThroughPoolOptimal = options.developer.route === 'pool';
|
||||
} else if (options?.poolOnly) isThroughPoolOptimal = true;
|
||||
else isThroughPoolOptimal = swapInfo.isThroughPoolOptimal;
|
||||
options?.logger?.('Swap is through pool (because route forced to pool)');
|
||||
} else if (options?.poolOnly) {
|
||||
options?.logger?.('Swap is through pool (because "poolOnly" option is true)');
|
||||
isThroughPoolOptimal = true;
|
||||
} else if (
|
||||
swapExchanges !== undefined
|
||||
&& poolExchangesList.length > 0
|
||||
&& swapExchanges.length === 1
|
||||
&& firstSwapExchange
|
||||
&& poolExchangesList.some((poolExchange) => poolExchange === firstSwapExchange)
|
||||
) {
|
||||
options?.logger?.(`Swap is through pool [via ${firstSwapExchange}] (detected by "exchanges" field)`);
|
||||
isThroughPoolOptimal = true;
|
||||
} else {
|
||||
if (swapInfo.isThroughPoolOptimal) options?.logger?.('Swap is through pool (detected by "isThroughPoolOptimal" field)');
|
||||
isThroughPoolOptimal = swapInfo.isThroughPoolOptimal;
|
||||
}
|
||||
|
||||
if (isThroughPoolOptimal) {
|
||||
options?.logger?.('Swap through pool');
|
||||
let factoryAddress: string | undefined;
|
||||
if (factories && firstSwapExchange) {
|
||||
factoryAddress = factories?.[firstSwapExchange];
|
||||
if (factoryAddress) options?.logger?.(`Factory address is ${factoryAddress}. Exchange is ${firstSwapExchange}`);
|
||||
}
|
||||
|
||||
const pathAddresses = swapInfo.path.map((name) => {
|
||||
const assetAddress = assetToAddress?.[name];
|
||||
if (!assetAddress) throw new Error(`No asset address for ${name}`);
|
||||
@@ -189,7 +230,7 @@ export default async function swapMarket({
|
||||
const unsignedSwapThroughOrionPoolTx = await exchangeContract.populateTransaction.swapThroughOrionPool(
|
||||
amountSpendBlockchainParam,
|
||||
amountReceiveBlockchainParam,
|
||||
pathAddresses,
|
||||
factoryAddress ? [factoryAddress, ...pathAddresses] : pathAddresses,
|
||||
type === 'exactSpend',
|
||||
);
|
||||
|
||||
@@ -244,6 +285,7 @@ export default async function swapMarket({
|
||||
|
||||
options?.logger?.('Signing transaction...');
|
||||
const swapThroughOrionPoolTxResponse = await signer.sendTransaction(unsignedSwapThroughOrionPoolTx);
|
||||
options?.logger?.(`Transaction sent. Tx hash: ${swapThroughOrionPoolTxResponse.hash}`);
|
||||
return {
|
||||
through: 'orion_pool',
|
||||
txHash: swapThroughOrionPoolTxResponse.hash,
|
||||
@@ -263,10 +305,6 @@ export default async function swapMarket({
|
||||
.multipliedBy(slippageMultiplier)
|
||||
.toString();
|
||||
|
||||
const [baseAssetName, quoteAssetName] = swapInfo.orderInfo.assetPair.split('-');
|
||||
const pairConfig = await simpleFetch(orionAggregator.getPairConfig)(`${baseAssetName}-${quoteAssetName}`);
|
||||
if (!pairConfig) throw new Error(`Pair config ${baseAssetName}-${quoteAssetName} not found`);
|
||||
|
||||
const baseAssetAddress = assetToAddress[baseAssetName];
|
||||
if (!baseAssetAddress) throw new Error(`No asset address for ${baseAssetName}`);
|
||||
const quoteAssetAddress = assetToAddress[quoteAssetName];
|
||||
@@ -361,6 +399,8 @@ export default async function swapMarket({
|
||||
if (!orderIsOk) throw new Error('Order is not valid');
|
||||
|
||||
const { orderId } = await simpleFetch(orionAggregator.placeOrder)(signedOrder, false);
|
||||
options?.logger?.(`Order placed. Order id: ${orderId}`);
|
||||
|
||||
return {
|
||||
through: 'aggregator',
|
||||
id: orderId,
|
||||
|
||||
@@ -41,6 +41,8 @@ export default class FarmingManager {
|
||||
if (amountBN.lte(0)) throw new Error('Amount must be greater than 0');
|
||||
if (!poolName.includes('-')) throw new Error('Pool name must be in the format of "assetA-AssetB"');
|
||||
const [assetA, assetB] = poolName.split('-');
|
||||
if (assetA === undefined) throw new Error('Asset A undefined');
|
||||
if (assetB === undefined) throw new Error('Asset B undefined');
|
||||
if (amountAsset !== assetA && amountAsset !== assetB) throw new Error('Amount asset must be either assetA or assetB');
|
||||
|
||||
const {
|
||||
@@ -219,6 +221,8 @@ export default class FarmingManager {
|
||||
}: RemoveAllLiquidityParams) {
|
||||
if (!poolName.includes('-')) throw new Error('Pool name must be in the format of "assetA-AssetB"');
|
||||
const [assetA, assetB] = poolName.split('-');
|
||||
if (assetA === undefined) throw new Error('Asset A is not defined');
|
||||
if (assetB === undefined) throw new Error('Asset B is not defined');
|
||||
|
||||
const {
|
||||
assetToAddress,
|
||||
|
||||
@@ -74,6 +74,7 @@ export default class OrionUnit {
|
||||
} else {
|
||||
const envInfo = envs[env];
|
||||
const envNetworks = envInfo?.networks;
|
||||
if (envNetworks === undefined) throw new Error('Env networks is undefined (constructor)');
|
||||
|
||||
if (isValidChainId(chain)) chainId = chain;
|
||||
else {
|
||||
@@ -94,7 +95,9 @@ export default class OrionUnit {
|
||||
: `Chains not found for chain name '${chain}' in env '${env}'.`,
|
||||
);
|
||||
}
|
||||
[chainId] = targetChains;
|
||||
const firstTargetChain = targetChains[0];
|
||||
if (firstTargetChain === undefined) throw new Error('First target chain is undefined');
|
||||
chainId = firstTargetChain;
|
||||
}
|
||||
|
||||
if (!(chainId in envNetworks)) {
|
||||
@@ -145,6 +148,8 @@ export default class OrionUnit {
|
||||
const envInfo = envs[this.env];
|
||||
const envNetworks = envInfo?.networks;
|
||||
|
||||
if (envNetworks === undefined) throw new Error('Env networks is undefined (siblings)');
|
||||
|
||||
const siblingsNetworks = Object
|
||||
.keys(envNetworks)
|
||||
.filter(isValidChainId)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
BigNumber.config({ EXPONENTIAL_AT: 1e9 });
|
||||
BigNumber.config({ EXPONENTIAL_AT: 1e+9 });
|
||||
|
||||
export * as config from './config';
|
||||
export { default as OrionUnit } from './OrionUnit';
|
||||
|
||||
@@ -15,6 +15,7 @@ const swapInfoBase = z.object({
|
||||
amount: z.number(),
|
||||
safePrice: z.number(),
|
||||
}).nullable(),
|
||||
exchanges: z.array(z.string()).optional(),
|
||||
price: z.number().nullable(), // spending asset price
|
||||
minAmountOut: z.number(),
|
||||
minAmountIn: z.number(),
|
||||
|
||||
@@ -329,6 +329,7 @@ class OrionAggregatorWS {
|
||||
minAmounOut: json.mao,
|
||||
minAmounIn: json.ma,
|
||||
path: json.ps,
|
||||
exchanges: json.e,
|
||||
poolOptimal: json.po,
|
||||
...json.oi && {
|
||||
orderInfo: {
|
||||
@@ -399,13 +400,13 @@ class OrionAggregatorWS {
|
||||
break;
|
||||
case MessageType.ASSET_PAIRS_CONFIG_UPDATE: {
|
||||
const pairs = json;
|
||||
let priceUpdates: Partial<Record<string, AssetPairUpdate>> = {};
|
||||
const priceUpdates: Partial<Record<string, AssetPairUpdate>> = {};
|
||||
|
||||
pairs.u.forEach(([pairName, minQty, pricePrecision]) => {
|
||||
priceUpdates[pairName] = {
|
||||
minQty,
|
||||
pricePrecision,
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
this.subscriptions[
|
||||
@@ -425,7 +426,7 @@ class OrionAggregatorWS {
|
||||
|
||||
prev[asset] = {
|
||||
tradable, reserved, contract, wallet, allowance,
|
||||
}
|
||||
};
|
||||
|
||||
return prev;
|
||||
}, {})
|
||||
@@ -437,7 +438,7 @@ class OrionAggregatorWS {
|
||||
const fullOrder = mapFullOrder(o);
|
||||
|
||||
prev.push(fullOrder);
|
||||
|
||||
|
||||
return prev;
|
||||
}, [])
|
||||
: undefined;
|
||||
@@ -475,10 +476,10 @@ class OrionAggregatorWS {
|
||||
}
|
||||
break;
|
||||
case MessageType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATE: {
|
||||
let brokerBalances: Partial<Record<string, number>> = {};
|
||||
const brokerBalances: Partial<Record<string, number>> = {};
|
||||
|
||||
json.bb.forEach(([asset, balance]) => {
|
||||
brokerBalances[asset] = balance
|
||||
brokerBalances[asset] = balance;
|
||||
});
|
||||
|
||||
this.subscriptions[
|
||||
|
||||
@@ -13,7 +13,7 @@ const swapInfoSchemaBase = baseMessageSchema.extend({
|
||||
mao: z.number(), // min amount out
|
||||
ps: z.string().array(), // path
|
||||
po: z.boolean(), // is swap through pool optimal
|
||||
|
||||
e: z.string().array().optional(), // Exchanges
|
||||
p: z.number().optional(), // price
|
||||
mp: z.number().optional(), // market price
|
||||
oi: z.object({ // info about order equivalent to this swap
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ethers } from 'ethers';
|
||||
import { z } from 'zod';
|
||||
import { makePartial } from '../../../utils';
|
||||
|
||||
@@ -7,6 +8,12 @@ const poolsConfigSchema = z.object({
|
||||
governanceAddress: z.string(),
|
||||
routerAddress: z.string(),
|
||||
votingAddress: z.string(),
|
||||
factories: z.record(
|
||||
z.string(),
|
||||
z.string().refine(ethers.utils.isAddress, 'Factory should be an address'),
|
||||
)
|
||||
.transform(makePartial)
|
||||
.optional(),
|
||||
pools: z.record(
|
||||
z.string(),
|
||||
z.object({
|
||||
|
||||
@@ -112,6 +112,7 @@ export type SwapInfoBase = {
|
||||
minAmounOut: number,
|
||||
|
||||
path: string[],
|
||||
exchanges?: string[],
|
||||
poolOptimal: boolean,
|
||||
|
||||
price?: number,
|
||||
|
||||
@@ -6,6 +6,8 @@ export default function isNetworkCodeInEnvironment(networkCode: string, env: str
|
||||
}
|
||||
const envInfo = envs[env];
|
||||
const envNetworks = envInfo?.networks;
|
||||
if (envNetworks === undefined) throw new Error('Env networks is undefined (isNetworkCodeInEnvironment)');
|
||||
|
||||
return Object.values(chains)
|
||||
.some((chain) => chain.code.toLowerCase() === networkCode.toLowerCase()
|
||||
&& chain.chainId in envNetworks);
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user