diff --git a/package-lock.json b/package-lock.json index 9cc7fbb..9e4bc27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@orionprotocol/sdk", - "version": "0.20.73", + "version": "0.20.79", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@orionprotocol/sdk", - "version": "0.20.73", + "version": "0.20.79", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index ee8c258..b9093ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.20.78", + "version": "0.20.80-rc3", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", diff --git a/src/Orion/index.ts b/src/Orion/index.ts index 7245c00..8ddf534 100644 --- a/src/Orion/index.ts +++ b/src/Orion/index.ts @@ -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 + overrides?: DeepPartial, + logger?: ((message: string) => void) | undefined ) { + this.logger = logger; + let config: EnvConfig; if (typeof envOrConfig === 'string') { const envConfig = envs[envOrConfig]; @@ -92,7 +97,7 @@ export default class Orion { // api: networkConfig.api, nodeJsonRpc: networkConfig.nodeJsonRpc, services: networkConfig.services, - }); + }, logger); return { ...acc, [chainId]: unit, diff --git a/src/Unit/index.ts b/src/Unit/index.ts index 85d7052..9b504cc 100644 --- a/src/Unit/index.ts +++ b/src/Unit/index.ts @@ -41,7 +41,10 @@ export default class Unit { public readonly contracts: Record; - 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, diff --git a/src/services/Aggregator/index.ts b/src/services/Aggregator/index.ts index f04e4c5..2cbc6c5 100644 --- a/src/services/Aggregator/index.ts +++ b/src/services/Aggregator/index.ts @@ -19,9 +19,9 @@ import httpToWS from '../../utils/httpToWS.js'; import { ethers } from 'ethers'; import orderSchema from './schemas/orderSchema.js'; import { fetchWithValidation } from 'simple-typed-fetch'; -import hmacSHA256 from "crypto-js/hmac-sha256"; -import Hex from "crypto-js/enc-hex"; -import {pmmOrderSchema} from "../../Unit/Pmm/schemas/order"; +import hmacSHA256 from 'crypto-js/hmac-sha256'; +import Hex from 'crypto-js/enc-hex'; +import { pmmOrderSchema } from '../../Unit/Pmm/schemas/order'; class Aggregator { private readonly apiUrl: string; @@ -34,11 +34,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 === '/' @@ -46,7 +51,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); @@ -373,24 +378,23 @@ class Aggregator { return fetchWithValidation(url.toString(), atomicSwapHistorySchema, { headers: this.basicAuthHeaders }); }; - - private encode_utf8(s : string) { + private encode_utf8(s: string) { return unescape(encodeURIComponent(s)); } - private sign(message : string, key: string) { + private sign(message: string, key: string) { return hmacSHA256( - this.encode_utf8(message), - this.encode_utf8(key) + this.encode_utf8(message), + this.encode_utf8(key) ).toString(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> { - + tokenFrom: string, + tokenTo: string, + fromTokenAmount: string, + apiKey: string, // + secretKey: string, + wallet: string + ): Promise> { // 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); } @@ -466,8 +467,7 @@ class Aggregator { res.error = ''; res.success = true; // return result; - } - catch(err) { + } catch (err) { res.error = `${err}`; } return res; diff --git a/src/services/Aggregator/ws/index.ts b/src/services/Aggregator/ws/index.ts index 69d214c..f0f0e8f 100644 --- a/src/services/Aggregator/ws/index.ts +++ b/src/services/Aggregator/ws/index.ts @@ -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]; } }