diff --git a/backend/src/api/services/wallets.ts b/backend/src/api/services/wallets.ts index b20087ead..eea4ee129 100644 --- a/backend/src/api/services/wallets.ts +++ b/backend/src/api/services/wallets.ts @@ -9,55 +9,52 @@ interface WalletAddress { address: string; active: boolean; transactions?: IEsploraApi.AddressTxSummary[]; + lastSync: number; } -interface WalletConfig { - url: string; +interface Wallet { name: string; - apiKey: string; -} - -interface Wallet extends WalletConfig { addresses: Record; lastPoll: number; } -const POLL_FREQUENCY = 60 * 60 * 1000; // 1 hour +const POLL_FREQUENCY = 5 * 60 * 1000; // 5 minutes class WalletApi { private wallets: Record = {}; private syncing = false; constructor() { - this.wallets = (config.WALLETS.WALLETS as WalletConfig[]).reduce((acc, wallet) => { - acc[wallet.name] = { ...wallet, addresses: {}, lastPoll: 0 }; + this.wallets = config.WALLETS.ENABLED ? (config.WALLETS.WALLETS as string[]).reduce((acc, wallet) => { + acc[wallet] = { name: wallet, addresses: {}, lastPoll: 0 }; return acc; - }, {} as Record); + }, {} as Record) : {}; } public getWallet(wallet: string): Record { return this.wallets?.[wallet]?.addresses || {}; } - // resync wallet addresses from the provided API + // resync wallet addresses from the services backend async $syncWallets(): Promise { + if (!config.WALLETS.ENABLED) { + return; + } this.syncing = true; for (const walletKey of Object.keys(this.wallets)) { const wallet = this.wallets[walletKey]; if (wallet.lastPoll < (Date.now() - POLL_FREQUENCY)) { try { - const response = await axios.get(`${wallet.url}/${wallet.name}`, { headers: { 'Authorization': `${wallet.apiKey}` } }); - const data: { walletBalances: WalletAddress[] } = response.data; - const addresses = data.walletBalances; - const newAddresses: Record = {}; + const response = await axios.get(config.MEMPOOL_SERVICES.API + `/wallets/${wallet.name}`); + const addresses: Record = response.data; + const addressList: WalletAddress[] = Object.values(addresses); // sync all current addresses - for (const address of addresses) { + for (const address of addressList) { await this.$syncWalletAddress(wallet, address); - newAddresses[address.address] = true; } // remove old addresses for (const address of Object.keys(wallet.addresses)) { - if (!newAddresses[address]) { + if (!addresses[address]) { delete wallet.addresses[address]; } } @@ -73,16 +70,16 @@ class WalletApi { // resync address transactions from esplora async $syncWalletAddress(wallet: Wallet, address: WalletAddress): Promise { - // fetch full transaction data if the address is new or still active - const refreshTransactions = !wallet.addresses[address.address] || address.active; + // fetch full transaction data if the address is new or still active and hasn't been synced in the last hour + const refreshTransactions = !wallet.addresses[address.address] || (address.active && (Date.now() - wallet.addresses[address.address].lastSync) > 60 * 60 * 1000); if (refreshTransactions) { try { const walletAddress: WalletAddress = { address: address.address, active: address.active, transactions: await bitcoinApi.$getAddressTransactionSummary(address.address), + lastSync: Date.now(), }; - logger.debug(`Synced ${walletAddress.transactions?.length || 0} transactions for wallet ${wallet.name} address ${address.address}`); wallet.addresses[address.address] = walletAddress; } catch (e) { logger.err(`Error syncing wallet address ${address.address}: ${(e instanceof Error ? e.message : e)}`); diff --git a/backend/src/config.ts b/backend/src/config.ts index ee95be62d..794421551 100644 --- a/backend/src/config.ts +++ b/backend/src/config.ts @@ -164,11 +164,7 @@ interface IConfig { }, WALLETS: { ENABLED: boolean; - WALLETS: { - url: string; - name: string; - apiKey: string; - }[]; + WALLETS: string[]; } }