From 2f362435a51e77f60bb3413e90bc7a1154fb7da4 Mon Sep 17 00:00:00 2001 From: Josep M Sobrepere Date: Fri, 17 May 2024 17:20:05 +0200 Subject: [PATCH] Fixing "Invalid" Error II (#407) I probably did a bad job at explanning how `shareReplay` works, my apologies. The thing is that every time that with `shareReplay` every time that its internal refCount goes down to zero, then it unsubscribes from the source. Therefore, there must be a subscription always open for the observable to be "shared". This is because observables are not eager. What was happening is that every time the old code was performing a `firstValueFrom` that creates a subscription and when the condition is met (and the promise resolves) then it unsubscribes from the observable. Since that was its only subscription, then the refcount goes down to 0 and the observable dies. So, the next `firstValueFrom` creates a brand new subscription. I realize that people coming from PJS may find Observables difficult to deal with. So, we will probably add an optional callback to the promise based functions so that you can introspect what's going on under the hood without having to learn how to work with observables. --- src/dripper/polkadot/PolkadotActions.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/dripper/polkadot/PolkadotActions.ts b/src/dripper/polkadot/PolkadotActions.ts index fe6ddf43..de0bca20 100644 --- a/src/dripper/polkadot/PolkadotActions.ts +++ b/src/dripper/polkadot/PolkadotActions.ts @@ -112,19 +112,19 @@ export class PolkadotActions { // client.submit(tx) waits for the finalized value, which might be important for real money, // but for the faucet drips, early respond is better UX const submit$ = client.submitAndWatch(tx).pipe(shareReplay(1)); - - const hash = (await firstValueFrom(submit$.pipe(filter((value) => value.type === "broadcasted")))).txHash; - - void firstValueFrom(submit$.pipe(filter((value) => value.type === "finalized"))) - .catch((err) => { - logger.error(`Transaction ${hash} failed to finalize`, err); - }) - .finally(() => { + let hash = ""; + submit$.subscribe({ + error: (err) => { + if (hash) logger.error(`Transaction ${hash} failed to finalize`, err); this.#pendingTransactions.delete(tx); - }); - - await firstValueFrom(submit$.pipe(filter((value) => value.type === "txBestBlocksState" && value.found))); + }, + complete: () => { + this.#pendingTransactions.delete(tx); + }, + }); + hash = (await firstValueFrom(submit$.pipe(filter((value) => value.type === "txBestBlocksState" && value.found)))) + .txHash; return hash; }