Skip to content

feat(opencode): build CoinbaseStableSwapper SwapV2 for stablecoin swaps - #1817

Merged
bmc08gt merged 6 commits into
code/cashfrom
feat/coinbase-swap-v2
Oct 22, 2026
Merged

bmc08gt merged 6 commits into
code/cashfrom
feat/coinbase-swap-v2

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Server-mediated stablecoin swaps now build CoinbaseStableSwapper SwapV2 and send swap_version = 2. This matches code-payments/ocp-server#278, where the server builds whichever instruction the request names and the client rebuilds and signs the same transaction.

The ocp-client-protocol pin is at 0.9.0 (3fef1e0), which carries swap_version.

What changed

  • CoinbaseStableSwapperProgram_SwapV2 is new. It uses discriminator [43, 4, 237, 11, 26, 201, 30, 98] and the v1 swap args. Its 15 accounts are v1's 16 with the whitelist (index 12) removed.
  • The v1 path is removed: CoinbaseStableSwapperProgram_Swap, _SwapForVersion, the builders' swapVersion parameter, and the whitelist PDA derivation. Every swap the app builds is SwapV2; SERVER_SWAP_VERSION stays as the value sent in swap_version.
  • SERVER_SWAP_VERSION = 2 feeds both the request field and the local builder, so the two cannot disagree.
    • Stateful: StatefulSwapRequest.stablecoinParams() and buildStablecoinSwapperInstructions.
    • Stateless: IntentStatelessSwap.stablecoinParams() and buildStatelessSwapInstructions.
  • The client-built deposit swaps (UsdfDepositInstructions, UsdcToUsdfSwapInstructions, both reached from PhantomWalletController) build SwapV2 too, without a version switch. The server never sees these transactions, so there is no swap_version to match.

Tests

  • CoinbaseStableSwapperProgramTest asserts the exact bytes and account list from the server's instructions_swap_v2_test.go. iOS asserts the same vector.
  • CoinbaseStablecoinSwapperInstructionsTest and StatelessSwapInstructionsTest check that both builders emit the 15-account SwapV2.
  • StablecoinSwapVersionRequestTest checks that both requests carry swap_version = 2.
  • ClientBuiltDepositSwapV2Test checks that both deposit builders emit the 15-account SwapV2.
  • CoinbaseStablecoinDepositTransactionTest pins the full encoded deposit transaction. Its SwapV2 bytes pass simulateTransaction on mainnet (Swapped 5000000 tokens, 59730 compute units), so mainnet CoinbaseStableSwapper accepts swap_v2 on the deposit path.

Before merging

  • Add support for swap v2 for the Coinbase Stableswapper ocp-server#278 is deployed. It had to be: an older server ignores swap_version and builds Swap, so the signed SwapV2 transaction wouldn't match.
  • On the stateful path, swap_version is also inside the signed proof's client_parameters, via verifiedMetadata(). That needs a confirmation from the server side that this is accepted.

Linked: iOS code-payments/code-ios-app#1104

…d stablecoin swaps

Add the SwapV2 instruction (no whitelist account, 15 accounts) and send
swap_version = 2 on the stateful and stateless stablecoin initiate
requests. The request and the locally built instruction both read
CoinbaseStableSwapperProgram.SERVER_SWAP_VERSION so they cannot drift.
The client-built deposit paths keep the legacy Swap.
@bmc08gt bmc08gt self-assigned this Oct 22, 2026
@github-actions github-actions Bot added type: feature New functionality area: crypto Solana, keys, encryption, signing area: network gRPC, connectivity, API, exchange rates area: intents Intent construction, submission, server-side state and removed type: feature New functionality labels Oct 22, 2026
0.9.0 carries swap_version on both CoinbaseStableSwapper initiate params.
@github-actions github-actions Bot added type: feature New functionality area: build-system Gradle, convention plugins, build-logic and removed type: feature New functionality labels Oct 22, 2026
@bmc08gt
bmc08gt marked this pull request as ready for review October 22, 2026 17:24
The USDF deposit and the USDC to USDF fund swap both moved from Swap to SwapV2, which drops the whitelist account. The deposit transaction fixture is regenerated from the builder; the v1 bytes it replaces were mainnet-simulated, and the v2 bytes are not yet.
@github-actions github-actions Bot added the type: feature New functionality label Oct 22, 2026
@bmc08gt
bmc08gt merged commit 38e2449 into code/cash Oct 22, 2026
6 of 7 checks passed
@bmc08gt
bmc08gt deleted the feat/coinbase-swap-v2 branch October 23, 2026 16:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: build-system Gradle, convention plugins, build-logic area: crypto Solana, keys, encryption, signing area: intents Intent construction, submission, server-side state area: network gRPC, connectivity, API, exchange rates type: feature New functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant