ChainSafe / ChainSafe/canton-middleware

feat(api): bridge API — deposit quotes, registration, unified status

Open
#358 0 comments 0 reactions 0 assignees View on GitHub
CIP-0086: Phase 2 Deliverable: D3 Type: Feature
Dominant language
Go
Stars
1
Forks
1
Avg merge
40m
Merged PRs (30d)
1

Description

# Goal

Token-agnostic bridge API on the api-server so the dapp can bridge **any** configured token without knowing its mechanism. Today there are no bridge endpoints at all (PROMPT withdrawals are initiated by scripts only).

# Design rule

**The dapp never encodes a bridge transaction.** Different tokens need different EVM calls (PROMPT: `approve` + `depositToCanton` on our `CantonBridge`; USDCx: `approve` + `depositToRemote` on Circle's xReserve with domain 10001, keccak recipient, hookData). The API returns a **quote** — fully ABI-encoded unsigned transactions the wallet signs blindly. EVM mirror of the existing Canton prepare/execute pattern.

# Endpoints

- `GET /api/v2/bridge/tokens` — supported tokens, mechanism, limits, fees, indicative ETA
- `POST /api/v2/bridge/deposit/quote` — body `{token, amount}`; authenticated user's Canton party resolved server-side (SIWE session -> userstore), so recipient encoding never leaks to the dapp:

```json
{
"quote_id": "q_7f3a...",
"chain_id": 1,
"steps": [
{"kind": "approve", "to": "0x", "data": "0x095ea7b3...", "value": "0"},
{"kind": "deposit", "to": "0x", "data": "0x...", "value": "0"}
],
"fees": {"bridge_fee": "0.15", "currency": "USDC"},
"estimated_seconds": 900,
"expires_at": "..."
}
```

- `approve` step included only when on-chain allowance is insufficient
- fees/ETA come from the mechanism (seconds + zero fee for wayfinder; ~15 min + Circle fee for xreserve)
- quote params persisted against `quote_id` so registration can be validated against what was quoted
- future optimization: EIP-2612 permit (USDC supports it) to collapse the approve step
- `POST /api/v2/bridge/deposits` — `{quote_id, tx_hash}`: registers the transfer for tracking (no-op-ish for wayfinder — the Source detects independently; required for xreserve)
- `POST /api/v2/bridge/withdraw/prepare|execute` — mechanism-dispatched Canton-side signing: wayfinder builds `InitiateWithdrawal`; xreserve builds `BridgeUserAgreement_Burn`. Execute registers the transfer.
- `GET /api/v2/bridge/transfers?address=...` and `/{id}` — unified status (`status` + `stage`)

Dapp flow for any token, present and future: `GET tokens` -> `POST deposit/quote` -> sign & send steps -> `POST deposits` -> poll `GET transfers/{id}`. Adding a token changes the token list, nothing else.

# Structure

```go
// pkg/bridgeapi — api-server local; quote construction is stateless ABI
// encoding and does not belong in the relayer.
type DepositQuoter interface {
DepositQuote(ctx context.Context, req QuoteRequest) (*Quote, error)
}
```

One implementation per mechanism, built from the same per-token config as the relayer registry. Registration and status read go to the relayer (internal `POST /api/v1/transfers`, `GET /api/v1/transfers`).

# Work items

- [ ] `pkg/bridgeapi/` — types, `DepositQuoter`, wayfinder + xreserve quoters, allowance check via eth client
- [ ] Quote persistence + validation on registration
- [ ] HTTP handlers + routes (chi), SIWE-authenticated
- [ ] Withdraw prepare/execute dispatch (wayfinder `InitiateWithdrawal` gives PROMPT withdrawals their first production API)
- [ ] Wayfinder withdrawal UX note: dapp shows `stage` honestly (offer submitted vs settled)
- [ ] Unit tests per quoter; e2e: quote -> sign (devstack key) -> deposit -> status

# Depends on

- Relayer multi-token refactor (shared per-token config, transfers registration endpoint)

# Related

- Works for PROMPT alone even before the xreserve adapter lands; USDCx quotes activate with the xreserve inbound issue.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reading the existing relayer transfer endpoints and the shared per-token configuration, then inspect the proposed pkg/bridgeapi/ interfaces and the chi route setup. Trace the SIWE session-to-userstore path and the Canton prepare/execute flow before separating wayfinder and xreserve behavior. Done means the documented bridge routes, quote persistence and validation, mechanism dispatch, unit tests, and the quote-to-status e2e flow work together.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, backend, blockchain
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.