From 384e349cfab47d83a957e3c98b7b109f73913d90 Mon Sep 17 00:00:00 2001 From: veado <61792675+veado@users.noreply.github.com> Date: Thu, 8 Dec 2022 16:46:25 +0100 Subject: [PATCH] Introduce `register9R` (#2474) to use custom axios `interceptor` for sending 'x-client-id' headers - [x] Helpers `add9Rheader` / `register9R` (main + renderer thread) - [x] Use patched `@cosmos-client/core` https://github.com/veado/cosmos-client-ts.git#patch/v0.45.13 - [x] Move `ASGARDEX_IDENTIFIER` to `shared/const` --- package.json | 2 +- src/main/electron.ts | 3 ++ src/renderer/components/swap/Swap.utils.ts | 3 +- src/renderer/const.ts | 2 -- src/renderer/index.tsx | 4 +++ src/renderer/services/midgard/service.ts | 11 ++---- src/renderer/services/thorchain/thornode.ts | 13 ++----- src/shared/api/ninerealms.ts | 40 +++++++++++++++++++++ src/shared/const.ts | 5 +++ yarn.lock | 21 ++++------- 10 files changed, 67 insertions(+), 37 deletions(-) create mode 100644 src/shared/api/ninerealms.ts diff --git a/package.json b/package.json index 37605d1aa..1594bb30b 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@ant-design/icons": "^4.7.0", "@binance-chain/javascript-sdk": "^4.2.0", "@cosmjs/stargate": "^0.28.10", - "@cosmos-client/core": "^0.45.10", + "@cosmos-client/core": "https://github.com/veado/cosmos-client-ts.git#patch/v0.45.13", "@craco/craco": "^7.0.0-alpha.7", "@devexperts/remote-data-ts": "^2.1.1", "@devexperts/rx-utils": "^1.0.0-alpha.14", diff --git a/src/main/electron.ts b/src/main/electron.ts index 0396e6055..93d112b4b 100644 --- a/src/main/electron.ts +++ b/src/main/electron.ts @@ -16,6 +16,7 @@ import { ipcLedgerDepositTxParamsIO, ipcLedgerSendTxParamsIO } from '../shared/api/io' +import { register9Rheader } from '../shared/api/ninerealms' import type { IPCExportKeystoreParams, IPCLedgerAdddressParams, StoreFileName } from '../shared/api/types' import { DEFAULT_STORAGES } from '../shared/const' import type { Locale } from '../shared/i18n/types' @@ -202,6 +203,8 @@ const init = async () => { await initMainWindow() app.on('window-all-closed', allClosedHandler) app.on('activate', activateHandler) + // Registers custom headers (9R endpoints only) + register9Rheader() initIPC() } diff --git a/src/renderer/components/swap/Swap.utils.ts b/src/renderer/components/swap/Swap.utils.ts index a03981efb..1d33a7d55 100644 --- a/src/renderer/components/swap/Swap.utils.ts +++ b/src/renderer/components/swap/Swap.utils.ts @@ -6,8 +6,9 @@ import * as E from 'fp-ts/Either' import * as FP from 'fp-ts/function' import * as O from 'fp-ts/Option' +import { ASGARDEX_IDENTIFIER } from '../../../shared/const' import { isLedgerWallet } from '../../../shared/utils/guard' -import { ASGARDEX_IDENTIFIER, ZERO_BASE_AMOUNT } from '../../const' +import { ZERO_BASE_AMOUNT } from '../../const' import { isChainAsset, isRuneNativeAsset, diff --git a/src/renderer/const.ts b/src/renderer/const.ts index f33e038e3..7f9830734 100644 --- a/src/renderer/const.ts +++ b/src/renderer/const.ts @@ -183,8 +183,6 @@ export const ZERO_BASE_AMOUNT = baseAmount(ZERO_BN) export const ZERO_POOL_DATA: PoolData = { runeBalance: ZERO_BASE_AMOUNT, assetBalance: ZERO_BASE_AMOUNT } -export const ASGARDEX_IDENTIFIER = 999 - export const RECOVERY_TOOL_URL: Record = { testnet: 'https://testnet.thorswap.finance/pending', stagenet: 'https://stagenet.thorswap.finance/pending', diff --git a/src/renderer/index.tsx b/src/renderer/index.tsx index 2072cb5e3..501996073 100644 --- a/src/renderer/index.tsx +++ b/src/renderer/index.tsx @@ -3,9 +3,13 @@ import React from 'react' import './index.css' import { createRoot } from 'react-dom/client' +import { register9Rheader } from '../shared/api/ninerealms' import { App } from './App' import * as serviceWorker from './serviceWorker' +// Registers custom headers (9R endpoints only) +register9Rheader() + // React 18 introduces a new root API // @see https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#updates-to-client-rendering-apis const container = document.getElementById('root') diff --git a/src/renderer/services/midgard/service.ts b/src/renderer/services/midgard/service.ts index 4c1f1fb97..0802d04e4 100644 --- a/src/renderer/services/midgard/service.ts +++ b/src/renderer/services/midgard/service.ts @@ -4,13 +4,13 @@ import * as O from 'fp-ts/Option' import * as Rx from 'rxjs' import * as RxOp from 'rxjs/operators' +import { add9Rheader } from '../../../shared/api/ninerealms' import { ApiUrls, Network } from '../../../shared/api/types' import { DEFAULT_MIDGARD_URLS } from '../../../shared/midgard/const' -import { ASGARDEX_IDENTIFIER } from '../../const' import { eqApiUrls } from '../../helpers/fp/eq' import { liveData } from '../../helpers/rx/liveData' import { triggerStream, TriggerStream$ } from '../../helpers/stateHelper' -import { Configuration, DefaultApi, Middleware, RequestArgs } from '../../types/generated/midgard' +import { Configuration, DefaultApi, Middleware } from '../../types/generated/midgard' import { network$ } from '../app/service' import { MIDGARD_MAX_RETRY } from '../const' import { getStorageState$, modifyStorage, getStorageState } from '../storage/common' @@ -67,12 +67,7 @@ const setMidgardUrl = (url: string, network: Network) => { modifyStorage(O.some({ midgard: midgardUrls })) } -const MIDGARD_API_MIDDLEWARE: Middleware = { - pre: (req: RequestArgs) => { - const headers = req?.headers ?? {} - return { ...req, headers: { ...headers, 'x-client-id': `${ASGARDEX_IDENTIFIER}` } } - } -} +const MIDGARD_API_MIDDLEWARE: Middleware = { pre: add9Rheader } /** * Helper to get `DefaultApi` instance for Midgard using custom basePath diff --git a/src/renderer/services/thorchain/thornode.ts b/src/renderer/services/thorchain/thornode.ts index 376836a13..862cb823c 100644 --- a/src/renderer/services/thorchain/thornode.ts +++ b/src/renderer/services/thorchain/thornode.ts @@ -9,7 +9,7 @@ import { PathReporter } from 'io-ts/lib/PathReporter' import * as Rx from 'rxjs' import * as RxOp from 'rxjs/operators' -import { ASGARDEX_IDENTIFIER } from '../../const' +import { add9Rheader } from '../../../shared/api/ninerealms' import { THORCHAIN_DECIMAL } from '../../helpers/assetHelper' import { LiveData, liveData } from '../../helpers/rx/liveData' import { triggerStream } from '../../helpers/stateHelper' @@ -21,8 +21,7 @@ import { Node, NodesApi, Pool, - PoolsApi, - RequestArgs + PoolsApi } from '../../types/generated/thornode' import { Network$ } from '../app/types' import { @@ -41,13 +40,7 @@ import { } from './types' export const getThornodeAPIConfiguration = (basePath: string): Configuration => { - const middleware: Middleware = { - pre: (req: RequestArgs) => { - const headers = req?.headers ?? {} - return { ...req, headers: { ...headers, 'x-client-id': `${ASGARDEX_IDENTIFIER}` } } - } - } - + const middleware: Middleware = { pre: add9Rheader } return new Configuration({ basePath, middleware: [middleware] }) } diff --git a/src/shared/api/ninerealms.ts b/src/shared/api/ninerealms.ts new file mode 100644 index 000000000..534935f12 --- /dev/null +++ b/src/shared/api/ninerealms.ts @@ -0,0 +1,40 @@ +import { cosmosclient } from '@cosmos-client/core' +import axios from 'axios' + +import { ASGARDEX_IDENTIFIER, NINE_REALMS_CLIENT_HEADER } from '../const' + +const { + config: { globalAxios } +} = cosmosclient + +/** + * Middleware to add custom header to requests (9R endpoints only) + * + * @param request RequestArgs (rxjs/ajax) | AxiosRequestConfig (axios) + * @returns RequestArgs (rxjs/ajax) | AxiosRequestConfig (axios) + */ +export const add9Rheader = (request: T) => { + try { + // URL throws an `TypeError` if `url` is not available and 'unknown-url' is set + // [TypeError: Invalid URL] input: 'unknown-url', code: 'ERR_INVALID_URL' } + const url = new URL(request?.url ?? 'unknown-url') + if (url.host.includes('ninerealms')) { + const headers = request?.headers ?? {} + // Add custom header to request before returning it + return { ...request, headers: { ...headers, [`${NINE_REALMS_CLIENT_HEADER}`]: `${ASGARDEX_IDENTIFIER}` } } + } + } catch (error) { + console.error(`Failed to add custom ${NINE_REALMS_CLIENT_HEADER} header`, error) + } + + // If it errors, just return same request and keep it untouched (no change) + return request +} + +/** + * Adds custom header to axios requests (9R endpoints only) + */ +export const register9Rheader = () => { + axios.interceptors.request.use(add9Rheader, (error) => Promise.reject(error)) + globalAxios.interceptors.request.use(add9Rheader, (error) => Promise.reject(error)) +} diff --git a/src/shared/const.ts b/src/shared/const.ts index 35c1c6c07..9782c11de 100644 --- a/src/shared/const.ts +++ b/src/shared/const.ts @@ -5,6 +5,11 @@ import { DEFAULT_LOCALE } from './i18n/const' import { DEFAULT_MIDGARD_URLS } from './midgard/const' import { DEFAULT_THORNODE_API_URLS, DEFAULT_THORNODE_RPC_URLS } from './thorchain/const' +export const ASGARDEX_IDENTIFIER = 999 + +// Header key for 9R endpoints +export const NINE_REALMS_CLIENT_HEADER = 'x-client-id' + export enum ExternalUrl { DOCS = 'https://docs.thorchain.org', DISCORD = 'https://discord.gg/pHcS67yX7Z', diff --git a/yarn.lock b/yarn.lock index 2b4ab4e89..5c7435ad5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1939,11 +1939,11 @@ __metadata: languageName: node linkType: hard -"@cosmos-client/core@npm:^0.45.10": +"@cosmos-client/core@https://github.com/veado/cosmos-client-ts.git#patch/v0.45.13": version: 0.45.13 - resolution: "@cosmos-client/core@npm:0.45.13" + resolution: "@cosmos-client/core@https://github.com/veado/cosmos-client-ts.git#commit=edffc1cc300f3bbd9c7c3c2354e88418a6a6c868" dependencies: - axios: ^0.23.0 + axios: ^0.25.0 bech32: ^1.1.4 bip32: ^2.0.6 bip39: ^3.0.4 @@ -1951,7 +1951,7 @@ __metadata: rxjs: ^7.4.0 secp256k1: ^4.0.2 tweetnacl: ^1.0.3 - checksum: 1e79f035d5ca84bdbbcfddaee43cf2efc56989a4de2ec32d6e74457eeb92ece2d5d2f8db707409093a9e49328149cc1b0e6a638a3c606a13d84cefbc868bd9c8 + checksum: 8e58581e97a9922833b4f50aff32bd03901d08e198beb91fcc8b6d45586de32c0a202aa475232005788f0d31754069a41efd3b6dfa5760192379b8edd4a435a9 languageName: node linkType: hard @@ -7608,7 +7608,7 @@ __metadata: "@ant-design/icons": ^4.7.0 "@binance-chain/javascript-sdk": ^4.2.0 "@cosmjs/stargate": ^0.28.10 - "@cosmos-client/core": ^0.45.10 + "@cosmos-client/core": "https://github.com/veado/cosmos-client-ts.git#patch/v0.45.13" "@craco/craco": ^7.0.0-alpha.7 "@devexperts/remote-data-ts": ^2.1.1 "@devexperts/rx-utils": ^1.0.0-alpha.14 @@ -7961,15 +7961,6 @@ __metadata: languageName: node linkType: hard -"axios@npm:^0.23.0": - version: 0.23.0 - resolution: "axios@npm:0.23.0" - dependencies: - follow-redirects: ^1.14.4 - checksum: 879f61022bd825da2a7ebb72410bc528683ba54c140436baa0b924b7cab02ec0919fe64a04a546f482a75f5fd570b77884f9826764a95f2fd88265e61dcb70db - languageName: node - linkType: hard - "axios@npm:^0.25.0": version: 0.25.0 resolution: "axios@npm:0.25.0" @@ -13361,7 +13352,7 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.10.0, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.4, follow-redirects@npm:^1.14.7, follow-redirects@npm:^1.14.8": +"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.10.0, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.14.7, follow-redirects@npm:^1.14.8": version: 1.15.1 resolution: "follow-redirects@npm:1.15.1" peerDependenciesMeta: