feat(relayer): TokenBridge adapter foundation - #373
Open
sadiq1971 wants to merge 4 commits into
Open
Conversation
Introduce the multi-token bridging foundation (#356): a TokenBridge adapter interface driven by a generic step loop, coexisting with the legacy single-token pipeline (untouched; port tracked in #372). - pkg/relayer: TokenBridge/Source/StepResult interfaces + Registry; per-token config map (mechanism, evm_address, decimals) - pkg/relayer/engine: Driver with one ingest loop per adapter source (detection only, bridge-scoped chain-state keys) and a step loop that advances adapter-owned transfers until terminal, with retry backoff and max-retry failure handling - transfers schema: bridge_key (legacy rows default 'wayfinder'), token_symbol, stage, metadata jsonb, next_step_at + indexes - store: GetSteppableTransfers / ApplyStep (jsonb metadata merge) / RecordStepError, instrumented + mocked - app wiring: registry built from bridge.tokens config; driver starts only when adapters are registered (none yet - xreserve lands in #357) - docs: bridging design (docs/bridging-design.md)
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #373 +/- ##
=======================================
Coverage ? 34.91%
=======================================
Files ? 167
Lines ? 13004
Branches ? 0
=======================================
Hits ? 4540
Misses ? 8098
Partials ? 366
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
The driver treats pending and in_progress identically, so the extra status added nothing; the stage column already communicates progress detail. Status enum is back to the legacy pending/completed/failed. Also update the design doc for stateless quotes (applied in the bridge API branch).
- ingest aborts the stream on a CreateTransfer failure instead of advancing the offset past an unrecorded event (was: silent event loss on transient DB errors) - ApplyStep resets retry_count on a successful step so the max-retries gate counts consecutive, not lifetime, failures (was: long-lived observer transfers force-failed by scattered transient errors) - Driver.Start tears down already-launched ingest goroutines when a later bridge's Sources() errors (was: leaked loops on partial start) - GetSteppableTransfers orders by next_step_at (due-time fairness) so a steady backlog cannot starve newer transfers - legacy GetPendingTransfers filters to the legacy bridge key so the reconcile loop never processes adapter-owned rows - per-Step timeout so one hung adapter can't stall the shared loop - StepResult.Reason persisted on adapter-terminated failure
sadiq1971
marked this pull request as ready for review
July 29, 2026 09:44
dhyaniarun1993
approved these changes
Aug 4, 2026
dhyaniarun1993
left a comment
Member
There was a problem hiding this comment.
I have one question:
Does this TokenBridge interface supposed to work in both direction toCanton and fromCanton?
Member
Author
yes |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #356. Part of epic #361.
What
The multi-token bridging foundation: a
TokenBridgeadapter interface driven by a generic step loop. No behavior change — the legacy single-token (PROMPT) pipeline is untouched and keeps running; its port to an adapter is deferred (#372). No adapter mechanisms are registered yet, so the new driver is dormant until the xreserve adapter lands (#357).Design:
docs/bridging-design.md(included in this PR).How it works
A transfer is a durable record advanced by an idempotent
Step(ctx, *Transfer) (StepResult, error)until it reaches a terminal status; mechanisms differ only in their stage sequences.pkg/relayer/bridge.go—TokenBridge(Key/Sources/Step),Source,StepResult,Registrypkg/relayer/engine/driver.go— one ingest loop per adapter source (detection only; offsets under bridge-scoped chain-state keys<bridge>:<chain>so adapters never share a cursor with the legacy pipeline) + one step loop for all mechanisms (retry backoff, max-retry failure, adapter-bug guards)transfersschema —bridge_key(existing + legacy-pipeline rows default'wayfinder'),token_symbol,stage,metadata jsonb,next_step_at; idempotent migration so fresh DBs (whose migration 1 creates the full model) pass through unchangedGetSteppableTransfers/ApplyStep(merges metadata, clearsnext_step_aton terminal) /RecordStepError; instrumented wrappers + regenerated mocksbridge.tokensconfig map (mechanism,evm_address,decimals); the driver only starts when adapters are registeredNotes for review
chain_statekeeps its single-key schema; adapter cursors are namespaced by key string instead of a composite-column migration, since the legacy pipeline shares the table until feat(relayer): port PROMPT to wayfinder adapter, remove legacy pipeline #372.Stepcontract: never blocks on external latency — adapters returnRetryAfterand the driver reschedules vianext_step_at.Testing
TransferFromEventgolangci-lintclean; existing relayer tests pass unchanged