UNPKG

@stellar/stellar-sdk

Version:

A library for working with the Stellar network, including communication with the Horizon and Soroban RPC servers.

122 lines (119 loc) 4.53 kB
import { Api } from '../rpc/api.js'; import { RpcServer } from '../rpc/server.js'; import { withExponentialBackoff } from './utils.js'; import { DEFAULT_TIMEOUT } from './types.js'; class SentTransaction { constructor(assembled) { this.assembled = assembled; const { server, allowHttp, headers, rpcUrl } = this.assembled.options; this.server = server ?? new RpcServer(rpcUrl, { allowHttp, headers }); } assembled; server; /** * The result of calling `sendTransaction` to broadcast the transaction to the * network. */ sendTransactionResponse; /** * If `sendTransaction` completes successfully (which means it has `status: 'PENDING'`), * then `getTransaction` will be called in a loop for * {@link MethodOptions.timeoutInSeconds} seconds. This array contains all * the results of those calls. */ getTransactionResponseAll; /** * The most recent result of calling `getTransaction`, from the * `getTransactionResponseAll` array. */ getTransactionResponse; static Errors = { SendFailed: class SendFailedError extends Error { }, SendResultOnly: class SendResultOnlyError extends Error { }, TransactionStillPending: class TransactionStillPendingError extends Error { } }; /** * Initialize a `SentTransaction` from {@link AssembledTransaction} * `assembled`, passing an optional {@link Watcher} `watcher`. This will also * send the transaction to the network. */ static init = async (assembled, watcher) => { const tx = new SentTransaction(assembled); const sent = await tx.send(watcher); return sent; }; send = async (watcher) => { this.sendTransactionResponse = await this.server.sendTransaction( this.assembled.signed ); if (this.sendTransactionResponse.status !== "PENDING") { throw new SentTransaction.Errors.SendFailed( `Sending the transaction to the network failed! ${JSON.stringify( this.sendTransactionResponse, null, 2 )}` ); } if (watcher?.onSubmitted) watcher.onSubmitted(this.sendTransactionResponse); const { hash } = this.sendTransactionResponse; const timeoutInSeconds = this.assembled.options.timeoutInSeconds ?? DEFAULT_TIMEOUT; this.getTransactionResponseAll = await withExponentialBackoff( async () => { const tx = await this.server.getTransaction(hash); if (watcher?.onProgress) watcher.onProgress(tx); return tx; }, (resp) => resp.status === Api.GetTransactionStatus.NOT_FOUND, timeoutInSeconds ); this.getTransactionResponse = this.getTransactionResponseAll[this.getTransactionResponseAll.length - 1]; if (this.getTransactionResponse.status === Api.GetTransactionStatus.NOT_FOUND) { throw new SentTransaction.Errors.TransactionStillPending( `Waited ${timeoutInSeconds} seconds for transaction to complete, but it did not. Returning anyway. Check the transaction status manually. Sent transaction: ${JSON.stringify( this.sendTransactionResponse, null, 2 )} All attempts to get the result: ${JSON.stringify( this.getTransactionResponseAll, null, 2 )}` ); } return this; }; get result() { if ("getTransactionResponse" in this && this.getTransactionResponse) { if ("returnValue" in this.getTransactionResponse) { return this.assembled.options.parseResultXdr( this.getTransactionResponse.returnValue ); } throw new Error("Transaction failed! Cannot parse result."); } if (this.sendTransactionResponse) { const errorResult = this.sendTransactionResponse.errorResult?.result(); if (errorResult) { throw new SentTransaction.Errors.SendFailed( `Transaction simulation looked correct, but attempting to send the transaction failed. Check \`simulation\` and \`sendTransactionResponseAll\` to troubleshoot. Decoded \`sendTransactionResponse.errorResultXdr\`: ${errorResult}` ); } throw new SentTransaction.Errors.SendResultOnly( `Transaction was sent to the network, but not yet awaited. No result to show. Await transaction completion with \`getTransaction(sendTransactionResponse.hash)\`` ); } throw new Error( `Sending transaction failed: ${JSON.stringify(this.assembled.signed)}` ); } } class Watcher { } export { SentTransaction, Watcher }; //# sourceMappingURL=sent_transaction.js.map