Moved fetching to simple-typed-fetch

This commit is contained in:
Aleksandr Kraiz
2023-03-24 21:59:04 +04:00
parent 07f947eb35
commit 51257adcd4
22 changed files with 256 additions and 653 deletions

View File

@@ -1,9 +1,9 @@
import { ethers } from 'ethers';
import type OrionUnit from '../../OrionUnit';
import simpleFetch from '../../simpleFetch';
import type { SupportedChainId } from '../../types';
import { isValidChainId } from '../../utils';
import ObjectID from 'bson-objectid';
import { simpleFetch } from 'simple-typed-fetch';
const getHistory = async (units: OrionUnit[], address: string, limit = 1000) => {
if (!ethers.utils.isAddress(address)) throw new Error(`Invalid address: ${address}`);

View File

@@ -12,12 +12,12 @@ import {
WITHDRAW_GAS_LIMIT
} from '../../constants';
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
import simpleFetch from '../../simpleFetch';
import { denormalizeNumber, generateSecret, normalizeNumber, toUpperCase } from '../../utils';
import type { SupportedChainId } from '../../types';
import type Orion from '..';
import type { z } from 'zod';
import type { placeAtomicSwapSchema } from '../../services/OrionAggregator/schemas';
import { simpleFetch } from 'simple-typed-fetch';
type Params = {
assetName: string

View File

@@ -5,11 +5,11 @@ import { chains, envs } from '../config';
import type { networkCodes } from '../constants';
import OrionUnit from '../OrionUnit';
import { ReferralSystem } from '../services/ReferralSystem';
import simpleFetch from '../simpleFetch';
import type { SupportedChainId, DeepPartial, VerboseOrionUnitConfig, KnownEnv } from '../types';
import { isValidChainId } from '../utils';
import swap from './bridge/swap';
import getHistory from './bridge/getHistory';
import { simpleFetch } from 'simple-typed-fetch';
type EnvConfig = {
analyticsAPI: string

View File

@@ -9,7 +9,7 @@ import {
} from '../../constants';
import { denormalizeNumber, normalizeNumber } from '../../utils';
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
import simpleFetch from '../../simpleFetch';
import { simpleFetch } from 'simple-typed-fetch';
export type DepositParams = {
asset: string

View File

@@ -1,10 +1,10 @@
import BigNumber from 'bignumber.js';
import { ethers } from 'ethers';
import { simpleFetch } from 'simple-typed-fetch';
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 simpleFetch from '../../simpleFetch';
import { calculateFeeInFeeAsset, denormalizeNumber, getNativeCryptocurrency } from '../../utils';
export type GetSwapInfoParams = {

View File

@@ -7,11 +7,11 @@ import getAvailableSources from '../../utils/getAvailableFundsSources';
import type OrionUnit from '..';
import { INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION, SWAP_THROUGH_ORION_POOL_GAS_LIMIT } from '../../constants';
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';
import { simpleFetch } from 'simple-typed-fetch';
export type SwapLimitParams = {
type: 'exactSpend' | 'exactReceive'

View File

@@ -6,12 +6,12 @@ import BalanceGuard from '../../BalanceGuard';
import getAvailableSources from '../../utils/getAvailableFundsSources';
import { INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION, SWAP_THROUGH_ORION_POOL_GAS_LIMIT } from '../../constants';
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';
import type { SwapLimitParams } from './swapLimit';
import { simpleFetch } from 'simple-typed-fetch';
export type SwapMarketParams = Omit<SwapLimitParams, 'price'> & {
slippagePercent: BigNumber.Value

View File

@@ -9,7 +9,7 @@ import {
} from '../../constants';
import { denormalizeNumber, normalizeNumber } from '../../utils';
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';
import simpleFetch from '../../simpleFetch';
import { simpleFetch } from 'simple-typed-fetch';
export type WithdrawParams = {
asset: string

View File

@@ -1,10 +1,10 @@
import { Exchange__factory, IUniswapV2Pair__factory, IUniswapV2Router__factory } from '@orionprotocol/contracts';
import BigNumber from 'bignumber.js';
import { ethers } from 'ethers';
import { simpleFetch } from 'simple-typed-fetch';
import type OrionUnit from '..';
import BalanceGuard from '../../BalanceGuard';
import { ADD_LIQUIDITY_GAS_LIMIT, INTERNAL_ORION_PRECISION, NATIVE_CURRENCY_PRECISION } from '../../constants';
import simpleFetch from '../../simpleFetch';
import { denormalizeNumber, normalizeNumber } from '../../utils';
import getBalances from '../../utils/getBalances';
import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency';

View File

@@ -1,6 +1,5 @@
import Orion from '../Orion';
import { ReferralSystem } from '../services/ReferralSystem';
import simpleFetch from '../simpleFetch';
import { SupportedChainId } from '../types';
import express from 'express';
import WebSocket from 'ws';
@@ -10,6 +9,7 @@ import {
createHttpTerminator,
} from 'http-terminator';
import { ethers } from 'ethers';
import { simpleFetch } from 'simple-typed-fetch';
jest.setTimeout(10000);

View File

@@ -1,154 +0,0 @@
import type { Schema, z } from 'zod';
import fetch from 'isomorphic-unfetch';
import {
err, fromPromise, fromThrowable, ok,
} from 'neverthrow';
export default async function fetchWithValidation<DataOut, DataIn, ErrorOut, ErrorIn>(
url: string,
schema: Schema<DataOut, z.ZodTypeDef, DataIn>,
options?: RequestInit,
errorSchema?: Schema<ErrorOut, z.ZodTypeDef, ErrorIn>,
) {
// Cases:
// fetchError (no network, connection refused, connection break)
// unknownFetchThrow
// unknownGetTextError
// unknownGetTextUnknownError
// serverError
// jsonParseError
// jsonParseUnknownError
// clientErrorWithResponsePayload
// clientErrorPayloadParseError
// clientError
// payloadParseError
// payload
const fetchResult = await fromPromise(fetch(url, {
...options ?? {},
headers: {
'Cache-Control': 'no-store, max-age=0',
...(options ? options.headers : {}),
},
}), (e) => {
if (e instanceof Error) {
return err({
type: 'fetchError' as const,
url,
message: e.message,
error: e,
});
}
return err({
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()) {
const textPayload = schema.safeParse(text);
if (textPayload.success) return ok(textPayload.data);
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}. Server error: ${JSON.stringify(serverError.data)}`,
status: response.status,
payload: serverError.data,
});
}
return err({
type: 'clientErrorPayloadParseError' as const,
url,
message: 'Can\'t recognize error message. Response: ' + text,
status: response.status,
text,
error: serverError.error,
});
}
return err({
type: 'clientError' as const,
url,
message: `Error: ${response.status} ${response.statusText}. Response: ${text}`,
status: response.status,
text,
});
}
const payload = schema.safeParse(json);
if (!payload.success) {
const issuesMessages = payload.error.issues.map((issue) => `[${issue.path.join('.')}] ${issue.message}`).join(', ');
return err({
type: 'payloadParseError' as const,
url,
message: `Can't recognize response payload: ${issuesMessages}`,
error: payload.error,
});
}
return ok(payload.data);
}

View File

@@ -1,15 +1,14 @@
import BigNumber from 'bignumber.js';
import { simpleFetch, fetchWithValidation } from 'simple-typed-fetch';
BigNumber.config({ EXPONENTIAL_AT: 1e+9 });
export * as config from './config';
export { default as OrionUnit } from './OrionUnit';
export { default as Orion } from './Orion';
export { default as initOrionUnit } from './initOrionUnit';
export { default as fetchWithValidation } from './fetchWithValidation';
export { default as simpleFetch } from './simpleFetch';
export * as utils from './utils';
export * as services from './services';
export * as crypt from './crypt';
export * from './constants';
export * from './types';
export { simpleFetch, fetchWithValidation };

View File

@@ -1,6 +1,5 @@
import type BigNumber from 'bignumber.js';
import { z } from 'zod';
import fetchWithValidation from '../../fetchWithValidation';
import swapInfoSchema from './schemas/swapInfoSchema';
import exchangeInfoSchema from './schemas/exchangeInfoSchema';
import cancelOrderSchema from './schemas/cancelOrderSchema';
@@ -20,6 +19,7 @@ import httpToWS from '../../utils/httpToWS';
import { ethers } from 'ethers';
import orderSchema from './schemas/orderSchema';
import { exchanges } from '../../constants';
import { fetchWithValidation } from 'simple-typed-fetch';
class OrionAggregator {
private readonly apiUrl: string;

View File

@@ -1,5 +1,4 @@
import { z } from 'zod';
import fetchWithValidation from '../../fetchWithValidation';
import {
IDOSchema, atomicHistorySchema,
poolsConfigSchema, poolsInfoSchema, infoSchema, historySchema,
@@ -18,6 +17,7 @@ import type redeemOrderSchema from '../OrionAggregator/schemas/redeemOrderSchema
import { sourceAtomicHistorySchema, targetAtomicHistorySchema } from './schemas/atomicHistorySchema';
import { makePartial } from '../../utils';
import type { networkCodes } from '../../constants';
import { fetchWithValidation } from 'simple-typed-fetch';
type IAdminAuthHeaders = {
auth: string

View File

@@ -1,4 +1,4 @@
import fetchWithValidation from '../../fetchWithValidation';
import { fetchWithValidation } from 'simple-typed-fetch';
import type { Exchange } from '../../types';
import { statisticsOverviewSchema, topPairsStatisticsSchema } from './schemas';
import candlesSchema from './schemas/candlesSchema';

View File

@@ -1,4 +1,4 @@
import fetchWithValidation from '../../fetchWithValidation';
import { fetchWithValidation } from 'simple-typed-fetch';
import {
errorSchema,
miniStatsSchema,

View File

@@ -1,30 +0,0 @@
import type { Schema, z } from 'zod';
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()) {
const { message, url } = result.error;
throw new Error(`${message} (${url})`);
}
return result.value;
};
}