Make waitForTransaction part of BaseBlockchain
This commit is contained in:
@@ -6,7 +6,7 @@ import {
|
||||
type BlockchainTransactions,
|
||||
} from './types.js';
|
||||
|
||||
import { type Transaction } from '@xocash/primitives';
|
||||
import { Transaction } from '@xocash/primitives';
|
||||
|
||||
export type BlockchainEvents = {
|
||||
isConnectedUpdated: boolean;
|
||||
@@ -177,4 +177,55 @@ export abstract class BaseBlockchain<
|
||||
transactionHash: string,
|
||||
callback: BlockchainCallback<TransactionNotificationPayload>,
|
||||
): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Waits for a transaction to be seen by the node.
|
||||
*
|
||||
* @param tx - The transaction to wait for. Can be a Uint8Array, Transaction instance, or a string.
|
||||
* @param timeoutMs - The maximum time to wait in milliseconds before timing out. Defaults to 10,000ms (10 seconds).
|
||||
* @returns A Promise that resolves when the transaction is seen by the node or rejects if the timeout is reached.
|
||||
* @throws Error if the transaction is not seen by the node within the specified timeout.
|
||||
*/
|
||||
async waitForTransaction(
|
||||
tx: Uint8Array | Transaction | string,
|
||||
timeoutMs = 10_000,
|
||||
) {
|
||||
// Cast the transaction.
|
||||
if (!(tx instanceof Transaction)) {
|
||||
tx = Transaction.from(tx);
|
||||
}
|
||||
|
||||
const txHash = tx.toHashHex();
|
||||
|
||||
// First, subscribe to the transaction
|
||||
let unsubscribeCallback: () => void;
|
||||
const subscriptionPromise = this.subscribeTransaction(txHash, () => {
|
||||
if (unsubscribeCallback) {
|
||||
unsubscribeCallback();
|
||||
}
|
||||
});
|
||||
|
||||
// Then create the wait promise without an async executor
|
||||
const waitForTxPromise = new Promise<void>((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
if (unsubscribeCallback) {
|
||||
unsubscribeCallback();
|
||||
}
|
||||
reject(new Error(`Failed to broadcast ${txHash}`));
|
||||
}, timeoutMs);
|
||||
|
||||
// Create a subscribe function so that we get notified when transaction is seen by network
|
||||
unsubscribeCallback = () => {
|
||||
clearTimeout(timeout);
|
||||
this.unsubscribeTransaction(txHash, unsubscribeCallback);
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
|
||||
// Wait for subscription to be set up first
|
||||
await subscriptionPromise;
|
||||
|
||||
// Then wait for either resolution or timeout
|
||||
return waitForTxPromise;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,40 +317,6 @@ export class BlockchainElectrum extends BaseBlockchain<
|
||||
return transactionsIndexed;
|
||||
}
|
||||
|
||||
async waitForTransaction(
|
||||
tx: Uint8Array | Transaction | string,
|
||||
timeoutMs = 10_000,
|
||||
) {
|
||||
// Cast the transaction.
|
||||
if (!(tx instanceof Transaction)) {
|
||||
tx = Transaction.from(tx);
|
||||
}
|
||||
|
||||
// Attempt to broadcast the transaction.
|
||||
const waitForTxPromise = new Promise<void>(async (resolve, reject) => {
|
||||
// Set a timeout.
|
||||
const timeout = setTimeout(() => {
|
||||
reject(new Error(`Failed to broadcast ${tx.toHashHex()}`));
|
||||
}, timeoutMs);
|
||||
|
||||
// Create a subscribe function so that we get notified when transaction is seen by network
|
||||
const subscribeCallback = () => {
|
||||
clearTimeout(timeout);
|
||||
this.unsubscribeTransaction(tx.toHashHex(), subscribeCallback);
|
||||
resolve();
|
||||
};
|
||||
|
||||
// Subscribe to the transaction.
|
||||
await this.subscribeTransaction(tx.toHashHex(), subscribeCallback);
|
||||
});
|
||||
|
||||
return waitForTxPromise;
|
||||
}
|
||||
|
||||
// TODO: Split out the "waitUntilSeen" into own function.
|
||||
// This'll be useful for protocols like BIP70/JPP/CashConnect, etc.
|
||||
// Also consider a fail callback:
|
||||
// If a "waitFor" fails, we probably want to invalidate the tx by sending those inputs elsewhere.
|
||||
async broadcastTransaction(
|
||||
tx: Transaction | Uint8Array | string,
|
||||
opts: BroadcastOpts = { timeoutMs: 10_000, waitUntilSeen: true },
|
||||
|
||||
Reference in New Issue
Block a user