mirror of
https://github.com/orionprotocol/sdk.git
synced 2026-03-24 22:58:01 +03:00
@@ -1,4 +1,4 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import type BigNumber from 'bignumber.js';
|
||||
import { z } from 'zod';
|
||||
import fetchWithValidation from '../../fetchWithValidation';
|
||||
import swapInfoSchema from './schemas/swapInfoSchema';
|
||||
@@ -9,12 +9,12 @@ import errorSchema from './schemas/errorSchema';
|
||||
import placeAtomicSwapSchema from './schemas/placeAtomicSwapSchema';
|
||||
import { OrionAggregatorWS } from './ws';
|
||||
import { atomicSwapHistorySchema } from './schemas/atomicSwapHistorySchema';
|
||||
import { Exchange, SignedCancelOrderRequest, SignedCFDOrder, SignedOrder } from '../../types';
|
||||
import { type Exchange, type SignedCancelOrderRequest, type SignedCFDOrder, type SignedOrder } from '../../types';
|
||||
import { pairConfigSchema } from './schemas';
|
||||
import {
|
||||
aggregatedOrderbookSchema, exchangeOrderbookSchema, poolReservesSchema,
|
||||
} from './schemas/aggregatedOrderbookSchema';
|
||||
import networkCodes from '../../constants/networkCodes';
|
||||
import type networkCodes from '../../constants/networkCodes';
|
||||
import toUpperCase from '../../utils/toUpperCase';
|
||||
import httpToWS from '../../utils/httpToWS';
|
||||
|
||||
@@ -146,7 +146,7 @@ class OrionAggregator {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
...partnerId && { 'X-Partner-Id': partnerId },
|
||||
...(partnerId !== undefined) && { 'X-Partner-Id': partnerId },
|
||||
};
|
||||
|
||||
return fetchWithValidation(
|
||||
@@ -232,7 +232,7 @@ class OrionAggregator {
|
||||
} else {
|
||||
url.searchParams.append('amountOut', amount);
|
||||
}
|
||||
if (exchanges) {
|
||||
if (exchanges !== undefined) {
|
||||
if (Array.isArray(exchanges)) {
|
||||
exchanges.forEach((exchange) => {
|
||||
url.searchParams.append('exchanges', exchange);
|
||||
@@ -241,7 +241,7 @@ class OrionAggregator {
|
||||
url.searchParams.append('exchanges', exchanges);
|
||||
}
|
||||
}
|
||||
if (instantSettlement) {
|
||||
if (instantSettlement !== undefined && instantSettlement) {
|
||||
url.searchParams.append('instantSettlement', 'true');
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ import {
|
||||
} from './schemas';
|
||||
import UnsubscriptionType from './UnsubscriptionType';
|
||||
import {
|
||||
SwapInfoBase, AssetPairUpdate, OrderbookItem, Balance,
|
||||
Exchange, CFDBalance, SwapInfo, FuturesTradeInfo,
|
||||
type SwapInfoBase, type AssetPairUpdate, type OrderbookItem,
|
||||
type Balance, type Exchange, type CFDBalance, type FuturesTradeInfo, type SwapInfo,
|
||||
} from '../../../types';
|
||||
import unsubscriptionDoneSchema from './schemas/unsubscriptionDoneSchema';
|
||||
import assetPairConfigSchema from './schemas/assetPairConfigSchema';
|
||||
import { fullOrderSchema, orderUpdateSchema } from './schemas/addressUpdateSchema';
|
||||
import { type fullOrderSchema, type orderUpdateSchema } from './schemas/addressUpdateSchema';
|
||||
import cfdAddressUpdateSchema from './schemas/cfdAddressUpdateSchema';
|
||||
import futuresTradeInfoSchema from './schemas/futuresTradeInfoSchema';
|
||||
// import errorSchema from './schemas/errorSchema';
|
||||
@@ -25,108 +25,108 @@ const UNSUBSCRIBE = 'u';
|
||||
// https://github.com/orionprotocol/orion-aggregator/tree/feature/OP-1752-symmetric-swap#swap-info-subscribe
|
||||
type SwapSubscriptionRequest = {
|
||||
// d: string, // swap request UUID, set by client side
|
||||
i: string, // asset in
|
||||
o: string, // asset out
|
||||
i: string // asset in
|
||||
o: string // asset out
|
||||
a: number // amount IN/OUT
|
||||
es?: Exchange[] | 'cex' | 'pools', // exchange list of all cex or all pools (ORION_POOL, UNISWAP, PANCAKESWAP etc)
|
||||
e?: boolean; // is amount IN? Value `false` means a = amount OUT, `true` if omitted
|
||||
is?: boolean; // instant settlement
|
||||
es?: Exchange[] | 'cex' | 'pools' // exchange list of all cex or all pools (ORION_POOL, UNISWAP, PANCAKESWAP etc)
|
||||
e?: boolean // is amount IN? Value `false` means a = amount OUT, `true` if omitted
|
||||
is?: boolean // instant settlement
|
||||
}
|
||||
|
||||
type BrokerTradableAtomicSwapBalanceSubscription = {
|
||||
callback: (balances: Partial<Record<string, number>>) => void,
|
||||
callback: (balances: Partial<Record<string, number>>) => void
|
||||
}
|
||||
|
||||
type PairsConfigSubscription = {
|
||||
callback: ({ kind, data }: {
|
||||
kind: 'initial' | 'update',
|
||||
data: Partial<Record<string, AssetPairUpdate>>,
|
||||
}) => void,
|
||||
kind: 'initial' | 'update'
|
||||
data: Partial<Record<string, AssetPairUpdate>>
|
||||
}) => void
|
||||
}
|
||||
|
||||
type PairConfigSubscription = {
|
||||
payload: string,
|
||||
payload: string
|
||||
callback: ({ kind, data }: {
|
||||
kind: 'initial' | 'update',
|
||||
data: AssetPairUpdate,
|
||||
}) => void,
|
||||
kind: 'initial' | 'update'
|
||||
data: AssetPairUpdate
|
||||
}) => void
|
||||
}
|
||||
|
||||
type AggregatedOrderbookSubscription = {
|
||||
payload: string,
|
||||
payload: string
|
||||
callback: (
|
||||
asks: OrderbookItem[],
|
||||
bids: OrderbookItem[],
|
||||
pair: string
|
||||
) => void,
|
||||
) => void
|
||||
}
|
||||
|
||||
type SwapInfoSubscription = {
|
||||
payload: SwapSubscriptionRequest,
|
||||
callback: (swapInfo: SwapInfo) => void,
|
||||
payload: SwapSubscriptionRequest
|
||||
callback: (swapInfo: SwapInfo) => void
|
||||
}
|
||||
|
||||
type FuturesTradeInfoSubscription = {
|
||||
payload: {
|
||||
s: string,
|
||||
i: string,
|
||||
a: number,
|
||||
p?: number,
|
||||
},
|
||||
callback: (futuresTradeInfo: FuturesTradeInfo) => void,
|
||||
s: string
|
||||
i: string
|
||||
a: number
|
||||
p?: number
|
||||
}
|
||||
callback: (futuresTradeInfo: FuturesTradeInfo) => void
|
||||
}
|
||||
|
||||
type AddressUpdateUpdate = {
|
||||
kind: 'update',
|
||||
kind: 'update'
|
||||
balances: Partial<
|
||||
Record<
|
||||
string,
|
||||
Balance
|
||||
>
|
||||
>,
|
||||
Record<
|
||||
string,
|
||||
Balance
|
||||
>
|
||||
>
|
||||
order?: z.infer<typeof orderUpdateSchema> | z.infer<typeof fullOrderSchema>
|
||||
}
|
||||
|
||||
type AddressUpdateInitial = {
|
||||
kind: 'initial',
|
||||
kind: 'initial'
|
||||
balances: Partial<
|
||||
Record<
|
||||
string,
|
||||
Balance
|
||||
>
|
||||
>,
|
||||
orders?: z.infer<typeof fullOrderSchema>[] // The field is not defined if the user has no orders
|
||||
Record<
|
||||
string,
|
||||
Balance
|
||||
>
|
||||
>
|
||||
orders?: Array<z.infer<typeof fullOrderSchema>> // The field is not defined if the user has no orders
|
||||
}
|
||||
|
||||
type CfdAddressUpdateUpdate = {
|
||||
kind: 'update',
|
||||
balances?: CFDBalance[],
|
||||
kind: 'update'
|
||||
balances?: CFDBalance[]
|
||||
order?: z.infer<typeof orderUpdateSchema> | z.infer<typeof fullOrderSchema>
|
||||
}
|
||||
|
||||
type CfdAddressUpdateInitial = {
|
||||
kind: 'initial',
|
||||
balances: CFDBalance[],
|
||||
orders?: z.infer<typeof fullOrderSchema>[] // The field is not defined if the user has no orders
|
||||
kind: 'initial'
|
||||
balances: CFDBalance[]
|
||||
orders?: Array<z.infer<typeof fullOrderSchema>> // The field is not defined if the user has no orders
|
||||
}
|
||||
|
||||
type AddressUpdateSubscription = {
|
||||
payload: string,
|
||||
callback: (data: AddressUpdateUpdate | AddressUpdateInitial) => void,
|
||||
payload: string
|
||||
callback: (data: AddressUpdateUpdate | AddressUpdateInitial) => void
|
||||
}
|
||||
|
||||
type CfdAddressUpdateSubscription = {
|
||||
payload: string,
|
||||
callback: (data: CfdAddressUpdateUpdate | CfdAddressUpdateInitial) => void,
|
||||
payload: string
|
||||
callback: (data: CfdAddressUpdateUpdate | CfdAddressUpdateInitial) => void
|
||||
}
|
||||
|
||||
type Subscription = {
|
||||
[SubscriptionType.ADDRESS_UPDATES_SUBSCRIBE]: AddressUpdateSubscription,
|
||||
[SubscriptionType.CFD_ADDRESS_UPDATES_SUBSCRIBE]: CfdAddressUpdateSubscription,
|
||||
[SubscriptionType.AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE]: AggregatedOrderbookSubscription,
|
||||
[SubscriptionType.ASSET_PAIRS_CONFIG_UPDATES_SUBSCRIBE]: PairsConfigSubscription,
|
||||
[SubscriptionType.ASSET_PAIR_CONFIG_UPDATES_SUBSCRIBE]: PairConfigSubscription,
|
||||
[SubscriptionType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_SUBSCRIBE]: BrokerTradableAtomicSwapBalanceSubscription,
|
||||
[SubscriptionType.ADDRESS_UPDATES_SUBSCRIBE]: AddressUpdateSubscription
|
||||
[SubscriptionType.CFD_ADDRESS_UPDATES_SUBSCRIBE]: CfdAddressUpdateSubscription
|
||||
[SubscriptionType.AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE]: AggregatedOrderbookSubscription
|
||||
[SubscriptionType.ASSET_PAIRS_CONFIG_UPDATES_SUBSCRIBE]: PairsConfigSubscription
|
||||
[SubscriptionType.ASSET_PAIR_CONFIG_UPDATES_SUBSCRIBE]: PairConfigSubscription
|
||||
[SubscriptionType.BROKER_TRADABLE_ATOMIC_SWAP_ASSETS_BALANCE_UPDATES_SUBSCRIBE]: BrokerTradableAtomicSwapBalanceSubscription
|
||||
[SubscriptionType.SWAP_SUBSCRIBE]: SwapInfoSubscription
|
||||
[SubscriptionType.FUTURES_TRADE_INFO_SUBSCRIBE]: FuturesTradeInfoSubscription
|
||||
}
|
||||
@@ -145,14 +145,14 @@ type BufferLike =
|
||||
| Uint8Array
|
||||
| ArrayBuffer
|
||||
| SharedArrayBuffer
|
||||
| ReadonlyArray<unknown>
|
||||
| ReadonlyArray<number>
|
||||
| { valueOf(): ArrayBuffer }
|
||||
| { valueOf(): SharedArrayBuffer }
|
||||
| { valueOf(): Uint8Array }
|
||||
| { valueOf(): ReadonlyArray<number> }
|
||||
| { valueOf(): string }
|
||||
| { [Symbol.toPrimitive](hint: string): string };
|
||||
| readonly unknown[]
|
||||
| readonly number[]
|
||||
| { valueOf: () => ArrayBuffer }
|
||||
| { valueOf: () => SharedArrayBuffer }
|
||||
| { valueOf: () => Uint8Array }
|
||||
| { valueOf: () => readonly number[] }
|
||||
| { valueOf: () => string }
|
||||
| { [Symbol.toPrimitive]: (hint: string) => string };
|
||||
|
||||
const isSubType = (subType: string): subType is keyof Subscription => Object.values(SubscriptionType).some((t) => t === subType);
|
||||
class OrionAggregatorWS {
|
||||
@@ -339,8 +339,9 @@ class OrionAggregatorWS {
|
||||
};
|
||||
this.ws.onmessage = (e) => {
|
||||
const { data } = e;
|
||||
this.logger?.(`OrionAggregatorWS: received message: ${e.data.toString()}`);
|
||||
const rawJson: unknown = JSON.parse(data.toString());
|
||||
if (typeof data !== 'string') throw new Error('OrionAggregatorWS: received non-string message');
|
||||
this.logger?.(`OrionAggregatorWS: received message: ${data}`);
|
||||
const rawJson: unknown = JSON.parse(data);
|
||||
|
||||
const messageSchema = z.union([
|
||||
initMessageSchema,
|
||||
@@ -385,7 +386,7 @@ class OrionAggregatorWS {
|
||||
path: json.ps,
|
||||
exchanges: json.e,
|
||||
poolOptimal: json.po,
|
||||
...json.oi && {
|
||||
...(json.oi) && {
|
||||
orderInfo: {
|
||||
pair: json.oi.p,
|
||||
side: json.oi.s,
|
||||
@@ -511,8 +512,8 @@ class OrionAggregatorWS {
|
||||
case MessageType.CFD_ADDRESS_UPDATE:
|
||||
switch (json.k) { // message kind
|
||||
case 'i': { // initial
|
||||
const fullOrders = json.o
|
||||
? json.o.reduce<z.infer<typeof fullOrderSchema>[]>((prev, o) => {
|
||||
const fullOrders = (json.o)
|
||||
? json.o.reduce<Array<z.infer<typeof fullOrderSchema>>>((prev, o) => {
|
||||
prev.push(o);
|
||||
|
||||
return prev;
|
||||
@@ -524,7 +525,7 @@ class OrionAggregatorWS {
|
||||
]?.[json.id]?.callback({
|
||||
kind: 'initial',
|
||||
orders: fullOrders,
|
||||
balances: json.b ?? [],
|
||||
balances: json.b,
|
||||
});
|
||||
}
|
||||
break;
|
||||
@@ -549,7 +550,7 @@ class OrionAggregatorWS {
|
||||
}
|
||||
break;
|
||||
case MessageType.ADDRESS_UPDATE: {
|
||||
const balances = json.b
|
||||
const balances = (json.b)
|
||||
? Object.entries(json.b)
|
||||
.reduce<Partial<Record<string, Balance>>>((prev, [asset, assetBalances]) => {
|
||||
if (!assetBalances) return prev;
|
||||
@@ -565,7 +566,7 @@ class OrionAggregatorWS {
|
||||
switch (json.k) { // message kind
|
||||
case 'i': { // initial
|
||||
const fullOrders = json.o
|
||||
? json.o.reduce<z.infer<typeof fullOrderSchema>[]>((prev, o) => {
|
||||
? json.o.reduce<Array<z.infer<typeof fullOrderSchema>>>((prev, o) => {
|
||||
prev.push(o);
|
||||
|
||||
return prev;
|
||||
|
||||
@@ -2,7 +2,7 @@ import fetchWithValidation from '../../fetchWithValidation';
|
||||
import overviewSchema from './schemas/overviewSchema';
|
||||
|
||||
export default class OrionAnalytics {
|
||||
private apiUrl: string;
|
||||
private readonly apiUrl: string;
|
||||
|
||||
constructor(apiUrl: string) {
|
||||
this.apiUrl = apiUrl;
|
||||
|
||||
@@ -3,63 +3,63 @@ import fetchWithValidation from '../../fetchWithValidation';
|
||||
import {
|
||||
IDOSchema, atomicHistorySchema,
|
||||
poolsConfigSchema, poolsInfoSchema, infoSchema, historySchema,
|
||||
addPoolSchema, adminPoolsListSchema, adminPoolSchema,
|
||||
type addPoolSchema, adminPoolsListSchema, adminPoolSchema,
|
||||
atomicSummarySchema,
|
||||
poolsLpAndStakedSchema,
|
||||
userVotesSchema,
|
||||
userEarnedSchema,
|
||||
PairStatusEnum,
|
||||
type PairStatusEnum,
|
||||
pairStatusSchema,
|
||||
cfdContractsSchema,
|
||||
cfdHistorySchema,
|
||||
} from './schemas';
|
||||
import redeemOrderSchema from '../OrionAggregator/schemas/redeemOrderSchema';
|
||||
import type redeemOrderSchema from '../OrionAggregator/schemas/redeemOrderSchema';
|
||||
import { sourceAtomicHistorySchema, targetAtomicHistorySchema } from './schemas/atomicHistorySchema';
|
||||
import { makePartial } from '../../utils';
|
||||
import { networkCodes } from '../../constants';
|
||||
import { type networkCodes } from '../../constants';
|
||||
|
||||
interface IAdminAuthHeaders {
|
||||
auth: string;
|
||||
type IAdminAuthHeaders = {
|
||||
auth: string
|
||||
[key: string]: string
|
||||
}
|
||||
|
||||
export interface IEditPool {
|
||||
tokenAIcon?: string;
|
||||
tokenBIcon?: string;
|
||||
symbol?: string;
|
||||
status: PairStatusEnum;
|
||||
minQty?: number;
|
||||
tokenASymbol?: string;
|
||||
tokenBSymbol?: string;
|
||||
tokensReversed?: boolean;
|
||||
export type IEditPool = {
|
||||
tokenAIcon?: string
|
||||
tokenBIcon?: string
|
||||
symbol?: string
|
||||
status: PairStatusEnum
|
||||
minQty?: number
|
||||
tokenASymbol?: string
|
||||
tokenBSymbol?: string
|
||||
tokensReversed?: boolean
|
||||
}
|
||||
|
||||
type AtomicSwapHistoryBaseQuery = {
|
||||
limit?: number
|
||||
sender?: string,
|
||||
receiver?: string,
|
||||
used?: 0 | 1,
|
||||
page?: number,
|
||||
sourceNetworkCode?: typeof networkCodes[number],
|
||||
}
|
||||
sender?: string
|
||||
receiver?: string
|
||||
used?: 0 | 1
|
||||
page?: number
|
||||
sourceNetworkCode?: typeof networkCodes[number]
|
||||
} & Partial<Record<string, string | number>>
|
||||
|
||||
type AtomicSwapHistorySourceQuery = AtomicSwapHistoryBaseQuery & {
|
||||
type?: 'source',
|
||||
expiredLock?: 0 | 1,
|
||||
state?: 'LOCKED' | 'CLAIMED' |'REFUNDED',
|
||||
type?: 'source'
|
||||
expiredLock?: 0 | 1
|
||||
state?: 'LOCKED' | 'CLAIMED' | 'REFUNDED'
|
||||
|
||||
}
|
||||
type AtomicSwapHistoryTargetQuery = AtomicSwapHistoryBaseQuery & {
|
||||
type?: 'target',
|
||||
expiredRedeem?: 0 | 1,
|
||||
state?: 'REDEEMED' | 'BEFORE-REDEEM',
|
||||
type?: 'target'
|
||||
expiredRedeem?: 0 | 1
|
||||
state?: 'REDEEMED' | 'BEFORE-REDEEM'
|
||||
}
|
||||
|
||||
type CfdHistoryQuery = {
|
||||
instrument?: string,
|
||||
page?: number,
|
||||
limit?: number,
|
||||
}
|
||||
instrument?: string
|
||||
page?: number
|
||||
limit?: number
|
||||
} & Partial<Record<string, string | number>>
|
||||
class OrionBlockchain {
|
||||
private readonly apiUrl: string;
|
||||
|
||||
@@ -110,12 +110,12 @@ class OrionBlockchain {
|
||||
return `${this.apiUrl}/`;
|
||||
}
|
||||
|
||||
private getSummaryRedeem = (brokerAddress: string, unshifted?: 1 | 0, sourceNetworkCode?: typeof networkCodes[number]) => {
|
||||
private readonly getSummaryRedeem = (brokerAddress: string, unshifted?: 1 | 0, sourceNetworkCode?: typeof networkCodes[number]) => {
|
||||
const url = new URL(`${this.apiUrl}/api/atomic/summary-redeem/${brokerAddress}`);
|
||||
if (unshifted) {
|
||||
if (unshifted !== undefined && unshifted === 1) {
|
||||
url.searchParams.append('unshifted', unshifted.toString());
|
||||
}
|
||||
if (sourceNetworkCode) {
|
||||
if (sourceNetworkCode !== undefined) {
|
||||
url.searchParams.append('sourceNetworkCode', sourceNetworkCode);
|
||||
}
|
||||
return fetchWithValidation(
|
||||
@@ -124,12 +124,12 @@ class OrionBlockchain {
|
||||
);
|
||||
};
|
||||
|
||||
private getSummaryClaim = (brokerAddress: string) => fetchWithValidation(
|
||||
private readonly getSummaryClaim = (brokerAddress: string) => fetchWithValidation(
|
||||
`${this.apiUrl}/api/atomic/summary-claim/${brokerAddress}`,
|
||||
atomicSummarySchema,
|
||||
);
|
||||
|
||||
private getQueueLength = () => fetchWithValidation(
|
||||
private readonly getQueueLength = () => fetchWithValidation(
|
||||
`${this.apiUrl}/api/queueLength`,
|
||||
z.number().int(),
|
||||
);
|
||||
@@ -357,7 +357,10 @@ class OrionBlockchain {
|
||||
const url = new URL(`${this.apiUrl}/api/atomic/history/`);
|
||||
|
||||
Object.entries(query)
|
||||
.forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
||||
.forEach(([key, value]) => {
|
||||
if (value === undefined) throw new Error('Value must be defined');
|
||||
url.searchParams.append(key, value.toString());
|
||||
});
|
||||
|
||||
return fetchWithValidation(url.toString(), atomicHistorySchema);
|
||||
};
|
||||
@@ -366,9 +369,12 @@ class OrionBlockchain {
|
||||
const url = new URL(`${this.apiUrl}/api/atomic/history/`);
|
||||
|
||||
Object.entries(query)
|
||||
.forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
||||
.forEach(([key, value]) => {
|
||||
if (value === undefined) throw new Error('Value must be defined');
|
||||
url.searchParams.append(key, value.toString());
|
||||
});
|
||||
|
||||
if (!query.type) url.searchParams.append('type', 'source');
|
||||
if (query.type !== undefined) url.searchParams.append('type', 'source');
|
||||
|
||||
return fetchWithValidation(url.toString(), sourceAtomicHistorySchema);
|
||||
};
|
||||
@@ -377,9 +383,12 @@ class OrionBlockchain {
|
||||
const url = new URL(`${this.apiUrl}/api/atomic/history/`);
|
||||
|
||||
Object.entries(query)
|
||||
.forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
||||
.forEach(([key, value]) => {
|
||||
if (value === undefined) throw new Error('Value must be defined');
|
||||
url.searchParams.append(key, value.toString());
|
||||
});
|
||||
|
||||
if (!query.type) url.searchParams.append('type', 'target');
|
||||
if (query.type !== undefined) url.searchParams.append('type', 'target');
|
||||
|
||||
return fetchWithValidation(url.toString(), targetAtomicHistorySchema);
|
||||
};
|
||||
@@ -406,7 +415,10 @@ class OrionBlockchain {
|
||||
const url = new URL(`${this.apiUrl}/api/cfd/deposit-withdraw/${address}`);
|
||||
|
||||
Object.entries(query)
|
||||
.forEach(([key, value]) => url.searchParams.append(key, value.toString()));
|
||||
.forEach(([key, value]) => {
|
||||
if (value === undefined) throw new Error('Value must be defined');
|
||||
url.searchParams.append(key, value.toString());
|
||||
});
|
||||
|
||||
return fetchWithValidation(url.toString(), cfdHistorySchema);
|
||||
};
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import fetchWithValidation from '../../fetchWithValidation';
|
||||
import { Exchange } from '../../types';
|
||||
import { type Exchange } from '../../types';
|
||||
import { statisticsOverviewSchema, topPairsStatisticsSchema } from './schemas';
|
||||
import candlesSchema from './schemas/candlesSchema';
|
||||
import { PriceFeedWS } from './ws';
|
||||
|
||||
class PriceFeed {
|
||||
private apiUrl: string;
|
||||
private readonly apiUrl: string;
|
||||
|
||||
readonly ws: PriceFeedWS;
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ import { tickerInfoSchema, candleSchema } from './schemas';
|
||||
import priceSchema from './schemas/priceSchema';
|
||||
|
||||
type TickerInfo = {
|
||||
pairName: string;
|
||||
lastPrice: string;
|
||||
openPrice: string;
|
||||
highPrice: string;
|
||||
lowPrice: string;
|
||||
volume24h: string;
|
||||
pairName: string
|
||||
lastPrice: string
|
||||
openPrice: string
|
||||
highPrice: string
|
||||
lowPrice: string
|
||||
volume24h: string
|
||||
}
|
||||
|
||||
const allTickersSchema = z.unknown().array()
|
||||
@@ -57,11 +57,11 @@ export type Subscription<
|
||||
Schema = z.infer<typeof subscriptions[T]['schema']>
|
||||
> = typeof subscriptions[T] extends { payload: true }
|
||||
? {
|
||||
callback: (data: Schema) => void,
|
||||
payload: string,
|
||||
} : {
|
||||
callback: (data: Schema) => void,
|
||||
}
|
||||
callback: (data: Schema) => void
|
||||
payload: string
|
||||
} : {
|
||||
callback: (data: Schema) => void
|
||||
}
|
||||
|
||||
export default class PriceFeedSubscription<T extends SubscriptionType = SubscriptionType> {
|
||||
public readonly id: string;
|
||||
@@ -104,16 +104,23 @@ export default class PriceFeedSubscription<T extends SubscriptionType = Subscrip
|
||||
this.isClosedIntentionally = false;
|
||||
|
||||
const { payload, url, type } = this;
|
||||
this.ws = new WebSocket(`${url}/${type}${payload ? `/${payload.toString()}` : ''}`);
|
||||
this.ws = new WebSocket(`${url}/${type}${payload !== undefined ? `/${payload.toString()}` : ''}`);
|
||||
|
||||
this.ws.onmessage = (e) => {
|
||||
if (e.data === 'pong') return;
|
||||
const json: unknown = JSON.parse(e.data.toString());
|
||||
const { data } = e;
|
||||
|
||||
// const isBufferArray = Array.isArray(data);
|
||||
// const isArrayBuffer = data instanceof ArrayBuffer;
|
||||
const isBuffer = Buffer.isBuffer(data);
|
||||
if (!isBuffer) throw new Error('Not a buffer');
|
||||
const dataString = data.toString();
|
||||
if (dataString === 'pong') return;
|
||||
const json: unknown = JSON.parse(dataString);
|
||||
const subscription = subscriptions[type];
|
||||
const parseResult = subscription.schema.safeParse(json);
|
||||
if (parseResult.success === false) {
|
||||
if (!parseResult.success) {
|
||||
const errorsMessage = parseResult.error.errors.map((error) => `[${error.path.join('.')}] ${error.message}`).join(', ');
|
||||
throw new Error(`Can't recognize PriceFeed "${type}" subscription message "${e.data.toString()}": ${errorsMessage}`);
|
||||
throw new Error(`Can't recognize PriceFeed "${type}" subscription message "${dataString}": ${errorsMessage}`);
|
||||
}
|
||||
this.callback(parseResult.data);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import PriceFeedSubscription, { SubscriptionType, Subscription } from './PriceFeedSubscription';
|
||||
import PriceFeedSubscription, { type SubscriptionType, type Subscription } from './PriceFeedSubscription';
|
||||
|
||||
export * as schemas from './schemas';
|
||||
export class PriceFeedWS {
|
||||
@@ -11,7 +11,7 @@ export class PriceFeedWS {
|
||||
>;
|
||||
}> = {};
|
||||
|
||||
private url: string;
|
||||
private readonly url: string;
|
||||
|
||||
constructor(url: string) {
|
||||
this.url = url;
|
||||
@@ -36,7 +36,7 @@ export class PriceFeedWS {
|
||||
return {
|
||||
type: sub.type,
|
||||
id: sub.id,
|
||||
unsubscribe: () => this.unsubscribe(sub.type, sub.id),
|
||||
unsubscribe: () => { this.unsubscribe(sub.type, sub.id); },
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,21 +6,21 @@ import globalAnalyticsSchema from './schemas/globalAnalyticsSchema';
|
||||
import linkSchema from './schemas/linkSchema';
|
||||
|
||||
type CreateLinkPayloadType = {
|
||||
referer: string;
|
||||
link_option: number;
|
||||
};
|
||||
referer: string
|
||||
link_option: number
|
||||
}
|
||||
|
||||
type SubscribePayloadType = {
|
||||
ref_target: string;
|
||||
referral: string;
|
||||
ref_target: string
|
||||
referral: string
|
||||
}
|
||||
|
||||
type SignatureType = {
|
||||
signature: string;
|
||||
};
|
||||
signature: string
|
||||
}
|
||||
|
||||
class ReferralSystem {
|
||||
private apiUrl: string;
|
||||
private readonly apiUrl: string;
|
||||
|
||||
get api() {
|
||||
return this.apiUrl;
|
||||
|
||||
Reference in New Issue
Block a user