Add Subscription example: pull payments without escrow lock - #74
Conversation
Alternative to PaymentAuthorization's lock-then-capture escrow. The coin stays customer-spendable at all times; the merchant gets a covenant-bound allowance to pull exactly pullAmount once per interval. Cancel settles any already-due periods to the merchant before releasing the rest.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Playground PreviewA live preview of this PR's playground is available at:
|
- cancel now computes elapsed = tx.offchainTime - nextPullTime once and guards on its sign, instead of re-deriving the same subtraction from tx.offchainTime/nextPullTime separately for the gate and for elapsed (matches the elapsed-time idiom used elsewhere, e.g. stability_vault.ark). - Test file reuses the shared leaf_asm/witness_names helpers instead of hand-rolling leaf/witness extraction. - Strengthened the pull output-0 assertion to check the exact merchant-pin token sequence, since pull pins two structurally similar outputs (merchant payout at 0, renewal VTXO at 1) and a presence-only check couldn't tell them apart.
Fresh environments have neither the wasm32 target nor wasm-pack installed. Also note wasm-pack's binaryen download can fail in restricted sandboxes (use --no-opt, not a Cargo.toml change), and that examples/ files auto-join the WASM build via contracts.js but need a manual main.js entry to appear in the playground's file-tree UI.
Summary
examples/subscription/subscription.ark: a pull-payment alternative topayment_auth's authorize/capture escrow. Instead of locking the customer's funds until the merchant captures or a timelock refunds, the coin stays customer-spendable at all times; the covenant carves out a bounded merchant allowance of exactlypullAmountonce perinterval.pull(merchantSig): merchant collects one period once it's due (tx.offchainTime >= nextPullTime); the remainder recreates the contract with the schedule advanced byinterval(missed periods accrue rather than resetting to "now", so billing dates never drift).cancel(customerSig): customer exits anytime, but any already-due periods are settled to the merchant first (billed-in-advance, sopullandcancelalways agree on what's currently owed). Debt is capped against the coin's balance before multiplying, to avoid overflow on a long-neglected subscription; sub-dust debt is forgiven.unilateral(customerSig)tapscript CSV exit, matching the project's standard L1 fallback pattern.tests/examples/compilation_roundtrip.rsand adds a dedicatedtests/examples/subscription.rswith structural assertions on spend-group count, witness/signature shape per function, the overflow-safe debt-cap ordering, and the recursive renewal output.Test plan
cargo test --test examples subscription— 11/11 new tests passcargo test --workspace— full suite passescargo clippy --workspace --all-targets -- -D warnings— cleancargo fmt --check— cleancargo run -- examples/subscription/subscription.ark -o /tmp/contract.json— compilesGenerated by Claude Code