Skip to content

feat(minter): automatic deposit flow - #274

Draft
gregorydemay wants to merge 163 commits into
mainfrom
DEFI-2780-automatic-deposit-flow-impl
Draft

gregorydemay wants to merge 163 commits into
mainfrom
DEFI-2780-automatic-deposit-flow-impl

Conversation

@gregorydemay

@gregorydemay gregorydemay commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Last pull request of the stack implementing the automatic deposit flow designed in #272, on top of #276 to #287 and #291, which add the flow piece by piece: the fee parameter, the watchlist and its schedule, the watch_deposit_address endpoint, the fee deduction, the batched balance reads, the scan timer, the re-arm of dropped sweeps, the watchlist snapshot on upgrade, the concurrency rule between deposit_sol and the scan, the origin of a queued deposit, and the metrics.

This one adds the end-to-end test on solana-test-validator, in which two deposits detected by the scan timer and two queued with deposit_sol are swept in a single transaction, minted with and without the automatic deposit fee, and the collected fees are reported by get_minter_info. It also adds the user documentation of the flow, the changelog entries and the rollout in two upgrades: the flow stays disabled until a second upgrade sets the automatic deposit fee.

🤖 Generated with Claude Code

@gregorydemay
gregorydemay added this pull request to stack #275 October 13, 2026 14:59
@gregorydemay gregorydemay changed the title DEFI 2780 automatic deposit flow impl feat(minter): automatic deposit flow Oct 13, 2026
gregorydemay and others added 16 commits October 14, 2026 06:41
Replace the outdated section 3.1.1, which described per-transaction
crediting with getSignaturesForAddress and quotas replenished by the
removed process_deposit endpoint, with a design that builds on the
balance sweep of deposit_sol: a free registration endpoint, a scan
timer reading watched deposit addresses in batches with
getMultipleAccounts, a schedule adapted from the ckETH minter, a fixed
fee in SOL deducted from the minted amount, and a watchlist persisted
only as a bounded snapshot at pre_upgrade. Every change to the
interface, the arguments and the event log is additive, since the
minter is deployed on mainnet.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
State that a re-armed account is reported as watching again, that the
main account receives the sweepable amount minus the fee share, correct
the worst-case cost arithmetic and state its success assumption, and
distinguish a failed upgrade from a reinstallation.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ring

Move the sequence diagram of the automatic flow ahead of its
explanation, remove the semicolon that broke the mermaid parser on
GitHub, and define the deposit id where it is first used in the section.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…he constraint

State that scan ticks are guarded like the other timers so that they
never overlap, and base the automatic deposit fee constraint on the
single-signature fee share that a pending mint actually bears.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Drop the separate status query: calling the registration endpoint again
returns the stored registration or the id of the deposit in flight, as
deposit_eth does in the ckETH minter.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… signature lookup

Spell out that scan ticks never overlap, that the fee derivation is a
single-attempt estimate with re-arm costs absorbed by the minter, and
that only manual deposits are retried by the caller. Remove
getSignaturesForAddress from the RPC inventory and cost tables, since
the minter no longer uses it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A re-armed entry restarts its schedule from the first gap, bounded by
the remaining window, and a re-arm only ever follows a detection.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Record the watchlist snapshot on every upgrade so that an older one
cannot be replayed after the watchlist emptied, and let the transaction
submission section account for deposits queued by the balance scan.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The window ends with the last scan, and the next registration call
starts a new window rather than reporting a registration without a
next scan.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…it ids

Follow the ckETH minter: a registration freezes neither the minimum
deposit amount nor the automatic deposit fee, both are quoted and the
values in force at detection apply, the fee being recorded with the
queued deposit. deposit_sol compares the latest deposit id of the
account before and after its balance read, and a registration is
allowed while a deposit_sol call is in progress.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…edule

Measure gaps from the previous scan as before, but end the window at a
fixed 24 hours after registration, as the ckETH minter does, so that
the accumulated tick and call delays have slack and clients and the
re-arm share one unambiguous boundary.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ence

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…owner rationale

