mirror of
https://github.com/orionprotocol/sdk.git
synced 2026-04-16 08:00:10 +03:00
New fetchWithValidation / introducing simpleFetch
This commit is contained in:
@@ -15,11 +15,11 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
parser: '@typescript-eslint/parser',
|
parser: '@typescript-eslint/parser',
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
tsconfigRootDir: "./",
|
tsconfigRootDir: __dirname,
|
||||||
project: [
|
project: [
|
||||||
"./tsconfig.json"
|
"./tsconfig.json"
|
||||||
],
|
],
|
||||||
ecmaVersion: 12,
|
ecmaVersion: 2021,
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|||||||
49
README.md
49
README.md
@@ -46,7 +46,7 @@ const chain = "0x61"; // bsc-testnet
|
|||||||
const env = "testing";
|
const env = "testing";
|
||||||
|
|
||||||
const startApp = async (provider: BaseProvider) => {
|
const startApp = async (provider: BaseProvider) => {
|
||||||
const web3provider = new providers.Web3Provider(provider);
|
const web3Provider = new providers.Web3Provider(provider);
|
||||||
await web3Provider.ready;
|
await web3Provider.ready;
|
||||||
const signer = web3Provider.getSigner(); // ready to go
|
const signer = web3Provider.getSigner(); // ready to go
|
||||||
const orionUnit = initOrionUnit(chain, env); // ready to go
|
const orionUnit = initOrionUnit(chain, env); // ready to go
|
||||||
@@ -128,7 +128,9 @@ orionUnit.farmingManager.removeAllLiquidity({
|
|||||||
### Get historical price
|
### Get historical price
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const candles = await orionUnit.priceFeed.getCandles(
|
import { simpleFetch } from "@orionprotocol/sdk";
|
||||||
|
|
||||||
|
const candles = await simpleFetch(orionUnit.priceFeed.getCandles)(
|
||||||
"ORN-USDT",
|
"ORN-USDT",
|
||||||
1650287678, // interval start
|
1650287678, // interval start
|
||||||
1650374078, // interval end
|
1650374078, // interval end
|
||||||
@@ -163,13 +165,16 @@ const orionVoting = contracts.OrionVoting__factory.connect(
|
|||||||
### Get tradable pairs
|
### Get tradable pairs
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const pairsList = await orionUnit.orionAggregator.getPairsList();
|
import { simpleFetch } from "@orionprotocol/sdk";
|
||||||
|
const pairsList = await simpleFetch(orionUnit.orionAggregator.getPairsList)();
|
||||||
```
|
```
|
||||||
|
|
||||||
### Get swap info
|
### Get swap info
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const swapInfo = await orionUnit.orionAggregator.getSwapInfo(
|
import { simpleFetch } from '@orionprotocol/sdk';
|
||||||
|
|
||||||
|
const swapInfo = await simpleFetch(orionUnit.orionAggregator.getSwapInfo)(
|
||||||
// Use 'exactSpend' when 'amount' is how much you want spend. Use 'exactReceive' otherwise
|
// Use 'exactSpend' when 'amount' is how much you want spend. Use 'exactReceive' otherwise
|
||||||
type: 'exactSpend',
|
type: 'exactSpend',
|
||||||
assetIn: 'ORN',
|
assetIn: 'ORN',
|
||||||
@@ -181,7 +186,12 @@ const swapInfo = await orionUnit.orionAggregator.getSwapInfo(
|
|||||||
### Place order in Orion Aggregator
|
### Place order in Orion Aggregator
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const { orderId } = await orionUnit.orionAggregator.placeOrder(
|
import { simpleFetch } from "@orionprotocol/sdk";
|
||||||
|
|
||||||
|
// You can yse simpleFetch or "default" (vebose) fetch
|
||||||
|
// Simple fetch
|
||||||
|
|
||||||
|
const { orderId } = await simpleFetch(orionUnit.orionAggregator.placeOrder)(
|
||||||
{
|
{
|
||||||
senderAddress: "0x61eed69c0d112c690fd6f44bb621357b89fbe67f",
|
senderAddress: "0x61eed69c0d112c690fd6f44bb621357b89fbe67f",
|
||||||
matcherAddress: "0xfbcad2c3a90fbd94c335fbdf8e22573456da7f68",
|
matcherAddress: "0xfbcad2c3a90fbd94c335fbdf8e22573456da7f68",
|
||||||
@@ -198,6 +208,35 @@ const { orderId } = await orionUnit.orionAggregator.placeOrder(
|
|||||||
},
|
},
|
||||||
false // Place in internal orderbook
|
false // Place in internal orderbook
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Default ("verbose") fetch
|
||||||
|
|
||||||
|
const placeOrderFetchResult = await simpleFetch(
|
||||||
|
orionUnit.orionAggregator.placeOrder
|
||||||
|
)();
|
||||||
|
// Same params as above
|
||||||
|
|
||||||
|
if (placeOrderFetchResult.isErr()) {
|
||||||
|
// You can handle fetching errors here
|
||||||
|
// You can access error text, statuses
|
||||||
|
const { error } = placeOrderFetchResult;
|
||||||
|
switch (error.type) {
|
||||||
|
case "fetchError": // (no network, connection refused, connection break)
|
||||||
|
console.error(error.message);
|
||||||
|
break;
|
||||||
|
case "unknownFetchError": // Instance of Error
|
||||||
|
console.error(`URL: ${error.url}, Error: ${error.message}`);
|
||||||
|
break;
|
||||||
|
case "unknownFetchThrow":
|
||||||
|
console.error("Something wrong happened furing fetching", error.error);
|
||||||
|
break;
|
||||||
|
// ... and 8 errors types more
|
||||||
|
// see src/fetchWithValidation.ts for details
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Succes result
|
||||||
|
const { orderId } = placeOrderFetchResult.value;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Orion Aggregator WebSocket
|
### Orion Aggregator WebSocket
|
||||||
|
|||||||
11
package-lock.json
generated
11
package-lock.json
generated
@@ -18,6 +18,7 @@
|
|||||||
"ethers": "^5.6.2",
|
"ethers": "^5.6.2",
|
||||||
"isomorphic-ws": "^4.0.1",
|
"isomorphic-ws": "^4.0.1",
|
||||||
"just-clone": "^5.0.1",
|
"just-clone": "^5.0.1",
|
||||||
|
"neverthrow": "^4.3.1",
|
||||||
"node-fetch": "^2.6.7",
|
"node-fetch": "^2.6.7",
|
||||||
"socket.io-client": "2.4.0",
|
"socket.io-client": "2.4.0",
|
||||||
"stream-browserify": "^3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
@@ -9135,6 +9136,11 @@
|
|||||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/neverthrow": {
|
||||||
|
"version": "4.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/neverthrow/-/neverthrow-4.3.1.tgz",
|
||||||
|
"integrity": "sha512-+vxjSaiDWjAj6kR6KKW0YDuV6O4UCNWGAO8m8ITjFKPWcTmU1GVnL+J5TAUTKpPnUAHCKDxXpOHVaERid223Ww=="
|
||||||
|
},
|
||||||
"node_modules/node-fetch": {
|
"node_modules/node-fetch": {
|
||||||
"version": "2.6.7",
|
"version": "2.6.7",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||||
@@ -17497,6 +17503,11 @@
|
|||||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"neverthrow": {
|
||||||
|
"version": "4.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/neverthrow/-/neverthrow-4.3.1.tgz",
|
||||||
|
"integrity": "sha512-+vxjSaiDWjAj6kR6KKW0YDuV6O4UCNWGAO8m8ITjFKPWcTmU1GVnL+J5TAUTKpPnUAHCKDxXpOHVaERid223Ww=="
|
||||||
|
},
|
||||||
"node-fetch": {
|
"node-fetch": {
|
||||||
"version": "2.6.7",
|
"version": "2.6.7",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@orionprotocol/sdk",
|
"name": "@orionprotocol/sdk",
|
||||||
"version": "0.3.4",
|
"version": "0.4.0",
|
||||||
"description": "Orion Protocol SDK",
|
"description": "Orion Protocol SDK",
|
||||||
"main": "./lib/esm/index.js",
|
"main": "./lib/esm/index.js",
|
||||||
"module": "./lib/esm/index.js",
|
"module": "./lib/esm/index.js",
|
||||||
@@ -70,6 +70,7 @@
|
|||||||
"ethers": "^5.6.2",
|
"ethers": "^5.6.2",
|
||||||
"isomorphic-ws": "^4.0.1",
|
"isomorphic-ws": "^4.0.1",
|
||||||
"just-clone": "^5.0.1",
|
"just-clone": "^5.0.1",
|
||||||
|
"neverthrow": "^4.3.1",
|
||||||
"node-fetch": "^2.6.7",
|
"node-fetch": "^2.6.7",
|
||||||
"socket.io-client": "2.4.0",
|
"socket.io-client": "2.4.0",
|
||||||
"stream-browserify": "^3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
} from '../../constants';
|
} from '../../constants';
|
||||||
import { normalizeNumber } from '../../utils';
|
import { normalizeNumber } from '../../utils';
|
||||||
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
|
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
|
||||||
|
import simpleFetch from '../../simpleFetch';
|
||||||
|
|
||||||
export type DepositParams = {
|
export type DepositParams = {
|
||||||
asset: string,
|
asset: string,
|
||||||
@@ -38,12 +39,12 @@ export default async function deposit({
|
|||||||
const {
|
const {
|
||||||
exchangeContractAddress,
|
exchangeContractAddress,
|
||||||
assetToAddress,
|
assetToAddress,
|
||||||
} = await orionBlockchain.getInfo();
|
} = await simpleFetch(orionBlockchain.getInfo)();
|
||||||
|
|
||||||
const nativeCryptocurrency = getNativeCryptocurrency(assetToAddress);
|
const nativeCryptocurrency = getNativeCryptocurrency(assetToAddress);
|
||||||
|
|
||||||
const exchangeContract = contracts.Exchange__factory.connect(exchangeContractAddress, provider);
|
const exchangeContract = contracts.Exchange__factory.connect(exchangeContractAddress, provider);
|
||||||
const gasPriceWei = await orionBlockchain.getGasPriceWei();
|
const gasPriceWei = await simpleFetch(orionBlockchain.getGasPriceWei)();
|
||||||
|
|
||||||
const assetAddress = assetToAddress[asset];
|
const assetAddress = assetToAddress[asset];
|
||||||
if (!assetAddress) throw new Error(`Asset '${asset}' not found`);
|
if (!assetAddress) throw new Error(`Asset '${asset}' not found`);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable max-len */
|
/* eslint-disable max-len */
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import { ethers } from 'ethers';
|
import { ethers } from 'ethers';
|
||||||
@@ -8,6 +9,7 @@ import OrionUnit from '..';
|
|||||||
import { contracts, crypt, utils } from '../..';
|
import { contracts, crypt, utils } from '../..';
|
||||||
import { INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION, SWAP_THROUGH_ORION_POOL_GAS_LIMIT } from '../../constants';
|
import { INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION, SWAP_THROUGH_ORION_POOL_GAS_LIMIT } from '../../constants';
|
||||||
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
|
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
|
||||||
|
import simpleFetch from '../../simpleFetch';
|
||||||
|
|
||||||
export type SwapMarketParams = {
|
export type SwapMarketParams = {
|
||||||
type: 'exactSpend' | 'exactReceive',
|
type: 'exactSpend' | 'exactReceive',
|
||||||
@@ -74,13 +76,13 @@ export default async function swapMarket({
|
|||||||
exchangeContractAddress,
|
exchangeContractAddress,
|
||||||
matcherAddress,
|
matcherAddress,
|
||||||
assetToAddress,
|
assetToAddress,
|
||||||
} = await orionBlockchain.getInfo();
|
} = await simpleFetch(orionBlockchain.getInfo)();
|
||||||
const nativeCryptocurrency = getNativeCryptocurrency(assetToAddress);
|
const nativeCryptocurrency = getNativeCryptocurrency(assetToAddress);
|
||||||
|
|
||||||
const exchangeContract = contracts.Exchange__factory.connect(exchangeContractAddress, provider);
|
const exchangeContract = contracts.Exchange__factory.connect(exchangeContractAddress, provider);
|
||||||
const feeAssets = await orionBlockchain.getTokensFee();
|
const feeAssets = await simpleFetch(orionBlockchain.getTokensFee)();
|
||||||
const pricesInOrn = await orionBlockchain.getPrices();
|
const pricesInOrn = await simpleFetch(orionBlockchain.getPrices)();
|
||||||
const gasPriceWei = await orionBlockchain.getGasPriceWei();
|
const gasPriceWei = await simpleFetch(orionBlockchain.getGasPriceWei)();
|
||||||
|
|
||||||
const gasPriceGwei = ethers.utils.formatUnits(gasPriceWei, 'gwei').toString();
|
const gasPriceGwei = ethers.utils.formatUnits(gasPriceWei, 'gwei').toString();
|
||||||
|
|
||||||
@@ -111,7 +113,7 @@ export default async function swapMarket({
|
|||||||
signer,
|
signer,
|
||||||
);
|
);
|
||||||
|
|
||||||
const swapInfo = await orionAggregator.getSwapInfo(type, assetIn, assetOut, amount.toString());
|
const swapInfo = await simpleFetch(orionAggregator.getSwapInfo)(type, assetIn, assetOut, amount.toString());
|
||||||
|
|
||||||
if (swapInfo.type === 'exactReceive' && amountBN.lt(swapInfo.minAmountOut)) {
|
if (swapInfo.type === 'exactReceive' && amountBN.lt(swapInfo.minAmountOut)) {
|
||||||
throw new Error(`Amount is too low. Min amountOut is ${swapInfo.minAmountOut} ${assetOut}`);
|
throw new Error(`Amount is too low. Min amountOut is ${swapInfo.minAmountOut} ${assetOut}`);
|
||||||
@@ -240,7 +242,7 @@ export default async function swapMarket({
|
|||||||
.toString();
|
.toString();
|
||||||
|
|
||||||
const [baseAssetName, quoteAssetName] = swapInfo.orderInfo.assetPair.split('-');
|
const [baseAssetName, quoteAssetName] = swapInfo.orderInfo.assetPair.split('-');
|
||||||
const pairConfig = await orionAggregator.getPairConfig(`${baseAssetName}-${quoteAssetName}`);
|
const pairConfig = await simpleFetch(orionAggregator.getPairConfig)(`${baseAssetName}-${quoteAssetName}`);
|
||||||
if (!pairConfig) throw new Error(`Pair config ${baseAssetName}-${quoteAssetName} not found`);
|
if (!pairConfig) throw new Error(`Pair config ${baseAssetName}-${quoteAssetName} not found`);
|
||||||
|
|
||||||
const baseAssetAddress = assetToAddress[baseAssetName];
|
const baseAssetAddress = assetToAddress[baseAssetName];
|
||||||
@@ -336,7 +338,7 @@ export default async function swapMarket({
|
|||||||
const orderIsOk = await exchangeContract.validateOrder(signedOrder);
|
const orderIsOk = await exchangeContract.validateOrder(signedOrder);
|
||||||
if (!orderIsOk) throw new Error('Order is not valid');
|
if (!orderIsOk) throw new Error('Order is not valid');
|
||||||
|
|
||||||
const { orderId } = await orionAggregator.placeOrder(signedOrder, false);
|
const { orderId } = await simpleFetch(orionAggregator.placeOrder)(signedOrder, false);
|
||||||
return {
|
return {
|
||||||
through: 'aggregator',
|
through: 'aggregator',
|
||||||
id: orderId,
|
id: orderId,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
} from '../../constants';
|
} from '../../constants';
|
||||||
import { normalizeNumber } from '../../utils';
|
import { normalizeNumber } from '../../utils';
|
||||||
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
|
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
|
||||||
|
import simpleFetch from '../../simpleFetch';
|
||||||
|
|
||||||
export type WithdrawParams = {
|
export type WithdrawParams = {
|
||||||
asset: string,
|
asset: string,
|
||||||
@@ -38,11 +39,11 @@ export default async function withdraw({
|
|||||||
const {
|
const {
|
||||||
exchangeContractAddress,
|
exchangeContractAddress,
|
||||||
assetToAddress,
|
assetToAddress,
|
||||||
} = await orionBlockchain.getInfo();
|
} = await simpleFetch(orionBlockchain.getInfo)();
|
||||||
|
|
||||||
const nativeCryptocurrency = getNativeCryptocurrency(assetToAddress);
|
const nativeCryptocurrency = getNativeCryptocurrency(assetToAddress);
|
||||||
const exchangeContract = contracts.Exchange__factory.connect(exchangeContractAddress, provider);
|
const exchangeContract = contracts.Exchange__factory.connect(exchangeContractAddress, provider);
|
||||||
const gasPriceWei = await orionBlockchain.getGasPriceWei();
|
const gasPriceWei = await simpleFetch(orionBlockchain.getGasPriceWei)();
|
||||||
|
|
||||||
const assetAddress = assetToAddress[asset];
|
const assetAddress = assetToAddress[asset];
|
||||||
if (!assetAddress) throw new Error(`Asset '${asset}' not found`);
|
if (!assetAddress) throw new Error(`Asset '${asset}' not found`);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import OrionUnit from '..';
|
|||||||
import { contracts } from '../..';
|
import { contracts } from '../..';
|
||||||
import BalanceGuard from '../../BalanceGuard';
|
import BalanceGuard from '../../BalanceGuard';
|
||||||
import { ADD_LIQUIDITY_GAS_LIMIT, INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION } from '../../constants';
|
import { ADD_LIQUIDITY_GAS_LIMIT, INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION } from '../../constants';
|
||||||
|
import simpleFetch from '../../simpleFetch';
|
||||||
import { denormalizeNumber, normalizeNumber } from '../../utils';
|
import { denormalizeNumber, normalizeNumber } from '../../utils';
|
||||||
import getBalances from '../../utils/getBalances';
|
import getBalances from '../../utils/getBalances';
|
||||||
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
|
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
|
||||||
@@ -46,7 +47,7 @@ export default class FarmingManager {
|
|||||||
exchangeContractAddress,
|
exchangeContractAddress,
|
||||||
assetToAddress,
|
assetToAddress,
|
||||||
assetToDecimals,
|
assetToDecimals,
|
||||||
} = await this.orionUnit.orionBlockchain.getInfo();
|
} = await simpleFetch(this.orionUnit.orionBlockchain.getInfo)();
|
||||||
|
|
||||||
const walletAddress = await signer.getAddress();
|
const walletAddress = await signer.getAddress();
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ export default class FarmingManager {
|
|||||||
signer,
|
signer,
|
||||||
);
|
);
|
||||||
|
|
||||||
const poolsConfig = await this.orionUnit.orionBlockchain.getPoolsConfig();
|
const poolsConfig = await simpleFetch(this.orionUnit.orionBlockchain.getPoolsConfig)();
|
||||||
const pool = poolsConfig.pools[poolName];
|
const pool = poolsConfig.pools[poolName];
|
||||||
if (!pool) throw new Error(`Pool ${poolName} not found`);
|
if (!pool) throw new Error(`Pool ${poolName} not found`);
|
||||||
|
|
||||||
@@ -223,7 +224,7 @@ export default class FarmingManager {
|
|||||||
assetToAddress,
|
assetToAddress,
|
||||||
assetToDecimals,
|
assetToDecimals,
|
||||||
exchangeContractAddress,
|
exchangeContractAddress,
|
||||||
} = await this.orionUnit.orionBlockchain.getInfo();
|
} = await simpleFetch(this.orionUnit.orionBlockchain.getInfo)();
|
||||||
|
|
||||||
const assetAAddress = assetToAddress[assetA];
|
const assetAAddress = assetToAddress[assetA];
|
||||||
if (!assetAAddress) throw new Error(`Asset '${assetA}' not found`);
|
if (!assetAAddress) throw new Error(`Asset '${assetA}' not found`);
|
||||||
@@ -235,7 +236,7 @@ export default class FarmingManager {
|
|||||||
const assetBDecimals = assetToDecimals[assetB];
|
const assetBDecimals = assetToDecimals[assetB];
|
||||||
if (!assetBDecimals) throw new Error(`Decimals for asset '${assetB}' not found`);
|
if (!assetBDecimals) throw new Error(`Decimals for asset '${assetB}' not found`);
|
||||||
|
|
||||||
const poolsConfig = await this.orionUnit.orionBlockchain.getPoolsConfig();
|
const poolsConfig = await simpleFetch(this.orionUnit.orionBlockchain.getPoolsConfig)();
|
||||||
const pool = poolsConfig.pools[poolName];
|
const pool = poolsConfig.pools[poolName];
|
||||||
if (!pool) throw new Error(`Pool ${poolName} not found`);
|
if (!pool) throw new Error(`Pool ${poolName} not found`);
|
||||||
|
|
||||||
|
|||||||
@@ -1,55 +1,155 @@
|
|||||||
import { Schema, z } from 'zod';
|
import { Schema, z } from 'zod';
|
||||||
import fetch, { RequestInit } from 'node-fetch';
|
import fetch, { FetchError, RequestInit } from 'node-fetch';
|
||||||
import { isWithError, isWithReason, HttpError } from './utils';
|
import {
|
||||||
|
err, fromPromise, fromThrowable, ok,
|
||||||
|
} from 'neverthrow';
|
||||||
|
|
||||||
export class ExtendedError extends Error {
|
export default async function fetchWithValidation<DataOut, DataIn, ErrorOut, ErrorIn>(
|
||||||
public url: string;
|
|
||||||
|
|
||||||
public status: number | null;
|
|
||||||
|
|
||||||
constructor(url: string, status: number | null, message: string) {
|
|
||||||
super();
|
|
||||||
this.url = url;
|
|
||||||
this.status = status;
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const fetchJsonWithValidation = async <DataOut, DataIn, ErrorOut, ErrorIn>(
|
|
||||||
url: string,
|
url: string,
|
||||||
schema: Schema<DataOut, z.ZodTypeDef, DataIn>,
|
schema: Schema<DataOut, z.ZodTypeDef, DataIn>,
|
||||||
options?: RequestInit,
|
options?: RequestInit,
|
||||||
errorSchema?: Schema<ErrorOut, z.ZodTypeDef, ErrorIn>,
|
errorSchema?: Schema<ErrorOut, z.ZodTypeDef, ErrorIn>,
|
||||||
) => {
|
) {
|
||||||
const response = await fetch(url, {
|
// Cases:
|
||||||
|
// 1. fetchError (no network, connection refused, connection break)
|
||||||
|
// 2. unknownFetchError
|
||||||
|
// 3. unknownFetchThrow
|
||||||
|
// 4. unknownGetTextError
|
||||||
|
// 5. unknownGetTextUnknownError
|
||||||
|
// 6. serverError
|
||||||
|
// 7. jsonParseError
|
||||||
|
// 8. jsonParseUnknownError
|
||||||
|
// 9. clientErrorWithResponsePayload
|
||||||
|
// 10. clientErrorPayloadParseError
|
||||||
|
// 11. clientError
|
||||||
|
// 12. payloadParseError
|
||||||
|
// 13. payload
|
||||||
|
|
||||||
|
const fetchResult = await fromPromise(fetch(url, {
|
||||||
...options || {},
|
...options || {},
|
||||||
headers: {
|
headers: {
|
||||||
'Cache-Control': 'no-store, max-age=0',
|
'Cache-Control': 'no-store, max-age=0',
|
||||||
...(options ? options.headers : {}),
|
...(options ? options.headers : {}),
|
||||||
},
|
},
|
||||||
});
|
}), (e) => {
|
||||||
const text = await response.text();
|
if (e instanceof FetchError) {
|
||||||
|
return err({
|
||||||
// The ok read-only property of the Response interface contains a Boolean
|
type: 'fetchError' as const,
|
||||||
// stating whether the response was successful (status in the range 200 - 299) or not.
|
url,
|
||||||
|
message: `${e.message} (${e.type})`,
|
||||||
if (!response.ok) {
|
error: e,
|
||||||
throw new HttpError(response.status, text, 'HTTP', response.statusText);
|
});
|
||||||
}
|
} if (e instanceof Error) {
|
||||||
|
return err({
|
||||||
const payload: unknown = JSON.parse(text);
|
type: 'unknownFetchError' as const,
|
||||||
|
url,
|
||||||
try {
|
message: e.message,
|
||||||
const data = schema.parse(payload);
|
error: e,
|
||||||
return data;
|
});
|
||||||
} catch (e) {
|
|
||||||
if (errorSchema) {
|
|
||||||
const errorObj = errorSchema.parse(payload);
|
|
||||||
if (isWithError(errorObj) && isWithReason(errorObj.error)) {
|
|
||||||
throw new ExtendedError(url, response.status, errorObj.error.reason);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (e instanceof Error) throw new ExtendedError(url, response.status, e.message);
|
return err({
|
||||||
throw e;
|
type: 'unknownFetchThrow' as const,
|
||||||
|
url,
|
||||||
|
message: 'Unknown fetch error',
|
||||||
|
error: e,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (fetchResult.isErr()) return fetchResult.error;
|
||||||
|
|
||||||
|
const response = fetchResult.value;
|
||||||
|
|
||||||
|
const textResult = await fromPromise(response.text(), (e) => {
|
||||||
|
if (e instanceof Error) {
|
||||||
|
return err({
|
||||||
|
type: 'unknownGetTextError' as const,
|
||||||
|
url,
|
||||||
|
message: `Can't get response content: ${e.message}`,
|
||||||
|
error: e,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return err({
|
||||||
|
type: 'unknownGetTextUnknownError' as const,
|
||||||
|
url,
|
||||||
|
message: "Can't get response content: unknown error",
|
||||||
|
error: e,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (textResult.isErr()) return textResult.error;
|
||||||
|
|
||||||
|
const text = textResult.value;
|
||||||
|
|
||||||
|
if (response.status >= 500) { // Server error
|
||||||
|
return err({
|
||||||
|
type: 'serverError' as const,
|
||||||
|
url,
|
||||||
|
message: `Server error: ${response.status} ${response.statusText}`,
|
||||||
|
status: response.status,
|
||||||
|
text,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
const safeParseJson = fromThrowable(JSON.parse, (e) => {
|
||||||
|
if (e instanceof Error) {
|
||||||
|
return err({
|
||||||
|
type: 'jsonParseError' as const,
|
||||||
|
url,
|
||||||
|
message: e.message,
|
||||||
|
error: e,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return err({
|
||||||
|
type: 'jsonParseUnknownError' as const,
|
||||||
|
url,
|
||||||
|
message: 'Unknown JSON parse error',
|
||||||
|
error: e,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const jsonResult = safeParseJson(text);
|
||||||
|
|
||||||
|
if (jsonResult.isErr()) return jsonResult.error;
|
||||||
|
|
||||||
|
const json: unknown = jsonResult.value;
|
||||||
|
|
||||||
|
if (response.status >= 400) { // Client error
|
||||||
|
if (errorSchema) {
|
||||||
|
const serverError = errorSchema.safeParse(json);
|
||||||
|
if (serverError.success) {
|
||||||
|
return err({
|
||||||
|
type: 'clientErrorWithResponsePayload' as const,
|
||||||
|
url,
|
||||||
|
message: `Client error: ${response.status} ${response.statusText}`,
|
||||||
|
status: response.status,
|
||||||
|
payload: serverError.data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return err({
|
||||||
|
type: 'clientErrorPayloadParseError' as const,
|
||||||
|
message: 'Can\'t recognize error message',
|
||||||
|
status: response.status,
|
||||||
|
text,
|
||||||
|
error: serverError.error,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return err({
|
||||||
|
type: 'clientError' as const,
|
||||||
|
url,
|
||||||
|
message: `Error: ${response.status} ${response.statusText}`,
|
||||||
|
status: response.status,
|
||||||
|
text,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = schema.safeParse(json);
|
||||||
|
if (!payload.success) {
|
||||||
|
return err({
|
||||||
|
type: 'payloadParseError' as const,
|
||||||
|
url,
|
||||||
|
message: 'Can\'t recognize response payload',
|
||||||
|
error: payload.error,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return ok(payload.data);
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ export * as config from './config';
|
|||||||
// export * from './entities';
|
// export * from './entities';
|
||||||
export { default as OrionUnit } from './OrionUnit';
|
export { default as OrionUnit } from './OrionUnit';
|
||||||
export { default as initOrionUnit } from './initOrionUnit';
|
export { default as initOrionUnit } from './initOrionUnit';
|
||||||
export * from './fetchWithValidation';
|
export { default as fetchWithValidation } from './fetchWithValidation';
|
||||||
|
export { default as simpleFetch } from './simpleFetch';
|
||||||
export * as utils from './utils';
|
export * as utils from './utils';
|
||||||
export * as services from './services';
|
export * as services from './services';
|
||||||
export * as contracts from './artifacts/contracts';
|
export * as contracts from './artifacts/contracts';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { fetchJsonWithValidation } from '../../fetchWithValidation';
|
import fetchWithValidation from '../../fetchWithValidation';
|
||||||
import swapInfoSchema from './schemas/swapInfoSchema';
|
import swapInfoSchema from './schemas/swapInfoSchema';
|
||||||
import exchangeInfoSchema from './schemas/exchangeInfoSchema';
|
import exchangeInfoSchema from './schemas/exchangeInfoSchema';
|
||||||
import cancelOrderSchema from './schemas/cancelOrderSchema';
|
import cancelOrderSchema from './schemas/cancelOrderSchema';
|
||||||
@@ -8,7 +8,7 @@ import orderBenefitsSchema from './schemas/orderBenefitsSchema';
|
|||||||
import errorSchema from './errorSchema';
|
import errorSchema from './errorSchema';
|
||||||
import placeAtomicSwapSchema from './schemas/placeAtomicSwapSchema';
|
import placeAtomicSwapSchema from './schemas/placeAtomicSwapSchema';
|
||||||
import { OrionAggregatorWS } from './ws';
|
import { OrionAggregatorWS } from './ws';
|
||||||
import atomicSwapHistorySchema from './schemas/atomicSwapHistorySchema';
|
import { atomicSwapHistorySchema } from './schemas/atomicSwapHistorySchema';
|
||||||
import { SignedCancelOrderRequest, SignedOrder, SupportedChainId } from '../../types';
|
import { SignedCancelOrderRequest, SignedOrder, SupportedChainId } from '../../types';
|
||||||
import { pairConfigSchema } from './schemas';
|
import { pairConfigSchema } from './schemas';
|
||||||
|
|
||||||
@@ -20,6 +20,18 @@ class OrionAggregator {
|
|||||||
constructor(apiUrl: string, chainId: SupportedChainId) {
|
constructor(apiUrl: string, chainId: SupportedChainId) {
|
||||||
this.apiUrl = apiUrl;
|
this.apiUrl = apiUrl;
|
||||||
this.ws = new OrionAggregatorWS(this.aggregatorWSUrl, chainId);
|
this.ws = new OrionAggregatorWS(this.aggregatorWSUrl, chainId);
|
||||||
|
|
||||||
|
this.getHistoryAtomicSwaps = this.getHistoryAtomicSwaps.bind(this);
|
||||||
|
this.getPairConfig = this.getPairConfig.bind(this);
|
||||||
|
this.getPairConfigs = this.getPairConfigs.bind(this);
|
||||||
|
this.getPairsList = this.getPairsList.bind(this);
|
||||||
|
this.getSwapInfo = this.getSwapInfo.bind(this);
|
||||||
|
this.getTradeProfits = this.getTradeProfits.bind(this);
|
||||||
|
this.placeAtomicSwap = this.placeAtomicSwap.bind(this);
|
||||||
|
this.placeOrder = this.placeOrder.bind(this);
|
||||||
|
this.cancelOrder = this.cancelOrder.bind(this);
|
||||||
|
this.checkWhitelisted = this.checkWhitelisted.bind(this);
|
||||||
|
this.getLockedBalance = this.getLockedBalance.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
get aggregatorWSUrl() { return `wss://${this.apiUrl}/v1`; }
|
get aggregatorWSUrl() { return `wss://${this.apiUrl}/v1`; }
|
||||||
@@ -29,14 +41,14 @@ class OrionAggregator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getPairsList() {
|
getPairsList() {
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`${this.aggregatorUrl}/api/v1/pairs/list`,
|
`${this.aggregatorUrl}/api/v1/pairs/list`,
|
||||||
z.array(z.string()),
|
z.array(z.string()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPairConfigs() {
|
getPairConfigs() {
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`${this.aggregatorUrl}/api/v1/pairs/exchangeInfo`,
|
`${this.aggregatorUrl}/api/v1/pairs/exchangeInfo`,
|
||||||
exchangeInfoSchema,
|
exchangeInfoSchema,
|
||||||
undefined,
|
undefined,
|
||||||
@@ -45,7 +57,7 @@ class OrionAggregator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getPairConfig(assetPair: string) {
|
getPairConfig(assetPair: string) {
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`${this.aggregatorUrl}/api/v1/pairs/exchangeInfo/${assetPair}`,
|
`${this.aggregatorUrl}/api/v1/pairs/exchangeInfo/${assetPair}`,
|
||||||
pairConfigSchema,
|
pairConfigSchema,
|
||||||
undefined,
|
undefined,
|
||||||
@@ -54,7 +66,7 @@ class OrionAggregator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkWhitelisted(address: string) {
|
checkWhitelisted(address: string) {
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`${this.aggregatorUrl}/api/v1/whitelist/check?address=${address}`,
|
`${this.aggregatorUrl}/api/v1/whitelist/check?address=${address}`,
|
||||||
z.boolean(),
|
z.boolean(),
|
||||||
undefined,
|
undefined,
|
||||||
@@ -73,7 +85,7 @@ class OrionAggregator {
|
|||||||
...partnerId && { 'X-Partner-Id': partnerId },
|
...partnerId && { 'X-Partner-Id': partnerId },
|
||||||
};
|
};
|
||||||
|
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`${this.aggregatorUrl}/api/v1/order/${isCreateInternalOrder ? 'internal' : ''}`,
|
`${this.aggregatorUrl}/api/v1/order/${isCreateInternalOrder ? 'internal' : ''}`,
|
||||||
z.object({
|
z.object({
|
||||||
orderId: z.string(),
|
orderId: z.string(),
|
||||||
@@ -95,7 +107,7 @@ class OrionAggregator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cancelOrder(signedCancelOrderRequest: SignedCancelOrderRequest) {
|
cancelOrder(signedCancelOrderRequest: SignedCancelOrderRequest) {
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`${this.aggregatorUrl}/api/v1/order`,
|
`${this.aggregatorUrl}/api/v1/order`,
|
||||||
cancelOrderSchema,
|
cancelOrderSchema,
|
||||||
{
|
{
|
||||||
@@ -128,7 +140,7 @@ class OrionAggregator {
|
|||||||
url.searchParams.append('amountOut', amount);
|
url.searchParams.append('amountOut', amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
url.toString(),
|
url.toString(),
|
||||||
swapInfoSchema,
|
swapInfoSchema,
|
||||||
undefined,
|
undefined,
|
||||||
@@ -139,7 +151,7 @@ class OrionAggregator {
|
|||||||
getLockedBalance(address: string, currency: string) {
|
getLockedBalance(address: string, currency: string) {
|
||||||
const url = new URL(`${this.aggregatorUrl}/api/v1/address/balance/reserved/${currency}`);
|
const url = new URL(`${this.aggregatorUrl}/api/v1/address/balance/reserved/${currency}`);
|
||||||
url.searchParams.append('address', address);
|
url.searchParams.append('address', address);
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
url.toString(),
|
url.toString(),
|
||||||
z.object({
|
z.object({
|
||||||
[currency]: z.number(),
|
[currency]: z.number(),
|
||||||
@@ -159,7 +171,7 @@ class OrionAggregator {
|
|||||||
url.searchParams.append('amount', amount.toString());
|
url.searchParams.append('amount', amount.toString());
|
||||||
url.searchParams.append('side', isBuy ? 'buy' : 'sell');
|
url.searchParams.append('side', isBuy ? 'buy' : 'sell');
|
||||||
|
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
url.toString(),
|
url.toString(),
|
||||||
orderBenefitsSchema,
|
orderBenefitsSchema,
|
||||||
undefined,
|
undefined,
|
||||||
@@ -177,7 +189,7 @@ class OrionAggregator {
|
|||||||
secretHash: string,
|
secretHash: string,
|
||||||
sourceNetworkCode: string,
|
sourceNetworkCode: string,
|
||||||
) {
|
) {
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`${this.aggregatorUrl}/api/v1/atomic-swap`,
|
`${this.aggregatorUrl}/api/v1/atomic-swap`,
|
||||||
placeAtomicSwapSchema,
|
placeAtomicSwapSchema,
|
||||||
{
|
{
|
||||||
@@ -204,7 +216,7 @@ class OrionAggregator {
|
|||||||
const url = new URL(`${this.aggregatorUrl}/api/v1/atomic-swap/history/all`);
|
const url = new URL(`${this.aggregatorUrl}/api/v1/atomic-swap/history/all`);
|
||||||
url.searchParams.append('sender', sender);
|
url.searchParams.append('sender', sender);
|
||||||
url.searchParams.append('limit', limit.toString());
|
url.searchParams.append('limit', limit.toString());
|
||||||
return fetchJsonWithValidation(url.toString(), atomicSwapHistorySchema);
|
return fetchWithValidation(url.toString(), atomicSwapHistorySchema);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export * as schemas from './schemas';
|
export * as schemas from './schemas';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { fetchJsonWithValidation } from '../../fetchWithValidation';
|
import fetchWithValidation from '../../fetchWithValidation';
|
||||||
import { PairStatusEnum, pairStatusSchema } from './schemas/adminPoolsListSchema';
|
import { PairStatusEnum, pairStatusSchema } from './schemas/adminPoolsListSchema';
|
||||||
import {
|
import {
|
||||||
IDOSchema, atomicHistorySchema,
|
IDOSchema, atomicHistorySchema,
|
||||||
@@ -56,6 +56,32 @@ class OrionBlockchain {
|
|||||||
constructor(apiUrl: string) {
|
constructor(apiUrl: string) {
|
||||||
this.apiUrl = apiUrl;
|
this.apiUrl = apiUrl;
|
||||||
this.ws = new OrionBlockchainSocketIO(`https://${apiUrl}/`);
|
this.ws = new OrionBlockchainSocketIO(`https://${apiUrl}/`);
|
||||||
|
|
||||||
|
this.getAtomicSwapAssets = this.getAtomicSwapAssets.bind(this);
|
||||||
|
this.getAtomicSwapHistory = this.getAtomicSwapHistory.bind(this);
|
||||||
|
this.getAuthToken = this.getAuthToken.bind(this);
|
||||||
|
this.getCirculatingSupply = this.getCirculatingSupply.bind(this);
|
||||||
|
this.getInfo = this.getInfo.bind(this);
|
||||||
|
this.getPoolsConfig = this.getPoolsConfig.bind(this);
|
||||||
|
this.getPoolsInfo = this.getPoolsInfo.bind(this);
|
||||||
|
this.getHistory = this.getHistory.bind(this);
|
||||||
|
this.getPrices = this.getPrices.bind(this);
|
||||||
|
this.getTokensFee = this.getTokensFee.bind(this);
|
||||||
|
this.getGasPriceWei = this.getGasPriceWei.bind(this);
|
||||||
|
this.checkFreeRedeemAvailable = this.checkFreeRedeemAvailable.bind(this);
|
||||||
|
this.redeemAtomicSwap = this.redeemAtomicSwap.bind(this);
|
||||||
|
this.redeem2AtomicSwaps = this.redeem2AtomicSwaps.bind(this);
|
||||||
|
this.checkRedeem = this.checkRedeem.bind(this);
|
||||||
|
this.checkRedeem2Atomics = this.checkRedeem2Atomics.bind(this);
|
||||||
|
this.getIDOInfo = this.getIDOInfo.bind(this);
|
||||||
|
this.checkAuth = this.checkAuth.bind(this);
|
||||||
|
this.addPool = this.addPool.bind(this);
|
||||||
|
this.editPool = this.editPool.bind(this);
|
||||||
|
this.getPoolsList = this.getPoolsList.bind(this);
|
||||||
|
this.getSourceAtomicSwapHistory = this.getSourceAtomicSwapHistory.bind(this);
|
||||||
|
this.getTargetAtomicSwapHistory = this.getTargetAtomicSwapHistory.bind(this);
|
||||||
|
this.checkPoolInformation = this.checkPoolInformation.bind(this);
|
||||||
|
this.checkIfHashUsed = this.checkIfHashUsed.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
get orionBlockchainWsUrl() {
|
get orionBlockchainWsUrl() {
|
||||||
@@ -63,43 +89,43 @@ class OrionBlockchain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getAuthToken() {
|
getAuthToken() {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/auth/token`, z.object({ token: z.string() }));
|
return fetchWithValidation(`https://${this.apiUrl}/api/auth/token`, z.object({ token: z.string() }));
|
||||||
}
|
}
|
||||||
|
|
||||||
getCirculatingSupply() {
|
getCirculatingSupply() {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/circulating-supply`, z.number());
|
return fetchWithValidation(`https://${this.apiUrl}/api/circulating-supply`, z.number());
|
||||||
}
|
}
|
||||||
|
|
||||||
getInfo() {
|
getInfo() {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/info`, infoSchema);
|
return fetchWithValidation(`https://${this.apiUrl}/api/info`, infoSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPoolsConfig() {
|
getPoolsConfig() {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/pools/config`, poolsConfigSchema);
|
return fetchWithValidation(`https://${this.apiUrl}/api/pools/config`, poolsConfigSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPoolsInfo() {
|
getPoolsInfo() {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/pools/info`, poolsInfoSchema);
|
return fetchWithValidation(`https://${this.apiUrl}/api/pools/info`, poolsInfoSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
getHistory(address: string) {
|
getHistory(address: string) {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/history/${address}`, historySchema);
|
return fetchWithValidation(`https://${this.apiUrl}/api/history/${address}`, historySchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPrices() {
|
getPrices() {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/prices`, z.record(z.string()).transform(utils.makePartial));
|
return fetchWithValidation(`https://${this.apiUrl}/api/prices`, z.record(z.string()).transform(utils.makePartial));
|
||||||
}
|
}
|
||||||
|
|
||||||
getTokensFee() {
|
getTokensFee() {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/tokensFee`, z.record(z.string()).transform(utils.makePartial));
|
return fetchWithValidation(`https://${this.apiUrl}/api/tokensFee`, z.record(z.string()).transform(utils.makePartial));
|
||||||
}
|
}
|
||||||
|
|
||||||
getGasPriceWei() {
|
getGasPriceWei() {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/gasPrice`, z.string());
|
return fetchWithValidation(`https://${this.apiUrl}/api/gasPrice`, z.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFreeRedeemAvailable(walletAddress: string) {
|
checkFreeRedeemAvailable(walletAddress: string) {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/atomic/has-free-redeem/${walletAddress}`, z.boolean());
|
return fetchWithValidation(`https://${this.apiUrl}/api/atomic/has-free-redeem/${walletAddress}`, z.boolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
redeemAtomicSwap(
|
redeemAtomicSwap(
|
||||||
@@ -107,7 +133,7 @@ class OrionBlockchain {
|
|||||||
secret: string,
|
secret: string,
|
||||||
sourceNetwork: string,
|
sourceNetwork: string,
|
||||||
) {
|
) {
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`https://${this.apiUrl}/api/atomic/matcher-redeem`,
|
`https://${this.apiUrl}/api/atomic/matcher-redeem`,
|
||||||
z.string(),
|
z.string(),
|
||||||
{
|
{
|
||||||
@@ -131,7 +157,7 @@ class OrionBlockchain {
|
|||||||
secret2: string,
|
secret2: string,
|
||||||
sourceNetwork: string,
|
sourceNetwork: string,
|
||||||
) {
|
) {
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`https://${this.apiUrl}/api/atomic/matcher-redeem2atomics`,
|
`https://${this.apiUrl}/api/atomic/matcher-redeem2atomics`,
|
||||||
z.string(),
|
z.string(),
|
||||||
{
|
{
|
||||||
@@ -151,31 +177,31 @@ class OrionBlockchain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkRedeem(secretHash: string) {
|
checkRedeem(secretHash: string) {
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`https://${this.apiUrl}/api/atomic/matcher-redeem/${secretHash}`,
|
`https://${this.apiUrl}/api/atomic/matcher-redeem/${secretHash}`,
|
||||||
z.enum(['OK', 'FAIL']).nullable(),
|
z.enum(['OK', 'FAIL']).nullable(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkRedeem2Atomics(firstSecretHash: string, secondSecretHash: string) {
|
checkRedeem2Atomics(firstSecretHash: string, secondSecretHash: string) {
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`https://${this.apiUrl}/api/atomic/matcher-redeem/${firstSecretHash}-${secondSecretHash}`,
|
`https://${this.apiUrl}/api/atomic/matcher-redeem/${firstSecretHash}-${secondSecretHash}`,
|
||||||
z.enum(['OK', 'FAIL']).nullable(),
|
z.enum(['OK', 'FAIL']).nullable(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getIDOInfo() {
|
getIDOInfo() {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/solarflare`, IDOSchema);
|
return fetchWithValidation(`https://${this.apiUrl}/api/solarflare`, IDOSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkAuth(headers: IAdminAuthHeaders) {
|
checkAuth(headers: IAdminAuthHeaders) {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/auth/check`, z.object({
|
return fetchWithValidation(`https://${this.apiUrl}/api/auth/check`, z.object({
|
||||||
auth: z.boolean(),
|
auth: z.boolean(),
|
||||||
}), { headers });
|
}), { headers });
|
||||||
}
|
}
|
||||||
|
|
||||||
getPoolsList(headers: IAdminAuthHeaders) {
|
getPoolsList(headers: IAdminAuthHeaders) {
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`https://${this.apiUrl}/api/pools/list`,
|
`https://${this.apiUrl}/api/pools/list`,
|
||||||
adminPoolsListSchema,
|
adminPoolsListSchema,
|
||||||
{ headers },
|
{ headers },
|
||||||
@@ -183,7 +209,7 @@ class OrionBlockchain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
editPool(address: string, data: IEditPool, headers: IAdminAuthHeaders) {
|
editPool(address: string, data: IEditPool, headers: IAdminAuthHeaders) {
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`https://${this.apiUrl}/api/pools/edit/${address}`,
|
`https://${this.apiUrl}/api/pools/edit/${address}`,
|
||||||
pairStatusSchema,
|
pairStatusSchema,
|
||||||
{
|
{
|
||||||
@@ -198,22 +224,27 @@ class OrionBlockchain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addPool(data: z.infer<typeof addPoolSchema>) {
|
addPool(data: z.infer<typeof addPoolSchema>) {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/pools/add`, z.number(), {
|
return fetchWithValidation(
|
||||||
method: 'POST',
|
`https://${this.apiUrl}/api/pools/add`,
|
||||||
body: JSON.stringify(data),
|
z.number(),
|
||||||
headers: {
|
{
|
||||||
'Content-Type': 'application/json',
|
method: 'POST',
|
||||||
Accept: 'application/json',
|
body: JSON.stringify(data),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
z.string(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkPoolInformation(poolAddress: string) {
|
checkPoolInformation(poolAddress: string) {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/pools/check/${poolAddress}`, pairStatusSchema);
|
return fetchWithValidation(`https://${this.apiUrl}/api/pools/check/${poolAddress}`, pairStatusSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
getAtomicSwapAssets() {
|
getAtomicSwapAssets() {
|
||||||
return fetchJsonWithValidation(`https://${this.apiUrl}/api/atomic/swap-assets`, z.array(z.string()));
|
return fetchWithValidation(`https://${this.apiUrl}/api/atomic/swap-assets`, z.array(z.string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -226,7 +257,7 @@ class OrionBlockchain {
|
|||||||
Object.entries(query)
|
Object.entries(query)
|
||||||
.forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
.forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
||||||
|
|
||||||
return fetchJsonWithValidation(url.toString(), atomicHistorySchema);
|
return fetchWithValidation(url.toString(), atomicHistorySchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSourceAtomicSwapHistory(query: AtomicSwapHistorySourceQuery) {
|
getSourceAtomicSwapHistory(query: AtomicSwapHistorySourceQuery) {
|
||||||
@@ -237,7 +268,7 @@ class OrionBlockchain {
|
|||||||
|
|
||||||
if (!query.type) url.searchParams.append('type', 'source');
|
if (!query.type) url.searchParams.append('type', 'source');
|
||||||
|
|
||||||
return fetchJsonWithValidation(url.toString(), sourceAtomicHistorySchema);
|
return fetchWithValidation(url.toString(), sourceAtomicHistorySchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTargetAtomicSwapHistory(query: AtomicSwapHistoryTargetQuery) {
|
getTargetAtomicSwapHistory(query: AtomicSwapHistoryTargetQuery) {
|
||||||
@@ -248,11 +279,11 @@ class OrionBlockchain {
|
|||||||
|
|
||||||
if (!query.type) url.searchParams.append('type', 'target');
|
if (!query.type) url.searchParams.append('type', 'target');
|
||||||
|
|
||||||
return fetchJsonWithValidation(url.toString(), targetAtomicHistorySchema);
|
return fetchWithValidation(url.toString(), targetAtomicHistorySchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkIfHashUsed(secretHashes: string[]) {
|
checkIfHashUsed(secretHashes: string[]) {
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
`https://${this.apiUrl}/api/atomic/is-hash-used`,
|
`https://${this.apiUrl}/api/atomic/is-hash-used`,
|
||||||
z.record(z.boolean()).transform(utils.makePartial),
|
z.record(z.boolean()).transform(utils.makePartial),
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { fetchJsonWithValidation } from '../../fetchWithValidation';
|
import fetchWithValidation from '../../fetchWithValidation';
|
||||||
import candlesSchema from './schemas/candlesSchema';
|
import candlesSchema from './schemas/candlesSchema';
|
||||||
|
|
||||||
class PriceFeed {
|
class PriceFeed {
|
||||||
@@ -6,6 +6,8 @@ class PriceFeed {
|
|||||||
|
|
||||||
constructor(apiUrl: string) {
|
constructor(apiUrl: string) {
|
||||||
this.apiUrl = apiUrl;
|
this.apiUrl = apiUrl;
|
||||||
|
|
||||||
|
this.getCandles = this.getCandles.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
getCandles(
|
getCandles(
|
||||||
@@ -22,7 +24,7 @@ class PriceFeed {
|
|||||||
url.searchParams.append('interval', interval);
|
url.searchParams.append('interval', interval);
|
||||||
url.searchParams.append('exchange', exchange);
|
url.searchParams.append('exchange', exchange);
|
||||||
|
|
||||||
return fetchJsonWithValidation(
|
return fetchWithValidation(
|
||||||
url.toString(),
|
url.toString(),
|
||||||
candlesSchema,
|
candlesSchema,
|
||||||
);
|
);
|
||||||
|
|||||||
28
src/simpleFetch.ts
Normal file
28
src/simpleFetch.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { Schema, z } from 'zod';
|
||||||
|
import { RequestInit } from 'node-fetch';
|
||||||
|
import fetchWithValidation from './fetchWithValidation';
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/64919133
|
||||||
|
class Wrapper<DataOut, DataIn, ErrorOut, ErrorIn> {
|
||||||
|
// eslint-disable-next-line class-methods-use-this
|
||||||
|
wrapped(
|
||||||
|
url: string,
|
||||||
|
schema: Schema<DataOut, z.ZodTypeDef, DataIn>,
|
||||||
|
options?: RequestInit,
|
||||||
|
errorSchema?: Schema<ErrorOut, z.ZodTypeDef, ErrorIn>,
|
||||||
|
) {
|
||||||
|
return fetchWithValidation<DataOut, DataIn, ErrorOut, ErrorIn>(url, schema, options, errorSchema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type FetchWithValidationInternalType<O, I, EO, EI> = ReturnType<Wrapper<O, I, EO, EI>['wrapped']>
|
||||||
|
|
||||||
|
export default function simpleFetch<O, I, EO, EI, P extends unknown[]>(
|
||||||
|
f: (...params: P) => FetchWithValidationInternalType<O, I, EO, EI>,
|
||||||
|
) {
|
||||||
|
return async (...params: Parameters<typeof f>) => {
|
||||||
|
const result = await f(...params);
|
||||||
|
if (result.isErr()) throw new Error(result.error.message);
|
||||||
|
return result.value;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -30,10 +30,13 @@ export default async function getBalance(
|
|||||||
}
|
}
|
||||||
const assetContractBalance = await exchangeContract.getBalance(assetAddress, walletAddress);
|
const assetContractBalance = await exchangeContract.getBalance(assetAddress, walletAddress);
|
||||||
const denormalizedAssetInContractBalance = utils.denormalizeNumber(assetContractBalance, INTERNAL_ORION_PRECISION);
|
const denormalizedAssetInContractBalance = utils.denormalizeNumber(assetContractBalance, INTERNAL_ORION_PRECISION);
|
||||||
const denormalizedAssetLockedBalance = await orionAggregator.getLockedBalance(walletAddress, asset);
|
const denormalizedAssetLockedBalanceResult = await orionAggregator.getLockedBalance(walletAddress, asset);
|
||||||
|
if (denormalizedAssetLockedBalanceResult.isErr()) {
|
||||||
|
throw new Error(denormalizedAssetLockedBalanceResult.error.message);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
exchange: denormalizedAssetInContractBalance.minus(denormalizedAssetLockedBalance[asset] ?? 0),
|
exchange: denormalizedAssetInContractBalance.minus(denormalizedAssetLockedBalanceResult.value[asset] ?? 0),
|
||||||
wallet: denormalizedAssetInWalletBalance,
|
wallet: denormalizedAssetInWalletBalance,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ export { default as normalizeNumber } from './normalizeNumber';
|
|||||||
export { default as getSwapPair } from './getSwapPair';
|
export { default as getSwapPair } from './getSwapPair';
|
||||||
export { default as getSwapSide } from './getSwapSide';
|
export { default as getSwapSide } from './getSwapSide';
|
||||||
|
|
||||||
export { default as HttpError } from './httpError';
|
// export { default as HttpError } from './httpError';
|
||||||
|
|
||||||
export * from './typeHelpers';
|
export * from './typeHelpers';
|
||||||
|
|||||||
Reference in New Issue
Block a user