From af041e2213a5c15c003527da68f0dd49e625e6cb Mon Sep 17 00:00:00 2001 From: agoltzman <106151463+agoltzman@users.noreply.github.com> Date: Wed, 23 Oct 2024 13:47:41 +0300 Subject: [PATCH] feat(@fireblocks/recovery-relay): :sparkles: updated wallets to use configurable RPCs --- .changeset/tidy-shirts-mix.md | 5 +++ apps/recovery-relay/lib/wallets/ADA/index.ts | 10 +++-- apps/recovery-relay/lib/wallets/ALGO/index.ts | 22 ++++++---- apps/recovery-relay/lib/wallets/ATOM/index.ts | 14 ++++--- .../lib/wallets/BTCBased/BCH.ts | 19 +++++---- .../lib/wallets/BTCBased/BSV.ts | 12 +++--- .../lib/wallets/BTCBased/BTC.ts | 7 +++- .../lib/wallets/BTCBased/BTCRelayWallet.ts | 10 ++--- .../lib/wallets/BTCBased/DASH.ts | 6 ++- .../lib/wallets/BTCBased/DOGE.ts | 7 ++-- .../lib/wallets/BTCBased/LTC.ts | 9 ++-- .../lib/wallets/BTCBased/ZEC.ts | 11 +++-- .../lib/wallets/CELESTIA/index.ts | 13 +++--- .../lib/wallets/ConnectedWallet.ts | 8 +++- apps/recovery-relay/lib/wallets/DOT/index.ts | 13 +++--- apps/recovery-relay/lib/wallets/EOS/index.ts | 24 ++++++----- .../recovery-relay/lib/wallets/ERC20/index.ts | 4 +- apps/recovery-relay/lib/wallets/EVM/AETH.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/AOA.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/AVAX.ts | 2 +- .../recovery-relay/lib/wallets/EVM/BNB_BSC.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/CELO.ts | 2 +- .../lib/wallets/EVM/CORE_COREDAO.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/ETC.ts | 15 ++++--- apps/recovery-relay/lib/wallets/EVM/ETH.ts | 27 +----------- apps/recovery-relay/lib/wallets/EVM/ETHW.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/EVMOS.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/FTM.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/GLMR.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/MATIC.ts | 10 ++--- apps/recovery-relay/lib/wallets/EVM/MOVR.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/OETH.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/RBTC.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/RON.ts | 13 +++++- apps/recovery-relay/lib/wallets/EVM/SGB.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/TKX.ts | 13 +++++- apps/recovery-relay/lib/wallets/EVM/VLX.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/XDC.ts | 2 +- apps/recovery-relay/lib/wallets/EVM/index.ts | 23 ++++++---- apps/recovery-relay/lib/wallets/HBAR/index.ts | 6 +++ apps/recovery-relay/lib/wallets/KSM/index.ts | 14 ++++--- apps/recovery-relay/lib/wallets/LUNA/index.ts | 22 +++++----- apps/recovery-relay/lib/wallets/NEAR/index.ts | 10 ++++- apps/recovery-relay/lib/wallets/NEM/index.ts | 16 +++---- apps/recovery-relay/lib/wallets/SOL/index.ts | 23 +++++----- apps/recovery-relay/lib/wallets/TRON/index.ts | 26 ++++++------ apps/recovery-relay/lib/wallets/XLM/index.ts | 20 +++++---- apps/recovery-relay/lib/wallets/XRP/index.ts | 42 ++++++++++--------- apps/recovery-relay/lib/wallets/XTZ/index.ts | 33 ++++++++------- 49 files changed, 299 insertions(+), 240 deletions(-) create mode 100644 .changeset/tidy-shirts-mix.md diff --git a/.changeset/tidy-shirts-mix.md b/.changeset/tidy-shirts-mix.md new file mode 100644 index 00000000..d8fecb93 --- /dev/null +++ b/.changeset/tidy-shirts-mix.md @@ -0,0 +1,5 @@ +--- +'@fireblocks/recovery-relay': patch +--- + +Updated wallets to use configurable RPCs diff --git a/apps/recovery-relay/lib/wallets/ADA/index.ts b/apps/recovery-relay/lib/wallets/ADA/index.ts index 5a399def..70357ed2 100644 --- a/apps/recovery-relay/lib/wallets/ADA/index.ts +++ b/apps/recovery-relay/lib/wallets/ADA/index.ts @@ -35,19 +35,23 @@ export class Cardano extends BaseCardano implements LateInitConnectedWallet { private bkfClient: BlockFrostAPI | undefined = undefined; - private endpoint: string | undefined = undefined; + public rpcURL: string | undefined; constructor(input: Input) { super(input); this.isLateInit = () => true; } + public setRPCUrl(url: string): void { + this.rpcURL = url; + } + public getLateInitLabel(): string { return 'Blockfrost Project ID or GraphQL Url'; } public updateDataEndpoint(endpoint: string): void { - this.endpoint = endpoint; + this.rpcURL = endpoint; if (endpoint.startsWith('http')) { this.gqlClient = new ApolloClient({ uri: endpoint, @@ -120,7 +124,7 @@ export class Cardano extends BaseCardano implements LateInitConnectedWallet { const preparedData = { utxos, balance: balance / 1_000_000, - endpoint: this.endpoint, + endpoint: this.rpcURL, insufficientBalance: balance / 1_000_000 < 0.001, }; diff --git a/apps/recovery-relay/lib/wallets/ALGO/index.ts b/apps/recovery-relay/lib/wallets/ALGO/index.ts index 9a43d460..bde65890 100644 --- a/apps/recovery-relay/lib/wallets/ALGO/index.ts +++ b/apps/recovery-relay/lib/wallets/ALGO/index.ts @@ -1,15 +1,19 @@ import { Algorand as BaseALGO } from '@fireblocks/wallet-derivation'; +import { Algodv2 } from 'algosdk'; import { AccountData } from '../types'; import { LateInitConnectedWallet } from '../LateInitConnectedWallet'; -import { Algodv2 } from 'algosdk'; - export class Algorand extends BaseALGO implements LateInitConnectedWallet { - private endpoint: string | undefined; + public rpcURL: string | undefined; + private algoClient: Algodv2 | undefined; public updateDataEndpoint(endpoint: string): void { - this.endpoint = endpoint; + this.rpcURL = endpoint; + } + + public setRPCUrl(url: string): void { + this.rpcURL = url; } public getLateInitLabel(): string { @@ -24,6 +28,7 @@ export class Algorand extends BaseALGO implements LateInitConnectedWallet { } return accountInfo.amount; } + public async prepare(): Promise { this.createClient(); @@ -42,15 +47,16 @@ export class Algorand extends BaseALGO implements LateInitConnectedWallet { return { balance, extraParams, - endpoint: this.endpoint, + endpoint: this.rpcURL, }; } + public broadcastTx(tx: string): Promise { throw new Error('Method not implemented.'); } private createClient() { - if (!this.endpoint) { + if (!this.rpcURL) { throw new Error('Wallet not initialized yet'); } @@ -58,8 +64,8 @@ export class Algorand extends BaseALGO implements LateInitConnectedWallet { return; } - const [host, port, apiToken] = this.endpoint.split(':'); + const [host, port, apiToken] = this.rpcURL.split(':'); - this.algoClient = new Algodv2(apiToken, host, parseInt(port)); + this.algoClient = new Algodv2(apiToken, host, parseInt(port, 10)); } } diff --git a/apps/recovery-relay/lib/wallets/ATOM/index.ts b/apps/recovery-relay/lib/wallets/ATOM/index.ts index ebb7de99..9a086957 100644 --- a/apps/recovery-relay/lib/wallets/ATOM/index.ts +++ b/apps/recovery-relay/lib/wallets/ATOM/index.ts @@ -1,7 +1,7 @@ import { Cosmos as BaseCosmos, Input } from '@fireblocks/wallet-derivation'; import { Tendermint34Client } from '@cosmjs/tendermint-rpc'; import { StargateClient } from '@cosmjs/stargate'; -import { SignDoc, TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx'; +import { TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx'; import { AccountData } from '../types'; import { ConnectedWallet } from '../ConnectedWallet'; @@ -10,13 +10,15 @@ export class Cosmos extends BaseCosmos implements ConnectedWallet { private stargateClient: StargateClient | undefined; - private rpcURL: string; + public rpcURL: string | undefined; constructor(input: Input) { super(input); - this.tendermintClient = undefined; - this.rpcURL = input.isTestnet ? 'https://rpc.sentry-01.theta-testnet.polypore.xyz' : 'https://cosmos-rpc.publicnode.com'; + } + + public setRPCUrl(url: string): void { + this.rpcURL = url; } public async getBalance(): Promise { @@ -56,8 +58,8 @@ export class Cosmos extends BaseCosmos implements ConnectedWallet { private async prepareClients(): Promise { if (!this.tendermintClient || !this.stargateClient) { - this.tendermintClient = await Tendermint34Client.connect(this.rpcURL); - this.stargateClient = await StargateClient.connect(this.rpcURL); + this.tendermintClient = await Tendermint34Client.connect(this.rpcURL!); + this.stargateClient = await StargateClient.connect(this.rpcURL!); } } } diff --git a/apps/recovery-relay/lib/wallets/BTCBased/BCH.ts b/apps/recovery-relay/lib/wallets/BTCBased/BCH.ts index 673c7323..27b78de2 100644 --- a/apps/recovery-relay/lib/wallets/BTCBased/BCH.ts +++ b/apps/recovery-relay/lib/wallets/BTCBased/BCH.ts @@ -5,16 +5,19 @@ import { LateInitConnectedWallet } from '../LateInitConnectedWallet'; import { BCHUTXO } from './types'; export class BitcoinCash extends BCHBase implements LateInitConnectedWallet { - private endpoint: string; - private network: Networks.Network; + public rpcURL: string | undefined; + constructor(input: Input) { super(input); - this.endpoint = 'https://rest.bch.actorforth.org/v2'; this.network = Networks.mainnet; } + public setRPCUrl(url: string): void { + this.rpcURL = url; + } + // eslint-disable-next-line class-methods-use-this public getLateInitLabel() { return ''; @@ -25,18 +28,18 @@ export class BitcoinCash extends BCHBase implements LateInitConnectedWallet { } public updateDataEndpoint(endpoint: string): void { - this.endpoint = endpoint; + this.rpcURL = endpoint; } public async getBalance(): Promise { - if (this.isLateInit() && this.endpoint === '') { + if (this.isLateInit() && (this.rpcURL === '' || this.rpcURL === undefined)) { throw new Error('Endpoint not initialized yet'); } return (await this.prepare()).balance; } public async prepare(): Promise { - if (this.isLateInit() && this.endpoint === '') { + if (this.isLateInit() && (this.rpcURL === '' || this.rpcURL === undefined)) { throw new Error('Endpoint not initialized yet'); } @@ -73,7 +76,7 @@ export class BitcoinCash extends BCHBase implements LateInitConnectedWallet { } private async _get(path: string) { - const res = await fetch(`${this.endpoint}${path}`); + const res = await fetch(`${this.rpcURL}${path}`); const data: Promise = res.json(); @@ -81,7 +84,7 @@ export class BitcoinCash extends BCHBase implements LateInitConnectedWallet { } private async _post(path: string) { - const res = await fetch(`${this.endpoint}${path}`, { + const res = await fetch(`${this.rpcURL}${path}`, { method: 'POST', }); diff --git a/apps/recovery-relay/lib/wallets/BTCBased/BSV.ts b/apps/recovery-relay/lib/wallets/BTCBased/BSV.ts index 5bf2c28f..f64f53e3 100644 --- a/apps/recovery-relay/lib/wallets/BTCBased/BSV.ts +++ b/apps/recovery-relay/lib/wallets/BTCBased/BSV.ts @@ -20,14 +20,12 @@ type BSVAddressSummary = { }; export class BitcoinSV extends BSVBase implements ConnectedWallet { - private baseUrl: string = ''; + public rpcURL: string | undefined; - private utils; - - constructor(input: Input) { - super(input); - this.baseUrl = input.isTestnet ? 'https://api.whatsonchain.com/v1/bsv/test' : 'https://api.whatsonchain.com/v1/bsv/main'; + private utils: unknown | undefined; + public setRPCUrl(url: string): void { + this.rpcURL = url; // When calling any custom function provided as part of the relay wallet utils // we bind it to `this` from the BTCRelayWallet class, thus every internal reference to this // within the custom functions must be considered as a call to the BTCRelayWalletUtils and not @@ -107,7 +105,7 @@ export class BitcoinSV extends BSVBase implements ConnectedWallet { return txBroadcastRes; } - })(this.baseUrl); + })(this.rpcURL!); } public async getBalance(): Promise { diff --git a/apps/recovery-relay/lib/wallets/BTCBased/BTC.ts b/apps/recovery-relay/lib/wallets/BTCBased/BTC.ts index 8b94ffc5..567ecca4 100644 --- a/apps/recovery-relay/lib/wallets/BTCBased/BTC.ts +++ b/apps/recovery-relay/lib/wallets/BTCBased/BTC.ts @@ -10,13 +10,12 @@ import { AddressSummary, FullUTXO, StandardUTXO, UTXOSummary } from './types'; export class Bitcoin extends BaseBTC implements ConnectedWallet { private static readonly satsPerBtc = 100000000; - private readonly baseUrl: string; + public rpcURL: string | undefined; private utils: BTCRelayWalletUtils | undefined; constructor(input: Input) { super(input); - this.baseUrl = input.isTestnet ? 'https://api.blockchair.com/bitcoin/testnet' : 'https://api.blockchair.com/bitcoin'; // Legacy requires a custom site if (this.isLegacy) { // When calling any custom function provided as part of the relay wallet utils @@ -104,6 +103,10 @@ export class Bitcoin extends BaseBTC implements ConnectedWallet { } } + public setRPCUrl(url: string): void { + this.rpcURL = url; + } + public async getBalance(): Promise { return BTCRelayWallet.prototype.getBalance.bind(this)(); } diff --git a/apps/recovery-relay/lib/wallets/BTCBased/BTCRelayWallet.ts b/apps/recovery-relay/lib/wallets/BTCBased/BTCRelayWallet.ts index 6686ae05..03034d96 100644 --- a/apps/recovery-relay/lib/wallets/BTCBased/BTCRelayWallet.ts +++ b/apps/recovery-relay/lib/wallets/BTCBased/BTCRelayWallet.ts @@ -10,7 +10,7 @@ export class BTCRelayWallet { public async getBalance(): Promise { // @ts-ignore - const utils = (this.utils as BTCRelayWalletUtils) || new StandardBTCRelayWalletUtils(this.baseUrl); + const utils = (this.utils as BTCRelayWalletUtils) || new StandardBTCRelayWalletUtils(this.rpcURL); // @ts-ignore const balance = await utils.getAddressBalance(this.address); const btcBalance = BTCRelayWallet._satsToBtc(balance); @@ -19,10 +19,10 @@ export class BTCRelayWallet { public async prepare(): Promise { // @ts-ignore - const { isLegacy, relayLogger: logger, baseUrl, address } = this; + const { isLegacy, relayLogger: logger, rpcURL, address } = this; // @ts-ignore - const utils = (this.utils as BTCRelayWalletUtils) || new StandardBTCRelayWalletUtils(baseUrl); + const utils = (this.utils as BTCRelayWalletUtils) || new StandardBTCRelayWalletUtils(rpcURL); const balance = await BTCRelayWallet.prototype.getBalance.bind(this)(); if (balance === 0) { @@ -57,10 +57,10 @@ export class BTCRelayWallet { // const tx = Psbt.fromHex(txHex, { network: this.network }); // @ts-ignore - const { relayLogger: logger, baseUrl } = this; + const { relayLogger: logger, rpcURL } = this; // @ts-ignore - const utils = (this.utils as BTCRelayWalletUtils) || new StandardBTCRelayWalletUtils(baseUrl); + const utils = (this.utils as BTCRelayWalletUtils) || new StandardBTCRelayWalletUtils(rpcURL); // @ts-ignore return utils.broadcastTx(txHex, logger); diff --git a/apps/recovery-relay/lib/wallets/BTCBased/DASH.ts b/apps/recovery-relay/lib/wallets/BTCBased/DASH.ts index 45900323..041e8bf9 100644 --- a/apps/recovery-relay/lib/wallets/BTCBased/DASH.ts +++ b/apps/recovery-relay/lib/wallets/BTCBased/DASH.ts @@ -4,7 +4,7 @@ import { ConnectedWallet } from '../ConnectedWallet'; import { BTCRelayWallet } from './BTCRelayWallet'; export class DASH extends BaseDASH implements ConnectedWallet { - private readonly baseUrl: string; + public rpcURL: string | undefined; constructor(input: Input) { super(input); @@ -12,8 +12,10 @@ export class DASH extends BaseDASH implements ConnectedWallet { if (input.isTestnet) { throw new Error('No Dash testnet support.'); } + } - this.baseUrl = 'https://api.blockchair.com/dash'; + public setRPCUrl(url: string): void { + this.rpcURL = url; } public async getBalance(): Promise { diff --git a/apps/recovery-relay/lib/wallets/BTCBased/DOGE.ts b/apps/recovery-relay/lib/wallets/BTCBased/DOGE.ts index 98a71375..27203eb1 100644 --- a/apps/recovery-relay/lib/wallets/BTCBased/DOGE.ts +++ b/apps/recovery-relay/lib/wallets/BTCBased/DOGE.ts @@ -6,11 +6,10 @@ import { BTCRelayWallet } from './BTCRelayWallet'; export class DOGE extends BaseDOGE implements ConnectedWallet { private static readonly satsPerBtc = 100000000; - private readonly baseUrl: string; + public rpcURL: string | undefined; - constructor(input: Input) { - super(input); - this.baseUrl = 'https://api.blockchair.com/dogecoin'; + public setRPCUrl(url: string): void { + this.rpcURL = url; } public async prepare(): Promise { diff --git a/apps/recovery-relay/lib/wallets/BTCBased/LTC.ts b/apps/recovery-relay/lib/wallets/BTCBased/LTC.ts index e8b7e2bc..e4fad6e2 100644 --- a/apps/recovery-relay/lib/wallets/BTCBased/LTC.ts +++ b/apps/recovery-relay/lib/wallets/BTCBased/LTC.ts @@ -1,4 +1,4 @@ -import { LiteCoin as BaseLTC, Input } from '@fireblocks/wallet-derivation'; +import { LiteCoin as BaseLTC } from '@fireblocks/wallet-derivation'; import { AccountData } from '../types'; import { ConnectedWallet } from '../ConnectedWallet'; import { BTCRelayWallet } from './BTCRelayWallet'; @@ -6,11 +6,10 @@ import { BTCRelayWallet } from './BTCRelayWallet'; export class LTC extends BaseLTC implements ConnectedWallet { private static readonly satsPerBtc = 100000000; - private readonly baseUrl: string; + public rpcURL: string | undefined; - constructor(input: Input) { - super(input); - this.baseUrl = 'https://api.blockchair.com/litecoin'; + public setRPCUrl(url: string): void { + this.rpcURL = url; } public async getBalance(): Promise { diff --git a/apps/recovery-relay/lib/wallets/BTCBased/ZEC.ts b/apps/recovery-relay/lib/wallets/BTCBased/ZEC.ts index 95ec987a..35a6706a 100644 --- a/apps/recovery-relay/lib/wallets/BTCBased/ZEC.ts +++ b/apps/recovery-relay/lib/wallets/BTCBased/ZEC.ts @@ -1,4 +1,4 @@ -import { ZCash as BaseZEC, Input } from '@fireblocks/wallet-derivation'; +import { ZCash as BaseZEC } from '@fireblocks/wallet-derivation'; import { AccountData } from '../types'; import { ConnectedWallet } from '../ConnectedWallet'; import { BTCRelayWallet } from './BTCRelayWallet'; @@ -7,11 +7,10 @@ import { StandardBTCRelayWalletUtils } from './BTCRelayWalletUtils'; export class ZEC extends BaseZEC implements ConnectedWallet { private static readonly satsPerBtc = 100000000; - private readonly baseUrl: string; + public rpcURL: string | undefined; - constructor(input: Input) { - super(input); - this.baseUrl = 'https://api.blockchair.com/zcash'; + public setRPCUrl(url: string): void { + this.rpcURL = url; } public async prepare(): Promise { @@ -31,7 +30,7 @@ export class ZEC extends BaseZEC implements ConnectedWallet { } private async _getCurrentBlockHeight() { - const utils = new StandardBTCRelayWalletUtils(this.baseUrl); + const utils = new StandardBTCRelayWalletUtils(this.rpcURL!); const stats = await utils.requestJson<{ data: { blocks: number; diff --git a/apps/recovery-relay/lib/wallets/CELESTIA/index.ts b/apps/recovery-relay/lib/wallets/CELESTIA/index.ts index a3313a4f..1256abba 100644 --- a/apps/recovery-relay/lib/wallets/CELESTIA/index.ts +++ b/apps/recovery-relay/lib/wallets/CELESTIA/index.ts @@ -1,7 +1,7 @@ import { Celestia as BaseCelestia, Input } from '@fireblocks/wallet-derivation'; import { Tendermint34Client } from '@cosmjs/tendermint-rpc'; import { StargateClient } from '@cosmjs/stargate'; -import { SignDoc, TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx'; +import { TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx'; import { AccountData } from '../types'; import { ConnectedWallet } from '../ConnectedWallet'; @@ -10,13 +10,16 @@ export class Celestia extends BaseCelestia implements ConnectedWallet { private stargateClient: StargateClient | undefined; - private rpcURL: string; + public rpcURL: string | undefined; constructor(input: Input) { super(input); this.tendermintClient = undefined; - this.rpcURL = input.isTestnet ? 'https://celestia-mocha-rpc.publicnode.com' : 'https://celestia-rpc.publicnode.com'; + } + + public setRPCUrl(url: string): void { + this.rpcURL = url; } public async getBalance(): Promise { @@ -55,8 +58,8 @@ export class Celestia extends BaseCelestia implements ConnectedWallet { private async prepareClients(): Promise { if (!this.tendermintClient || !this.stargateClient) { - this.tendermintClient = await Tendermint34Client.connect(this.rpcURL); - this.stargateClient = await StargateClient.connect(this.rpcURL); + this.tendermintClient = await Tendermint34Client.connect(this.rpcURL!); + this.stargateClient = await StargateClient.connect(this.rpcURL!); } } } diff --git a/apps/recovery-relay/lib/wallets/ConnectedWallet.ts b/apps/recovery-relay/lib/wallets/ConnectedWallet.ts index 2f2495d8..a895425c 100644 --- a/apps/recovery-relay/lib/wallets/ConnectedWallet.ts +++ b/apps/recovery-relay/lib/wallets/ConnectedWallet.ts @@ -2,9 +2,13 @@ import { BaseWallet } from '@fireblocks/wallet-derivation'; import { AccountData } from './types'; export abstract class ConnectedWallet extends BaseWallet { + public rpcURL: string | undefined; + public abstract getBalance(): Promise; - public abstract prepare(): Promise; + public abstract prepare(to?: string, memo?: string): Promise; + + public abstract broadcastTx(txHex: string): Promise; - public abstract broadcastTx(txHex: string, customUrl?: string): Promise; + public abstract setRPCUrl(url: string): void; } diff --git a/apps/recovery-relay/lib/wallets/DOT/index.ts b/apps/recovery-relay/lib/wallets/DOT/index.ts index dc16f5b5..e3329052 100644 --- a/apps/recovery-relay/lib/wallets/DOT/index.ts +++ b/apps/recovery-relay/lib/wallets/DOT/index.ts @@ -1,17 +1,19 @@ -import { Polkadot as BaseDOT, Input } from '@fireblocks/wallet-derivation'; +import { Polkadot as BaseDOT } from '@fireblocks/wallet-derivation'; import { ApiPromise, WsProvider } from '@polkadot/api'; import { construct } from '@substrate/txwrapper-polkadot'; import { ConnectedWallet } from '../ConnectedWallet'; import { AccountData } from '../types'; export class Polkadot extends BaseDOT implements ConnectedWallet { - private provider: WsProvider; + public rpcURL: string | undefined; + + private provider: WsProvider | undefined; private polkadotApi: ApiPromise | undefined; - constructor(input: Input) { - super(input); - this.provider = new WsProvider(input.isTestnet ? 'wss://westend-rpc.polkadot.io' : 'wss://rpc.polkadot.io'); + public setRPCUrl(url: string): void { + this.rpcURL = url; + this.provider = new WsProvider(url); } public async getBalance(): Promise { @@ -24,7 +26,6 @@ export class Polkadot extends BaseDOT implements ConnectedWallet { public async prepare(): Promise { const balance = await this.getBalance(); - //@ts-ignore const { nonce } = await this.polkadotApi!.query.system.account(this.address); const genesisHash = this.polkadotApi!.genesisHash.toHex(); const blockHash = (await this.polkadotApi!.rpc.chain.getBlockHash()).toHex(); diff --git a/apps/recovery-relay/lib/wallets/EOS/index.ts b/apps/recovery-relay/lib/wallets/EOS/index.ts index a25409a5..fcc358d6 100644 --- a/apps/recovery-relay/lib/wallets/EOS/index.ts +++ b/apps/recovery-relay/lib/wallets/EOS/index.ts @@ -9,13 +9,15 @@ import { AccountData } from '../types'; import { EmptySigProvider } from './EmptySigProvider'; export class EOS extends BaseEOS implements ConnectedWallet { - private api: Api; + private api: Api | undefined; private accounts: string[] | undefined; - constructor(input: Input) { - super(input); - const rpc = new JsonRpc(input.isTestnet ? 'https://jungle.eosusa.io' : 'https://api.eoseoul.io', { fetch }); + public rpcURL: string | undefined; + + public setRPCUrl(url: string): void { + this.rpcURL = url; + const rpc = new JsonRpc(url, { fetch }); const signatureProvider = new EmptySigProvider(); this.api = new Api({ rpc, @@ -24,7 +26,7 @@ export class EOS extends BaseEOS implements ConnectedWallet { } private async _getAccounts(): Promise { - const { accounts } = await this.api.rpc.get_accounts_by_authorizers([], [this.address]); + const { accounts } = await this.api!.rpc.get_accounts_by_authorizers([], [this.address]); accounts.forEach((account) => { if (account.permission_name === 'owner') { if (!this.accounts) { @@ -41,7 +43,7 @@ export class EOS extends BaseEOS implements ConnectedWallet { } // We should theoretically have only a single account that we're the owner of, but this should be adjusted if there exists a scenario where we are not owners of a single account. const accountName = this.accounts![0]; - const account = await this.api.rpc.get_account(accountName); + const account = await this.api!.rpc.get_account(accountName); return parseFloat(account.core_liquid_balance!.replace(' EOS', '')); } @@ -58,11 +60,11 @@ export class EOS extends BaseEOS implements ConnectedWallet { insufficientBalance: true, }; } - await this.api.getAbi('eosio.token'); - const txBuilder = this.api.buildTransaction() as TransactionBuilder; + await this.api!.getAbi('eosio.token'); + const txBuilder = this.api!.buildTransaction() as TransactionBuilder; const actionBuilder = txBuilder.with('eosio.token').as([{ actor: this.accounts![0], permission: 'owner' }]); const action = await actionBuilder.transfer(this.accounts![0], to!, `${balance} EOS`, memo ?? ''); - const tx: PushTransactionArgs = (await this.api.transact( + const tx: PushTransactionArgs = (await this.api!.transact( { actions: [action], }, @@ -74,7 +76,7 @@ export class EOS extends BaseEOS implements ConnectedWallet { requiredKeys: [this.address], }, )) as PushTransactionArgs; - const chainId = (await this.api.rpc.get_info()).chain_id; + const chainId = (await this.api!.rpc.get_info()).chain_id; const serTx = superjson.stringify(tx); extraParams.set(this.KEY_TX, serTx); extraParams.set(this.KEY_CHAIN_ID, chainId); @@ -91,7 +93,7 @@ export class EOS extends BaseEOS implements ConnectedWallet { public async broadcastTx(txHex: string): Promise { try { const tx = superjson.parse(txHex); - const txRes = (await this.api.pushSignedTransaction(tx)) as TransactResult; + const txRes = (await this.api!.pushSignedTransaction(tx)) as TransactResult; this.relayLogger.debug(`EOS: Tx broadcasted: ${JSON.stringify(txRes, null, 2)}`); return txRes.transaction_id; } catch (e) { diff --git a/apps/recovery-relay/lib/wallets/ERC20/index.ts b/apps/recovery-relay/lib/wallets/ERC20/index.ts index 1b8579f7..a5d64059 100644 --- a/apps/recovery-relay/lib/wallets/ERC20/index.ts +++ b/apps/recovery-relay/lib/wallets/ERC20/index.ts @@ -35,10 +35,10 @@ export class ERC20 extends Ethereum implements ConnectedWallet { } public async generateTx(to: string, amount: number): Promise { - const nonce = await this.provider.getTransactionCount(this.address, 'latest'); + const nonce = await this.provider!.getTransactionCount(this.address, 'latest'); // Should we use maxGasPrice? i.e. EIP1559. - const { gasPrice } = await this.provider.getFeeData(); + const { gasPrice } = await this.provider!.getFeeData(); const tx = { from: this.address, diff --git a/apps/recovery-relay/lib/wallets/EVM/AETH.ts b/apps/recovery-relay/lib/wallets/EVM/AETH.ts index a4020d7b..27ef1c28 100644 --- a/apps/recovery-relay/lib/wallets/EVM/AETH.ts +++ b/apps/recovery-relay/lib/wallets/EVM/AETH.ts @@ -4,6 +4,6 @@ import { EVM } from '.'; export class Arbitrum extends EVM implements ConnectedWallet { constructor(input: Input) { - super(input, `${input.isTestnet ? 'https://goerli-rollup.arbitrum.io/rpc' : 'https://arbitrum-goerli.public.blastapi.io'}`); + super(input, input.isTestnet ? 421611 : 42161); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/AOA.ts b/apps/recovery-relay/lib/wallets/EVM/AOA.ts index 9c2165c1..b60842d7 100644 --- a/apps/recovery-relay/lib/wallets/EVM/AOA.ts +++ b/apps/recovery-relay/lib/wallets/EVM/AOA.ts @@ -7,6 +7,6 @@ export class Aurora extends EVM implements ConnectedWallet { if (input.isTestnet) { throw new Error('No Aurora testnet support'); } - super(input, 'https://mainnet.aurora.dev'); + super(input, 1313161554); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/AVAX.ts b/apps/recovery-relay/lib/wallets/EVM/AVAX.ts index 9d8ab6e1..7e0b7438 100644 --- a/apps/recovery-relay/lib/wallets/EVM/AVAX.ts +++ b/apps/recovery-relay/lib/wallets/EVM/AVAX.ts @@ -4,6 +4,6 @@ import { EVM } from '.'; export class Avalanche extends EVM implements ConnectedWallet { constructor(input: Input) { - super(input, `${input.isTestnet ? 'https://api.avax-test.network/ext/bc/C/rpc' : 'https://api.avax.network/ext/bc/C/rpc'}`); + super(input, input.isTestnet ? 43113 : 43114); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/BNB_BSC.ts b/apps/recovery-relay/lib/wallets/EVM/BNB_BSC.ts index bc4328f8..77d0999e 100644 --- a/apps/recovery-relay/lib/wallets/EVM/BNB_BSC.ts +++ b/apps/recovery-relay/lib/wallets/EVM/BNB_BSC.ts @@ -4,6 +4,6 @@ import { EVM } from '.'; export class BinanceSmartChain extends EVM implements ConnectedWallet { constructor(input: Input) { - super(input, `${input.isTestnet ? 'https://data-seed-prebsc-1-s1.binance.org:8545/' : 'https://bsc-dataseed.binance.org/'}`); + super(input, input.isTestnet ? 97 : 56); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/CELO.ts b/apps/recovery-relay/lib/wallets/EVM/CELO.ts index a9e71994..f8ed8eb5 100644 --- a/apps/recovery-relay/lib/wallets/EVM/CELO.ts +++ b/apps/recovery-relay/lib/wallets/EVM/CELO.ts @@ -7,6 +7,6 @@ export class Celo extends EVM implements ConnectedWallet { if (input.isTestnet) { throw new Error('No CELO testnet support.'); } - super(input, 'https://forno.celo.org'); + super(input, 42220); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/CORE_COREDAO.ts b/apps/recovery-relay/lib/wallets/EVM/CORE_COREDAO.ts index ac579928..c582eb7c 100644 --- a/apps/recovery-relay/lib/wallets/EVM/CORE_COREDAO.ts +++ b/apps/recovery-relay/lib/wallets/EVM/CORE_COREDAO.ts @@ -5,7 +5,7 @@ import { AccountData } from '../types'; export class CoreDAO extends EVM implements ConnectedWallet { constructor(input: Input) { - super(input, input.isTestnet ? 'https://rpc.test.btcs.network ' : 'https://rpc.coredao.org', input.isTestnet ? 1115 : 1116); + super(input, input.isTestnet ? 1115 : 1116); } public override async prepare(): Promise { diff --git a/apps/recovery-relay/lib/wallets/EVM/ETC.ts b/apps/recovery-relay/lib/wallets/EVM/ETC.ts index 510412fc..bcb39f80 100644 --- a/apps/recovery-relay/lib/wallets/EVM/ETC.ts +++ b/apps/recovery-relay/lib/wallets/EVM/ETC.ts @@ -1,18 +1,21 @@ import { Input, ETC as BaseETC } from '@fireblocks/wallet-derivation'; import { ConnectedWallet } from '../ConnectedWallet'; import { EVM } from '.'; -import { AccountData, TxPayload, RawSignature } from '../types'; +import { AccountData } from '../types'; export class EthereumClassic extends BaseETC implements ConnectedWallet { private evmWallet: EVM; + public rpcURL: string | undefined; + constructor(input: Input) { super(input); - this.evmWallet = new EVM( - input, - input.isTestnet ? 'https://geth-mordor.etc-network.info' : 'https://geth-de.etc-network.info', - input.isTestnet ? 63 : 61, - ); + this.evmWallet = new EVM(input, input.isTestnet ? 63 : 61); + } + + public setRPCUrl(url: string): void { + this.rpcURL = url; + this.evmWallet.setRPCUrl(url); } public async getBalance(): Promise { diff --git a/apps/recovery-relay/lib/wallets/EVM/ETH.ts b/apps/recovery-relay/lib/wallets/EVM/ETH.ts index 04107dd7..5d78e544 100644 --- a/apps/recovery-relay/lib/wallets/EVM/ETH.ts +++ b/apps/recovery-relay/lib/wallets/EVM/ETH.ts @@ -4,30 +4,7 @@ import { EVM } from '.'; export class Ethereum extends EVM implements ConnectedWallet { constructor(input: Input) { - let cluster: string; - let rpcEndpoint: string = ''; - - switch (input.assetId) { - case 'ETH': - cluster = 'mainnet'; - break; - case 'ETH_TEST3': - cluster = 'goerli'; - break; - case 'ETH_TEST6': - cluster = 'holesky'; - rpcEndpoint = 'https://ethereum-holesky-rpc.publicnode.com'; - break; - case 'ETH_TEST5': - cluster = 'sepolia'; - rpcEndpoint = 'https://ethereum-sepolia-rpc.publicnode.com'; - break; - default: - throw new Error('Unsupported asset'); - } - - rpcEndpoint = rpcEndpoint === '' ? `https://${cluster}.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161` : rpcEndpoint; - - super(input, rpcEndpoint); + // eslint-disable-next-line no-nested-ternary + super(input, input.isTestnet ? (input.assetId === 'ETH_TEST3' ? 6 : input.assetId === 'ETH_TEST5' ? 11155111 : 17000) : 1); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/ETHW.ts b/apps/recovery-relay/lib/wallets/EVM/ETHW.ts index 14ae543f..db26e20f 100644 --- a/apps/recovery-relay/lib/wallets/EVM/ETHW.ts +++ b/apps/recovery-relay/lib/wallets/EVM/ETHW.ts @@ -7,6 +7,6 @@ export class EthereumPoW extends EVM implements ConnectedWallet { if (input.isTestnet) { throw new Error('No EthereumPOW Testnet support.'); } - super(input, `https://mainnet.ethereumpow.org`); + super(input, 10001); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/EVMOS.ts b/apps/recovery-relay/lib/wallets/EVM/EVMOS.ts index 4afc8375..1b9e94f8 100644 --- a/apps/recovery-relay/lib/wallets/EVM/EVMOS.ts +++ b/apps/recovery-relay/lib/wallets/EVM/EVMOS.ts @@ -7,6 +7,6 @@ export class EVMOS extends EVM implements ConnectedWallet { if (input.isTestnet) { throw new Error('No EVMOS testnet support'); } - super(input, 'https://evmos-evm.publicnode.com'); + super(input, 9001); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/FTM.ts b/apps/recovery-relay/lib/wallets/EVM/FTM.ts index 31ad90f6..d771c34c 100644 --- a/apps/recovery-relay/lib/wallets/EVM/FTM.ts +++ b/apps/recovery-relay/lib/wallets/EVM/FTM.ts @@ -7,6 +7,6 @@ export class Fantom extends EVM implements ConnectedWallet { if (input.isTestnet) { throw new Error('No Fantom testnet support'); } - super(input, 'https://rpcapi.fantom.network'); + super(input, 250); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/GLMR.ts b/apps/recovery-relay/lib/wallets/EVM/GLMR.ts index fa5da0cf..ed8d8262 100644 --- a/apps/recovery-relay/lib/wallets/EVM/GLMR.ts +++ b/apps/recovery-relay/lib/wallets/EVM/GLMR.ts @@ -7,6 +7,6 @@ export class Moonbeam extends EVM implements ConnectedWallet { if (input.isTestnet) { throw new Error('No Moonbeam testnet support'); } - super(input, 'https://rpc.api.moonbeam.network'); + super(input, 1284); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/MATIC.ts b/apps/recovery-relay/lib/wallets/EVM/MATIC.ts index 472c5503..7fbfbd84 100644 --- a/apps/recovery-relay/lib/wallets/EVM/MATIC.ts +++ b/apps/recovery-relay/lib/wallets/EVM/MATIC.ts @@ -4,21 +4,21 @@ import { EVM } from '.'; export class Matic extends EVM implements ConnectedWallet { constructor(input: Input) { - let rpcEndpoint: string; + let chainId: number; switch (input.assetId) { case 'MATIC_POLYGON_MUMBAI': - rpcEndpoint = 'https://polygon-mumbai-bor-rpc.publicnode.com'; + chainId = 80001; break; case 'AMOY_POLYGON_TEST': - rpcEndpoint = 'https://polygon-amoy-bor-rpc.publicnode.com'; + chainId = 80002; break; case 'MATIC_POLYGON': - rpcEndpoint = 'https://polygon-bor-rpc.publicnode.com'; + chainId = 137; break; default: throw new Error('Unsupported asset'); } - super(input, rpcEndpoint); + super(input, chainId); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/MOVR.ts b/apps/recovery-relay/lib/wallets/EVM/MOVR.ts index 880866bd..d36303c4 100644 --- a/apps/recovery-relay/lib/wallets/EVM/MOVR.ts +++ b/apps/recovery-relay/lib/wallets/EVM/MOVR.ts @@ -7,6 +7,6 @@ export class Moonriver extends EVM implements ConnectedWallet { if (input.isTestnet) { throw new Error('No Moonriver testnet support.'); } - super(input, 'https://rpc.api.moonriver.moonbeam.network'); + super(input, 1285); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/OETH.ts b/apps/recovery-relay/lib/wallets/EVM/OETH.ts index fb2049c5..62e11b9c 100644 --- a/apps/recovery-relay/lib/wallets/EVM/OETH.ts +++ b/apps/recovery-relay/lib/wallets/EVM/OETH.ts @@ -4,6 +4,6 @@ import { EVM } from '.'; export class Optimism extends EVM implements ConnectedWallet { constructor(input: Input) { - super(input, input.isTestnet ? 'https://kovan.optimism.io' : 'https://mainnet.optimism.io'); + super(input, input.isTestnet ? 69 : 10); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/RBTC.ts b/apps/recovery-relay/lib/wallets/EVM/RBTC.ts index 0a27c66d..84800c16 100644 --- a/apps/recovery-relay/lib/wallets/EVM/RBTC.ts +++ b/apps/recovery-relay/lib/wallets/EVM/RBTC.ts @@ -4,6 +4,6 @@ import { EVM } from '.'; export class RootstockBTC extends EVM implements ConnectedWallet { constructor(input: Input) { - super(input, input.isTestnet ? 'https://public-node.testnet.rsk.co' : 'https://public-node.rsk.co'); + super(input, input.isTestnet ? 31 : 30); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/RON.ts b/apps/recovery-relay/lib/wallets/EVM/RON.ts index 185b054c..2bb81155 100644 --- a/apps/recovery-relay/lib/wallets/EVM/RON.ts +++ b/apps/recovery-relay/lib/wallets/EVM/RON.ts @@ -1,6 +1,6 @@ import { EVMWallet as EVMBase, Input } from '@fireblocks/wallet-derivation'; import { LateInitConnectedWallet } from '../LateInitConnectedWallet'; -import { AccountData, TxPayload, RawSignature } from '../types'; +import { AccountData } from '../types'; import { EVM } from '.'; export class Ronin extends EVMBase implements LateInitConnectedWallet { @@ -8,6 +8,8 @@ export class Ronin extends EVMBase implements LateInitConnectedWallet { private subWallet: EVM | undefined; + public rpcURL: string | undefined; + public getLateInitLabel() { return 'Ronin'; } @@ -20,6 +22,11 @@ export class Ronin extends EVMBase implements LateInitConnectedWallet { this.inputDup = JSON.parse(JSON.stringify(input)) as Input; } + public setRPCUrl(url: string): void { + this.rpcURL = url; + this.updateDataEndpoint(url); + } + public async getBalance(): Promise { if (this.subWallet === undefined) { throw new Error('Wallet not initalized yet'); @@ -50,7 +57,9 @@ export class Ronin extends EVMBase implements LateInitConnectedWallet { public updateDataEndpoint(endpoint: string): void { try { - this.subWallet = new EVM(this.inputDup, endpoint); + this.rpcURL = endpoint; + this.subWallet = new EVM(this.inputDup, 2020); + this.subWallet.setRPCUrl(this.rpcURL!); } catch (e) { this.subWallet = undefined; throw new Error(`Failed updating endpoint: ${e}`); diff --git a/apps/recovery-relay/lib/wallets/EVM/SGB.ts b/apps/recovery-relay/lib/wallets/EVM/SGB.ts index 902c4c65..5d38d156 100644 --- a/apps/recovery-relay/lib/wallets/EVM/SGB.ts +++ b/apps/recovery-relay/lib/wallets/EVM/SGB.ts @@ -7,6 +7,6 @@ export class Songbird extends EVM implements ConnectedWallet { if (input.isTestnet) { throw new Error('No Songbird testnet support.'); } - super(input, 'https://sgb.ftso.com.au/ext/bc/C/rpc'); + super(input, 19); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/TKX.ts b/apps/recovery-relay/lib/wallets/EVM/TKX.ts index b25c8811..23bd8be2 100644 --- a/apps/recovery-relay/lib/wallets/EVM/TKX.ts +++ b/apps/recovery-relay/lib/wallets/EVM/TKX.ts @@ -8,6 +8,8 @@ export class TokenX extends EVMBase implements LateInitConnectedWallet { private subWallet: EVM | undefined; + public rpcURL: string | undefined; + public getLateInitLabel() { return 'TokenX'; } @@ -20,6 +22,11 @@ export class TokenX extends EVMBase implements LateInitConnectedWallet { this.inputDup = JSON.parse(JSON.stringify(input)) as Input; } + public setRPCUrl(url: string): void { + this.rpcURL = url; + this.updateDataEndpoint(url); + } + public async getBalance(): Promise { if (this.subWallet === undefined) { throw new Error('Wallet not initalized yet'); @@ -48,9 +55,11 @@ export class TokenX extends EVMBase implements LateInitConnectedWallet { return (await this.subWallet!.broadcastTx(txHex)) as string; } - public updateDataEndpoint(endpoint: string): void { + public updateDataEndpoint(url: string): void { try { - this.subWallet = new EVM(this.inputDup, endpoint); + this.rpcURL = url; + this.subWallet = new EVM(this.inputDup, 18888); + this.subWallet.setRPCUrl(this.rpcURL!); } catch (e) { this.subWallet = undefined; throw new Error(`Failed updating endpoint: ${e}`); diff --git a/apps/recovery-relay/lib/wallets/EVM/VLX.ts b/apps/recovery-relay/lib/wallets/EVM/VLX.ts index ebb2109f..69f96667 100644 --- a/apps/recovery-relay/lib/wallets/EVM/VLX.ts +++ b/apps/recovery-relay/lib/wallets/EVM/VLX.ts @@ -4,6 +4,6 @@ import { EVM } from '.'; export class Velas extends EVM implements ConnectedWallet { constructor(input: Input) { - super(input, input.isTestnet ? 'https://api.testnet.velas.com' : 'https://api.velas.com'); + super(input, input.isTestnet ? 111 : 106); } } diff --git a/apps/recovery-relay/lib/wallets/EVM/XDC.ts b/apps/recovery-relay/lib/wallets/EVM/XDC.ts index 6934f6ab..c251107b 100644 --- a/apps/recovery-relay/lib/wallets/EVM/XDC.ts +++ b/apps/recovery-relay/lib/wallets/EVM/XDC.ts @@ -7,7 +7,7 @@ export class XinFin extends EVM implements ConnectedWallet { if (input.isTestnet) { throw new Error('No XDC testnet support.'); } - super(input, 'https://rpc.xinfin.network'); + super(input, 50); } protected getAddress(): string { diff --git a/apps/recovery-relay/lib/wallets/EVM/index.ts b/apps/recovery-relay/lib/wallets/EVM/index.ts index e8ff398a..01078971 100644 --- a/apps/recovery-relay/lib/wallets/EVM/index.ts +++ b/apps/recovery-relay/lib/wallets/EVM/index.ts @@ -5,20 +5,25 @@ import { ConnectedWallet } from '../ConnectedWallet'; import BigNumber from 'bignumber.js'; export class EVM extends EVMBase implements ConnectedWallet { - protected readonly provider: JsonRpcProvider; + protected provider: JsonRpcProvider | undefined; protected weiBalance: bigint = BigInt(0); - constructor(input: Input, rpcEndpoint: string, chainId?: number) { + public rpcURL: string | undefined; + + constructor(input: Input, private chainId?: number) { super(input); - this.relayLogger.info('Creating EVM wallet:', { rpcEndpoint, chainId, input }); + this.relayLogger.info('Creating EVM wallet:', { chainId, input }); + } - this.provider = new JsonRpcProvider(rpcEndpoint, chainId, { cacheTimeout: -1 }); + public setRPCUrl(url: string): void { + this.rpcURL = url; + this.provider = new JsonRpcProvider(this.rpcURL, this.chainId, { cacheTimeout: -1 }); } public async getBalance() { - this.weiBalance = await this.provider.getBalance(this.address); + this.weiBalance = await this.provider!.getBalance(this.address); const balance = formatEther(this.weiBalance); const ethBalance = Number(balance); @@ -37,10 +42,10 @@ export class EVM extends EVMBase implements ConnectedWallet { }; } - const nonce = await this.provider.getTransactionCount(this.address, 'latest'); + const nonce = await this.provider!.getTransactionCount(this.address, 'latest'); // Should we use maxGasPrice? i.e. EIP1559. - const { gasPrice } = await this.provider.getFeeData(); + const { gasPrice } = await this.provider!.getFeeData(); if (!gasPrice) { throw new Error('No gas price found'); @@ -55,7 +60,7 @@ export class EVM extends EVMBase implements ConnectedWallet { this.relayLogger.error('Insufficient balance'); } - const chainId = (await this.provider.getNetwork()).chainId; + const chainId = (await this.provider!.getNetwork()).chainId; const extraParams = new Map(); extraParams.set(this.KEY_EVM_WEI_BALANCE, adjustedBalance.toString(16)); @@ -74,7 +79,7 @@ export class EVM extends EVMBase implements ConnectedWallet { public async broadcastTx(tx: string): Promise { try { - const txRes = await this.provider.broadcastTransaction(tx); + const txRes = await this.provider!.broadcastTransaction(tx); this.relayLogger.debug(`EVM: Tx broadcasted: ${JSON.stringify(txRes, null, 2)}`); return txRes.hash; } catch (e) { diff --git a/apps/recovery-relay/lib/wallets/HBAR/index.ts b/apps/recovery-relay/lib/wallets/HBAR/index.ts index a63f2748..93b188ac 100644 --- a/apps/recovery-relay/lib/wallets/HBAR/index.ts +++ b/apps/recovery-relay/lib/wallets/HBAR/index.ts @@ -4,6 +4,8 @@ import { LateInitConnectedWallet } from '../LateInitConnectedWallet'; import { AccountData } from '../types'; export class Hedera extends BaseHBAR implements LateInitConnectedWallet { + public rpcURL: string | undefined; + private client: Client | undefined; public updateDataEndpoint(endpoint: string): void { @@ -13,6 +15,10 @@ export class Hedera extends BaseHBAR implements LateInitConnectedWallet { return 'The address of your Hedera Hashgraph wallet'; } + public setRPCUrl(url: string): void { + this.rpcURL = url; + } + public isLateInit(): boolean { return true; } diff --git a/apps/recovery-relay/lib/wallets/KSM/index.ts b/apps/recovery-relay/lib/wallets/KSM/index.ts index b885abd0..2a028b30 100644 --- a/apps/recovery-relay/lib/wallets/KSM/index.ts +++ b/apps/recovery-relay/lib/wallets/KSM/index.ts @@ -5,16 +5,22 @@ import { ConnectedWallet } from '../ConnectedWallet'; import { AccountData } from '../types'; export class Kusama extends BaseKSM implements ConnectedWallet { - protected provider: WsProvider; + protected provider: WsProvider | undefined; private kusamaApi: ApiPromise | undefined; + public rpcURL: string | undefined; + constructor(input: Input) { super(input); if (input.isTestnet) { throw new Error("Can't use testnet with Kusama, please use Westend"); } - this.provider = new WsProvider('wss://kusama-rpc.polkadot.io'); + } + + public setRPCUrl(url: string): void { + this.rpcURL = url; + this.provider = new WsProvider(this.rpcURL); } public async getBalance(): Promise { @@ -27,7 +33,6 @@ export class Kusama extends BaseKSM implements ConnectedWallet { public async prepare(): Promise { const balance = await this.getBalance(); - //@ts-ignore const { nonce } = await this.kusamaApi!.query.system.account(this.address); const genesisHash = this.kusamaApi!.genesisHash.toHex(); const blockHash = (await this.kusamaApi!.rpc.chain.getBlockHash()).toHex(); @@ -35,7 +40,6 @@ export class Kusama extends BaseKSM implements ConnectedWallet { const specVersion = this.kusamaApi!.runtimeVersion.specVersion.toNumber(); const specName = this.kusamaApi!.runtimeVersion.specName.toHuman(); const transactionVersion = this.kusamaApi!.runtimeVersion.transactionVersion.toNumber(); - const rpc = (await this.kusamaApi!.rpc.state.getMetadata()).toHex(); const extraParams = new Map(); extraParams.set(this.KEY_BLOCK_HASH, blockHash); @@ -72,6 +76,6 @@ export class Kusama extends BaseKSM implements ConnectedWallet { if (this.kusamaApi) { return; } - this.kusamaApi = await ApiPromise.create({ provider: this.provider }); + this.kusamaApi = await ApiPromise.create({ provider: this.provider! }); } } diff --git a/apps/recovery-relay/lib/wallets/LUNA/index.ts b/apps/recovery-relay/lib/wallets/LUNA/index.ts index bf6fb454..4fe1076b 100644 --- a/apps/recovery-relay/lib/wallets/LUNA/index.ts +++ b/apps/recovery-relay/lib/wallets/LUNA/index.ts @@ -5,20 +5,22 @@ import { AccountData } from '../types'; import SuperJSON from 'superjson'; export class Luna extends BaseLuna implements ConnectedWallet { - private lcdClient: LCDClient; + private lcdClient: LCDClient | undefined; - constructor(input: Input) { - super(input); + public rpcURL: string | undefined; + + public setRPCUrl(url: string): void { + this.rpcURL = url; this.lcdClient = new LCDClient({ - URL: input.isTestnet ? 'https://pisco-lcd.terra.dev/' : 'https://phoenix-lcd.terra.dev', - chainID: input.isTestnet ? 'pisco-1' : 'phoenix-1', + URL: this.rpcURL, + chainID: this.isTestnet ? 'pisco-1' : 'phoenix-1', isClassic: false, }); } public async getBalance(): Promise { - const balances = await this.lcdClient.bank.balance(this.address, { + const balances = await this.lcdClient!.bank.balance(this.address, { 'pagination.limit': '500', }); @@ -46,12 +48,12 @@ export class Luna extends BaseLuna implements ConnectedWallet { }; } - const account = await this.lcdClient.auth.accountInfo(this.address); + const account = await this.lcdClient!.auth.accountInfo(this.address); const sequence = account.getSequenceNumber(); const sendMsg = new MsgSend(this.address, to!, { uluna: balance * 1000000 }); - const fee = await this.lcdClient.tx.estimateFee([{ sequenceNumber: sequence, publicKey: account.getPublicKey() }], { + const fee = await this.lcdClient!.tx.estimateFee([{ sequenceNumber: sequence, publicKey: account.getPublicKey() }], { msgs: [sendMsg], memo, }); @@ -59,7 +61,7 @@ export class Luna extends BaseLuna implements ConnectedWallet { const extraParams = new Map(); extraParams.set(this.KEY_SEQUENCE, sequence); extraParams.set(this.KEY_FEE_ESTIMATE, fee); - extraParams.set(this.KEY_CHAIN_ID, this.lcdClient.config.chainID); + extraParams.set(this.KEY_CHAIN_ID, this.lcdClient!.config.chainID); extraParams.set(this.KEY_ACCOUNT_NUMBER, account.getAccountNumber()); const preparedData = { @@ -81,7 +83,7 @@ export class Luna extends BaseLuna implements ConnectedWallet { }), ); const signedTx = Tx.fromData(halfBaked); - const res = await this.lcdClient.tx.broadcast(signedTx); + const res = await this.lcdClient!.tx.broadcast(signedTx); if (res.txhash && res.logs.length > 0) { this.relayLogger.debug(`Luna: Tx broadcasted: ${JSON.stringify(res, null, 2)}`); return res.txhash; diff --git a/apps/recovery-relay/lib/wallets/NEAR/index.ts b/apps/recovery-relay/lib/wallets/NEAR/index.ts index a141788d..31fcdf72 100644 --- a/apps/recovery-relay/lib/wallets/NEAR/index.ts +++ b/apps/recovery-relay/lib/wallets/NEAR/index.ts @@ -5,6 +5,8 @@ import { AccountData } from '../types'; import { ConnectedWallet } from '../ConnectedWallet'; export class Near extends BaseNEAR implements ConnectedWallet { + public rpcURL: string | undefined; + private near: NearApi | undefined; public async getBalance(): Promise { @@ -15,6 +17,10 @@ export class Near extends BaseNEAR implements ConnectedWallet { return parseFloat(balance.available) / 10 ** 24; } + public setRPCUrl(url: string): void { + this.rpcURL = url; + } + public async prepare(): Promise { const balance = await this.getBalance(); const near = this.near!; @@ -55,7 +61,7 @@ export class Near extends BaseNEAR implements ConnectedWallet { } const mainnetConfig = { networkId: 'mainnet', - nodeUrl: 'https://rpc.mainnet.near.org', + nodeUrl: this.rpcURL!, walletUrl: 'https://wallet.mainnet.near.org', helperUrl: 'https://helper.mainnet.near.org', explorerUrl: 'https://explorer.mainnet.near.org', @@ -63,7 +69,7 @@ export class Near extends BaseNEAR implements ConnectedWallet { }; const testnetConfig = { networkId: 'testnet', - nodeUrl: 'https://rpc.testnet.near.org', + nodeUrl: this.rpcURL!, walletUrl: 'https://wallet.testnet.near.org', helperUrl: 'https://helper.testnet.near.org', explorerUrl: 'https://explorer.testnet.near.org', diff --git a/apps/recovery-relay/lib/wallets/NEM/index.ts b/apps/recovery-relay/lib/wallets/NEM/index.ts index 0a349ecd..79461c62 100644 --- a/apps/recovery-relay/lib/wallets/NEM/index.ts +++ b/apps/recovery-relay/lib/wallets/NEM/index.ts @@ -3,16 +3,16 @@ import { ConnectedWallet } from '../ConnectedWallet'; import { AccountData } from '../types'; import axios from 'axios'; export class NEM extends BaseNEM implements ConnectedWallet { - private endpoint: string; + public rpcURL: string | undefined; + + private endpoint: string | undefined; - private readonly defaultMainnet: string = 'http://hugealice3.nem.ninja'; - private readonly defaultTestnet: string = 'http://hugetestalice.nem.ninja'; private readonly defaultPort: number = 7890; private readonly websocketPort: number = 7778; - constructor(input: Input) { - super(input); - this.endpoint = this.isTestnet ? `${this.defaultTestnet}:${this.defaultPort}` : `${this.defaultMainnet}:${this.defaultPort}`; + public setRPCUrl(url: string): void { + this.rpcURL = url; + this.endpoint = this.isTestnet ? `${url}:${this.defaultPort}` : `${url}:${this.defaultPort}`; } public async getBalance(): Promise { @@ -22,7 +22,7 @@ export class NEM extends BaseNEM implements ConnectedWallet { headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, - url: this.endpoint + `/account/get?address=${this.address}`, + url: this.endpoint! + `/account/get?address=${this.address}`, }) ).data.account; return accountData.balance / 1000000; @@ -42,7 +42,7 @@ export class NEM extends BaseNEM implements ConnectedWallet { const txRes = ( await axios({ method: 'POST', - url: `${this.endpoint}/transaction/announce`, + url: `${this.endpoint!}/transaction/announce`, headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.from(tx, 'hex').byteLength, diff --git a/apps/recovery-relay/lib/wallets/SOL/index.ts b/apps/recovery-relay/lib/wallets/SOL/index.ts index b3a6afe3..d2d32ccc 100644 --- a/apps/recovery-relay/lib/wallets/SOL/index.ts +++ b/apps/recovery-relay/lib/wallets/SOL/index.ts @@ -1,21 +1,20 @@ import { Buffer } from 'buffer'; import * as web3 from '@solana/web3.js'; import { ipcRenderer } from 'electron'; -import { Solana as BaseSolana, Input } from '@fireblocks/wallet-derivation'; +import { Solana as BaseSolana } from '@fireblocks/wallet-derivation'; import { AccountData } from '../types'; import { ConnectedWallet } from '../ConnectedWallet'; export class Solana extends BaseSolana implements ConnectedWallet { - private readonly solConnection: web3.Connection; + public rpcURL: string | undefined; - constructor(input: Input) { - super(input); + private solConnection: web3.Connection | undefined; - const endpoint = input.isTestnet ? web3.clusterApiUrl('devnet') : web3.clusterApiUrl('mainnet-beta'); + public setRPCUrl(url: string): void { + this.rpcURL = url; - this.solConnection = new web3.Connection(endpoint, { + this.solConnection = new web3.Connection(url, { commitment: 'confirmed', - //@ts-ignore fetch: async (input: string | URL | Request, init) => { const res = await ipcRenderer.invoke('main_proc_fetch', input, init); return new Response(res); @@ -24,14 +23,14 @@ export class Solana extends BaseSolana implements ConnectedWallet { } public async getBalance() { - const lamports = await this.solConnection.getBalance(this.web3PubKey); + const lamports = await this.solConnection!.getBalance(this.web3PubKey); const balance = lamports / web3.LAMPORTS_PER_SOL; return balance; } public async broadcastTx(tx: string): Promise { try { - const txHash = await this.solConnection.sendRawTransaction(Buffer.from(tx, 'hex')); + const txHash = await this.solConnection!.sendRawTransaction(Buffer.from(tx, 'hex')); this.relayLogger.debug(`Solana: Tx broadcasted: ${txHash}`); return txHash; } catch (e) { @@ -42,7 +41,7 @@ export class Solana extends BaseSolana implements ConnectedWallet { public async prepare(): Promise { const accountBalance = await this.getBalance(); - let blockInfo = (await this.solConnection.getLatestBlockhash()).blockhash; + let blockInfo = (await this.solConnection!.getLatestBlockhash()).blockhash; //Simulate tx for fee const tx = new web3.Transaction({ feePayer: this.web3PubKey, recentBlockhash: blockInfo }); @@ -54,9 +53,9 @@ export class Solana extends BaseSolana implements ConnectedWallet { }), ); - const feeForTx = ((await this.solConnection.getFeeForMessage(tx.compileMessage())).value ?? 0) / web3.LAMPORTS_PER_SOL; + const feeForTx = ((await this.solConnection!.getFeeForMessage(tx.compileMessage())).value ?? 0) / web3.LAMPORTS_PER_SOL; - blockInfo = (await this.solConnection.getLatestBlockhash()).blockhash; + blockInfo = (await this.solConnection!.getLatestBlockhash()).blockhash; const extraParams = new Map(); extraParams.set(this.KEY_RECENT_BLOCKHASH, blockInfo); diff --git a/apps/recovery-relay/lib/wallets/TRON/index.ts b/apps/recovery-relay/lib/wallets/TRON/index.ts index 4ba57c23..9c74b611 100644 --- a/apps/recovery-relay/lib/wallets/TRON/index.ts +++ b/apps/recovery-relay/lib/wallets/TRON/index.ts @@ -1,16 +1,19 @@ -import { Tron as BaseTron, Input } from '@fireblocks/wallet-derivation'; +import { Tron as BaseTron } from '@fireblocks/wallet-derivation'; import superjson from 'superjson'; import { ConnectedWallet } from '../ConnectedWallet'; import { AccountData } from '../types'; export class Tron extends BaseTron implements ConnectedWallet { - private tronWeb; + private tronWeb: any | undefined; - constructor(input: Input) { - super(input); + public rpcURL: string | undefined; + + public setRPCUrl(url: string): void { + this.rpcURL = url; + // eslint-disable-next-line global-require const TronWeb = require('tronweb'); const { HttpProvider } = TronWeb.providers; - const endpointUrl = input.isTestnet ? 'https://api.shasta.trongrid.io' : 'https://api.trongrid.io'; + const endpointUrl = this.rpcURL; const fullNode = new HttpProvider(endpointUrl); const solidityNode = new HttpProvider(endpointUrl); const eventServer = new HttpProvider(endpointUrl); @@ -18,12 +21,12 @@ export class Tron extends BaseTron implements ConnectedWallet { } public async getBalance(): Promise { - return ((await this.tronWeb.trx.getBalance(this.address)) as number) / 1_000_000; + return ((await this.tronWeb!.trx.getBalance(this.address)) as number) / 1_000_000; } - public async prepare(to?: string): Promise { + public async prepare(): Promise { const balance = await this.getBalance(); - const blockData = await this.tronWeb.fullNode.request('wallet/getblock', { detail: false }, 'post'); + const blockData = await this.tronWeb!.fullNode.request('wallet/getblock', { detail: false }, 'post'); const metadata = { ref_block_bytes: blockData.block_header.raw_data.number.toString(16).slice(-4).padStart(4, '0'), ref_block_hash: blockData.blockID.slice(16, 32), @@ -31,8 +34,8 @@ export class Tron extends BaseTron implements ConnectedWallet { timestamp: blockData.block_header.raw_data.timestamp, }; - // let tx = await this.tronWeb.transactionBuilder.sendTrx(to, balance * 1_000_000, this.address); - // tx = await this.tronWeb.transactionBuilder.extendExpiration(tx, 600); // 10 minutes + // let tx = await this.tronWeb!.transactionBuilder.sendTrx(to, balance * 1_000_000, this.address); + // tx = await this.tronWeb!.transactionBuilder.extendExpiration(tx, 600); // 10 minutes const extraParams = new Map(); // extraParams.set(this.KEY_TX, superjson.stringify(tx)); extraParams.set(this.KEY_METADATA, metadata); @@ -48,13 +51,12 @@ export class Tron extends BaseTron implements ConnectedWallet { public async broadcastTx(txHex: string): Promise { const tx = superjson.parse(txHex); - const hash = await this.tronWeb.trx.sendRawTransaction(tx); + const hash = await this.tronWeb!.trx.sendRawTransaction(tx); if ('code' in hash) { this.relayLogger.error(`Tron: Error broadcasting tx: ${JSON.stringify(hash, null, 2)}`); throw new Error(hash.code); } this.relayLogger.debug(`Tron: Tx broadcasted: ${hash.txid}`); - //@ts-ignore return hash.txid; } } diff --git a/apps/recovery-relay/lib/wallets/XLM/index.ts b/apps/recovery-relay/lib/wallets/XLM/index.ts index d6f9e876..ccc6d165 100644 --- a/apps/recovery-relay/lib/wallets/XLM/index.ts +++ b/apps/recovery-relay/lib/wallets/XLM/index.ts @@ -1,18 +1,20 @@ -import { Stellar as BaseXLM, Input } from '@fireblocks/wallet-derivation'; +import { Stellar as BaseXLM } from '@fireblocks/wallet-derivation'; import { AccountResponse, Networks, Server, Transaction, xdr } from 'stellar-sdk'; import { ConnectedWallet } from '../ConnectedWallet'; import { AccountData } from '../types'; export class Stellar extends BaseXLM implements ConnectedWallet { - private xlmServer: Server; + public rpcURL: string | undefined; - private account: AccountResponse | undefined; + private xlmServer: Server | undefined; - constructor(input: Input) { - super(input); - this.xlmServer = new Server(input.isTestnet ? 'https://horizon-testnet.stellar.org/' : 'https://horizon.stellar.org/'); + public setRPCUrl(url: string): void { + this.rpcURL = url; + this.xlmServer = new Server(url); } + private account: AccountResponse | undefined; + public async getBalance(): Promise { await this._loadAccount(); const { balances } = this.account!; @@ -33,7 +35,7 @@ export class Stellar extends BaseXLM implements ConnectedWallet { const preparedData = { balance, - feeRate: await this.xlmServer.fetchBaseFee(), + feeRate: await this.xlmServer!.fetchBaseFee(), extraParams, insufficientBalance: balance < 0.00001, }; @@ -48,7 +50,7 @@ export class Stellar extends BaseXLM implements ConnectedWallet { this.isTestnet ? Networks.TESTNET : Networks.PUBLIC, ); try { - const txResponse = await this.xlmServer.submitTransaction(tx); + const txResponse = await this.xlmServer!.submitTransaction(tx); this.relayLogger.debug(`Stellar: Tx broadcasted: ${txResponse}`); return txResponse.hash; } catch (e: any) { @@ -66,6 +68,6 @@ export class Stellar extends BaseXLM implements ConnectedWallet { private async _loadAccount(): Promise { if (this.account !== undefined) return; - this.account = await this.xlmServer.loadAccount(this.address); + this.account = await this.xlmServer!.loadAccount(this.address); } } diff --git a/apps/recovery-relay/lib/wallets/XRP/index.ts b/apps/recovery-relay/lib/wallets/XRP/index.ts index 5b21dfb1..6d504a9d 100644 --- a/apps/recovery-relay/lib/wallets/XRP/index.ts +++ b/apps/recovery-relay/lib/wallets/XRP/index.ts @@ -1,4 +1,4 @@ -import { Ripple as BaseRipple, Input } from '@fireblocks/wallet-derivation'; +import { Ripple as BaseRipple } from '@fireblocks/wallet-derivation'; import { Client, SubmitResponse, xrpToDrops } from 'xrpl'; import getFeeXrp from 'xrpl/dist/npm/sugar/getFeeXrp'; import BigNumber from 'bignumber.js'; @@ -6,18 +6,20 @@ import { ConnectedWallet } from '../ConnectedWallet'; import { AccountData } from '../types'; export class Ripple extends BaseRipple implements ConnectedWallet { - private xrpClient: Client; + public rpcURL: string | undefined; - constructor(input: Input) { - super(input); - this.xrpClient = new Client(input.isTestnet ? 'wss://s.altnet.rippletest.net:51233' : 'wss://xrplcluster.com/'); + private xrpClient: Client | undefined; + + public setRPCUrl(url: string): void { + this.rpcURL = url; + this.xrpClient = new Client(url); } public async getBalance(): Promise { - if (!this.xrpClient.isConnected()) { - await this.xrpClient.connect(); + if (!this.xrpClient!.isConnected()) { + await this.xrpClient!.connect(); } - const balances = await this.xrpClient.getBalances(this.address); + const balances = await this.xrpClient!.getBalances(this.address); return balances .filter((tokenBalance) => tokenBalance.currency === 'XRP') .map((tokenBalance) => parseFloat(tokenBalance.value))[0]; @@ -26,21 +28,21 @@ export class Ripple extends BaseRipple implements ConnectedWallet { public async prepare(): Promise { const balance = await this.getBalance(); // Fee calculation - const netFeeXRP = await getFeeXrp(this.xrpClient); + const netFeeXRP = await getFeeXrp(this.xrpClient!); const netFeeDrops = xrpToDrops(netFeeXRP); let baseFee = new BigNumber(netFeeDrops); baseFee = BigNumber.sum(baseFee, new BigNumber(netFeeDrops).times(2).toString()); - const maxFeeDrops = xrpToDrops(this.xrpClient.maxFeeXRP); + const maxFeeDrops = xrpToDrops(this.xrpClient!.maxFeeXRP); const totalFee = BigNumber.min(baseFee, maxFeeDrops); const fee = totalFee.dp(0, BigNumber.ROUND_CEIL).toString(10); const extraParams = new Map(); - extraParams.set(this.KEY_LEDGER_SEQUENCE, (await this.xrpClient.getLedgerIndex()) + 100); + extraParams.set(this.KEY_LEDGER_SEQUENCE, (await this.xrpClient!.getLedgerIndex()) + 100); extraParams.set(this.KEY_FEE, fee); extraParams.set( this.KEY_SEQUENCE, ( - await this.xrpClient.request({ + await this.xrpClient!.request({ command: 'account_info', account: this.address, ledger_index: 'current', @@ -59,19 +61,19 @@ export class Ripple extends BaseRipple implements ConnectedWallet { } public async broadcastTx(tx: string): Promise { - if (!this.xrpClient.isConnected()) { - await this.xrpClient.connect(); + if (!this.xrpClient!.isConnected()) { + await this.xrpClient!.connect(); } try { - const { result: txResult } = (await this.xrpClient.submit(tx)) as SubmitResponse; + const { result: txResult } = (await this.xrpClient!.submit(tx)) as SubmitResponse; this.relayLogger.debug(`Ripple: Tx broadcasted: ${JSON.stringify(txResult, null, 2)}`); const { hash } = txResult.tx_json; if (!hash) { - const errorMessage = txResult.accepted - ? "Unknown error - Transaction didn't return hash" - : `Transaction not accepted: ${txResult.engine_result_message}`; - this.relayLogger.error('XRP: Failed to broadcast transaction', errorMessage, txResult); - throw new Error(errorMessage); + const errorMessage = txResult.accepted + ? "Unknown error - Transaction didn't return hash" + : `Transaction not accepted: ${txResult.engine_result_message}`; + this.relayLogger.error('XRP: Failed to broadcast transaction', errorMessage, txResult); + throw new Error(errorMessage); } return hash; } catch (e) { diff --git a/apps/recovery-relay/lib/wallets/XTZ/index.ts b/apps/recovery-relay/lib/wallets/XTZ/index.ts index bd56f239..e24cee3a 100644 --- a/apps/recovery-relay/lib/wallets/XTZ/index.ts +++ b/apps/recovery-relay/lib/wallets/XTZ/index.ts @@ -1,5 +1,6 @@ -import { Tezos as BaseXTZ, Input } from '@fireblocks/wallet-derivation'; -import { DEFAULT_FEE, DEFAULT_STORAGE_LIMIT, TezosToolkit } from '@taquito/taquito'; +/* eslint-disable @typescript-eslint/naming-convention */ +import { Tezos as BaseXTZ } from '@fireblocks/wallet-derivation'; +import { DEFAULT_FEE, TezosToolkit } from '@taquito/taquito'; import axios from 'axios'; import { ConnectedWallet } from '../ConnectedWallet'; import { AccountData } from '../types'; @@ -7,17 +8,19 @@ import BigNumber from 'bignumber.js'; import { NoopSigner } from './NoopSigner'; export class Tezos extends BaseXTZ implements ConnectedWallet { - private tezos: TezosToolkit; + public rpcURL: string | undefined; - constructor(input: Input) { - super(input); - this.tezos = new TezosToolkit(input.isTestnet ? 'https://ghostnet.smartpy.io' : 'https://rpc.tzbeta.net'); + private tezos: TezosToolkit | undefined; + + public setRPCUrl(url: string): void { + this.rpcURL = url; + this.tezos = new TezosToolkit(url); this.tezos.setSignerProvider(new NoopSigner(this.publicKey, this.address)); } public async getBalance(): Promise { // TODO: Big number consideration? - return (await this.tezos.tz.getBalance(this.address)).toNumber() / 10 ** 6; + return (await this.tezos!.tz.getBalance(this.address)).toNumber() / 10 ** 6; } public async prepare(to?: string): Promise { @@ -28,7 +31,7 @@ export class Tezos extends BaseXTZ implements ConnectedWallet { insufficientBalance: true, }; } - const estimate = await this.tezos.estimate.transfer({ + const estimate = await this.tezos!.estimate.transfer({ to: to!, source: this.address, amount: Math.round((balance - DEFAULT_FEE.TRANSFER / 10 ** 6) * 10 ** 6) / 10 ** 6, @@ -36,10 +39,10 @@ export class Tezos extends BaseXTZ implements ConnectedWallet { const protocolConstants = await this._getProtocolConstants(); const accountLimit = await this._getAccountLimits(protocolConstants); - const blockHash = (await this.tezos.rpc.getBlockHeader()).hash; - const protocol = (await this.tezos.rpc.getProtocols({ block: 'head' })).next_protocol; - const headCounter = (await this.tezos.rpc.getContract(this.address, { block: 'head' })).counter || '0'; - const manager = await this.tezos.rpc.getManagerKey(this.address, { block: 'head' }); + const blockHash = (await this.tezos!.rpc.getBlockHeader()).hash; + const protocol = (await this.tezos!.rpc.getProtocols({ block: 'head' })).next_protocol; + const headCounter = (await this.tezos!.rpc.getContract(this.address, { block: 'head' })).counter || '0'; + const manager = await this.tezos!.rpc.getManagerKey(this.address, { block: 'head' }); const revealNeeded = !(manager && typeof manager === 'object' ? !!manager.key : !!manager); const extraParams = new Map(); @@ -75,7 +78,7 @@ export class Tezos extends BaseXTZ implements ConnectedWallet { }); this.relayLogger.debug(`Tezos: Tx broadcasted: ${JSON.stringify(res, null, 2)}`); return res.data; - // return await this.tezos.rpc.injectOperation(tx); + // return await this.tezos!.rpc.injectOperation(tx); } catch (e: any) { const resData = e.response.data; this.relayLogger.error(`Tezos: Error broadcasting tx: ${JSON.stringify(resData, null, 2)}`); @@ -97,7 +100,7 @@ export class Tezos extends BaseXTZ implements ConnectedWallet { cost_per_byte, tx_rollup_origination_size, smart_rollup_origination_size, - } = await this.tezos.rpc.getConstants({ block: 'head' }); + } = await this.tezos!.rpc.getConstants({ block: 'head' }); return { time_between_blocks, minimal_block_delay, @@ -111,7 +114,7 @@ export class Tezos extends BaseXTZ implements ConnectedWallet { } private async _getAccountLimits(constants: any) { - const balance = await this.tezos.rpc.getBalance(this.address, { block: 'head' }); + const balance = await this.tezos!.rpc.getBalance(this.address, { block: 'head' }); const { hard_gas_limit_per_operation, hard_storage_limit_per_operation, cost_per_byte } = constants; return {