The fee recorded at detection matters for deposits an upgrade finds not
yet credited; a credited deposit has its mint amount in CreditedSweep.
The minter's principal is excluded as a deposit owner because its
default account is the ledger's minting account, not because of an
address collision.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@gregorydemay
gregorydemay force-pushed the DEFI-2780-automatic-deposit-flow-impl branch from 8e2c061 to dd0421b Compare October 14, 2026 06:45
Copilot AI balanced review requested due to automatic review settings October 14, 2026 06:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Raw provider responses cannot reliably reach consensus on mainnet, causing scans to fail and retry indefinitely.

1 open finding
What changed in this PR

Adds automatic SOL deposit detection through an expiring watchlist, scheduled balance scans, and automatic deposit fees.

Changes:

  • Adds the watch endpoint, scan timer, batching, concurrency handling, and upgrade persistence.
  • Tracks automatic fees, deposit history, metrics, and dashboard data.
  • Extends Candid types and comprehensive unit/integration coverage.
File Description
minter/​templates/​dashboard.html Displays automatic-deposit data.
minter/​src/​utils/​timed_sized_map/​tests.rs Tests the bounded TTL map.
minter/​src/​utils/​timed_sized_map/​mod.rs Implements the bounded TTL map.
minter/​src/​utils/​mod.rs Exports the new map module.
minter/​src/​test_fixtures/​runtime.rs Improves inter-canister call simulation.
minter/​src/​test_fixtures/​mod.rs Adds automatic-deposit fixtures.
minter/​src/​test_fixtures/​flow/​deposit.rs Supports automatic deposit test flows.
minter/​src/​storage/​mod.rs Tracks scan outcomes.
minter/​src/​state/​watchlist/​tests.rs Tests watchlist behavior.
minter/​src/​state/​watchlist/​mod.rs Implements watch registration and scheduling.
minter/​src/​state/​tests.rs Tests persistence, fees, and validation.
minter/​src/​state/​mod.rs Integrates watchlist and fee state.
minter/​src/​state/​event/​candid/​tests.rs Updates Candid event tests.
minter/​src/​state/​event/​candid/​mod.rs Converts new event types.
minter/​src/​state/​event.rs Adds automatic-deposit and snapshot events.
minter/​src/​state/​deposits/​tests.rs Tests returned dropped deposits.
minter/​src/​state/​deposits/​sweeps/​tests.rs Tests automatic fee deductions.
minter/​src/​state/​deposits/​sweeps/​mod.rs Applies automatic fees to mints.
minter/​src/​state/​deposits/​mod.rs Tracks automatic and latest deposits.
minter/​src/​state/​audit.rs Replays new state transitions.
minter/​src/​rpc/​tests.rs Tests batched balance RPC handling.
minter/​src/​rpc/​mod.rs Adds getMultipleAccounts support.
minter/​src/​metrics.rs Exposes automatic-flow metrics.
minter/​src/​main.rs Exposes endpoint and scan timer.
minter/​src/​lifecycle/​tests.rs Tests watchlist snapshots.
minter/​src/​lifecycle.rs Persists watchlist before upgrades.
minter/​src/​deposit/​sweep/​tests.rs Tests manual/automatic race handling.
minter/​src/​deposit/​sweep/​mod.rs Shares deposit queueing logic.
minter/​src/​deposit/​mod.rs Exports the automatic flow.
minter/​src/​deposit/​automatic/​tests.rs Tests watch endpoint behavior.
minter/​src/​deposit/​automatic/​scan/​tests.rs Tests scheduled balance scans.
minter/​src/​deposit/​automatic/​scan/​mod.rs Implements concurrent scans.
minter/​src/​deposit/​automatic/​mod.rs Implements watch registration API.
minter/​src/​dashboard/​tests.rs Tests automatic-flow dashboard output.
minter/​src/​dashboard/​mod.rs Builds watchlist dashboard data.
minter/​src/​cycles.rs Adds RPC-cost-only charging.
minter/​src/​constants.rs Defines scan and RPC limits.
minter/​src/​canbench.rs Updates benchmark fixtures.
minter/​cksol_minter.did Extends the public Candid interface.
minter/​Cargo.toml Promotes serde_json to runtime dependency.
libs/​types/​src/​lib.rs Adds public watch API types.
libs/​types-internal/​src/​lib.rs Adds fee configuration fields.
libs/​types-internal/​src/​event.rs Adds debug event types.
integration_tests/​tests/​tests.rs Adds end-to-end watch-flow tests.
integration_tests/​tests/​solana_test_validator.rs Tests mixed automatic/manual sweeping.
integration_tests/​src/​lib.rs Adds integration client helpers.
integration_tests/​src/​fixtures.rs Adds batched RPC mocks.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread minter/src/rpc/mod.rs Resolved
Copilot AI balanced review requested due to automatic review settings October 14, 2026 07:23
…xample with the automatic flow

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@gregorydemay
gregorydemay force-pushed the DEFI-2780-automatic-deposit-flow-impl branch from e25dd6b to 781f9fc Compare October 14, 2026 07:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It combines public API, upgrade persistence, asynchronous concurrency, fee accounting, and a documented mainnet RPC-consensus limitation.

