USDC arrives on a source chain and is registered against the Gateway unified balance — no bridging, no wrapped assets.
Apps that collect USDC across chains have to reconcile balances everywhere before they can pay anyone out. Portage routes each deposit through Circle Gateway into a single per-app balance on Arc — so you clear and pay from one ledger, with no bridging and no wrapped tokens.
Every deposit lands in Circle Gateway's unified balance, clears atomically on Arc, and settles into a single per-app ledger balance you draw down on demand.
USDC arrives on a source chain and is registered against the Gateway unified balance — no bridging, no wrapped assets.
A signed burn intent is attested by Circle, pinning the destination caller to Portage's forwarder so nothing can be misrouted.
Arc mints and credits in one atomic call. The app balance grows; solvency holds by construction.
An immutable core — registry, ledger, payout engine — with a thin periphery that lands mints and quarantines anything malformed. Funds never sit anywhere they can be mis-credited.
USDC lands on a source chain and is registered against Circle Gateway's unified balance.
A signed burn intent binds the deposit's metadata to its spec hash, ready for attestation.
Arc runs executeMintWithMeta, minting and crediting the ledger in one atomic call.
The payout engine releases a single settled USDC payment to the consignee, gated by the app's controller.
@erhnysr/portage-sdk is a non-custodial TypeScript client. Users sign burn intents with their own wallet; the SDK never holds keys. Amounts are atomic USDC units.
import { PortageClient, appIdFromName } from "@erhnysr/portage-sdk"
// Non-custodial: signs with the user's own wallet, never holds keys
const portage = new PortageClient({ network: "arcTestnet", arcPublicClient })
// 1 · Deposit USDC into Circle Gateway's unified balance
await portage.deposit(wallet, { chain: "baseSepolia", amount: 5_000000n })
// 2 · Build + sign the consolidation intent
const intent = portage.buildConsolidationIntent({ sourceChain: "baseSepolia", amount: 5_000000n, depositor })
const burnSig = await wallet.signTypedData({ account: depositor, ...intent.typedData })
// 3 · Submit for a Circle attestation
const { attestation, signature } = await portage.submitConsolidation(intent, burnSig)
// 4 · Clear on Arc — atomic mint + credit into the app ledger
await portage.executeMintWithMeta(arcWallet, { attestation, signature, meta, metaSig })