Skip to content

feat(scheduled-ops): durable-nonce family (scheduleSend + drip) #283

Description

@rz1989s

Background

Spec 5 PR-A. Sipher's `drip` and `scheduleSend` tools currently persist scheduled-op rows to SQLite but the COURIER crank can't broadcast them — the user signature isn't available when the op fires. Per the spec, the right primitive for time-bounded ops (hours to weeks) is a pre-signed durable-nonce flow: user signs once at create time, server stores the signed tx, broadcasts when due.

What to do

  1. `scheduled_ops` table — add columns: `signed_tx BLOB`, `nonce_account TEXT`, `op_kind TEXT` (`'awaiting_seal' | 'sealed' | 'pending' | ...`)
  2. `drip` / `scheduleSend` tool result — return `serializedTxs: string[]` + `nonceInitInstructions` for user to broadcast first, then sign all N chunks
  3. New endpoint `POST /api/scheduled-ops/:batchId/seal { signedTxs }` to persist signed txs
  4. COURIER executor — for `op_kind === 'sealed'`, read `signed_tx` and broadcast via `connection.sendRawTransaction`
  5. New tool `cancelScheduledOp(opId)` that withdraws the nonce account, invalidating remaining signed txs

Why

  • Unblocks 4 of 6 scheduled tools
  • User signs ONCE; server can broadcast indefinitely until nonce is consumed
  • Tx is bytes-immutable post-sign — server can't tamper

Cost

~2-3 weeks (one PR). Sub-tasks:

  • Nonce setup UX (user pays ~0.045 SOL for 30 nonce accounts in a 30-day drip)
  • Encrypt-at-rest for signed-tx blobs in SQLite
  • Cancellation path (nonce withdraw)
  • Feature flag: `SIPHER_SCHEDULED_OPS_ENABLED=false` until devnet-verified

References

Acceptance

  • drip(amount=10 SOL, days=7) produces 7 unsigned txs anchored to 7 nonce accounts
  • User signs nonce init batch first, then signs 7 drip txs without broadcasting
  • Server persists signed txs; COURIER broadcasts at scheduled times
  • Cancellation drains nonce account → invalidates pending signed_tx
  • Torque growth-hook fires per chunk with `sipher_recurring_send_tick` events

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions