Major Changes
-
8311e4c: feat(shuttle): add
OnChainEventReconciliationand a typedonchain_eventstableAdds first-class support for reconciling on-chain events between the hub
and the local database, mirroring the structure of
MessageReconciliation.Highlights:
-
New
OnChainEventReconciliationclass (in
src/shuttle/onChainEventReconciliation.ts) with
reconcileOnChainEventsForFid/reconcileOnChainEventsOfTypeForFid.
Both methods take an options object (rather than positional
arguments) so the optionalonDbOnChainEventcallback isn't a
landmine sitting between the hub callback and the time-window
arguments. The DB-side pass is opt-in via that callback. By default
it coversID_REGISTER,SIGNER,SIGNER_MIGRATED,STORAGE_RENT
andTIER_PURCHASEevents. The newRECONCILABLE_ONCHAIN_EVENT_TYPES
const +ReconcilableOnChainEventTypetype pin the publictypes
parameter to only the event kinds the reconciler actually has hub-
side fetch logic for. -
startTimestamp/stopTimestampare Farcaster timestamp numbers
(matchingMessageReconciliation), validated once up front in the
outer call, so input handling is consistent whether or not
onDbOnChainEventis provided. -
Promotes
onchain_eventsto a typed table onHubTables, with new
exportsOnChainEventsTable,OnChainEventRow,
InsertableOnChainEventRow, andOnChainEventBodyJson. Body shapes
are now JSON-safe (every protobufUint8Arrayfield — e.g.
IdRegisterEventBody.to,TierPurchaseBody.payer— is exposed as a
0x-prefixed string), so values round-trip through a Postgresjson
column without being persisted as numeric-index objects.chainId/
blockNumberare typed asnumberto match the package's global
int8→ JSnumberpg parser; declaring them asbigint(the
literal Postgres type) would silently mislead consumers and break
the IN-list comparisons used by reconciliation. -
Updates the example-app accordingly: migration
003_onchain_events
now includeschainIdand usesblockTimestamp(matching the hub
event payload), and the example handler records signer-migrated and
tier-purchase events alongside the existing ID-register / signer /
storage-rent ones. -
Adds integration test coverage for
OnChainEventReconciliation:
a regression test for thechainId/blockNumberIN-list
comparison (now that those columns deserialize as JSnumber),
hub-only and DB-only flagging, and thetypesfilter.
Marked as a major release because the new
onchain_eventsfield on the
exportedHubTablesinterface is a breaking change for consumers that
already extendHubTableswith their ownonchain_eventsshape, and
the example-app migration renames/adds columns relative to the prior
example schema. -
-
a089e1d: feat(shuttle): add
UsernameProofReconciliationand a typedusernamestableAdds first-class support for reconciling username proofs (
fname,
ENS L1, basenames) between the hub and the local database, mirroring
the structure ofMessageReconciliation:-
New
UsernameProofReconciliationclass (in
src/shuttle/usernameProofReconciliation.ts) with
reconcileUsernameProofsForFid/
reconcileUsernameProofsOfTypeForFid. The hub-side pass is always
run, and the DB-side pass is opt-in via anonDbProofcallback. -
Promotes
usernamesto a typed table onHubTables, with new
exportsUsernamesTable,UsernameRow,InsertableUsernameRow.
Adds an004_usernamesmigration to the example app.
Marked as a major release because the new
usernamesfield on the
exportedHubTablesinterface is a breaking change for consumers that
already extendHubTableswith their ownusernamestable shape. -
Minor Changes
-
2328cf4: feat(shuttle): allow disabling DB-side reconciliation and filtering message types
MessageReconciliationnow lets callers opt out of the
"DB messages missing from the hub" pass, which is useful during initial
backfills where every DB row is missing from the hub by definition and
streaming each one through the callback is just wasted work.onDbMessageis now optional on bothreconcileMessagesForFidand
reconcileMessagesOfTypeForFid. When omitted, the DB-side scan is
skipped entirely (noallActiveDbMessagesOfTypeForFidcall) and the
per-message hub-hash map that the DB pass needed is no longer
populated, removing a per-FID memory cost on large backfills.reconcileMessagesForFidaccepts a new optional
types: ReconcilableMessageType[]parameter to restrict
reconciliation to a subset of message types (e.g. onlyLEND_STORAGE
after a hub backfill of just that type). The new
RECONCILABLE_MESSAGE_TYPESconst +ReconcilableMessageTypetype
pin this to the message typesMessageReconciliationactually has
hub-side RPCs for, so passing e.g.CAST_REMOVEis a compile-time
error instead of a runtime "Unknown message type" throw.DBMessageis now exported so consumers can type theironDbMessage
callback without re-declaring the row shape.- Time-window resolution (
fromFarcasterTimeofstartTimestamp/
stopTimestamp) now happens once up front in
reconcileMessagesForFid/reconcileMessagesOfTypeForFidinstead
of per-type inside the DB pass, so input handling is consistent
whether or notonDbMessageis provided. - Bonus: fixes a stale
@farcaster/hub-shuttleimport in the example
app that would otherwise failtsc --noEmit.
No behavior change for existing callers that pass an
onDbMessage
callback.
Patch Changes
-
814c9f1: fix(shuttle): swallow
xtrimerrors when the Redis connection is no longer readyDuring process shutdown the periodic
HubEventStreamConsumer.clearOldEvents
timer can still fire while the underlying ioredis client is closing. The
follow-upxtrimcall against the closed connection produces unhandled
promise rejections.EventStreamConnection.trimnow wraps thextrimcall in a try/catch:
if it fails and the client is no longer in a"ready"state, the
error is swallowed (xtrim is best-effort periodic maintenance, the next
invocation against a fresh client will catch up). Any other failure is
rethrown so real errors stay visible.