Overview
Pair accounts link two registered tokens, including RWA/stablecoin and RWA/RWA pairs, enabling trading between them. Each pair is owned by a specific capital provider who controls its configuration, fees, and liquidity.Account Structures
Pair Account
["pair", liquidity_provider, quote_mint, base_mint]
New pairs require quote/base mints in ascending byte order. Existing pairs retain their stored order; quote does not necessarily mean stablecoin.
LpStableConfig Account
["lp_stable_config", stable_mint, liquidity_provider]
UserVaultInfo Account
["user_vault_info", mint_address, liquidity_provider]
VaultAuthority PDA
PDA Seeds:["vault_authority", liquidity_provider]
For permissioned mints (tokens), the issuer must separately whitelist (allowlist) both the
liquidity_provider address and the derived vault_authority PDA. The capital provider address owns the source token account; the PDA owns the destination vault ATA. Approval of one address does not apply to the other.The corresponding capital provider’s token account and PDA-owned vault ATA must also be thawed before a transfer can succeed. Creating the pair or vault ATA does not perform issuer whitelisting or thawing.vault_authority PDA is specific to each capital provider and owns that capital provider’s vault token accounts. The vault token accounts themselves are associated token accounts for (mint, vault_authority), so they are keyed by capital provider and mint without using the global program authority.
Pair Instructions
init_pair
Create a new trading pair. The capital provider signs and pays for all account creation.Parameters
Required Accounts
Behavior
- Creates Pair PDA account, paid for by the capital provider
- Validates distinct mints in canonical byte order; both assets may be RWAs
- Creates or updates LpStableConfig for each Stable mint in the pair
- Creates vault ATAs owned by the capital provider’s
vault_authorityPDA if they don’t exist - Creates UserVaultInfo accounts to track vault usage
- Increments
used_in_pairs_counton both asset configs - Initializes
redemption_fee_bpsanddiscount_rate_bpsfrom the instruction arguments - Requires program to be unpaused
- Pair pause state defaults to unpaused unless the capital provider later pauses it with
update_pair
Access Control
Access: Capital provider (signs asliquidity_provider).
Swaps still require every pause gate to be open: global config, both asset configs, applicable capital provider stable configs, the fee asset, and the pair itself.
Example
lpStableConfigQuote and lpStableConfigBase are supplied for Stable sides and null for RWA sides.
update_pair
Update pair configuration (fees and pause state).Parameters
Required Accounts
Behavior
- Updates fee configuration
- Updates pause state
- Requires program to be unpaused
- Validates both fee values are
<= 9900and their sum is< 10000
Access Control
Access: Capital provider (pair owner) onlyExample
close_pair
Permanently close a trading pair. The capital provider signs and receives the reclaimed rent for the pair account and any closed vault accounts; the configured global-config admin is referenced as a non-signing account and checked byhas_one.
Required Accounts
Behavior
- Closes Pair account
- Requires program to be unpaused
- Decrements
used_in_pairs_counton both asset configs - Requires the capital provider’s Treasury position to be empty, even if Treasury routing has been disabled
- Returns remaining vault tokens to the capital provider’s recipient token accounts
- Closes vault ATAs if no longer used by other pairs
- Closes the corresponding UserVaultInfo PDAs when their
usedcount reaches 0 - Returns reclaimed rent (Pair PDA, closed vault ATAs, and closed UserVaultInfo PDAs) to the capital provider
Access Control
Access: Capital provider (pair owner). Theadmin account must be provided and is verified against global_config.admin via has_one, but admin does not sign.
set_paused_for_lp_stable_config
Set pause state for all pairs of a capital provider/stablecoin combination.Parameters
Required Accounts
Behavior
- Updates pause state on LpStableConfig
- Affects ALL pairs using this capital provider/stablecoin combination
- Can be updated while the program is paused
Access Control
Access: Admin OR capital provider (config owner)Liquidity Instructions
Treasury Routing
The capital provider controls routing throughset_lp_treasury_enabled(enabled: bool). The flag is stored in LpProtocolFeeConfig, derived from ["lp_protocol_fee_config", liquidity_provider]. Enabling routing funds the capital provider vault-authority PDA for Treasury account rent; it does not move existing token balances by itself. Disabling routing does not redeem an existing position.
When the configuration is first created, its protocol-fee rates are copied from the global configuration. The admin can set those rates independently through set_lp_protocol_fee_config.
Routing requires an unpaused Treasury program and an unpaused asset registered as Stable in Treasury. For eligible assets, add_liquidity can deposit the entire post-transfer vault balance into Treasury, subject to its 1 of NAV value, and available pending-deposit capacity. Otherwise the input remains in the capital provider vault. Existing idle output liquidity is used before Treasury redemption.
The Treasury position and receipt-token account belong to the capital provider’s swap vault-authority PDA. The Treasury manager configures supported assets and their NAV sources separately from the swap program.
add_liquidity
Treasury account counts are zero when Treasury routing is unused.amount_threshold is an optional minimum receipt output for the Treasury deposit. The optional argument must be encoded even when omitted (None).
Deposit tokens into a vault.
Parameters
Required Accounts
Behavior
- Transfers tokens from the capital provider’s account to vault
- Vault is the mint’s ATA owned by the capital provider’s
vault_authorityPDA - Requires program, asset, and applicable capital provider stable config to be unpaused
- Amount must be greater than 0
- Deposits the whole post-transfer vault balance into Treasury when routing is enabled, Treasury and its Stable asset configuration are unpaused, and pending-deposit capacity is available
Access Control
Access: Capital provider (vault owner) onlyExample
remove_liquidity
With Treasury routing,exact_mode selects value in Treasury token units (ExactIn) or asset output (ExactOut). amount_threshold bounds minimum asset output or maximum Treasury tokens actually burned respectively; without Treasury routing, amount is the asset amount.
Withdraw tokens from a vault.
Parameters
Required Accounts
The common accounts are the capital provider, mint, capital provider token account, vault token account, capital provider vault authority, global config, capital provider protocol-fee config, and token program. Treasury routing uses the same Treasury accounts asadd_liquidity, except that treasury_latest_apy_entry replaces treasury_system_program. remove_liquidity does not take swap asset_config or lp_stable_config accounts. Exact account ordering is defined in the Program IDL.
Behavior
- Transfers tokens from vault to the capital provider’s account
- Vault is the mint’s ATA owned by the capital provider’s
vault_authorityPDA - Requires program to be unpaused
- Amount must be greater than 0
- Direct withdrawal requires sufficient idle vault balance
- Treasury-backed ExactOut uses idle vault liquidity first and redeems only the shortfall
- Treasury-backed ExactIn transfers the assets received from redemption; receipt tokens are burned only for the principal consumed, while yield is accounted for in the position
Access Control
Access: Capital provider (vault owner) onlyClosing Treasury and Fee Accounts
After withdrawing and settling the Treasury position, the capital provider can callclose_treasury_position to recover its rent. Principal, accumulated yield, and pending deposits must all be zero. The instruction also closes the receipt-token account when empty and returns the capital provider vault-authority PDA’s lamports to the capital provider.
close_lp_fee_account returns any remaining fee-token balance and closes the capital provider fee account. The capital provider closes its pairs first, because swaps require that fee account. Both instructions require the swap program to be unpaused.
Vault Architecture
Shared Vault Model
Vaults are shared across pairs for the same capital provider/token combination. Each capital provider has avault_authority PDA, and each vault is the associated token account for (mint, vault_authority):
UserVaultInfo Tracking
TheUserVaultInfo account tracks how many pairs use each vault:
- Incremented when pair is created
- Decremented when pair is closed
- Vault closed only when
usedreaches 0
Error Codes
Next: Price Sources
Learn about NAV pricing sources and oracle integration