@latticexyz/store-sync 2.2.18 → 2.2.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-IWCYCRDZ.js → chunk-BSNHZRRW.js} +2 -2
- package/dist/{chunk-IWCYCRDZ.js.map → chunk-BSNHZRRW.js.map} +1 -1
- package/dist/exports/internal.js +1 -1
- package/dist/index.js +1 -1
- package/dist/postgres/index.js +1 -1
- package/dist/postgres-decoded/index.js +1 -1
- package/dist/recs/index.js +1 -1
- package/dist/sqlite/index.js +1 -1
- package/dist/zustand/index.js +1 -1
- package/package.json +10 -10
|
@@ -208,7 +208,7 @@ import { getChainId, getTransactionReceipt } from "viem/actions";
|
|
|
208
208
|
// package.json
|
|
209
209
|
var package_default = {
|
|
210
210
|
name: "@latticexyz/store-sync",
|
|
211
|
-
version: "2.2.
|
|
211
|
+
version: "2.2.19",
|
|
212
212
|
description: "Utilities to sync MUD Store events with a client or cache",
|
|
213
213
|
repository: {
|
|
214
214
|
type: "git",
|
|
@@ -640,4 +640,4 @@ export {
|
|
|
640
640
|
SyncStep,
|
|
641
641
|
createStoreSync
|
|
642
642
|
};
|
|
643
|
-
//# sourceMappingURL=chunk-
|
|
643
|
+
//# sourceMappingURL=chunk-BSNHZRRW.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/SyncStep.ts","../src/createStoreSync.ts","../src/fromEventSource.ts","../src/fetchAndStoreLogs.ts","../src/watchLogs.ts","../package.json"],"sourcesContent":["export enum SyncStep {\n INITIALIZE = \"initialize\",\n SNAPSHOT = \"snapshot\",\n RPC = \"rpc\",\n LIVE = \"live\",\n}\n","import { MUDChain } from \"@latticexyz/common/chains\";\nimport { storeEventsAbi } from \"@latticexyz/store\";\nimport { GetTransactionReceiptErrorType, Hex, parseEventLogs } from \"viem\";\nimport { entryPoint07Abi } from \"viem/account-abstraction\";\nimport {\n StorageAdapter,\n StorageAdapterBlock,\n StoreEventsLog,\n SyncFilter,\n SyncOptions,\n SyncResult,\n internalTableIds,\n WaitForTransactionResult,\n} from \"./common\";\nimport { createBlockStream, getRpcClient } from \"@latticexyz/block-logs-stream\";\nimport {\n filter,\n map,\n tap,\n from,\n concat,\n concatMap,\n share,\n firstValueFrom,\n defer,\n of,\n catchError,\n shareReplay,\n combineLatest,\n scan,\n mergeMap,\n throwError,\n mergeWith,\n ignoreElements,\n} from \"rxjs\";\nimport { debug as parentDebug } from \"./debug\";\nimport { SyncStep } from \"./SyncStep\";\nimport { bigIntMax, chunk, isDefined, waitForIdle } from \"@latticexyz/common/utils\";\nimport { getSnapshot } from \"./getSnapshot\";\nimport { fromEventSource } from \"./fromEventSource\";\nimport { fetchAndStoreLogs } from \"./fetchAndStoreLogs\";\nimport { isLogsApiResponse } from \"./indexer-client/isLogsApiResponse\";\nimport { toStorageAdapterBlock } from \"./indexer-client/toStorageAdapterBlock\";\nimport { watchLogs } from \"./watchLogs\";\nimport { getAction } from \"viem/utils\";\nimport { getChainId, getTransactionReceipt } from \"viem/actions\";\nimport packageJson from \"../package.json\";\n\nconst debug = parentDebug.extend(\"createStoreSync\");\n\nconst defaultFilters: SyncFilter[] = internalTableIds.map((tableId) => ({ tableId }));\n\ntype CreateStoreSyncOptions = SyncOptions & {\n storageAdapter: StorageAdapter;\n onProgress?: (opts: {\n step: SyncStep;\n percentage: number;\n latestBlockNumber: bigint;\n lastBlockNumberProcessed: bigint;\n message: string;\n }) => void;\n};\n\nexport async function createStoreSync({\n storageAdapter,\n onProgress,\n address,\n filters: initialFilters = [],\n tableIds = [],\n followBlockTag = \"latest\",\n startBlock: initialStartBlock = 0n,\n maxBlockRange,\n initialState,\n initialBlockLogs,\n ...opts\n}: CreateStoreSyncOptions): Promise<SyncResult> {\n const filters: SyncFilter[] =\n initialFilters.length || tableIds.length\n ? [...initialFilters, ...tableIds.map((tableId) => ({ tableId })), ...defaultFilters]\n : [];\n\n const logFilter = filters.length\n ? (log: StoreEventsLog): boolean =>\n filters.some(\n (filter) =>\n filter.tableId === log.args.tableId &&\n (filter.key0 == null || filter.key0 === log.args.keyTuple[0]) &&\n (filter.key1 == null || filter.key1 === log.args.keyTuple[1]),\n )\n : undefined;\n\n const publicClient = getRpcClient(opts);\n const indexerUrl = ((): string | undefined => {\n if (opts.indexerUrl === false) return;\n if (opts.indexerUrl) return opts.indexerUrl;\n if (publicClient.chain) return (publicClient.chain as MUDChain).indexerUrl;\n })();\n\n const chainId = publicClient.chain?.id ?? (await getAction(publicClient, getChainId, \"getChainId\")({}));\n\n const initialBlockLogs$ = defer(async (): Promise<StorageAdapterBlock | undefined> => {\n onProgress?.({\n step: SyncStep.SNAPSHOT,\n percentage: 0,\n latestBlockNumber: 0n,\n lastBlockNumberProcessed: 0n,\n message: \"Getting snapshot\",\n });\n\n const snapshot = await getSnapshot({\n chainId,\n address,\n filters,\n initialState,\n initialBlockLogs,\n indexerUrl,\n });\n\n onProgress?.({\n step: SyncStep.SNAPSHOT,\n percentage: 100,\n latestBlockNumber: 0n,\n lastBlockNumberProcessed: 0n,\n message: \"Got snapshot\",\n });\n\n return snapshot;\n }).pipe(\n catchError((error) => {\n debug(\"error getting snapshot\", error);\n\n onProgress?.({\n step: SyncStep.SNAPSHOT,\n percentage: 100,\n latestBlockNumber: 0n,\n lastBlockNumberProcessed: initialStartBlock,\n message: \"Failed to get snapshot\",\n });\n\n return of(undefined);\n }),\n shareReplay(1),\n );\n\n const storedInitialBlockLogs$ = initialBlockLogs$.pipe(\n filter(isDefined),\n concatMap(async ({ blockNumber, logs }) => {\n debug(\"hydrating\", logs.length, \"logs to block\", blockNumber);\n\n onProgress?.({\n step: SyncStep.SNAPSHOT,\n percentage: 0,\n latestBlockNumber: 0n,\n lastBlockNumberProcessed: blockNumber,\n message: \"Hydrating from snapshot\",\n });\n\n // Split snapshot operations into chunks so we can update the progress callback (and ultimately render visual progress for the user).\n // This isn't ideal if we want to e.g. batch load these into a DB in a single DB tx, but we'll take it.\n //\n // Split into 50 equal chunks (for better `onProgress` updates) but only if we have 100+ items per chunk\n const chunkSize = Math.max(100, Math.floor(logs.length / 50));\n const chunks = Array.from(chunk(logs, chunkSize));\n for (const [i, chunk] of chunks.entries()) {\n await storageAdapter({ blockNumber, logs: chunk });\n onProgress?.({\n step: SyncStep.SNAPSHOT,\n percentage: ((i + 1) / chunks.length) * 100,\n latestBlockNumber: 0n,\n lastBlockNumberProcessed: blockNumber,\n message: \"Hydrating from snapshot\",\n });\n\n // RECS is a synchronous API so hydrating in a loop like this blocks downstream render cycles\n // that would display the percentage climbing up to 100.\n // We wait for idle callback here to give rendering a chance to complete.\n await waitForIdle();\n }\n\n onProgress?.({\n step: SyncStep.SNAPSHOT,\n percentage: 100,\n latestBlockNumber: 0n,\n lastBlockNumberProcessed: blockNumber,\n message: \"Hydrated from snapshot\",\n });\n\n return { blockNumber, logs };\n }),\n shareReplay(1),\n );\n\n let startBlock: bigint | null = null;\n const startBlock$ = initialBlockLogs$.pipe(\n map((block) => bigIntMax(block?.blockNumber ?? 0n, initialStartBlock)),\n // TODO: if start block is still 0, find via deploy event\n tap((blockNumber) => {\n startBlock = blockNumber;\n debug(\"starting sync from block\", startBlock);\n }),\n );\n\n let latestBlockNumber: bigint | null = null;\n const latestBlock$ = createBlockStream({ ...opts, blockTag: followBlockTag }).pipe(shareReplay(1));\n const latestBlockNumber$ = latestBlock$.pipe(\n map((block) => block.number),\n tap((blockNumber) => {\n latestBlockNumber = blockNumber;\n debug(\"on block number\", blockNumber, \"for\", followBlockTag, \"block tag\");\n }),\n shareReplay(1),\n );\n\n let lastBlockNumberProcessed: bigint | null = null;\n let caughtUp = false;\n\n const pendingLogsWebSocketUrl = publicClient.chain?.rpcUrls?.wiresaw?.webSocket?.[0];\n const storedPendingLogs$ = pendingLogsWebSocketUrl\n ? startBlock$.pipe(\n mergeMap((startBlock) => watchLogs({ url: pendingLogsWebSocketUrl, address, fromBlock: startBlock }).logs$),\n concatMap(async (block) => {\n await storageAdapter(block);\n return block;\n }),\n mergeWith(\n // The watchLogs API doesn't emit on empty logs, but consumers expect an emission on empty logs\n latestBlockNumber$.pipe(map((blockNumber) => ({ blockNumber, logs: [] }))),\n ),\n )\n : throwError(() => new Error(\"No pending logs WebSocket RPC URL provided\"));\n\n const storedIndexerLogs$ = indexerUrl\n ? startBlock$.pipe(\n mergeMap((startBlock) => {\n const url = new URL(\n `api/logs-live?${new URLSearchParams({\n input: JSON.stringify({ chainId, address, filters }),\n block_num: startBlock.toString(),\n include_tx_hash: \"true\",\n })}`,\n indexerUrl,\n );\n return fromEventSource<string>(url);\n }),\n map((messageEvent) => {\n const data = JSON.parse(messageEvent.data);\n if (!isLogsApiResponse(data)) {\n throw new Error(\"Received unexpected from indexer:\" + messageEvent.data);\n }\n return toStorageAdapterBlock(data);\n }),\n concatMap(async (block) => {\n await storageAdapter(block);\n return block;\n }),\n )\n : throwError(() => new Error(\"No indexer URL provided\"));\n\n const storedEthRpcLogs$ = combineLatest([startBlock$, latestBlockNumber$]).pipe(\n map(([startBlock, endBlock]) => ({ startBlock, endBlock })),\n concatMap((range) => {\n const storedBlocks = fetchAndStoreLogs({\n ...opts,\n address,\n events: storeEventsAbi,\n maxBlockRange,\n fromBlock: lastBlockNumberProcessed\n ? bigIntMax(range.startBlock, lastBlockNumberProcessed + 1n)\n : range.startBlock,\n toBlock: range.endBlock,\n logFilter,\n storageAdapter,\n });\n\n return from(storedBlocks);\n }),\n );\n\n const storedBlock$ = storedPendingLogs$.pipe(\n catchError((error) => {\n debug(\"failed to stream logs from pending log RPC:\", error.message);\n debug(\"falling back to streaming logs from indexer\");\n return storedIndexerLogs$;\n }),\n catchError((error) => {\n debug(\"failed to stream logs from indexer:\", error.message);\n debug(\"falling back to streaming logs from ETH RPC\");\n return storedEthRpcLogs$;\n }),\n // subscribe to `latestBlockNumber$` so the sync progress is updated\n // but don't merge/emit anything\n mergeWith(latestBlockNumber$.pipe(ignoreElements())),\n tap(async ({ logs, blockNumber }) => {\n debug(\"stored\", logs.length, \"logs for block\", blockNumber);\n lastBlockNumberProcessed = blockNumber;\n\n if (!caughtUp && startBlock != null && latestBlockNumber != null) {\n if (lastBlockNumberProcessed < latestBlockNumber) {\n const totalBlocks = latestBlockNumber - startBlock;\n const processedBlocks = lastBlockNumberProcessed - startBlock;\n onProgress?.({\n step: SyncStep.RPC,\n percentage: Number((processedBlocks * 1000n) / totalBlocks) / 10,\n latestBlockNumber,\n lastBlockNumberProcessed,\n message: \"Hydrating from RPC\",\n });\n } else {\n caughtUp = true;\n onProgress?.({\n step: SyncStep.LIVE,\n percentage: 100,\n latestBlockNumber,\n lastBlockNumberProcessed,\n message: \"All caught up!\",\n });\n }\n }\n }),\n share(),\n );\n\n const storedBlockLogs$ = concat(storedInitialBlockLogs$, storedBlock$).pipe(share());\n\n // keep 10 blocks worth processed transactions in memory\n const recentBlocksWindow = 10;\n // most recent block first, for ease of pulling the first one off the array\n const recentStoredBlocks$ = storedBlockLogs$.pipe(\n scan<StorageAdapterBlock, StorageAdapterBlock[]>(\n (recentBlocks, block) => [block, ...recentBlocks].slice(0, recentBlocksWindow),\n [],\n ),\n filter((recentBlocks) => recentBlocks.length > 0),\n shareReplay(1),\n );\n\n // TODO: move to its own file so we can test it, have its own debug instance, etc.\n async function waitForTransaction(tx: Hex): Promise<WaitForTransactionResult> {\n debug(\"waiting for tx\", tx);\n\n // This currently blocks for async call on each block processed\n // We could potentially speed this up a tiny bit by racing to see if 1) tx exists in processed block or 2) fetch tx receipt for latest block processed\n const hasTransaction$ = recentStoredBlocks$.pipe(\n // We use `mergeMap` instead of `concatMap` here to send the fetch request immediately when a new block range appears,\n // instead of sending the next request only when the previous one completed.\n mergeMap(async (storedBlocks) => {\n for (const storedBlock of storedBlocks) {\n // If stored block had Store event logs associated with tx, it must have succeeded.\n if (storedBlock.logs.some((log) => log.transactionHash === tx)) {\n return { blockNumber: storedBlock.blockNumber, status: \"success\", transactionHash: tx } as const;\n }\n }\n\n try {\n const lastStoredBlock = storedBlocks[0];\n debug(\"fetching tx receipt for block\", lastStoredBlock.blockNumber);\n const receipt = await getAction(publicClient, getTransactionReceipt, \"getTransactionReceipt\")({ hash: tx });\n\n // Skip if sync hasn't caught up to this transaction's block.\n if (lastStoredBlock.blockNumber < receipt.blockNumber) return;\n\n // Check if this was a user op so we can get the internal user op status.\n const userOpEvents = parseEventLogs({\n logs: receipt.logs,\n abi: entryPoint07Abi,\n eventName: \"UserOperationEvent\" as const,\n });\n if (userOpEvents.length) {\n debug(\"tx receipt appears to be a user op, using user op status instead\");\n if (userOpEvents.length > 1) {\n const issueLink = `https://github.com/latticexyz/mud/issues/new${new URLSearchParams({\n title: \"waitForTransaction found more than one user op\",\n body: `MUD version: ${packageJson.version}\\nChain ID: ${chainId}\\nTransaction: ${tx}\\n`,\n })}`;\n console.warn(\n // eslint-disable-next-line max-len\n `Receipt for transaction ${tx} had more than one \\`UserOperationEvent\\`. This may have unexpected behavior.\\n\\nIf you encounter this, please open an issue:\\n${issueLink}`,\n );\n }\n\n return {\n status: userOpEvents[0].args.success ? \"success\" : \"reverted\",\n blockNumber: receipt.blockNumber,\n transactionHash: receipt.transactionHash,\n } as const;\n }\n\n return {\n status: receipt.status,\n blockNumber: receipt.blockNumber,\n transactionHash: receipt.transactionHash,\n };\n } catch (e) {\n const error = e as GetTransactionReceiptErrorType;\n if (error.name === \"TransactionReceiptNotFoundError\") {\n return;\n }\n throw error;\n }\n }),\n );\n\n return await firstValueFrom(hasTransaction$.pipe(filter(isDefined)));\n }\n\n return {\n latestBlock$,\n latestBlockNumber$,\n storedBlockLogs$,\n waitForTransaction,\n };\n}\n","import { Observable } from \"rxjs\";\n\nexport function fromEventSource<T>(url: string | URL): Observable<MessageEvent<T>> {\n return new Observable<MessageEvent>((subscriber) => {\n const eventSource = new EventSource(url);\n eventSource.onmessage = (ev): void => subscriber.next(ev);\n eventSource.onerror = (): void => subscriber.error(new Error(\"Event source failed\" + new URL(url).origin));\n return () => eventSource.close();\n });\n}\n","import { FetchLogsOptions, fetchLogs, groupLogsByBlockNumber } from \"@latticexyz/block-logs-stream\";\nimport { StoreEventsAbi } from \"@latticexyz/store\";\nimport { StorageAdapter, StorageAdapterBlock, StoreEventsLog } from \"./common\";\n\ntype FetchAndStoreLogsOptions = FetchLogsOptions<StoreEventsAbi> & {\n storageAdapter: StorageAdapter;\n logFilter?: (log: StoreEventsLog) => boolean;\n};\n\nexport async function* fetchAndStoreLogs({\n storageAdapter,\n logFilter,\n ...fetchLogsOptions\n}: FetchAndStoreLogsOptions): AsyncGenerator<StorageAdapterBlock> {\n for await (const { logs, toBlock } of fetchLogs<StoreEventsAbi>(fetchLogsOptions)) {\n const blocks = groupLogsByBlockNumber(logFilter ? logs.filter(logFilter) : logs, toBlock);\n for (const block of blocks) {\n await storageAdapter(block);\n yield block;\n }\n }\n}\n","import { Observable } from \"rxjs\";\nimport { Hex, LogTopic, RpcLog, encodeEventTopics, formatLog, parseEventLogs, toHex } from \"viem\";\nimport { StorageAdapterBlock, StoreEventsLog } from \"./common\";\nimport { storeEventsAbi } from \"@latticexyz/store\";\nimport { logSort } from \"@latticexyz/common\";\nimport { SocketRpcClient, getWebSocketRpcClient } from \"viem/utils\";\nimport { debug as parentDebug } from \"./debug\";\n\nconst debug = parentDebug.extend(\"watchLogs\");\n\ntype WatchLogsInput = {\n url: string;\n fromBlock: bigint;\n address?: Hex;\n};\n\ntype WatchLogsResult = {\n logs$: Observable<StorageAdapterBlock>;\n};\n\ntype WatchLogsEvent = {\n blockNumber: string;\n logs: RpcLog[];\n};\n\nexport function watchLogs({ url, address, fromBlock }: WatchLogsInput): WatchLogsResult {\n const topics = [\n storeEventsAbi.flatMap((event) => encodeEventTopics({ abi: [event], eventName: event.name })),\n ] as LogTopic[]; // https://github.com/wevm/viem/blob/63a5ac86eb9a2962f7323b4cc76ef54f9f5ef7ed/src/actions/public/getLogs.ts#L171\n\n let resumeBlock = fromBlock;\n\n let pingTimer: ReturnType<typeof setTimeout> | undefined = undefined;\n // how often to ping to keep socket alive\n const pingInterval = 3000;\n // how long to wait for ping response before we attempt to reconnect\n const pingTimeout = 5000;\n\n const logs$ = new Observable<StorageAdapterBlock>((subscriber) => {\n debug(\"logs$ subscribed\");\n\n let client: SocketRpcClient<WebSocket>;\n\n async function setupClient(): Promise<void> {\n debug(\"setupClient called\");\n\n // Buffer the live logs received until the gap from `startBlock` to `currentBlock` is closed\n let caughtUp = false;\n const logBuffer: StoreEventsLog[] = [];\n\n client = await getWebSocketRpcClient(url, { keepAlive: false });\n debug(\"got websocket rpc client\");\n\n async function ping(): Promise<void> {\n try {\n debug(\"pinging socket\");\n await client.requestAsync({ body: { method: \"net_version\" }, timeout: pingTimeout });\n } catch (error) {\n debug(\"ping failed, closing...\", error);\n client.close();\n }\n }\n\n function schedulePing(): void {\n debug(\"scheduling next ping\");\n pingTimer = setTimeout(() => ping().then(schedulePing), pingInterval);\n }\n\n schedulePing();\n\n client.socket.addEventListener(\"error\", (error) => {\n debug(\"socket error, closing...\", error);\n client.close();\n });\n\n client.socket.addEventListener(\"close\", async () => {\n debug(\"socket close, setting up new client...\");\n clearTimeout(pingTimer);\n setupClient().catch((error) => {\n debug(\"error trying to setup new client\", error);\n subscriber.error(error);\n });\n });\n\n // Start watching pending logs\n const subscriptionId: Hex = (\n await client.requestAsync({\n body: {\n method: \"wiresaw_watchLogs\",\n params: [{ address, topics }],\n },\n })\n ).result;\n debug(\"got watchLogs subscription\", subscriptionId);\n\n // Listen for wiresaw_watchLogs subscription\n // Need to use low level methods since viem's socekt client only handles `eth_subscription` messages.\n // (https://github.com/wevm/viem/blob/f81d497f2afc11b9b81a79057d1f797694b69793/src/utils/rpc/socket.ts#L178)\n client.socket.addEventListener(\"message\", (message) => {\n const response = JSON.parse(message.data);\n if (\"error\" in response) {\n debug(\"JSON-RPC error, returning error to subscriber\");\n subscriber.error(response.error);\n return;\n }\n\n // Parse the logs from wiresaw_watchLogs\n if (\"params\" in response && response.params.subscription === subscriptionId) {\n debug(\"parsing logs\");\n const result: WatchLogsEvent = response.params.result;\n const formattedLogs = result.logs.map((log) => formatLog(log));\n const parsedLogs = parseEventLogs({ abi: storeEventsAbi, logs: formattedLogs });\n const blockNumber = BigInt(result.blockNumber);\n debug(\"got logs\", parsedLogs, \"for pending block\", blockNumber);\n if (caughtUp) {\n debug(\"handing off logs to subscriber\");\n subscriber.next({ blockNumber, logs: parsedLogs });\n // Since this the event's block number corresponds to a pending block, we have to refetch this block in case of a restart\n resumeBlock = blockNumber;\n } else {\n debug(\"buffering logs\");\n logBuffer.push(...parsedLogs);\n }\n return;\n }\n });\n\n // Catch up to the pending logs\n try {\n debug(\"fetching initial logs\");\n const initialLogs = await fetchInitialLogs({ client, address, fromBlock: resumeBlock, topics });\n debug(\"got initial logs\", initialLogs);\n const logs = [...initialLogs.logs, ...logBuffer].sort(logSort);\n debug(\"combining with log buffer\", logs);\n const blockNumber = logs.at(-1)?.blockNumber ?? initialLogs.blockNumber;\n subscriber.next({ blockNumber, logs });\n // Since this the block number can correspond to a pending block, we have to refetch this block in case of a restart\n resumeBlock = blockNumber;\n caughtUp = true;\n } catch (error) {\n debug(\"could not get initial logs\", error);\n subscriber.error(\"Could not fetch initial wiresaw logs\");\n }\n }\n\n setupClient().catch((error) => {\n debug(\"error setting up initial client\", error);\n subscriber.error(error);\n });\n\n return () => {\n debug(\"logs$ subscription closed\");\n clearTimeout(pingTimer);\n client?.close();\n };\n });\n\n return { logs$ };\n}\n\ntype FetchInitialLogsInput = { client: SocketRpcClient<WebSocket>; topics: LogTopic[] } & Omit<WatchLogsInput, \"url\">;\n\nasync function fetchInitialLogs({\n client,\n address,\n topics,\n fromBlock,\n}: FetchInitialLogsInput): Promise<{ blockNumber: bigint; logs: StoreEventsLog[] }> {\n // Fetch latest block number\n const latestBlockNumber: Hex = (\n await client.requestAsync({\n body: {\n method: \"eth_blockNumber\",\n },\n })\n ).result;\n\n // Request all logs from `fromBlock` to the latest block number\n const rawInitialLogs: RpcLog[] = await client\n .requestAsync({\n body: {\n method: \"eth_getLogs\",\n params: [{ address, topics, fromBlock: toHex(fromBlock), toBlock: latestBlockNumber }],\n },\n })\n .then((res) => res.result);\n\n // Return all logs from `fromBlock` until the current pending block state as initial result\n const formattedLogs = rawInitialLogs.map((log) => formatLog(log));\n return { blockNumber: BigInt(latestBlockNumber), logs: parseEventLogs({ abi: storeEventsAbi, logs: formattedLogs }) };\n}\n","{\n \"name\": \"@latticexyz/store-sync\",\n \"version\": \"2.2.18\",\n \"description\": \"Utilities to sync MUD Store events with a client or cache\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/latticexyz/mud.git\",\n \"directory\": \"packages/store-sync\"\n },\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"exports\": {\n \".\": \"./dist/index.js\",\n \"./indexer-client\": \"./dist/indexer-client/index.js\",\n \"./internal\": \"./dist/exports/internal.js\",\n \"./react\": \"./dist/exports/react.js\",\n \"./postgres\": \"./dist/postgres/index.js\",\n \"./postgres-decoded\": \"./dist/postgres-decoded/index.js\",\n \"./recs\": \"./dist/recs/index.js\",\n \"./sqlite\": \"./dist/sqlite/index.js\",\n \"./trpc-indexer\": \"./dist/trpc-indexer/index.js\",\n \"./world\": \"./dist/world/index.js\",\n \"./zustand\": \"./dist/zustand/index.js\"\n },\n \"typesVersions\": {\n \"*\": {\n \"index\": [\n \"./dist/index.d.ts\"\n ],\n \"indexer-client\": [\n \"./dist/indexer-client/index.d.ts\"\n ],\n \"internal\": [\n \"./dist/exports/internal.d.ts\"\n ],\n \"react\": [\n \"./dist/exports/react.d.ts\"\n ],\n \"postgres\": [\n \"./dist/postgres/index.d.ts\"\n ],\n \"postgres-decoded\": [\n \"./dist/postgres-decoded/index.d.ts\"\n ],\n \"recs\": [\n \"./dist/recs/index.d.ts\"\n ],\n \"sqlite\": [\n \"./dist/sqlite/index.d.ts\"\n ],\n \"trpc-indexer\": [\n \"./dist/trpc-indexer/index.d.ts\"\n ],\n \"world\": [\n \"./dist/world/index.d.ts\"\n ],\n \"zustand\": [\n \"./dist/zustand/index.d.ts\"\n ]\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"bench\": \"vitest bench\",\n \"build\": \"pnpm run build:js\",\n \"build:js\": \"tsup\",\n \"clean\": \"pnpm run clean:js\",\n \"clean:js\": \"shx rm -rf dist\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint .\",\n \"test\": \"vitest\",\n \"test:ci\": \"vitest --run\"\n },\n \"dependencies\": {\n \"@ark/util\": \"0.2.2\",\n \"@latticexyz/block-logs-stream\": \"workspace:*\",\n \"@latticexyz/common\": \"workspace:*\",\n \"@latticexyz/config\": \"workspace:*\",\n \"@latticexyz/protocol-parser\": \"workspace:*\",\n \"@latticexyz/recs\": \"workspace:*\",\n \"@latticexyz/schema-type\": \"workspace:*\",\n \"@latticexyz/stash\": \"workspace:*\",\n \"@latticexyz/store\": \"workspace:*\",\n \"@latticexyz/world\": \"workspace:*\",\n \"@trpc/client\": \"10.34.0\",\n \"@trpc/server\": \"10.34.0\",\n \"change-case\": \"^5.2.0\",\n \"debug\": \"^4.3.4\",\n \"drizzle-orm\": \"^0.28.5\",\n \"fast-deep-equal\": \"^3.1.3\",\n \"kysely\": \"^0.26.3\",\n \"postgres\": \"^3.3.5\",\n \"rxjs\": \"7.5.5\",\n \"sql.js\": \"^1.8.0\",\n \"superjson\": \"^1.12.4\",\n \"zod\": \"3.23.8\",\n \"zustand\": \"^4.3.7\"\n },\n \"devDependencies\": {\n \"@tanstack/react-query\": \"^5.56.2\",\n \"@testing-library/react\": \"^16.0.0\",\n \"@testing-library/react-hooks\": \"^8.0.1\",\n \"@types/debug\": \"^4.1.7\",\n \"@types/react\": \"18.2.22\",\n \"@types/sql.js\": \"^1.4.4\",\n \"eslint-plugin-react\": \"7.31.11\",\n \"eslint-plugin-react-hooks\": \"4.6.0\",\n \"react\": \"18.2.0\",\n \"react-dom\": \"18.2.0\",\n \"viem\": \"2.21.19\",\n \"wagmi\": \"2.12.11\"\n },\n \"peerDependencies\": {\n \"@tanstack/react-query\": \"5.x\",\n \"react\": \"18.x\",\n \"viem\": \"2.x\",\n \"wagmi\": \"2.x\"\n },\n \"peerDependenciesMeta\": {\n \"@tanstack/react-query\": {\n \"optional\": true\n },\n \"react\": {\n \"optional\": true\n },\n \"wagmi\": {\n \"optional\": true\n }\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n"],"mappings":"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","names":["SyncStep","storeEventsAbi","parseEventLogs","Observable","debug","Observable","debug","filter","chunk","startBlock","storeEventsAbi","parseEventLogs"]}
|
|
1
|
+
{"version":3,"sources":["../src/SyncStep.ts","../src/createStoreSync.ts","../src/fromEventSource.ts","../src/fetchAndStoreLogs.ts","../src/watchLogs.ts","../package.json"],"sourcesContent":["export enum SyncStep {\n INITIALIZE = \"initialize\",\n SNAPSHOT = \"snapshot\",\n RPC = \"rpc\",\n LIVE = \"live\",\n}\n","import { MUDChain } from \"@latticexyz/common/chains\";\nimport { storeEventsAbi } from \"@latticexyz/store\";\nimport { GetTransactionReceiptErrorType, Hex, parseEventLogs } from \"viem\";\nimport { entryPoint07Abi } from \"viem/account-abstraction\";\nimport {\n StorageAdapter,\n StorageAdapterBlock,\n StoreEventsLog,\n SyncFilter,\n SyncOptions,\n SyncResult,\n internalTableIds,\n WaitForTransactionResult,\n} from \"./common\";\nimport { createBlockStream, getRpcClient } from \"@latticexyz/block-logs-stream\";\nimport {\n filter,\n map,\n tap,\n from,\n concat,\n concatMap,\n share,\n firstValueFrom,\n defer,\n of,\n catchError,\n shareReplay,\n combineLatest,\n scan,\n mergeMap,\n throwError,\n mergeWith,\n ignoreElements,\n} from \"rxjs\";\nimport { debug as parentDebug } from \"./debug\";\nimport { SyncStep } from \"./SyncStep\";\nimport { bigIntMax, chunk, isDefined, waitForIdle } from \"@latticexyz/common/utils\";\nimport { getSnapshot } from \"./getSnapshot\";\nimport { fromEventSource } from \"./fromEventSource\";\nimport { fetchAndStoreLogs } from \"./fetchAndStoreLogs\";\nimport { isLogsApiResponse } from \"./indexer-client/isLogsApiResponse\";\nimport { toStorageAdapterBlock } from \"./indexer-client/toStorageAdapterBlock\";\nimport { watchLogs } from \"./watchLogs\";\nimport { getAction } from \"viem/utils\";\nimport { getChainId, getTransactionReceipt } from \"viem/actions\";\nimport packageJson from \"../package.json\";\n\nconst debug = parentDebug.extend(\"createStoreSync\");\n\nconst defaultFilters: SyncFilter[] = internalTableIds.map((tableId) => ({ tableId }));\n\ntype CreateStoreSyncOptions = SyncOptions & {\n storageAdapter: StorageAdapter;\n onProgress?: (opts: {\n step: SyncStep;\n percentage: number;\n latestBlockNumber: bigint;\n lastBlockNumberProcessed: bigint;\n message: string;\n }) => void;\n};\n\nexport async function createStoreSync({\n storageAdapter,\n onProgress,\n address,\n filters: initialFilters = [],\n tableIds = [],\n followBlockTag = \"latest\",\n startBlock: initialStartBlock = 0n,\n maxBlockRange,\n initialState,\n initialBlockLogs,\n ...opts\n}: CreateStoreSyncOptions): Promise<SyncResult> {\n const filters: SyncFilter[] =\n initialFilters.length || tableIds.length\n ? [...initialFilters, ...tableIds.map((tableId) => ({ tableId })), ...defaultFilters]\n : [];\n\n const logFilter = filters.length\n ? (log: StoreEventsLog): boolean =>\n filters.some(\n (filter) =>\n filter.tableId === log.args.tableId &&\n (filter.key0 == null || filter.key0 === log.args.keyTuple[0]) &&\n (filter.key1 == null || filter.key1 === log.args.keyTuple[1]),\n )\n : undefined;\n\n const publicClient = getRpcClient(opts);\n const indexerUrl = ((): string | undefined => {\n if (opts.indexerUrl === false) return;\n if (opts.indexerUrl) return opts.indexerUrl;\n if (publicClient.chain) return (publicClient.chain as MUDChain).indexerUrl;\n })();\n\n const chainId = publicClient.chain?.id ?? (await getAction(publicClient, getChainId, \"getChainId\")({}));\n\n const initialBlockLogs$ = defer(async (): Promise<StorageAdapterBlock | undefined> => {\n onProgress?.({\n step: SyncStep.SNAPSHOT,\n percentage: 0,\n latestBlockNumber: 0n,\n lastBlockNumberProcessed: 0n,\n message: \"Getting snapshot\",\n });\n\n const snapshot = await getSnapshot({\n chainId,\n address,\n filters,\n initialState,\n initialBlockLogs,\n indexerUrl,\n });\n\n onProgress?.({\n step: SyncStep.SNAPSHOT,\n percentage: 100,\n latestBlockNumber: 0n,\n lastBlockNumberProcessed: 0n,\n message: \"Got snapshot\",\n });\n\n return snapshot;\n }).pipe(\n catchError((error) => {\n debug(\"error getting snapshot\", error);\n\n onProgress?.({\n step: SyncStep.SNAPSHOT,\n percentage: 100,\n latestBlockNumber: 0n,\n lastBlockNumberProcessed: initialStartBlock,\n message: \"Failed to get snapshot\",\n });\n\n return of(undefined);\n }),\n shareReplay(1),\n );\n\n const storedInitialBlockLogs$ = initialBlockLogs$.pipe(\n filter(isDefined),\n concatMap(async ({ blockNumber, logs }) => {\n debug(\"hydrating\", logs.length, \"logs to block\", blockNumber);\n\n onProgress?.({\n step: SyncStep.SNAPSHOT,\n percentage: 0,\n latestBlockNumber: 0n,\n lastBlockNumberProcessed: blockNumber,\n message: \"Hydrating from snapshot\",\n });\n\n // Split snapshot operations into chunks so we can update the progress callback (and ultimately render visual progress for the user).\n // This isn't ideal if we want to e.g. batch load these into a DB in a single DB tx, but we'll take it.\n //\n // Split into 50 equal chunks (for better `onProgress` updates) but only if we have 100+ items per chunk\n const chunkSize = Math.max(100, Math.floor(logs.length / 50));\n const chunks = Array.from(chunk(logs, chunkSize));\n for (const [i, chunk] of chunks.entries()) {\n await storageAdapter({ blockNumber, logs: chunk });\n onProgress?.({\n step: SyncStep.SNAPSHOT,\n percentage: ((i + 1) / chunks.length) * 100,\n latestBlockNumber: 0n,\n lastBlockNumberProcessed: blockNumber,\n message: \"Hydrating from snapshot\",\n });\n\n // RECS is a synchronous API so hydrating in a loop like this blocks downstream render cycles\n // that would display the percentage climbing up to 100.\n // We wait for idle callback here to give rendering a chance to complete.\n await waitForIdle();\n }\n\n onProgress?.({\n step: SyncStep.SNAPSHOT,\n percentage: 100,\n latestBlockNumber: 0n,\n lastBlockNumberProcessed: blockNumber,\n message: \"Hydrated from snapshot\",\n });\n\n return { blockNumber, logs };\n }),\n shareReplay(1),\n );\n\n let startBlock: bigint | null = null;\n const startBlock$ = initialBlockLogs$.pipe(\n map((block) => bigIntMax(block?.blockNumber ?? 0n, initialStartBlock)),\n // TODO: if start block is still 0, find via deploy event\n tap((blockNumber) => {\n startBlock = blockNumber;\n debug(\"starting sync from block\", startBlock);\n }),\n );\n\n let latestBlockNumber: bigint | null = null;\n const latestBlock$ = createBlockStream({ ...opts, blockTag: followBlockTag }).pipe(shareReplay(1));\n const latestBlockNumber$ = latestBlock$.pipe(\n map((block) => block.number),\n tap((blockNumber) => {\n latestBlockNumber = blockNumber;\n debug(\"on block number\", blockNumber, \"for\", followBlockTag, \"block tag\");\n }),\n shareReplay(1),\n );\n\n let lastBlockNumberProcessed: bigint | null = null;\n let caughtUp = false;\n\n const pendingLogsWebSocketUrl = publicClient.chain?.rpcUrls?.wiresaw?.webSocket?.[0];\n const storedPendingLogs$ = pendingLogsWebSocketUrl\n ? startBlock$.pipe(\n mergeMap((startBlock) => watchLogs({ url: pendingLogsWebSocketUrl, address, fromBlock: startBlock }).logs$),\n concatMap(async (block) => {\n await storageAdapter(block);\n return block;\n }),\n mergeWith(\n // The watchLogs API doesn't emit on empty logs, but consumers expect an emission on empty logs\n latestBlockNumber$.pipe(map((blockNumber) => ({ blockNumber, logs: [] }))),\n ),\n )\n : throwError(() => new Error(\"No pending logs WebSocket RPC URL provided\"));\n\n const storedIndexerLogs$ = indexerUrl\n ? startBlock$.pipe(\n mergeMap((startBlock) => {\n const url = new URL(\n `api/logs-live?${new URLSearchParams({\n input: JSON.stringify({ chainId, address, filters }),\n block_num: startBlock.toString(),\n include_tx_hash: \"true\",\n })}`,\n indexerUrl,\n );\n return fromEventSource<string>(url);\n }),\n map((messageEvent) => {\n const data = JSON.parse(messageEvent.data);\n if (!isLogsApiResponse(data)) {\n throw new Error(\"Received unexpected from indexer:\" + messageEvent.data);\n }\n return toStorageAdapterBlock(data);\n }),\n concatMap(async (block) => {\n await storageAdapter(block);\n return block;\n }),\n )\n : throwError(() => new Error(\"No indexer URL provided\"));\n\n const storedEthRpcLogs$ = combineLatest([startBlock$, latestBlockNumber$]).pipe(\n map(([startBlock, endBlock]) => ({ startBlock, endBlock })),\n concatMap((range) => {\n const storedBlocks = fetchAndStoreLogs({\n ...opts,\n address,\n events: storeEventsAbi,\n maxBlockRange,\n fromBlock: lastBlockNumberProcessed\n ? bigIntMax(range.startBlock, lastBlockNumberProcessed + 1n)\n : range.startBlock,\n toBlock: range.endBlock,\n logFilter,\n storageAdapter,\n });\n\n return from(storedBlocks);\n }),\n );\n\n const storedBlock$ = storedPendingLogs$.pipe(\n catchError((error) => {\n debug(\"failed to stream logs from pending log RPC:\", error.message);\n debug(\"falling back to streaming logs from indexer\");\n return storedIndexerLogs$;\n }),\n catchError((error) => {\n debug(\"failed to stream logs from indexer:\", error.message);\n debug(\"falling back to streaming logs from ETH RPC\");\n return storedEthRpcLogs$;\n }),\n // subscribe to `latestBlockNumber$` so the sync progress is updated\n // but don't merge/emit anything\n mergeWith(latestBlockNumber$.pipe(ignoreElements())),\n tap(async ({ logs, blockNumber }) => {\n debug(\"stored\", logs.length, \"logs for block\", blockNumber);\n lastBlockNumberProcessed = blockNumber;\n\n if (!caughtUp && startBlock != null && latestBlockNumber != null) {\n if (lastBlockNumberProcessed < latestBlockNumber) {\n const totalBlocks = latestBlockNumber - startBlock;\n const processedBlocks = lastBlockNumberProcessed - startBlock;\n onProgress?.({\n step: SyncStep.RPC,\n percentage: Number((processedBlocks * 1000n) / totalBlocks) / 10,\n latestBlockNumber,\n lastBlockNumberProcessed,\n message: \"Hydrating from RPC\",\n });\n } else {\n caughtUp = true;\n onProgress?.({\n step: SyncStep.LIVE,\n percentage: 100,\n latestBlockNumber,\n lastBlockNumberProcessed,\n message: \"All caught up!\",\n });\n }\n }\n }),\n share(),\n );\n\n const storedBlockLogs$ = concat(storedInitialBlockLogs$, storedBlock$).pipe(share());\n\n // keep 10 blocks worth processed transactions in memory\n const recentBlocksWindow = 10;\n // most recent block first, for ease of pulling the first one off the array\n const recentStoredBlocks$ = storedBlockLogs$.pipe(\n scan<StorageAdapterBlock, StorageAdapterBlock[]>(\n (recentBlocks, block) => [block, ...recentBlocks].slice(0, recentBlocksWindow),\n [],\n ),\n filter((recentBlocks) => recentBlocks.length > 0),\n shareReplay(1),\n );\n\n // TODO: move to its own file so we can test it, have its own debug instance, etc.\n async function waitForTransaction(tx: Hex): Promise<WaitForTransactionResult> {\n debug(\"waiting for tx\", tx);\n\n // This currently blocks for async call on each block processed\n // We could potentially speed this up a tiny bit by racing to see if 1) tx exists in processed block or 2) fetch tx receipt for latest block processed\n const hasTransaction$ = recentStoredBlocks$.pipe(\n // We use `mergeMap` instead of `concatMap` here to send the fetch request immediately when a new block range appears,\n // instead of sending the next request only when the previous one completed.\n mergeMap(async (storedBlocks) => {\n for (const storedBlock of storedBlocks) {\n // If stored block had Store event logs associated with tx, it must have succeeded.\n if (storedBlock.logs.some((log) => log.transactionHash === tx)) {\n return { blockNumber: storedBlock.blockNumber, status: \"success\", transactionHash: tx } as const;\n }\n }\n\n try {\n const lastStoredBlock = storedBlocks[0];\n debug(\"fetching tx receipt for block\", lastStoredBlock.blockNumber);\n const receipt = await getAction(publicClient, getTransactionReceipt, \"getTransactionReceipt\")({ hash: tx });\n\n // Skip if sync hasn't caught up to this transaction's block.\n if (lastStoredBlock.blockNumber < receipt.blockNumber) return;\n\n // Check if this was a user op so we can get the internal user op status.\n const userOpEvents = parseEventLogs({\n logs: receipt.logs,\n abi: entryPoint07Abi,\n eventName: \"UserOperationEvent\" as const,\n });\n if (userOpEvents.length) {\n debug(\"tx receipt appears to be a user op, using user op status instead\");\n if (userOpEvents.length > 1) {\n const issueLink = `https://github.com/latticexyz/mud/issues/new${new URLSearchParams({\n title: \"waitForTransaction found more than one user op\",\n body: `MUD version: ${packageJson.version}\\nChain ID: ${chainId}\\nTransaction: ${tx}\\n`,\n })}`;\n console.warn(\n // eslint-disable-next-line max-len\n `Receipt for transaction ${tx} had more than one \\`UserOperationEvent\\`. This may have unexpected behavior.\\n\\nIf you encounter this, please open an issue:\\n${issueLink}`,\n );\n }\n\n return {\n status: userOpEvents[0].args.success ? \"success\" : \"reverted\",\n blockNumber: receipt.blockNumber,\n transactionHash: receipt.transactionHash,\n } as const;\n }\n\n return {\n status: receipt.status,\n blockNumber: receipt.blockNumber,\n transactionHash: receipt.transactionHash,\n };\n } catch (e) {\n const error = e as GetTransactionReceiptErrorType;\n if (error.name === \"TransactionReceiptNotFoundError\") {\n return;\n }\n throw error;\n }\n }),\n );\n\n return await firstValueFrom(hasTransaction$.pipe(filter(isDefined)));\n }\n\n return {\n latestBlock$,\n latestBlockNumber$,\n storedBlockLogs$,\n waitForTransaction,\n };\n}\n","import { Observable } from \"rxjs\";\n\nexport function fromEventSource<T>(url: string | URL): Observable<MessageEvent<T>> {\n return new Observable<MessageEvent>((subscriber) => {\n const eventSource = new EventSource(url);\n eventSource.onmessage = (ev): void => subscriber.next(ev);\n eventSource.onerror = (): void => subscriber.error(new Error(\"Event source failed\" + new URL(url).origin));\n return () => eventSource.close();\n });\n}\n","import { FetchLogsOptions, fetchLogs, groupLogsByBlockNumber } from \"@latticexyz/block-logs-stream\";\nimport { StoreEventsAbi } from \"@latticexyz/store\";\nimport { StorageAdapter, StorageAdapterBlock, StoreEventsLog } from \"./common\";\n\ntype FetchAndStoreLogsOptions = FetchLogsOptions<StoreEventsAbi> & {\n storageAdapter: StorageAdapter;\n logFilter?: (log: StoreEventsLog) => boolean;\n};\n\nexport async function* fetchAndStoreLogs({\n storageAdapter,\n logFilter,\n ...fetchLogsOptions\n}: FetchAndStoreLogsOptions): AsyncGenerator<StorageAdapterBlock> {\n for await (const { logs, toBlock } of fetchLogs<StoreEventsAbi>(fetchLogsOptions)) {\n const blocks = groupLogsByBlockNumber(logFilter ? logs.filter(logFilter) : logs, toBlock);\n for (const block of blocks) {\n await storageAdapter(block);\n yield block;\n }\n }\n}\n","import { Observable } from \"rxjs\";\nimport { Hex, LogTopic, RpcLog, encodeEventTopics, formatLog, parseEventLogs, toHex } from \"viem\";\nimport { StorageAdapterBlock, StoreEventsLog } from \"./common\";\nimport { storeEventsAbi } from \"@latticexyz/store\";\nimport { logSort } from \"@latticexyz/common\";\nimport { SocketRpcClient, getWebSocketRpcClient } from \"viem/utils\";\nimport { debug as parentDebug } from \"./debug\";\n\nconst debug = parentDebug.extend(\"watchLogs\");\n\ntype WatchLogsInput = {\n url: string;\n fromBlock: bigint;\n address?: Hex;\n};\n\ntype WatchLogsResult = {\n logs$: Observable<StorageAdapterBlock>;\n};\n\ntype WatchLogsEvent = {\n blockNumber: string;\n logs: RpcLog[];\n};\n\nexport function watchLogs({ url, address, fromBlock }: WatchLogsInput): WatchLogsResult {\n const topics = [\n storeEventsAbi.flatMap((event) => encodeEventTopics({ abi: [event], eventName: event.name })),\n ] as LogTopic[]; // https://github.com/wevm/viem/blob/63a5ac86eb9a2962f7323b4cc76ef54f9f5ef7ed/src/actions/public/getLogs.ts#L171\n\n let resumeBlock = fromBlock;\n\n let pingTimer: ReturnType<typeof setTimeout> | undefined = undefined;\n // how often to ping to keep socket alive\n const pingInterval = 3000;\n // how long to wait for ping response before we attempt to reconnect\n const pingTimeout = 5000;\n\n const logs$ = new Observable<StorageAdapterBlock>((subscriber) => {\n debug(\"logs$ subscribed\");\n\n let client: SocketRpcClient<WebSocket>;\n\n async function setupClient(): Promise<void> {\n debug(\"setupClient called\");\n\n // Buffer the live logs received until the gap from `startBlock` to `currentBlock` is closed\n let caughtUp = false;\n const logBuffer: StoreEventsLog[] = [];\n\n client = await getWebSocketRpcClient(url, { keepAlive: false });\n debug(\"got websocket rpc client\");\n\n async function ping(): Promise<void> {\n try {\n debug(\"pinging socket\");\n await client.requestAsync({ body: { method: \"net_version\" }, timeout: pingTimeout });\n } catch (error) {\n debug(\"ping failed, closing...\", error);\n client.close();\n }\n }\n\n function schedulePing(): void {\n debug(\"scheduling next ping\");\n pingTimer = setTimeout(() => ping().then(schedulePing), pingInterval);\n }\n\n schedulePing();\n\n client.socket.addEventListener(\"error\", (error) => {\n debug(\"socket error, closing...\", error);\n client.close();\n });\n\n client.socket.addEventListener(\"close\", async () => {\n debug(\"socket close, setting up new client...\");\n clearTimeout(pingTimer);\n setupClient().catch((error) => {\n debug(\"error trying to setup new client\", error);\n subscriber.error(error);\n });\n });\n\n // Start watching pending logs\n const subscriptionId: Hex = (\n await client.requestAsync({\n body: {\n method: \"wiresaw_watchLogs\",\n params: [{ address, topics }],\n },\n })\n ).result;\n debug(\"got watchLogs subscription\", subscriptionId);\n\n // Listen for wiresaw_watchLogs subscription\n // Need to use low level methods since viem's socekt client only handles `eth_subscription` messages.\n // (https://github.com/wevm/viem/blob/f81d497f2afc11b9b81a79057d1f797694b69793/src/utils/rpc/socket.ts#L178)\n client.socket.addEventListener(\"message\", (message) => {\n const response = JSON.parse(message.data);\n if (\"error\" in response) {\n debug(\"JSON-RPC error, returning error to subscriber\");\n subscriber.error(response.error);\n return;\n }\n\n // Parse the logs from wiresaw_watchLogs\n if (\"params\" in response && response.params.subscription === subscriptionId) {\n debug(\"parsing logs\");\n const result: WatchLogsEvent = response.params.result;\n const formattedLogs = result.logs.map((log) => formatLog(log));\n const parsedLogs = parseEventLogs({ abi: storeEventsAbi, logs: formattedLogs });\n const blockNumber = BigInt(result.blockNumber);\n debug(\"got logs\", parsedLogs, \"for pending block\", blockNumber);\n if (caughtUp) {\n debug(\"handing off logs to subscriber\");\n subscriber.next({ blockNumber, logs: parsedLogs });\n // Since this the event's block number corresponds to a pending block, we have to refetch this block in case of a restart\n resumeBlock = blockNumber;\n } else {\n debug(\"buffering logs\");\n logBuffer.push(...parsedLogs);\n }\n return;\n }\n });\n\n // Catch up to the pending logs\n try {\n debug(\"fetching initial logs\");\n const initialLogs = await fetchInitialLogs({ client, address, fromBlock: resumeBlock, topics });\n debug(\"got initial logs\", initialLogs);\n const logs = [...initialLogs.logs, ...logBuffer].sort(logSort);\n debug(\"combining with log buffer\", logs);\n const blockNumber = logs.at(-1)?.blockNumber ?? initialLogs.blockNumber;\n subscriber.next({ blockNumber, logs });\n // Since this the block number can correspond to a pending block, we have to refetch this block in case of a restart\n resumeBlock = blockNumber;\n caughtUp = true;\n } catch (error) {\n debug(\"could not get initial logs\", error);\n subscriber.error(\"Could not fetch initial wiresaw logs\");\n }\n }\n\n setupClient().catch((error) => {\n debug(\"error setting up initial client\", error);\n subscriber.error(error);\n });\n\n return () => {\n debug(\"logs$ subscription closed\");\n clearTimeout(pingTimer);\n client?.close();\n };\n });\n\n return { logs$ };\n}\n\ntype FetchInitialLogsInput = { client: SocketRpcClient<WebSocket>; topics: LogTopic[] } & Omit<WatchLogsInput, \"url\">;\n\nasync function fetchInitialLogs({\n client,\n address,\n topics,\n fromBlock,\n}: FetchInitialLogsInput): Promise<{ blockNumber: bigint; logs: StoreEventsLog[] }> {\n // Fetch latest block number\n const latestBlockNumber: Hex = (\n await client.requestAsync({\n body: {\n method: \"eth_blockNumber\",\n },\n })\n ).result;\n\n // Request all logs from `fromBlock` to the latest block number\n const rawInitialLogs: RpcLog[] = await client\n .requestAsync({\n body: {\n method: \"eth_getLogs\",\n params: [{ address, topics, fromBlock: toHex(fromBlock), toBlock: latestBlockNumber }],\n },\n })\n .then((res) => res.result);\n\n // Return all logs from `fromBlock` until the current pending block state as initial result\n const formattedLogs = rawInitialLogs.map((log) => formatLog(log));\n return { blockNumber: BigInt(latestBlockNumber), logs: parseEventLogs({ abi: storeEventsAbi, logs: formattedLogs }) };\n}\n","{\n \"name\": \"@latticexyz/store-sync\",\n \"version\": \"2.2.19\",\n \"description\": \"Utilities to sync MUD Store events with a client or cache\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/latticexyz/mud.git\",\n \"directory\": \"packages/store-sync\"\n },\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"exports\": {\n \".\": \"./dist/index.js\",\n \"./indexer-client\": \"./dist/indexer-client/index.js\",\n \"./internal\": \"./dist/exports/internal.js\",\n \"./react\": \"./dist/exports/react.js\",\n \"./postgres\": \"./dist/postgres/index.js\",\n \"./postgres-decoded\": \"./dist/postgres-decoded/index.js\",\n \"./recs\": \"./dist/recs/index.js\",\n \"./sqlite\": \"./dist/sqlite/index.js\",\n \"./trpc-indexer\": \"./dist/trpc-indexer/index.js\",\n \"./world\": \"./dist/world/index.js\",\n \"./zustand\": \"./dist/zustand/index.js\"\n },\n \"typesVersions\": {\n \"*\": {\n \"index\": [\n \"./dist/index.d.ts\"\n ],\n \"indexer-client\": [\n \"./dist/indexer-client/index.d.ts\"\n ],\n \"internal\": [\n \"./dist/exports/internal.d.ts\"\n ],\n \"react\": [\n \"./dist/exports/react.d.ts\"\n ],\n \"postgres\": [\n \"./dist/postgres/index.d.ts\"\n ],\n \"postgres-decoded\": [\n \"./dist/postgres-decoded/index.d.ts\"\n ],\n \"recs\": [\n \"./dist/recs/index.d.ts\"\n ],\n \"sqlite\": [\n \"./dist/sqlite/index.d.ts\"\n ],\n \"trpc-indexer\": [\n \"./dist/trpc-indexer/index.d.ts\"\n ],\n \"world\": [\n \"./dist/world/index.d.ts\"\n ],\n \"zustand\": [\n \"./dist/zustand/index.d.ts\"\n ]\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"bench\": \"vitest bench\",\n \"build\": \"pnpm run build:js\",\n \"build:js\": \"tsup\",\n \"clean\": \"pnpm run clean:js\",\n \"clean:js\": \"shx rm -rf dist\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint .\",\n \"test\": \"vitest\",\n \"test:ci\": \"vitest --run\"\n },\n \"dependencies\": {\n \"@ark/util\": \"0.2.2\",\n \"@latticexyz/block-logs-stream\": \"workspace:*\",\n \"@latticexyz/common\": \"workspace:*\",\n \"@latticexyz/config\": \"workspace:*\",\n \"@latticexyz/protocol-parser\": \"workspace:*\",\n \"@latticexyz/recs\": \"workspace:*\",\n \"@latticexyz/schema-type\": \"workspace:*\",\n \"@latticexyz/stash\": \"workspace:*\",\n \"@latticexyz/store\": \"workspace:*\",\n \"@latticexyz/world\": \"workspace:*\",\n \"@trpc/client\": \"10.34.0\",\n \"@trpc/server\": \"10.34.0\",\n \"change-case\": \"^5.2.0\",\n \"debug\": \"^4.3.4\",\n \"drizzle-orm\": \"^0.28.5\",\n \"fast-deep-equal\": \"^3.1.3\",\n \"kysely\": \"^0.26.3\",\n \"postgres\": \"^3.3.5\",\n \"rxjs\": \"7.5.5\",\n \"sql.js\": \"^1.8.0\",\n \"superjson\": \"^1.12.4\",\n \"zod\": \"3.23.8\",\n \"zustand\": \"^4.3.7\"\n },\n \"devDependencies\": {\n \"@tanstack/react-query\": \"^5.56.2\",\n \"@testing-library/react\": \"^16.0.0\",\n \"@testing-library/react-hooks\": \"^8.0.1\",\n \"@types/debug\": \"^4.1.7\",\n \"@types/react\": \"18.2.22\",\n \"@types/sql.js\": \"^1.4.4\",\n \"eslint-plugin-react\": \"7.31.11\",\n \"eslint-plugin-react-hooks\": \"4.6.0\",\n \"react\": \"18.2.0\",\n \"react-dom\": \"18.2.0\",\n \"viem\": \"2.21.19\",\n \"wagmi\": \"2.12.11\"\n },\n \"peerDependencies\": {\n \"@tanstack/react-query\": \"5.x\",\n \"react\": \"18.x\",\n \"viem\": \"2.x\",\n \"wagmi\": \"2.x\"\n },\n \"peerDependenciesMeta\": {\n \"@tanstack/react-query\": {\n \"optional\": true\n },\n \"react\": {\n \"optional\": true\n },\n \"wagmi\": {\n \"optional\": true\n }\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n"],"mappings":"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","names":["SyncStep","storeEventsAbi","parseEventLogs","Observable","debug","Observable","debug","filter","chunk","startBlock","storeEventsAbi","parseEventLogs"]}
|
package/dist/exports/internal.js
CHANGED
package/dist/index.js
CHANGED
package/dist/postgres/index.js
CHANGED
package/dist/recs/index.js
CHANGED
package/dist/sqlite/index.js
CHANGED
package/dist/zustand/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@latticexyz/store-sync",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.19",
|
|
4
4
|
"description": "Utilities to sync MUD Store events with a client or cache",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -77,15 +77,15 @@
|
|
|
77
77
|
"superjson": "^1.12.4",
|
|
78
78
|
"zod": "3.23.8",
|
|
79
79
|
"zustand": "^4.3.7",
|
|
80
|
-
"@latticexyz/block-logs-stream": "2.2.
|
|
81
|
-
"@latticexyz/common": "2.2.
|
|
82
|
-
"@latticexyz/config": "2.2.
|
|
83
|
-
"@latticexyz/
|
|
84
|
-
"@latticexyz/
|
|
85
|
-
"@latticexyz/schema-type": "2.2.
|
|
86
|
-
"@latticexyz/
|
|
87
|
-
"@latticexyz/store": "2.2.
|
|
88
|
-
"@latticexyz/
|
|
80
|
+
"@latticexyz/block-logs-stream": "2.2.19",
|
|
81
|
+
"@latticexyz/common": "2.2.19",
|
|
82
|
+
"@latticexyz/config": "2.2.19",
|
|
83
|
+
"@latticexyz/recs": "2.2.19",
|
|
84
|
+
"@latticexyz/protocol-parser": "2.2.19",
|
|
85
|
+
"@latticexyz/schema-type": "2.2.19",
|
|
86
|
+
"@latticexyz/world": "2.2.19",
|
|
87
|
+
"@latticexyz/store": "2.2.19",
|
|
88
|
+
"@latticexyz/stash": "2.2.19"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@tanstack/react-query": "^5.56.2",
|