1 open finding

🧠 Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 14, 2026 07:28
mbjorkqvist and others added 10 commits November 5, 2026 09:41
The sum only grows, across upgrades too, since replaying the event log
rebuilds it whole before the first query can read it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…oldest registration

The age of the oldest registration stays within the window whether the
scan timer runs or not, so no threshold separates a healthy minter from
a broken one. A due scan that has not run yet ages only while the timer
does not keep up, e.g. when a tick whose calls never return keeps its
guard, which an alert then sees within minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An alert on a filling watchlist can then compare the number of live
registrations with the capacity in force instead of hard-coding it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d after it ran

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An expired registration stays in the watchlist until the next tick
evicts it, and replaying an older snapshot can bring back a batch of
them, none of which is watched any more.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the next scan

Times in nanoseconds can't be read at a glance; they are shown as on the
dashboard of the ckETH minter. The next scan of each address shows when
the scan timer is behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t-snapshot

# Conflicts:
#	docs/src/development/design.md
#	integration_tests/tests/tests.rs
#	minter/src/deposit/automatic/scan/mod.rs
#	minter/src/deposit/automatic/scan/tests.rs
#	minter/src/deposit/sweep/tests.rs
#	minter/src/state/event/candid/mod.rs
#	minter/src/state/tests.rs
#	minter/src/state/watchlist/mod.rs
#	minter/src/state/watchlist/tests.rs
…ics' into DEFI-2780-automatic-deposit-flow-impl

# Conflicts:
#	docs/src/development/design.md

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mbjorkqvist and others added 6 commits November 10, 2026 12:39
…atched address

The age of the oldest live registration is bounded by the watch window, so it was
replaced by the scan lag as a metric and has no caller.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…bled

Without a snapshot, the previous version would still mint the automatic deposits
already queued without deducting their fee.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… into DEFI-2780-12-automatic-flow-metrics

# Conflicts:
#	minter/src/state/watchlist/mod.rs
#	minter/src/state/watchlist/tests.rs
…sits

A sweep that keeps failing re-arms its automatic deposits over and over, and a
full watchlist leaves them to their users; both are visible only in the logs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A dropped automatic deposit is re-armed while a dropped manual deposit waits for
its user, so the two call for different follow-ups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ics' into DEFI-2780-automatic-deposit-flow-impl

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mbjorkqvist and others added 5 commits November 10, 2026 13:45
…c-flow-metrics

# Conflicts:
#	minter/src/state/watchlist/mod.rs
#	minter/src/state/watchlist/tests.rs
…ics' into DEFI-2780-automatic-deposit-flow-impl
…six columns

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d collect the fee

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ics' into DEFI-2780-automatic-deposit-flow-impl

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mbjorkqvist and others added 2 commits November 10, 2026 14:25
…between tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ics' into DEFI-2780-automatic-deposit-flow-impl

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mbjorkqvist and others added 2 commits November 10, 2026 14:55
…ad advances

A registration removed, replaced or expired while the read was in flight was
counted, unlike after a successful read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t of the automatic flow

Qualify when the id of the latest deposit is returned, list the user-visible
changes of the stack in the changelogs, and enable the flow in a second upgrade.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants