From 25b484022a01530323694d19a35e8e7cc20635ac Mon Sep 17 00:00:00 2001 From: Harvey Zuccon Date: Tue, 2 Sep 2025 07:09:41 +0000 Subject: [PATCH] Resolve "Wallets: Emit statusUpdated if payload is not specialized" --- .../src/blockchain/blockchain-inmemory.ts | 37 +++++-------------- packages/stack/src/wallet/wallet-p2pkh.ts | 15 +++++--- 2 files changed, 19 insertions(+), 33 deletions(-) diff --git a/packages/stack/src/blockchain/blockchain-inmemory.ts b/packages/stack/src/blockchain/blockchain-inmemory.ts index 3b68c2e..4fb5111 100644 --- a/packages/stack/src/blockchain/blockchain-inmemory.ts +++ b/packages/stack/src/blockchain/blockchain-inmemory.ts @@ -6,8 +6,7 @@ import { type BlockchainUTXO, type BlockchainUTXOs, type BlockchainChainTip, - AddressStatusPayload, - BlockHeightPayload, + type BlockHeightPayload, } from './types.js'; import { @@ -29,10 +28,7 @@ import { /** * @remarks This provider DOES NOT enforce the 100 confirmations Coinbase Transaction rule. **/ -export class BlockchainInMemory extends BaseBlockchain< - AddressStatusPayload, - BlockHeightPayload -> { +export class BlockchainInMemory extends BaseBlockchain { static async from(this: T) { const blockchain = new this(); await blockchain.start(); @@ -41,10 +37,7 @@ export class BlockchainInMemory extends BaseBlockchain< private blockHeaders: Array; private transactions: BlockchainTransactions; - private addressSubscriptions: Map< - string, - Set> - >; + private addressSubscriptions: Map>; private transactionSubscriptions: Map>; constructor() { @@ -177,7 +170,7 @@ export class BlockchainInMemory extends BaseBlockchain< async subscribeLockscript( lockscript: string | Uint8Array, - callback: BlockchainCallback, + callback: BlockchainCallback, ) { // Fulcrum does not support subscribing to lockscripts, so we cast it to an address. const address = Address.fromLockscript(lockscript); @@ -191,7 +184,7 @@ export class BlockchainInMemory extends BaseBlockchain< async unsubscribeLockscript( lockscript: string | Uint8Array, - callback: BlockchainCallback, + callback: BlockchainCallback, ): Promise { // Fulcrum does not support subscribing to lockscripts, so we cast it to an address. const address = Address.fromLockscript(lockscript); @@ -203,10 +196,7 @@ export class BlockchainInMemory extends BaseBlockchain< return await this.unsubscribeAddress(address.toCashAddr(), callback); } - async subscribeAddress( - address: string, - callback: BlockchainCallback, - ) { + async subscribeAddress(address: string, callback: BlockchainCallback) { // Convert the address to it's lockscript hex so that it's consistently represented. const lockscriptHex = Address.from(address).toLockscriptHex(); @@ -222,10 +212,7 @@ export class BlockchainInMemory extends BaseBlockchain< return async () => await this.unsubscribeAddress(address, callback); } - async unsubscribeAddress( - address: string, - callback: BlockchainCallback, - ) { + async unsubscribeAddress(address: string, callback: BlockchainCallback) { // Convert the address to it's lockscript hex so that it's consistently represented. const lockscriptHex = Address.from(address).toLockscriptHex(); @@ -282,12 +269,6 @@ export class BlockchainInMemory extends BaseBlockchain< } private notifyAddressSubscribers(tx: Transaction) { - const payload = { - type: 'address-status', - // 32 random characters. Since we only need this to be unique per transaction, we can just randomise the first 16 bytes and pad the rest with 0s. - status: Math.random().toString(36).substring(2).padEnd(32, '0'), - } as const; - // First, notify all source output listeners. tx.getInputs().forEach((input) => { // Skip coinbase-like inputs @@ -307,7 +288,7 @@ export class BlockchainInMemory extends BaseBlockchain< const callbacks = this.addressSubscriptions.get(address); if (callbacks) { - callbacks.forEach((callback) => callback(address, payload)); + callbacks.forEach((callback) => callback(address)); } }); @@ -320,7 +301,7 @@ export class BlockchainInMemory extends BaseBlockchain< const callbacks = this.addressSubscriptions.get(address); if (callbacks) { - callbacks.forEach((callback) => callback(address, payload)); + callbacks.forEach((callback) => callback(address)); } }); } diff --git a/packages/stack/src/wallet/wallet-p2pkh.ts b/packages/stack/src/wallet/wallet-p2pkh.ts index 0d5c28f..6e729f1 100644 --- a/packages/stack/src/wallet/wallet-p2pkh.ts +++ b/packages/stack/src/wallet/wallet-p2pkh.ts @@ -380,14 +380,19 @@ export class WalletP2PKH extends BaseWallet { _address: string, payload?: AddressStatusPayload, ) { - // If wallet state has changed... - if (payload && payload.status !== this.status) { + // Not all blockchain adapters will provide a status payload. But if they do, we check if it's the same as our current status. + // If it is, we don't want the wallet to try to update its state as it will be the same and is a waste of resources. + if (payload && payload.status === this.status) { + return; + } + + if (payload) { // Set our new status. this.status = payload.status; - - // Emit an event. - this.emit('stateUpdated', this.status); } + + // Emit an event. + this.emit('stateUpdated', this.status); } }