Skip to main content

Documentation Index

Fetch the complete documentation index at: https://pacta.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Overview

An OTC (over-the-counter) desk lets two parties swap tokens directly — no order book, no AMM, just a direct deal. Pacta is a natural fit because:
  • Both parties lock their tokens before the swap
  • Settlement is atomic — both sides receive their tokens in the same transaction
  • No trusted intermediary holds funds

Example Deal

Alice wants to sell 10,000 SUI for 5,000 USDC. Bob wants to buy. They agree off-platform, then execute on Pacta.

Step 1 — Alice Creates the Agreement

import { PactaClient, ConditionPreset } from "@pacta/sdk"

const pacta = new PactaClient({ network: "testnet" })

// Alice creates the deal
await pacta.createAgreement(aliceSigner, {
  partyA:            aliceSigner.address,   // Alice — selling SUI
  partyB:            bobAddress,             // Bob — selling USDC
  arbiter:           "0x0",                  // No arbiter for simple swaps
  releaseConditions: ConditionPreset.DepositOnly, // Both deposit = swap executes
  termsHash:         "0xDEAL_HASH...",       // Hash of the agreed swap terms
  expiryMs:          BigInt(Date.now() + 2 * 60 * 60 * 1000), // 2 hour window
  unlockTimeMs:      0n,
})
Using DepositOnly means as soon as both parties deposit, anyone can trigger settlement with no approval step needed. This is the fastest path for OTC swaps.

Step 2 — Alice Deposits SUI

await pacta.depositCoin(aliceSigner, {
  agreementId:  agreementId,
  coinObjectId: aliceSuiCoinId,
  coinType:     "0x2::sui::SUI",
})

Step 3 — Bob Deposits USDC

await pacta.depositCoin(bobSigner, {
  agreementId:  agreementId,
  coinObjectId: bobUsdcCoinId,
  coinType:     "0xUSDC_PACKAGE::usdc::USDC",
})

Step 4 — Anyone Triggers Settlement

The moment both have deposited, all conditions are met. Your platform backend settles automatically:
await pacta.settle(platformBotWallet, { agreementId })

Step 5 — Each Party Claims

// Bob claims Alice's SUI
await pacta.claimCoin(bobSigner, {
  agreementId,
  coinType: "0x2::sui::SUI",
})

// Alice claims Bob's USDC
await pacta.claimCoin(aliceSigner, {
  agreementId,
  coinType: "0xUSDC_PACKAGE::usdc::USDC",
})

Adding an Approval Step for Large Deals

For large institutional deals, you may want both parties to explicitly confirm before settlement. Use FullConsent instead:
releaseConditions: ConditionPreset.FullConsent // both deposit + both approve
Then both parties call approve() after depositing to confirm the deal terms before funds move.

Handling a Failed Deal

If Bob never deposits within the 2-hour window, Alice can cancel after expiry:
await pacta.cancelExpired(aliceSigner, agreementId)

// Alice then claims back her SUI
await pacta.claimCoin(aliceSigner, {
  agreementId,
  coinType: "0x2::sui::SUI",
})

Monitoring Deal Status in Your UI

const agreement = await pacta.getAgreement(agreementId)

const timeLeft = Number(agreement.expiryMs) - Date.now()

if (!agreement.aDeposited) {
  showStatus("Waiting for Alice to deposit SUI")
} else if (!agreement.bDeposited) {
  showStatus(`Waiting for Bob to deposit USDC — ${Math.floor(timeLeft / 60000)} minutes left`)
} else {
  showStatus("Both deposited — settling...")
  await pacta.settle(botWallet, { agreementId })
}

What Your OTC Desk Does NOT Need to Build

  • Custody of either party’s tokens
  • An escrow smart contract
  • Settlement or swap logic
  • Expiry enforcement
All of that is Pacta. You build the deal matching UI, the price negotiation flow, and the user dashboard.