Quotes live on the ledger
A quote is a signed on-ledger commitment, not a row in a database
When you call POST /maker/quotes, the desk does not just record a price. The
quote becomes a pair of DvpProposal contracts on the Canton ledger, signed
by your party, using DA's utility-settlement-app-v1 package:
- main proposal — the swap itself, counterparty = the taker;
- fee proposal — the desk fee, counterparty = the desk operator.
The contract id of your main proposal is the quote's anchor
(proposalCid). The desk's book keeps only a cache; the commitment itself
lives on the ledger.
Why this matters to you
- Your quote is binding. Once anchored, the taker can accept it without any further action from you — accepting consumes your main proposal in the taker's own transaction. There is no window where you can be filled twice: a second accept dies on contract-id contention.
- Quoting costs a ledger round-trip (~1–2 s on DevNet). The proposals go out before the book is updated, so a failed ledger write leaves no phantom quote.
- Funding is NOT checked at quoting time. The desk verifies your holdings at accept; an underfunded win fails the trade (see Error handling).
Anchoring
The desk cannot sign the pair for you, so POST /maker/quotes returns before
the proposals exist on the ledger. The two hashes wait for you on
GET /tx/pending (a passkey maker's browser signs the identical pair
automatically) — see The sign queue.
Until both signatures land, the quote is unanchored: the taker does not
see it, and accepting it answers 409 RETRY_LATER. When they do land,
quote.anchored {quoteId, rfqId, proposalCid} fires on your stream and the
quote is live.
Withdrawal
Re-quoting the same RFQ or calling DELETE /maker/quotes/:id marks the old
quote revoked and cancels its proposal pair on the ledger
(UserService_CancelDvpProposal). Expired quotes are swept the same way.
Once a quote is accepted and settling, it can no longer be revoked (409).