How it works
A single sentence: GBP/EUR → USDC on Base → BRL via PIX, with a Privy wallet holding the USDC and Bridge doing every fiat leg.
The full round-trip
The four moving pieces
| Piece | Owned by | Purpose |
|---|---|---|
| Privy embedded wallet | User | Signs on-chain USDC transfers. Non-custodial. GrinGo can't move funds. |
| Bridge virtual account | Bridge | UK sort-code / EU IBAN in the user's name. GBP/EUR arriving there auto-mints as USDC into the user's Privy wallet. |
| Bridge liquidation address | Bridge | A one-shot on-chain address for each PIX payment or withdrawal. USDC sent to it auto-off-ramps to BRL/GBP/EUR fiat. |
| GrinGo API | GrinGo | Stateless orchestrator: creates Bridge entities, verifies Privy JWTs, records ledger rows, processes webhooks. |
Why USDC on Base
- Base: L2 on Ethereum with cheap gas (~$0.001 per USDC transfer at current prices) and full Privy paymaster support.
- USDC: Regulated stablecoin, direct Bridge support in both directions.
- Invisible to users: All UI is in USD; the underlying token is an implementation detail.
Why liquidation addresses (not an operational wallet)
The architecturally important choice. See architecture/liquidation-addresses for the deep dive; the short version:
- GrinGo does not run a USDC operational wallet.
- Every PIX payment gets its own Bridge liquidation address, created just-in-time via
POST /v0/customers/{id}/liquidation_addresses. - The user's Privy wallet sends USDC directly to that address; Bridge auto-drains it to fiat.
- No
POST /v0/transferscalls, no float, no key rotation, no incident risk from a custodial pool.