Merge pull request #137 from orionprotocol/feat/basic-auth

feat: basic auth
This commit is contained in:
Oleg Nechiporenko
2023-06-21 02:50:37 +05:00
committed by GitHub
8 changed files with 156 additions and 37 deletions

View File

@@ -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",

View File

@@ -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);
}

View File

@@ -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';

View File

@@ -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}`);

View File

@@ -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 },
);
}

View File

@@ -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() {

View File

@@ -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<S extends SubscriptionType>(
@@ -25,7 +40,7 @@ export class PriceFeedWS {
) {
const sub = new PriceFeedSubscription(
type,
this.url,
this.api,
params,
onOpen
);

View File

@@ -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];