Skip to content

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

@rz1989s

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions