mirror of
https://github.com/orionprotocol/sdk.git
synced 2026-03-30 01:27:57 +03:00
removed crypto-js dependency
This commit is contained in:
@@ -21,10 +21,15 @@ export default class Orion {
|
||||
|
||||
// TODO: get tradable pairs (aggregated)
|
||||
|
||||
public logger: ((message: string) => void) | undefined;
|
||||
|
||||
constructor(
|
||||
envOrConfig: KnownEnv | EnvConfig = 'production',
|
||||
overrides?: DeepPartial<EnvConfig>
|
||||
overrides?: DeepPartial<EnvConfig>,
|
||||
logger?: ((message: string) => void) | undefined
|
||||
) {
|
||||
this.logger = logger;
|
||||
|
||||
let config: EnvConfig;
|
||||
if (typeof envOrConfig === 'string') {
|
||||
const envConfig = envs[envOrConfig];
|
||||
@@ -33,7 +38,7 @@ export default class Orion {
|
||||
}
|
||||
this.env = envOrConfig;
|
||||
config = {
|
||||
analyticsAPI: envConfig.analyticsAPI,
|
||||
analyticsAPI: envConfig?.analyticsAPI,
|
||||
referralAPI: envConfig.referralAPI,
|
||||
networks: Object.entries(envConfig.networks).map(([chainId, networkConfig]) => {
|
||||
if (!isValidChainId(chainId)) throw new Error(`Invalid chainId: ${chainId}`);
|
||||
@@ -92,7 +97,7 @@ export default class Orion {
|
||||
// api: networkConfig.api,
|
||||
nodeJsonRpc: networkConfig.nodeJsonRpc,
|
||||
services: networkConfig.services,
|
||||
});
|
||||
}, logger);
|
||||
return {
|
||||
...acc,
|
||||
[chainId]: unit,
|
||||
|
||||
@@ -397,7 +397,7 @@ async function shouldUseExchangeBalance(
|
||||
let useExchangeBalance = true;
|
||||
let additionalTransferAmount = 0n;
|
||||
|
||||
if (exchangeBalance == 0n) {
|
||||
if (walletBalance >= amount || exchangeBalance == 0n) {
|
||||
useExchangeBalance = false;
|
||||
additionalTransferAmount = amount;
|
||||
} else {
|
||||
|
||||
@@ -41,7 +41,10 @@ export default class Unit {
|
||||
|
||||
public readonly contracts: Record<string, string>;
|
||||
|
||||
constructor(config: KnownConfig | VerboseUnitConfig) {
|
||||
public logger: ((message: string) => void) | undefined;
|
||||
|
||||
constructor(config: KnownConfig | VerboseUnitConfig, logger?: ((message: string) => void) | undefined) {
|
||||
this.logger = logger;
|
||||
if ('env' in config) {
|
||||
const staticConfig = envs[config.env];
|
||||
if (!staticConfig) {
|
||||
@@ -118,7 +121,8 @@ export default class Unit {
|
||||
this.aggregator = new Aggregator(
|
||||
this.config.services.aggregator.http,
|
||||
this.config.services.aggregator.ws,
|
||||
this.config.basicAuth
|
||||
this.config.basicAuth,
|
||||
logger,
|
||||
);
|
||||
this.priceFeed = new PriceFeed(
|
||||
this.config.services.priceFeed.api,
|
||||
|
||||
@@ -219,5 +219,18 @@
|
||||
"WETH": "0xe5d7c2a44ffddf6b295a15c148167daaaf5cf34f",
|
||||
"curveRegistry": ""
|
||||
}
|
||||
},
|
||||
"43114": {
|
||||
"chainId": "43114",
|
||||
"label": "Avalanche Network",
|
||||
"shortName": "Avax",
|
||||
"code": "avax",
|
||||
"baseCurrencyName": "AVAX",
|
||||
"rpc": "https://api.avax.network/ext/bc/C/rpc/",
|
||||
"explorer": "https://snowtrace.io/",
|
||||
"contracts": {
|
||||
"WETH": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
|
||||
"curveRegistry": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"production": {
|
||||
"analyticsAPI": "https://trade.orion.xyz/api/stats",
|
||||
"referralAPI": "https://trade.orion.xyz/referral-api",
|
||||
"networks": {
|
||||
"1": {
|
||||
@@ -165,11 +164,28 @@
|
||||
"http": "/orion-indexer/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"43114": {
|
||||
"api": "https://trade.orion.xyz/avalanche-c-chain",
|
||||
"services": {
|
||||
"aggregator": {
|
||||
"http": "/backend",
|
||||
"ws": "/v1"
|
||||
},
|
||||
"blockchain": {
|
||||
"http": ""
|
||||
},
|
||||
"priceFeed": {
|
||||
"all": "/price-feed"
|
||||
},
|
||||
"indexer": {
|
||||
"http": "/orion-indexer/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"testing": {
|
||||
"analyticsAPI": "https://trade.orion.xyz/api/stats",
|
||||
"referralAPI": "https://testing.orion.xyz/referral-api",
|
||||
"networks": {
|
||||
"97": {
|
||||
@@ -284,7 +300,6 @@
|
||||
}
|
||||
},
|
||||
"staging": {
|
||||
"analyticsAPI": "https://trade.orion.xyz/api/stats",
|
||||
"referralAPI": "https://staging.orion.xyz/referral-api",
|
||||
"networks": {
|
||||
"1": {
|
||||
@@ -448,11 +463,28 @@
|
||||
"http": "/orion-indexer/"
|
||||
}
|
||||
}
|
||||
},
|
||||
"43114": {
|
||||
"api": "https://trade.orion.xyz/avalanche-c-chain",
|
||||
"services": {
|
||||
"aggregator": {
|
||||
"http": "/backend",
|
||||
"ws": "/v1"
|
||||
},
|
||||
"blockchain": {
|
||||
"http": ""
|
||||
},
|
||||
"priceFeed": {
|
||||
"all": "/price-feed"
|
||||
},
|
||||
"indexer": {
|
||||
"http": "/orion-indexer/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"experimental": {
|
||||
"analyticsAPI": "https://trade.orion.xyz/api/stats",
|
||||
"referralAPI": "https://testing.orion.xyz/referral-api",
|
||||
"networks": {
|
||||
"97": {
|
||||
@@ -494,7 +526,6 @@
|
||||
}
|
||||
},
|
||||
"kucoin-production": {
|
||||
"analyticsAPI": "https://trade.orion.xyz/api/stats",
|
||||
"referralAPI": "https://trade.orion.xyz/referral-api",
|
||||
"networks": {
|
||||
"1": {
|
||||
|
||||
@@ -23,7 +23,7 @@ export const pureEnvNetworksSchema = z.object({
|
||||
});
|
||||
|
||||
export const pureEnvPayloadSchema = z.object({
|
||||
analyticsAPI: z.string().url(),
|
||||
analyticsAPI: z.string().url().optional(),
|
||||
referralAPI: z.string().url(),
|
||||
networks: z.record(
|
||||
z.nativeEnum(SupportedChainId),
|
||||
|
||||
@@ -19,4 +19,5 @@ export const productionChains = [
|
||||
SupportedChainId.OPBNB,
|
||||
SupportedChainId.INEVM,
|
||||
SupportedChainId.LINEA,
|
||||
SupportedChainId.AVAX,
|
||||
];
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default ['ftm', 'bsc', 'eth', 'polygon', 'okc', 'arb', 'drip', 'opbnb', 'inevm', 'linea'] as const;
|
||||
export default ['ftm', 'bsc', 'eth', 'polygon', 'okc', 'arb', 'drip', 'opbnb', 'inevm', 'linea', 'avax'] as const;
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default ['FTM', 'BSC', 'ETH', 'POLYGON', 'OKC', 'ARB', 'OPBNB', 'INEVM', 'LINEA'] as const;
|
||||
export default ['FTM', 'BSC', 'ETH', 'POLYGON', 'OKC', 'ARB', 'OPBNB', 'INEVM', 'LINEA', 'AVAX'] as const;
|
||||
|
||||
@@ -35,11 +35,16 @@ class Aggregator {
|
||||
return this.apiUrl;
|
||||
}
|
||||
|
||||
public logger: ((message: string) => void) | undefined;
|
||||
|
||||
constructor(
|
||||
httpAPIUrl: string,
|
||||
wsAPIUrl: string,
|
||||
basicAuth?: BasicAuthCredentials
|
||||
basicAuth?: BasicAuthCredentials,
|
||||
logger?: ((message: string) => void) | undefined
|
||||
) {
|
||||
this.logger = logger;
|
||||
|
||||
// const oaUrl = new URL(apiUrl);
|
||||
// const oaWsProtocol = oaUrl.protocol === 'https:' ? 'wss' : 'ws';
|
||||
// const aggregatorWsUrl = `${oaWsProtocol}://${oaUrl.host + (oaUrl.pathname === '/'
|
||||
@@ -47,7 +52,7 @@ class Aggregator {
|
||||
// : oaUrl.pathname)}/v1`;
|
||||
|
||||
this.apiUrl = httpAPIUrl;
|
||||
this.ws = new AggregatorWS(httpToWS(wsAPIUrl));
|
||||
this.ws = new AggregatorWS(httpToWS(wsAPIUrl), undefined, logger);
|
||||
this.basicAuth = basicAuth;
|
||||
|
||||
this.getHistoryAtomicSwaps = this.getHistoryAtomicSwaps.bind(this);
|
||||
@@ -374,8 +379,7 @@ class Aggregator {
|
||||
return fetchWithValidation(url.toString(), atomicSwapHistorySchema, { headers: this.basicAuthHeaders });
|
||||
};
|
||||
|
||||
|
||||
private encode_utf8(s : string) {
|
||||
private encode_utf8(s: string) {
|
||||
return unescape(encodeURIComponent(s));
|
||||
}
|
||||
|
||||
@@ -385,12 +389,12 @@ class Aggregator {
|
||||
.digest('hex');
|
||||
}
|
||||
|
||||
private generateHeaders(body : any, method : string, path : string, timestamp : number, apiKey : string, secretKey : string) {
|
||||
private generateHeaders(body: any, method: string, path: string, timestamp: number, apiKey: string, secretKey: string) {
|
||||
const sortedBody = Object.keys(body)
|
||||
.sort()
|
||||
.map((key) => (
|
||||
`${key}=${body[key]}`
|
||||
)).join('&');
|
||||
.sort()
|
||||
.map((key) => (
|
||||
`${key}=${body[key]}`
|
||||
)).join('&');
|
||||
|
||||
const payload = timestamp + method.toUpperCase() + path + sortedBody;
|
||||
|
||||
@@ -407,40 +411,38 @@ class Aggregator {
|
||||
}
|
||||
|
||||
public async RFQOrder(
|
||||
tokenFrom: string,
|
||||
tokenTo: string,
|
||||
fromTokenAmount: string,
|
||||
apiKey: string, //
|
||||
secretKey: string,
|
||||
wallet: string
|
||||
) : Promise<z.infer<typeof pmmOrderSchema>> {
|
||||
|
||||
tokenFrom: string,
|
||||
tokenTo: string,
|
||||
fromTokenAmount: string,
|
||||
apiKey: string, //
|
||||
secretKey: string,
|
||||
wallet: string
|
||||
): Promise<z.infer<typeof pmmOrderSchema>> {
|
||||
// Making the order structure
|
||||
const
|
||||
path = '/rfq'
|
||||
, url = `${this.apiUrl}/api/v1/integration/pmm`+path
|
||||
, headers = {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
, data = {
|
||||
"baseToken":tokenFrom, // USDT
|
||||
"quoteToken":tokenTo, // ORN
|
||||
"amount": fromTokenAmount, // 100
|
||||
"taker": wallet,
|
||||
"feeBps": 0
|
||||
}
|
||||
, method = 'POST'
|
||||
, timestamp = Date.now()
|
||||
, signatureHeaders = this.generateHeaders(data, method, path, timestamp, apiKey, secretKey)
|
||||
, compiledHeaders = {...headers, ...signatureHeaders.headers, }
|
||||
, body = JSON.stringify(data)
|
||||
path = '/rfq';
|
||||
const url = `${this.apiUrl}/api/v1/integration/pmm` + path;
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
const data = {
|
||||
baseToken: tokenFrom, // USDT
|
||||
quoteToken: tokenTo, // ORN
|
||||
amount: fromTokenAmount, // 100
|
||||
taker: wallet,
|
||||
feeBps: 0
|
||||
};
|
||||
const method = 'POST';
|
||||
const timestamp = Date.now();
|
||||
const signatureHeaders = this.generateHeaders(data, method, path, timestamp, apiKey, secretKey);
|
||||
const compiledHeaders = { ...headers, ...signatureHeaders.headers, };
|
||||
const body = JSON.stringify(data)
|
||||
;
|
||||
|
||||
|
||||
let res = pmmOrderSchema.parse({});
|
||||
const res = pmmOrderSchema.parse({});
|
||||
|
||||
try {
|
||||
const result = await fetch(url,{
|
||||
const result = await fetch(url, {
|
||||
headers: compiledHeaders,
|
||||
method,
|
||||
body
|
||||
@@ -449,14 +451,13 @@ class Aggregator {
|
||||
const json = await result.json();
|
||||
const parseResult = pmmOrderSchema.safeParse(json);
|
||||
|
||||
if(!parseResult.success) {
|
||||
if (!parseResult.success) {
|
||||
// Try to parse error answer
|
||||
const errorSchema = z.object({error: z.object({code: z.number(), reason: z.string()})});
|
||||
const errorSchema = z.object({ error: z.object({ code: z.number(), reason: z.string() }) });
|
||||
|
||||
const errorParseResult = errorSchema.safeParse(json);
|
||||
|
||||
if(!errorParseResult.success)
|
||||
throw Error(`Unrecognized answer from aggregator: ${json}`);
|
||||
if (!errorParseResult.success) { throw Error(`Unrecognized answer from aggregator: ${json}`); }
|
||||
|
||||
throw Error(errorParseResult.data.error.reason);
|
||||
}
|
||||
@@ -465,8 +466,8 @@ class Aggregator {
|
||||
res.signature = parseResult.data.signature;
|
||||
res.error = '';
|
||||
res.success = true;
|
||||
}
|
||||
catch(err) {
|
||||
// return result;
|
||||
} catch (err) {
|
||||
res.error = `${err}`;
|
||||
}
|
||||
return res;
|
||||
|
||||
@@ -66,10 +66,11 @@ type PairConfigSubscription = {
|
||||
|
||||
type AggregatedOrderbookSubscription = {
|
||||
payload: string
|
||||
dc?: number
|
||||
callback: (
|
||||
asks: OrderbookItem[],
|
||||
bids: OrderbookItem[],
|
||||
pair: string
|
||||
pair: string,
|
||||
) => void
|
||||
errorCb?: (message: string) => void
|
||||
}
|
||||
@@ -195,9 +196,10 @@ class AggregatorWS {
|
||||
|
||||
readonly basicAuth?: BasicAuthCredentials | undefined;
|
||||
|
||||
constructor(wsUrl: string, basicAuth?: BasicAuthCredentials) {
|
||||
constructor(wsUrl: string, basicAuth?: BasicAuthCredentials, logger?: ((message: string) => void) | undefined) {
|
||||
this.wsUrl = wsUrl;
|
||||
this.basicAuth = basicAuth;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
private messageQueue: BufferLike[] = [];
|
||||
@@ -252,7 +254,7 @@ class AggregatorWS {
|
||||
subscription: Subscription[T],
|
||||
prevSubscriptionId?: string
|
||||
) {
|
||||
const id = type === 'aobus'
|
||||
const id = type === SubscriptionType.AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE
|
||||
? ((subscription as any).payload as string) // TODO: Refactor!!!
|
||||
: uuidv4();
|
||||
|
||||
@@ -262,6 +264,12 @@ class AggregatorWS {
|
||||
subRequest['T'] = type;
|
||||
subRequest['id'] = id;
|
||||
|
||||
if ('dc' in subscription) {
|
||||
if (typeof subscription.dc === 'number') {
|
||||
subRequest['dc'] = subscription.dc;
|
||||
}
|
||||
}
|
||||
|
||||
if ('payload' in subscription) {
|
||||
if (typeof subscription.payload === 'string') {
|
||||
subRequest['S'] = subscription.payload;
|
||||
@@ -369,11 +377,11 @@ class AggregatorWS {
|
||||
delete this.subscriptions[SubscriptionType.ASSET_PAIR_CONFIG_UPDATES_SUBSCRIBE]?.[newestSubId];
|
||||
// !!! swap info subscription is uuid that contains hyphen
|
||||
} else if (isOrderBooksSubscription(newestSubId)) { // is pair name(AGGREGATED_ORDER_BOOK_UPDATE)
|
||||
const aobSubscriptions = this.subscriptions[SubscriptionType.AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE];
|
||||
if (aobSubscriptions) {
|
||||
const targetAobSub = Object.entries(aobSubscriptions).find(([, value]) => value?.payload === newestSubId);
|
||||
if (targetAobSub) {
|
||||
const [key] = targetAobSub;
|
||||
const aobusSubscriptions = this.subscriptions[SubscriptionType.AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE];
|
||||
if (aobusSubscriptions) {
|
||||
const targetAobusSub = Object.entries(aobusSubscriptions).find(([, value]) => value?.payload === newestSubId);
|
||||
if (targetAobusSub) {
|
||||
const [key] = targetAobusSub;
|
||||
delete this.subscriptions[SubscriptionType.AGGREGATED_ORDER_BOOK_UPDATES_SUBSCRIBE]?.[key];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +114,7 @@ class BlockchainService {
|
||||
this.getRedeemOrderBySecretHash = this.getRedeemOrderBySecretHash.bind(this);
|
||||
this.claimOrder = this.claimOrder.bind(this);
|
||||
this.getGasLimits = this.getGasLimits.bind(this);
|
||||
this.getExchangeContractWalletBalance = this.getExchangeContractWalletBalance.bind(this);
|
||||
}
|
||||
|
||||
get basicAuthHeaders() {
|
||||
@@ -495,6 +496,12 @@ class BlockchainService {
|
||||
z.record(z.number()),
|
||||
{ headers: this.basicAuthHeaders }
|
||||
);
|
||||
|
||||
getExchangeContractWalletBalance = (exchangeContractAddress: string) => fetchWithValidation(
|
||||
`${this.apiUrl}/api/broker/getWalletBalance/${exchangeContractAddress}`,
|
||||
z.record(z.string()),
|
||||
{ headers: this.basicAuthHeaders }
|
||||
);
|
||||
}
|
||||
|
||||
export * as schemas from './schemas/index.js';
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
PoolV2InfoResponseSchema,
|
||||
testIncrementorSchema,
|
||||
veORNInfoResponseSchema,
|
||||
votingInfoResponseSchema
|
||||
votingInfoResponseSchema,
|
||||
} from './schemas';
|
||||
import { fetchWithValidation } from 'simple-typed-fetch';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
@@ -94,6 +94,7 @@ class IndexerService {
|
||||
this.veORNInfo = this.veORNInfo.bind(this);
|
||||
this.listAmount = this.listAmount.bind(this);
|
||||
this.getAmountByORN = this.getAmountByORN.bind(this);
|
||||
this.getAmountAt = this.getAmountAt.bind(this);
|
||||
this.getAmountAtCurrent = this.getAmountAtCurrent.bind(this);
|
||||
this.getVotingInfo = this.getVotingInfo.bind(this);
|
||||
}
|
||||
@@ -117,6 +118,23 @@ class IndexerService {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} amount - amount
|
||||
* @param {number} [timestamp = Date.now()] - timestamp, defaults to current time
|
||||
*/
|
||||
readonly getAmountAt = (
|
||||
amount: number,
|
||||
timestamp = Date.now()
|
||||
): BigNumber => {
|
||||
const finalTimestamp = timestamp / 1000;
|
||||
|
||||
// sqrt
|
||||
return BigNumber(amount).dividedBy(this.getK(finalTimestamp));
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated since version 69 in favor of getAmountAt
|
||||
*/
|
||||
readonly getAmountAtCurrent = (amount: number): BigNumber => {
|
||||
const timestamp = Date.now() / 1000;
|
||||
|
||||
@@ -134,8 +152,7 @@ class IndexerService {
|
||||
const multSQRT = deltaDaysBN.dividedBy(WEEK_DAYS).sqrt();
|
||||
const multCUBE = deltaDaysBN.dividedBy(alpha).pow(3);
|
||||
|
||||
return BigNumber(amountToken)
|
||||
.multipliedBy(multSQRT.plus(multCUBE));
|
||||
return BigNumber(amountToken).multipliedBy(multSQRT.plus(multCUBE));
|
||||
};
|
||||
|
||||
readonly getVotingInfo = (userAddress?: string) => {
|
||||
@@ -208,7 +225,11 @@ class IndexerService {
|
||||
});
|
||||
};
|
||||
|
||||
readonly poolV2Info = (token0: string, token1: string, address: string | undefined) => {
|
||||
readonly poolV2Info = (
|
||||
token0: string,
|
||||
token1: string,
|
||||
address: string | undefined
|
||||
) => {
|
||||
return fetchWithValidation(this.apiUrl, PoolV2InfoResponseSchema, {
|
||||
method: 'POST',
|
||||
body: this.makeRPCPayload({
|
||||
|
||||
@@ -90,6 +90,7 @@ export enum SupportedChainId {
|
||||
OPBNB = '204',
|
||||
INEVM = '2525',
|
||||
LINEA = '59144',
|
||||
AVAX = '43114',
|
||||
|
||||
POLYGON_TESTNET = '80001',
|
||||
FANTOM_TESTNET = '4002',
|
||||
@@ -279,7 +280,7 @@ export type KnownEnv = typeof knownEnvs[number];
|
||||
export type Json = string | number | boolean | null | Json[] | { [key: string]: Json };
|
||||
|
||||
export type EnvConfig = {
|
||||
analyticsAPI: string
|
||||
analyticsAPI: string | undefined
|
||||
referralAPI: string
|
||||
networks: Partial<
|
||||
Record<
|
||||
|
||||
Reference in New Issue
Block a user