From 7ea665bed8d2c77e900965d99425857ae66932af Mon Sep 17 00:00:00 2001 From: Veado Date: Tue, 23 Aug 2022 19:47:12 +0200 Subject: [PATCH 1/5] Fix: cosmosstation.io api is down 'https://lcd-cosmoshub.keplr.app' is not available for few days now, switch to `https://lcd-cosmoshub.keplr.app`. Note: keplr.app api does not support all endpoints. --- .env.sample | 3 + src/main/api/ledger/cosmos/transaction.ts | 7 ++- src/renderer/services/cosmos/common.ts | 70 ++++++++++++----------- src/shared/cosmos/client.ts | 21 ++++--- 4 files changed, 57 insertions(+), 44 deletions(-) diff --git a/.env.sample b/.env.sample index 9180614fa..73c7c3405 100644 --- a/.env.sample +++ b/.env.sample @@ -47,3 +47,6 @@ REACT_APP_LTC_NODE_TESTNET_URL=https://testnet.ltc.thorchain.info REACT_APP_LTC_NODE_MAINNET_URL=https://ltc.thorchain.info REACT_APP_LTC_NODE_USERNAME=XXX REACT_APP_LTC_NODE_PASSWORD=XXX + +# COSMOS +REACT_APP_COSMOS_MAINNET_LCD = https://lcd-cosmoshub.keplr.app diff --git a/src/main/api/ledger/cosmos/transaction.ts b/src/main/api/ledger/cosmos/transaction.ts index 19110e0d6..6d38b6007 100644 --- a/src/main/api/ledger/cosmos/transaction.ts +++ b/src/main/api/ledger/cosmos/transaction.ts @@ -11,7 +11,8 @@ import { protoFee, protoAuthInfo, protoMsgSend, - protoTxBody + protoTxBody, + getDefaultChainIds } from '@xchainjs/xchain-cosmos' import { Asset, assetToString, BaseAmount } from '@xchainjs/xchain-util' import BigNumber from 'bignumber.js' @@ -76,7 +77,9 @@ export const send = async ({ const fee = protoFee({ denom, amount: feeAmount, gasLimit }) const clientUrls = getClientUrls() - const chainId = await getChainId(clientUrls[clientNetwork]) + const chainId = + // request chain id (for testnet only, cosmoshub.keplr.app does not an endpoint for it) + network === 'testnet' ? await getChainId(clientUrls[clientNetwork]) : getDefaultChainIds()[network] const app = new CosmosApp(transport) const path = getDerivationPath(walletIndex) diff --git a/src/renderer/services/cosmos/common.ts b/src/renderer/services/cosmos/common.ts index 43d5fa8f1..ee2a4c44c 100644 --- a/src/renderer/services/cosmos/common.ts +++ b/src/renderer/services/cosmos/common.ts @@ -1,5 +1,5 @@ import * as RD from '@devexperts/remote-data-ts' -import { Client, getChainId } from '@xchainjs/xchain-cosmos' +import { Client, getChainId, getDefaultChainIds } from '@xchainjs/xchain-cosmos' import { CosmosChain } from '@xchainjs/xchain-util' import * as FP from 'fp-ts/lib/function' import * as O from 'fp-ts/lib/Option' @@ -23,40 +23,42 @@ import type { Client$, ClientState, ClientState$ } from './types' */ const clientState$: ClientState$ = FP.pipe( Rx.combineLatest([keystoreService.keystoreState$, clientNetwork$, Rx.of(getClientUrls())]), - RxOp.switchMap( - ([keystore, network, clientUrls]): ClientState$ => - FP.pipe( - // request chain id whenever network or keystore are changed - Rx.from(getChainId(clientUrls[network])), - RxOp.catchError((error) => - Rx.of(RD.failure(new Error(`Failed to get Cosmos' chain id (${error?.msg ?? error.toString()})`))) - ), - RxOp.switchMap((chainId) => - Rx.of( - FP.pipe( - getPhrase(keystore), - O.map((phrase) => { - try { - const client = new Client({ - network, - phrase, - clientUrls: getClientUrls(), - chainIds: { ...INITIAL_CHAIN_IDS, [network]: chainId } - }) - return RD.success(client) - } catch (error) { - return RD.failure(isError(error) ? error : new Error('Failed to create Cosmos client')) - } - }), - // Set back to `initial` if no phrase is available (locked wallet) - O.getOrElse(() => RD.initial) - ) + RxOp.switchMap(([keystore, network, clientUrls]): ClientState$ => { + console.log('network:', network) + return FP.pipe( + // request chain id (for testnet only, cosmoshub.keplr.app does not an endpoint for it) + Rx.of(network === 'testnet' ? getChainId(clientUrls[network]) : getDefaultChainIds()[network]), + RxOp.switchMap((chainId) => { + console.log('chainId:', chainId) + console.log('clientUrls:', clientUrls[network]) + return Rx.of( + FP.pipe( + getPhrase(keystore), + O.map((phrase) => { + try { + const client = new Client({ + network, + phrase, + clientUrls: getClientUrls(), + chainIds: { ...INITIAL_CHAIN_IDS, [network]: chainId } + }) + return RD.success(client) + } catch (error) { + return RD.failure(isError(error) ? error : new Error('Failed to create Cosmos client')) + } + }), + // Set back to `initial` if no phrase is available (locked wallet) + O.getOrElse(() => RD.initial) ) - ), - RxOp.startWith(RD.pending) - ) - ), - RxOp.startWith(RD.initial), + ) + }), + RxOp.catchError((error) => + Rx.of(RD.failure(new Error(`Failed to get Cosmos' chain id (${error?.msg ?? error.toString()})`))) + ), + RxOp.startWith(RD.pending) + ) + }), + RxOp.startWith(RD.initial), RxOp.shareReplay(1) ) diff --git a/src/shared/cosmos/client.ts b/src/shared/cosmos/client.ts index 98b615ae1..fc36848b4 100644 --- a/src/shared/cosmos/client.ts +++ b/src/shared/cosmos/client.ts @@ -1,23 +1,28 @@ import { Network } from '@xchainjs/xchain-client' import { ChainIds, ClientUrls } from '@xchainjs/xchain-cosmos' -const clientUrl = 'https://lcd-cosmos.cosmostation.io' +import { envOrDefault } from '../utils/env' + +// expose env (needed to access ENVs by `envOrDefault`) in `main` thread) +require('dotenv').config() + +const MAINNET_LCD = envOrDefault(process.env.REACT_APP_COSMOS_MAINNET_LCD, 'https://lcd-cosmoshub.keplr.app') export const getClientUrls = (): ClientUrls => ({ - [Network.Stagenet]: clientUrl, - [Network.Mainnet]: clientUrl, + [Network.Stagenet]: MAINNET_LCD, + [Network.Mainnet]: MAINNET_LCD, [Network.Testnet]: 'https://rest.sentry-01.theta-testnet.polypore.xyz' }) +const mainChainId = 'cosmoshub-4' /** * Default Cosmos' chain ids * - * Note: All are 'unknown' by default - * They need to be requested from Cosmos API + * Note: All 'unknown' will be fetched from Cosmos `node_info`` endpoint * just before initializing a `xchain-cosmos` client */ export const INITIAL_CHAIN_IDS: ChainIds = { - [Network.Mainnet]: 'unkown-mainnet-chain-id', - [Network.Stagenet]: 'unkown-stagenet-chain-id', - [Network.Testnet]: 'unkown-testnet-chain-id' + [Network.Mainnet]: mainChainId, // can't be fetched for `lcd-cosmoshub.keplr.app` + [Network.Stagenet]: mainChainId, // can't be fetched for `lcd-cosmoshub.keplr.app` + [Network.Testnet]: 'unkown-testnet-chain-id' // will be fetched } From cbc717709d68da82d1a8c06fdc266d1f94b88c57 Mon Sep 17 00:00:00 2001 From: Veado Date: Tue, 23 Aug 2022 19:47:44 +0200 Subject: [PATCH 2/5] Quick fix: `catchError` in service/thorchain --- src/renderer/services/thorchain/common.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/renderer/services/thorchain/common.ts b/src/renderer/services/thorchain/common.ts index 10b533dbd..f492cf4a3 100644 --- a/src/renderer/services/thorchain/common.ts +++ b/src/renderer/services/thorchain/common.ts @@ -40,9 +40,6 @@ const clientState$: ClientState$ = FP.pipe( FP.pipe( // request chain id from node whenever network or keystore state have been changed Rx.from(getChainId(clientUrl[network].node)), - RxOp.catchError((error) => - Rx.of(RD.failure(new Error(`Failed to get THORChain's chain id (${error?.msg ?? error.toString()})`))) - ), RxOp.switchMap((chainId) => Rx.of( FP.pipe( @@ -65,10 +62,13 @@ const clientState$: ClientState$ = FP.pipe( ) ) ), + RxOp.catchError((error) => + Rx.of(RD.failure(new Error(`Failed to get THORChain's chain id (${error?.msg ?? error.toString()})`))) + ), RxOp.startWith(RD.pending) ) ), - RxOp.startWith(RD.initial), + RxOp.startWith(RD.initial), RxOp.shareReplay(1) ) From 30c03d57219a8d2f82f2686ce98b54021e1efead Mon Sep 17 00:00:00 2001 From: Veado Date: Tue, 23 Aug 2022 19:48:30 +0200 Subject: [PATCH 3/5] Quick fix: