diff --git a/package.json b/package.json index f993685..c679120 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@orionprotocol/sdk", - "version": "0.19.27", + "version": "0.19.28-rc1", "description": "Orion Protocol SDK", "main": "./lib/index.cjs", "module": "./lib/index.js", diff --git a/src/Unit/index.ts b/src/Unit/index.ts index 6fcd0a6..b9fb66c 100644 --- a/src/Unit/index.ts +++ b/src/Unit/index.ts @@ -72,12 +72,13 @@ export default class Unit { this.provider = new ethers.providers.StaticJsonRpcProvider(this.config.nodeJsonRpc, intNetwork); this.provider.pollingInterval = 1000; - this.blockchainService = new BlockchainService(this.config.services.blockchainService.http); + this.blockchainService = new BlockchainService(this.config.services.blockchainService.http, this.config.basicAuth); this.aggregator = new Aggregator( this.config.services.aggregator.http, this.config.services.aggregator.ws, + this.config.basicAuth, ); - this.priceFeed = new PriceFeed(this.config.services.priceFeed.api); + this.priceFeed = new PriceFeed(this.config.services.priceFeed.api, this.config.basicAuth); this.exchange = new Exchange(this); this.farmingManager = new FarmingManager(this); } diff --git a/src/services/Aggregator/index.ts b/src/services/Aggregator/index.ts index 7c504ea..f4858e8 100644 --- a/src/services/Aggregator/index.ts +++ b/src/services/Aggregator/index.ts @@ -8,7 +8,7 @@ import errorSchema from './schemas/errorSchema.js'; import placeAtomicSwapSchema from './schemas/placeAtomicSwapSchema.js'; import { AggregatorWS } from './ws/index.js'; import { atomicSwapHistorySchema } from './schemas/atomicSwapHistorySchema.js'; -import type { Exchange, SignedCancelOrderRequest, SignedCFDOrder, SignedOrder } from '../../types.js'; +import type { BasicAuthCredentials, Exchange, SignedCancelOrderRequest, SignedCFDOrder, SignedOrder } from '../../types.js'; import { pairConfigSchema } from './schemas/index.js'; import { aggregatedOrderbookSchema, exchangeOrderbookSchema, poolReservesSchema, @@ -26,6 +26,8 @@ class Aggregator { readonly ws: AggregatorWS; + private readonly basicAuth?: BasicAuthCredentials | undefined; + get api() { return this.apiUrl; } @@ -33,6 +35,7 @@ class Aggregator { constructor( httpAPIUrl: string, wsAPIUrl: string, + basicAuth?: BasicAuthCredentials ) { // const oaUrl = new URL(apiUrl); // const oaWsProtocol = oaUrl.protocol === 'https:' ? 'wss' : 'ws'; @@ -42,6 +45,7 @@ class Aggregator { this.apiUrl = httpAPIUrl; this.ws = new AggregatorWS(httpToWS(wsAPIUrl)); + this.basicAuth = basicAuth; this.getHistoryAtomicSwaps = this.getHistoryAtomicSwaps.bind(this); this.getPairConfig = this.getPairConfig.bind(this); @@ -61,6 +65,15 @@ class Aggregator { this.getVersion = this.getVersion.bind(this); } + get basicAuthHeaders() { + if (this.basicAuth) { + return { + Authorization: `Basic ${btoa(`${this.basicAuth.username}:${this.basicAuth.password}`)}`, + }; + } + return {}; + } + getOrder = (orderId: string, owner?: string) => { if (!ethers.utils.isHexString(orderId)) { throw new Error(`Invalid order id: ${orderId}. Must be a hex string`); @@ -76,7 +89,7 @@ class Aggregator { return fetchWithValidation( url.toString(), orderSchema, - undefined, + { headers: this.basicAuthHeaders }, errorSchema, ); } @@ -88,6 +101,7 @@ class Aggregator { return fetchWithValidation( url.toString(), z.array(z.string().toUpperCase()), + { headers: this.basicAuthHeaders }, ); }; @@ -98,7 +112,7 @@ class Aggregator { return fetchWithValidation( url.toString(), aggregatedOrderbookSchema, - undefined, + { headers: this.basicAuthHeaders }, errorSchema, ); }; @@ -123,7 +137,7 @@ class Aggregator { return fetchWithValidation( url.toString(), exchangeOrderbookSchema, - undefined, + { headers: this.basicAuthHeaders }, errorSchema, ); }; @@ -135,7 +149,7 @@ class Aggregator { return fetchWithValidation( url.toString(), exchangeInfoSchema, - undefined, + { headers: this.basicAuthHeaders }, errorSchema, ); } @@ -148,7 +162,7 @@ class Aggregator { return fetchWithValidation( url.toString(), poolReservesSchema, - undefined, + { headers: this.basicAuthHeaders }, errorSchema, ); }; @@ -160,21 +174,21 @@ class Aggregator { version: z.string(), apiVersion: z.string(), }), - undefined, + { headers: this.basicAuthHeaders }, errorSchema, ); getPairConfig = (assetPair: string) => fetchWithValidation( `${this.apiUrl}/api/v1/pairs/exchangeInfo/${assetPair}`, pairConfigSchema, - undefined, + { headers: this.basicAuthHeaders }, errorSchema, ); checkWhitelisted = (address: string) => fetchWithValidation( `${this.apiUrl}/api/v1/whitelist/check?address=${address}`, z.boolean(), - undefined, + { headers: this.basicAuthHeaders }, errorSchema, ); @@ -191,6 +205,7 @@ class Aggregator { 'X-Reverse-Order': isReversedOrder ? 'true' : 'false', }, ...(partnerId !== undefined) && { 'X-Partner-Id': partnerId }, + ...this.basicAuthHeaders, }; const url = new URL(`${this.apiUrl}/api/v1/order/${isCreateInternalOrder ? 'internal' : ''}`); @@ -224,6 +239,7 @@ class Aggregator { headers: { 'Content-Type': 'application/json', Accept: 'application/json', + ...this.basicAuthHeaders, }, body: JSON.stringify({ ...signedCancelOrderRequest, @@ -243,6 +259,7 @@ class Aggregator { ...(isReversedOrder !== undefined) && { 'X-Reverse-Order': isReversedOrder ? 'true' : 'false', }, + ...this.basicAuthHeaders, }; return fetchWithValidation( @@ -298,7 +315,7 @@ class Aggregator { return fetchWithValidation( url.toString(), swapInfoSchema, - undefined, + { headers: this.basicAuthHeaders }, errorSchema, ); }; @@ -311,7 +328,7 @@ class Aggregator { z.object({ [currency]: z.number(), }).partial(), - undefined, + { headers: this.basicAuthHeaders }, errorSchema, ); }; @@ -329,7 +346,7 @@ class Aggregator { return fetchWithValidation( url.toString(), orderBenefitsSchema, - undefined, + { headers: this.basicAuthHeaders }, errorSchema, ); }; @@ -350,6 +367,7 @@ class Aggregator { headers: { 'Content-Type': 'application/json', Accept: 'application/json', + ...this.basicAuthHeaders, }, method: 'POST', body: JSON.stringify({ @@ -369,7 +387,7 @@ class Aggregator { const url = new URL(`${this.apiUrl}/api/v1/atomic-swap/history/all`); url.searchParams.append('sender', sender); url.searchParams.append('limit', limit.toString()); - return fetchWithValidation(url.toString(), atomicSwapHistorySchema); + return fetchWithValidation(url.toString(), atomicSwapHistorySchema, { headers: this.basicAuthHeaders }); }; } export * as schemas from './schemas/index.js'; diff --git a/src/services/Aggregator/ws/index.ts b/src/services/Aggregator/ws/index.ts index 1b83aba..363cf98 100644 --- a/src/services/Aggregator/ws/index.ts +++ b/src/services/Aggregator/ws/index.ts @@ -11,7 +11,7 @@ import { import UnsubscriptionType from './UnsubscriptionType.js'; import type { SwapInfoBase, AssetPairUpdate, OrderbookItem, - Balance, Exchange, CFDBalance, FuturesTradeInfo, SwapInfo, Json, + Balance, Exchange, CFDBalance, FuturesTradeInfo, SwapInfo, Json, BasicAuthCredentials, } from '../../../types.js'; import unsubscriptionDoneSchema from './schemas/unsubscriptionDoneSchema.js'; import assetPairConfigSchema from './schemas/assetPairConfigSchema.js'; @@ -221,13 +221,23 @@ class AggregatorWS { private isAlive = false; get api() { - return this.wsUrl; + const wsUrl = new URL(this.wsUrl); + + if (this.basicAuth) { + wsUrl.username = this.basicAuth.username; + wsUrl.password = this.basicAuth.password; + } + + return wsUrl; } readonly instanceId = uuidv4(); - constructor(wsUrl: string) { + readonly basicAuth?: BasicAuthCredentials | undefined; + + constructor(wsUrl: string, basicAuth?: BasicAuthCredentials) { this.wsUrl = wsUrl; + this.basicAuth = basicAuth; } private messageQueue: BufferLike[] = []; @@ -447,7 +457,7 @@ class AggregatorWS { private init(isReconnect = false) { this.isClosedIntentionally = false; - this.ws = new WebSocket(this.wsUrl); + this.ws = new WebSocket(this.api); this.ws.onerror = (err) => { this.onError?.(`AggregatorWS error: ${err.message}`); this.logger?.(`AggregatorWS: ${err.message}`); diff --git a/src/services/BlockchainService/index.ts b/src/services/BlockchainService/index.ts index 8a48ab9..06ce1fa 100644 --- a/src/services/BlockchainService/index.ts +++ b/src/services/BlockchainService/index.ts @@ -21,6 +21,7 @@ import { sourceAtomicHistorySchema, targetAtomicHistorySchema } from './schemas/ import { makePartial } from '../../utils/index.js'; import type { networkCodes } from '../../constants/index.js'; import { fetchWithValidation } from 'simple-typed-fetch'; +import type { BasicAuthCredentials } from '../../types.js'; type IAdminAuthHeaders = { auth: string @@ -67,12 +68,15 @@ type CfdHistoryQuery = { class BlockchainService { private readonly apiUrl: string; + private readonly basicAuth?: BasicAuthCredentials | undefined; + get api() { return this.apiUrl; } - constructor(apiUrl: string) { + constructor(apiUrl: string, basicAuth?: BasicAuthCredentials) { this.apiUrl = apiUrl; + this.basicAuth = basicAuth; this.getAtomicSwapAssets = this.getAtomicSwapAssets.bind(this); this.getAtomicSwapHistory = this.getAtomicSwapHistory.bind(this); @@ -114,6 +118,15 @@ class BlockchainService { this.getGovernanceChainsInfo = this.getGovernanceChainsInfo.bind(this); } + get basicAuthHeaders() { + if (this.basicAuth) { + return { + Authorization: `Basic ${btoa(`${this.basicAuth.username}:${this.basicAuth.password}`)}`, + }; + } + return {}; + } + get blockchainServiceWsUrl() { return `${this.apiUrl}/`; } @@ -129,17 +142,20 @@ class BlockchainService { return fetchWithValidation( url.toString(), atomicSummarySchema, + { headers: this.basicAuthHeaders } ); }; private readonly getSummaryClaim = (brokerAddress: string) => fetchWithValidation( `${this.apiUrl}/api/atomic/summary-claim/${brokerAddress}`, atomicSummarySchema, + { headers: this.basicAuthHeaders }, ); private readonly getQueueLength = () => fetchWithValidation( `${this.apiUrl}/api/queueLength`, z.number().int(), + { headers: this.basicAuthHeaders }, ); get internal() { @@ -153,11 +169,13 @@ class BlockchainService { getAuthToken = () => fetchWithValidation( `${this.apiUrl}/api/auth/token`, z.object({ token: z.string() }), + { headers: this.basicAuthHeaders } ); getCirculatingSupply = () => fetchWithValidation( `${this.apiUrl}/api/circulating-supply`, z.number(), + { headers: this.basicAuthHeaders } ); getInfo = () => fetchWithValidation(`${this.apiUrl}/api/info`, infoSchema); @@ -165,56 +183,67 @@ class BlockchainService { getPoolsConfig = () => fetchWithValidation( `${this.apiUrl}/api/pools/config`, poolsConfigSchema, + { headers: this.basicAuthHeaders } ); getPoolsInfo = () => fetchWithValidation( `${this.apiUrl}/api/pools/info`, poolsInfoSchema, + { headers: this.basicAuthHeaders } ); getPoolsLpAndStaked = (address: string) => fetchWithValidation( `${this.apiUrl}/api/pools/user-lp/${address}`, poolsLpAndStakedSchema, + { headers: this.basicAuthHeaders } ); getUserVotes = (address: string) => fetchWithValidation( `${this.apiUrl}/api/pools/user-votes/${address}`, userVotesSchema, + { headers: this.basicAuthHeaders } ); getUserEarned = (address: string) => fetchWithValidation( `${this.apiUrl}/api/pools/user-earned/${address}`, userEarnedSchema, + { headers: this.basicAuthHeaders } ); getHistory = (address: string) => fetchWithValidation( `${this.apiUrl}/api/history/${address}`, historySchema, + { headers: this.basicAuthHeaders } ); getPrices = () => fetchWithValidation( `${this.apiUrl}/api/prices`, z.record(z.string()).transform(makePartial), + { headers: this.basicAuthHeaders } ); getCFDPrices = () => fetchWithValidation( `${this.apiUrl}/api/cfd/prices`, z.record(z.string()).transform(makePartial), + { headers: this.basicAuthHeaders } ); getTokensFee = () => fetchWithValidation( `${this.apiUrl}/api/tokensFee`, z.record(z.string()).transform(makePartial), + { headers: this.basicAuthHeaders } ); getGasPriceWei = () => fetchWithValidation( `${this.apiUrl}/api/gasPrice`, z.string(), + { headers: this.basicAuthHeaders } ); checkFreeRedeemAvailable = (walletAddress: string) => fetchWithValidation( `${this.apiUrl}/api/atomic/has-free-redeem/${walletAddress}`, z.boolean(), + { headers: this.basicAuthHeaders } ); getRedeemOrderBySecretHash = (secretHash: string) => fetchWithValidation( @@ -224,6 +253,7 @@ class BlockchainService { secret: z.string(), redeemTxHash: z.string(), }), + { headers: this.basicAuthHeaders } ); claimOrder = ( @@ -242,6 +272,7 @@ class BlockchainService { }), headers: { 'Content-Type': 'application/json', + ...this.basicAuthHeaders, }, }, ); @@ -262,6 +293,7 @@ class BlockchainService { }), headers: { 'Content-Type': 'application/json', + ...this.basicAuthHeaders, }, }, ); @@ -286,6 +318,7 @@ class BlockchainService { }), headers: { 'Content-Type': 'application/json', + ...this.basicAuthHeaders, }, }, ); @@ -293,31 +326,33 @@ class BlockchainService { checkRedeem = (secretHash: string) => fetchWithValidation( `${this.apiUrl}/api/atomic/matcher-redeem/${secretHash}`, z.enum(['OK', 'FAIL']).nullable(), + { headers: this.basicAuthHeaders } ); checkRedeem2Atomics = (firstSecretHash: string, secondSecretHash: string) => fetchWithValidation( `${this.apiUrl}/api/atomic/matcher-redeem/${firstSecretHash}-${secondSecretHash}`, z.enum(['OK', 'FAIL']).nullable(), + { headers: this.basicAuthHeaders } ); - getBlockNumber = () => fetchWithValidation(`${this.apiUrl}/api/blocknumber`, z.number().int()); + getBlockNumber = () => fetchWithValidation(`${this.apiUrl}/api/blocknumber`, z.number().int(), { headers: this.basicAuthHeaders }); - getIDOInfo = () => fetchWithValidation(`${this.apiUrl}/api/solarflare`, IDOSchema); + getIDOInfo = () => fetchWithValidation(`${this.apiUrl}/api/solarflare`, IDOSchema, { headers: this.basicAuthHeaders }); checkAuth = (headers: IAdminAuthHeaders) => fetchWithValidation(`${this.apiUrl}/api/auth/check`, z.object({ auth: z.boolean(), - }), { headers }); + }), { headers: { ...headers, ...this.basicAuthHeaders }}); getPool = (address: string, headers: IAdminAuthHeaders) => fetchWithValidation( `${this.apiUrl}/api/pools/${address}`, adminPoolSchema, - { headers }, + { headers: { ...headers, ...this.basicAuthHeaders }}, ); getPoolsList = (headers: IAdminAuthHeaders) => fetchWithValidation( `${this.apiUrl}/api/pools/list`, adminPoolsListSchema, - { headers }, + { headers: { ...headers, ...this.basicAuthHeaders }}, ); editPool = (address: string, data: IEditPool, headers: IAdminAuthHeaders) => fetchWithValidation( @@ -329,6 +364,7 @@ class BlockchainService { headers: { 'Content-Type': 'application/json', ...headers, + ...this.basicAuthHeaders, }, }, ); @@ -342,6 +378,7 @@ class BlockchainService { headers: { 'Content-Type': 'application/json', Accept: 'application/json', + ...this.basicAuthHeaders, }, }, z.string(), @@ -350,11 +387,13 @@ class BlockchainService { checkPoolInformation = (poolAddress: string) => fetchWithValidation( `${this.apiUrl}/api/pools/check/${poolAddress}`, pairStatusSchema, + { headers: this.basicAuthHeaders }, ); getAtomicSwapAssets = () => fetchWithValidation( `${this.apiUrl}/api/atomic/swap-assets`, z.array(z.string()), + { headers: this.basicAuthHeaders }, ); /** @@ -370,7 +409,7 @@ class BlockchainService { url.searchParams.append(key, value.toString()); }); - return fetchWithValidation(url.toString(), atomicHistorySchema); + return fetchWithValidation(url.toString(), atomicHistorySchema, { headers: this.basicAuthHeaders }); }; getSourceAtomicSwapHistory = (query: AtomicSwapHistorySourceQuery) => { @@ -384,7 +423,7 @@ class BlockchainService { if (query.type === undefined) url.searchParams.append('type', 'source'); - return fetchWithValidation(url.toString(), sourceAtomicHistorySchema); + return fetchWithValidation(url.toString(), sourceAtomicHistorySchema, { headers: this.basicAuthHeaders }); }; getTargetAtomicSwapHistory = (query: AtomicSwapHistoryTargetQuery) => { @@ -398,7 +437,7 @@ class BlockchainService { if (query.type === undefined) url.searchParams.append('type', 'target'); - return fetchWithValidation(url.toString(), targetAtomicHistorySchema); + return fetchWithValidation(url.toString(), targetAtomicHistorySchema, { headers: this.basicAuthHeaders }); }; checkIfHashUsed = (secretHashes: string[]) => fetchWithValidation( @@ -408,6 +447,7 @@ class BlockchainService { headers: { 'Content-Type': 'application/json', Accept: 'application/json', + ...this.basicAuthHeaders, }, method: 'POST', body: JSON.stringify(secretHashes), @@ -417,6 +457,7 @@ class BlockchainService { getCFDContracts = () => fetchWithValidation( `${this.apiUrl}/api/cfd/contracts`, cfdContractsSchema, + { headers: this.basicAuthHeaders }, ); getCFDHistory = (address: string, query: CfdHistoryQuery = {}) => { @@ -428,27 +469,31 @@ class BlockchainService { url.searchParams.append(key, value.toString()); }); - return fetchWithValidation(url.toString(), cfdHistorySchema); + return fetchWithValidation(url.toString(), cfdHistorySchema, { headers: this.basicAuthHeaders }); }; getGovernanceContracts = () => fetchWithValidation( `${this.apiUrl}/api/governance/info`, governanceContractsSchema, + { headers: this.basicAuthHeaders }, ); getGovernancePools = () => fetchWithValidation( `${this.apiUrl}/api/governance/pools`, governancePoolsSchema, + { headers: this.basicAuthHeaders }, ); getGovernancePool = (address: string) => fetchWithValidation( `${this.apiUrl}/api/governance/pools/${address}`, governancePoolSchema, + { headers: this.basicAuthHeaders }, ); getGovernanceChainsInfo = () => fetchWithValidation( `${this.apiUrl}/api/governance/chains-info`, governanceChainsInfoSchema, + { headers: this.basicAuthHeaders }, ); } diff --git a/src/services/PriceFeed/index.ts b/src/services/PriceFeed/index.ts index b9b0cc6..5eb0c1a 100644 --- a/src/services/PriceFeed/index.ts +++ b/src/services/PriceFeed/index.ts @@ -1,5 +1,5 @@ import { fetchWithValidation } from 'simple-typed-fetch'; -import type { Exchange } from '../../types.js'; +import type { BasicAuthCredentials, Exchange } from '../../types.js'; import { statisticsOverviewSchema, topPairsStatisticsSchema } from './schemas/index.js'; import candlesSchema from './schemas/candlesSchema.js'; import { PriceFeedWS } from './ws/index.js'; @@ -7,21 +7,33 @@ import { PriceFeedWS } from './ws/index.js'; class PriceFeed { private readonly apiUrl: string; + private readonly basicAuth?: BasicAuthCredentials | undefined; + readonly ws: PriceFeedWS; get api() { return this.apiUrl; } - constructor(apiUrl: string) { + constructor(apiUrl: string, basicAuth?: BasicAuthCredentials) { this.apiUrl = apiUrl; this.ws = new PriceFeedWS(this.wsUrl); + this.basicAuth = basicAuth; this.getCandles = this.getCandles.bind(this); this.getStatisticsOverview = this.getStatisticsOverview.bind(this); this.getTopPairStatistics = this.getTopPairStatistics.bind(this); } + get basicAuthHeaders() { + if (this.basicAuth) { + return { + Authorization: `Basic ${btoa(`${this.basicAuth.username}:${this.basicAuth.password}`)}`, + }; + } + return {}; + } + getCandles = ( symbol: string, timeStart: number, @@ -36,21 +48,33 @@ class PriceFeed { url.searchParams.append('interval', interval); url.searchParams.append('exchange', exchange); - return fetchWithValidation(url.toString(), candlesSchema); + return fetchWithValidation( + url.toString(), + candlesSchema, + { headers: this.basicAuthHeaders } + ); }; getStatisticsOverview = (exchange: Exchange | 'ALL' = 'ALL') => { const url = new URL(`${this.statisticsUrl}/overview`); url.searchParams.append('exchange', exchange); - return fetchWithValidation(url.toString(), statisticsOverviewSchema); + return fetchWithValidation( + url.toString(), + statisticsOverviewSchema, + { headers: this.basicAuthHeaders } + ); } getTopPairStatistics = (exchange: Exchange | 'ALL' = 'ALL') => { const url = new URL(`${this.statisticsUrl}/top-pairs`); url.searchParams.append('exchange', exchange); - return fetchWithValidation(url.toString(), topPairsStatisticsSchema); + return fetchWithValidation( + url.toString(), + topPairsStatisticsSchema, + { headers: this.basicAuthHeaders } + ); } get wsUrl() { diff --git a/src/services/PriceFeed/ws/index.ts b/src/services/PriceFeed/ws/index.ts index 6eda1ed..f086800 100644 --- a/src/services/PriceFeed/ws/index.ts +++ b/src/services/PriceFeed/ws/index.ts @@ -1,5 +1,6 @@ import type WebSocket from 'ws'; import PriceFeedSubscription, { type SubscriptionType, type Subscription } from './PriceFeedSubscription.js'; +import type { BasicAuthCredentials } from '../../../types.js'; export * as schemas from './schemas/index.js'; export class PriceFeedWS { @@ -14,8 +15,22 @@ export class PriceFeedWS { private readonly url: string; - constructor(url: string) { + readonly basicAuth?: BasicAuthCredentials | undefined; + + constructor(url: string, basicAuth?: BasicAuthCredentials) { this.url = url; + this.basicAuth = basicAuth; + } + + get api() { + const url = new URL(this.url); + + if (this.basicAuth) { + url.username = this.basicAuth.username; + url.password = this.basicAuth.password; + } + + return url.toString(); } subscribe( @@ -25,7 +40,7 @@ export class PriceFeedWS { ) { const sub = new PriceFeedSubscription( type, - this.url, + this.api, params, onOpen ); diff --git a/src/types.ts b/src/types.ts index 56c1f7e..6005172 100644 --- a/src/types.ts +++ b/src/types.ts @@ -263,6 +263,11 @@ export enum HistoryTransactionStatus { CANCELLED = 'Cancelled', } +export type BasicAuthCredentials = { + username: string + password: string +} + export type VerboseUnitConfig = { // env?: string; // api: string; @@ -292,6 +297,7 @@ export type VerboseUnitConfig = { // https://price-feed:3003/ } } + basicAuth?: BasicAuthCredentials, } export type KnownEnv = typeof knownEnvs[number];