Skip to content

Commit

Permalink
feat(store-sync): add status and block number to return type of waitF…
Browse files Browse the repository at this point in the history
…orTransaction (#2668)
  • Loading branch information
alvrs authored Apr 16, 2024
1 parent de3bc3d commit 8c3dcf7
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/warm-flies-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@latticexyz/store-sync": patch
---

`waitForTransaction` now returns a `Promise<{ blockNumber: bigint, status: "success" | "reverted" }>` instead of `Promise<void>`, to allow consumers to react to reverted transactions without refetching the transaction receipt.
6 changes: 4 additions & 2 deletions packages/store-sync/src/common.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -113,11 +113,13 @@ export type SyncOptions<config extends StoreConfig = StoreConfig> = {
};
};

export type WaitForTransactionResult = Pick<TransactionReceipt, "blockNumber" | "status" | "transactionHash">;

export type SyncResult = {
latestBlock$: Observable<Block>;
latestBlockNumber$: Observable<bigint>;
storedBlockLogs$: Observable<StorageAdapterBlock>;
waitForTransaction: (tx: Hex) => Promise<void>;
waitForTransaction: (tx: Hex) => Promise<WaitForTransactionResult>;
};

// TODO: add optional, original log to this?
Expand Down
22 changes: 15 additions & 7 deletions packages/store-sync/src/createStoreSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
SyncOptions,
SyncResult,
internalTableIds,
WaitForTransactionResult,
} from "./common";
import { createBlockStream } from "@latticexyz/block-logs-stream";
import {
Expand Down Expand Up @@ -262,7 +263,7 @@ export async function createStoreSync<config extends StoreConfig = StoreConfig>(
);

// TODO: move to its own file so we can test it, have its own debug instance, etc.
async function waitForTransaction(tx: Hex): Promise<void> {
async function waitForTransaction(tx: Hex): Promise<WaitForTransactionResult> {
debug("waiting for tx", tx);

// This currently blocks for async call on each block processed
Expand All @@ -271,25 +272,32 @@ export async function createStoreSync<config extends StoreConfig = StoreConfig>(
// 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, transactionHash: tx };
}
}

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, transactionHash } = await publicClient.getTransactionReceipt({ hash: tx });
if (lastBlock.blockNumber >= blockNumber) {
return { status, blockNumber, transactionHash };
}
} catch (error) {
if (error instanceof TransactionReceiptNotFoundError) {
return false;
return;
}
throw error;
}
}),
tap((result) => debug("has tx?", tx, result)),
);

await firstValueFrom(hasTransaction$.pipe(filter(identity)));
return await firstValueFrom(hasTransaction$.pipe(filter(isDefined)));
}

return {
Expand Down

0 comments on commit 8c3dcf7

Please sign in to comment.