diff --git a/.changeset/empty-icons-pull.md b/.changeset/empty-icons-pull.md new file mode 100644 index 000000000..8a6e73761 --- /dev/null +++ b/.changeset/empty-icons-pull.md @@ -0,0 +1,5 @@ +--- +"@lightsparkdev/lightspark-sdk": patch +--- + +Move transaction polling into new client method diff --git a/apps/examples/uma-vasp/src/ReceivingVasp.ts b/apps/examples/uma-vasp/src/ReceivingVasp.ts index 4d3e5706d..8fffb3f3c 100644 --- a/apps/examples/uma-vasp/src/ReceivingVasp.ts +++ b/apps/examples/uma-vasp/src/ReceivingVasp.ts @@ -49,7 +49,6 @@ export default class ReceivingVasp { } private async handleUmaLnurlp(req: Request, res: Response, next: any) { - const uuid = req.params.uuid; let umaQuery: uma.LnurlpRequest; try { umaQuery = uma.parseLnurlpRequest( diff --git a/packages/lightspark-sdk/src/client.ts b/packages/lightspark-sdk/src/client.ts index d56996c4a..6321dc675 100644 --- a/packages/lightspark-sdk/src/client.ts +++ b/packages/lightspark-sdk/src/client.ts @@ -18,6 +18,7 @@ import { LightsparkException, LightsparkSigningException, NodeKeyCache, + pollUntil, Requester, SigningKeyType, StubAuthProvider, @@ -46,6 +47,7 @@ import { SendPayment } from "./graphql/SendPayment.js"; import { SingleNodeDashboard as SingleNodeDashboardQuery } from "./graphql/SingleNodeDashboard.js"; import { TransactionsForNode } from "./graphql/TransactionsForNode.js"; import { TransactionSubscription } from "./graphql/TransactionSubscription.js"; +import { TransactionStatus } from "./index.js"; import NodeKeyLoaderCache from "./NodeKeyLoaderCache.js"; import Account from "./objects/Account.js"; import { ApiTokenFromJson } from "./objects/ApiToken.js"; @@ -789,6 +791,53 @@ class LightsparkClient { ); } + /** + * Waits for a transaction to have a completed status, and returns the transaction. + * + * @param transactionId The ID of the transaction to wait for + * @param pollTimeoutSecs The timeout in seconds that we will wait before throwing an exception + */ + public async waitForTransactionComplete( + transactionId: string, + pollTimeoutSecs = 60, + ) { + const pollIntervalMs = 250; + const pollMaxTimeouts = (pollTimeoutSecs * 1000) / pollIntervalMs; + const pollIgnoreErrors = false; + + const transaction = (await pollUntil( + () => { + return this.getTransaction(transactionId); + }, + (current, response) => { + if ( + current && + [ + TransactionStatus.SUCCESS, + TransactionStatus.CANCELLED, + TransactionStatus.FAILED, + ].includes(current.status) + ) { + return { + stopPolling: true, + value: current, + }; + } + return response; + }, + pollIntervalMs, + pollMaxTimeouts, + pollIgnoreErrors, + () => + new LightsparkException( + "Timeout", + "Timeout waiting for transaction to complete.", + ), + )) as Transaction; + + return transaction; + } + /** * Sends a payment directly to a node on the Lightning Network through the public key of the node without an invoice. * diff --git a/packages/lightspark-sdk/src/tests/integration/client.test.ts b/packages/lightspark-sdk/src/tests/integration/client.test.ts index 4b9bea2b0..9f7b47ab1 100644 --- a/packages/lightspark-sdk/src/tests/integration/client.test.ts +++ b/packages/lightspark-sdk/src/tests/integration/client.test.ts @@ -6,7 +6,6 @@ import { BitcoinNetwork, PaymentRequestStatus, TransactionStatus, - type Transaction, } from "../../index.js"; import { logger } from "../../logger.js"; @@ -155,27 +154,14 @@ describe("lightspark-sdk client", () => { const payment = await lightsparkClient.payInvoice(nodeId, invoice, 60); log("payment.id", payment?.id); - const transaction = (await pollUntil( - () => { - if (!payment) { - throw new Error("No payment"); - } - return lightsparkClient.getTransaction(payment.id); - }, - (current, response) => { - if (current && current.status === TransactionStatus.SUCCESS) { - return { - stopPolling: true, - value: current, - }; - } - return response; - }, - pollIntervalMs, - pollMaxTimeouts, - pollIgnoreErrors, - () => new Error("Timeout waiting for payment to be received"), - )) as Transaction; + if (!payment) { + throw new Error("No payment"); + } + + const transaction = await lightsparkClient.waitForTransactionComplete( + payment.id, + pollTimeoutSecs, + ); expect(transaction.status).toEqual(TransactionStatus.SUCCESS); }, 30_000);