From 0cfdda3742449ad36f833d94477f659784ca3e95 Mon Sep 17 00:00:00 2001 From: alvrs Date: Tue, 16 Apr 2024 14:16:10 +0100 Subject: [PATCH 1/4] feat(store-sync): add status and block number to return type of waitForTransaction --- packages/store-sync/src/common.ts | 6 ++++-- packages/store-sync/src/createStoreSync.ts | 20 +++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/packages/store-sync/src/common.ts b/packages/store-sync/src/common.ts index e1ba55fd76..bfaec16d62 100644 --- a/packages/store-sync/src/common.ts +++ b/packages/store-sync/src/common.ts @@ -1,4 +1,4 @@ -import { Address, Block, Hex, Log, PublicClient } from "viem"; +import { Address, Block, Hex, Log, PublicClient, TransactionReceipt } from "viem"; import { StoreEventsAbiItem, StoreEventsAbi } from "@latticexyz/store"; import { resolveConfig } from "@latticexyz/store/internal"; import { Observable } from "rxjs"; @@ -113,11 +113,13 @@ export type SyncOptions = { }; }; +export type WaitForTransactionResult = Pick; + export type SyncResult = { latestBlock$: Observable; latestBlockNumber$: Observable; storedBlockLogs$: Observable; - waitForTransaction: (tx: Hex) => Promise; + waitForTransaction: (tx: Hex) => Promise; }; // TODO: add optional, original log to this? diff --git a/packages/store-sync/src/createStoreSync.ts b/packages/store-sync/src/createStoreSync.ts index 4431a27003..914f63ac69 100644 --- a/packages/store-sync/src/createStoreSync.ts +++ b/packages/store-sync/src/createStoreSync.ts @@ -8,6 +8,7 @@ import { SyncOptions, SyncResult, internalTableIds, + WaitForTransactionResult, } from "./common"; import { createBlockStream } from "@latticexyz/block-logs-stream"; import { @@ -262,7 +263,7 @@ export async function createStoreSync( ); // TODO: move to its own file so we can test it, have its own debug instance, etc. - async function waitForTransaction(tx: Hex): Promise { + async function waitForTransaction(tx: Hex): Promise { debug("waiting for tx", tx); // This currently blocks for async call on each block processed @@ -271,17 +272,22 @@ export async function createStoreSync( // We use `mergeMap` instead of `concatMap` here to send the fetch request immediately when a new block range appears, // instead of sending the next request only when the previous one completed. mergeMap(async (blocks) => { - const txs = blocks.flatMap((block) => block.logs.map((op) => op.transactionHash).filter(isDefined)); - if (txs.includes(tx)) return true; + for (const block of blocks) { + const txs = block.logs.map((op) => op.transactionHash); + // If the transaction caused a log, it must have succeeded + if (txs.includes(tx)) return { blockNumber: block.blockNumber, status: "success" as const }; + } try { const lastBlock = blocks[0]; debug("fetching tx receipt for block", lastBlock.blockNumber); - const receipt = await publicClient.getTransactionReceipt({ hash: tx }); - return lastBlock.blockNumber >= receipt.blockNumber; + const { status, blockNumber } = await publicClient.getTransactionReceipt({ hash: tx }); + if (lastBlock.blockNumber >= blockNumber) { + return { status, blockNumber }; + } } catch (error) { if (error instanceof TransactionReceiptNotFoundError) { - return false; + return; } throw error; } @@ -289,7 +295,7 @@ export async function createStoreSync( tap((result) => debug("has tx?", tx, result)), ); - await firstValueFrom(hasTransaction$.pipe(filter(identity))); + return await firstValueFrom(hasTransaction$.pipe(filter(isDefined))); } return { From 17ec3d54f7a09a58f663a97f1548c8b37ea4f483 Mon Sep 17 00:00:00 2001 From: alvarius Date: Tue, 16 Apr 2024 14:20:21 +0100 Subject: [PATCH 2/4] Create warm-flies-reply.md --- .changeset/warm-flies-reply.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/warm-flies-reply.md diff --git a/.changeset/warm-flies-reply.md b/.changeset/warm-flies-reply.md new file mode 100644 index 0000000000..bae18cd34d --- /dev/null +++ b/.changeset/warm-flies-reply.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/store-sync": path +--- + +`waitForTransaction` now returns a `Promise<{ blockNumber: bigint, status: "success" | "reverted" }>` instead of `Promise`, to allow consumers to react to reverted transactions without refetching the transaction receipt. From f10d34452ca6bdf48fb956004d1e9741ae432316 Mon Sep 17 00:00:00 2001 From: alvarius Date: Tue, 16 Apr 2024 14:20:43 +0100 Subject: [PATCH 3/4] Update warm-flies-reply.md --- .changeset/warm-flies-reply.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/warm-flies-reply.md b/.changeset/warm-flies-reply.md index bae18cd34d..2e48423785 100644 --- a/.changeset/warm-flies-reply.md +++ b/.changeset/warm-flies-reply.md @@ -1,5 +1,5 @@ --- -"@latticexyz/store-sync": path +"@latticexyz/store-sync": patch --- `waitForTransaction` now returns a `Promise<{ blockNumber: bigint, status: "success" | "reverted" }>` instead of `Promise`, to allow consumers to react to reverted transactions without refetching the transaction receipt. From 4e35c97a658425bd6fbe482ca842d98363b09c56 Mon Sep 17 00:00:00 2001 From: alvrs Date: Tue, 16 Apr 2024 14:37:19 +0100 Subject: [PATCH 4/4] add tx hash to return type --- packages/store-sync/src/common.ts | 2 +- packages/store-sync/src/createStoreSync.ts | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/store-sync/src/common.ts b/packages/store-sync/src/common.ts index bfaec16d62..72ccd53248 100644 --- a/packages/store-sync/src/common.ts +++ b/packages/store-sync/src/common.ts @@ -113,7 +113,7 @@ export type SyncOptions = { }; }; -export type WaitForTransactionResult = Pick; +export type WaitForTransactionResult = Pick; export type SyncResult = { latestBlock$: Observable; diff --git a/packages/store-sync/src/createStoreSync.ts b/packages/store-sync/src/createStoreSync.ts index 914f63ac69..07c8279ab1 100644 --- a/packages/store-sync/src/createStoreSync.ts +++ b/packages/store-sync/src/createStoreSync.ts @@ -275,15 +275,17 @@ export async function createStoreSync( for (const block of blocks) { const txs = block.logs.map((op) => op.transactionHash); // If the transaction caused a log, it must have succeeded - if (txs.includes(tx)) return { blockNumber: block.blockNumber, status: "success" as const }; + if (txs.includes(tx)) { + return { blockNumber: block.blockNumber, status: "success" as const, transactionHash: tx }; + } } try { const lastBlock = blocks[0]; debug("fetching tx receipt for block", lastBlock.blockNumber); - const { status, blockNumber } = await publicClient.getTransactionReceipt({ hash: tx }); + const { status, blockNumber, transactionHash } = await publicClient.getTransactionReceipt({ hash: tx }); if (lastBlock.blockNumber >= blockNumber) { - return { status, blockNumber }; + return { status, blockNumber, transactionHash }; } } catch (error) { if (error instanceof TransactionReceiptNotFoundError) {