mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-08-26 14:41:12 +00:00
Add validated shared quote orchestration, canonical planners for every guest instruction, and exact RISC Zero serialization. Expose integer-only slippage preparation and lossless JSON/C adapters without runtime deployment identity checks.
186 lines
8.0 KiB
Markdown
186 lines
8.0 KiB
Markdown
# AMM client JSON wire API
|
|
|
|
The C ABI accepts one tagged JSON object and returns one envelope:
|
|
|
|
```json
|
|
{"ok":true,"value":{}}
|
|
```
|
|
|
|
```json
|
|
{"ok":false,"error":{"code":"invalid_request","message":"..."}}
|
|
```
|
|
|
|
All `u128` amounts, reserves, supplies, fees, nonces, and balances are unsigned decimal strings.
|
|
All `u64` windows and deadlines are also decimal strings. Program IDs are arrays of eight `u32`
|
|
words. Account IDs are base58 strings. Account `data` is an even-length hexadecimal string.
|
|
|
|
## Shared inputs
|
|
|
|
Plan context:
|
|
|
|
```json
|
|
{
|
|
"ammProgramId": [0, 0, 0, 0, 0, 0, 0, 0],
|
|
"tokenProgramId": [0, 0, 0, 0, 0, 0, 0, 0],
|
|
"twapOracleProgramId": [0, 0, 0, 0, 0, 0, 0, 0],
|
|
"authority": "base58-account-id"
|
|
}
|
|
```
|
|
|
|
Decoded pool input used by existing-pool planners:
|
|
|
|
```json
|
|
{
|
|
"poolId": "base58-account-id",
|
|
"definitionTokenAId": "base58-account-id",
|
|
"definitionTokenBId": "base58-account-id",
|
|
"vaultAId": "base58-account-id",
|
|
"vaultBId": "base58-account-id",
|
|
"liquidityPoolId": "base58-account-id",
|
|
"liquidityPoolSupply": "2000",
|
|
"reserveA": "1000",
|
|
"reserveB": "500",
|
|
"fees": "30"
|
|
}
|
|
```
|
|
|
|
Fetched account snapshot used by quotes:
|
|
|
|
```json
|
|
{
|
|
"id": "base58-account-id",
|
|
"programOwner": [0, 0, 0, 0, 0, 0, 0, 0],
|
|
"balance": "0",
|
|
"nonce": "0",
|
|
"data": "00ff"
|
|
}
|
|
```
|
|
|
|
Existing-pool quote operations include these top-level state fields:
|
|
|
|
```json
|
|
{
|
|
"ammProgramId": [0, 0, 0, 0, 0, 0, 0, 0],
|
|
"config": { "...": "account snapshot" },
|
|
"snapshot": {
|
|
"pool": { "...": "account snapshot" },
|
|
"tokenADefinition": { "...": "account snapshot" },
|
|
"tokenBDefinition": { "...": "account snapshot" },
|
|
"vaultA": { "...": "account snapshot" },
|
|
"vaultB": { "...": "account snapshot" },
|
|
"liquidityDefinition": { "...": "account snapshot" }
|
|
}
|
|
}
|
|
```
|
|
|
|
## Plan operations
|
|
|
|
Send requests to `amm_client_plan` or `wire::plan_json`.
|
|
|
|
| `operation` | Additional fields |
|
|
|---|---|
|
|
| `initialize` | `ammProgramId`, `tokenProgramId`, `twapOracleProgramId`, `authority` |
|
|
| `update_config` | `context`, optional `tokenProgramId`, optional `twapOracleProgramId`, optional `newAuthority` |
|
|
| `create_price_observations` | `context`, `poolId`, `windowDuration` |
|
|
| `create_oracle_price_account` | `context`, `poolId`, `windowDuration` |
|
|
| `create_pool` | `context`, `tokenADefinitionId`, `tokenBDefinitionId`, `userHoldingA`, `userHoldingB`, `userHoldingLp`, `tokenAAmount`, `tokenBAmount`, `fees`, `deadline` |
|
|
| `add_liquidity` | `context`, `pool`, `userHoldingA`, `userHoldingB`, `userHoldingLp`, `minAmountLiquidity`, `maxAmountToAddTokenA`, `maxAmountToAddTokenB`, `deadline` |
|
|
| `remove_liquidity` | `context`, `pool`, `userHoldingA`, `userHoldingB`, `userHoldingLp`, `removeLiquidityAmount`, `minAmountToRemoveTokenA`, `minAmountToRemoveTokenB`, `deadline` |
|
|
| `swap_exact_input` | `context`, `pool`, `userInputHolding`, `userOutputHolding`, `swapAmountIn`, `minAmountOut`, `deadline` |
|
|
| `swap_exact_output` | `context`, `pool`, `userInputHolding`, `userOutputHolding`, `exactAmountOut`, `maxAmountIn`, `deadline` |
|
|
| `sync_reserves` | `context`, `pool` |
|
|
|
|
A successful plan value contains the following fields (`instructionWords` is abbreviated here):
|
|
|
|
```json
|
|
{
|
|
"instruction": "add_liquidity",
|
|
"programId": [0, 0, 0, 0, 0, 0, 0, 0],
|
|
"accounts": [
|
|
{
|
|
"id": "base58-account-id",
|
|
"role": "config",
|
|
"writable": false,
|
|
"signer": false,
|
|
"init": false
|
|
}
|
|
],
|
|
"instructionWords": [5]
|
|
}
|
|
```
|
|
|
|
The real `instructionWords` array contains the complete encoding produced directly from the
|
|
canonical `amm_core::Instruction` with RISC Zero Serde. Account rows follow guest/IDL order.
|
|
|
|
## Quote operations
|
|
|
|
Send requests to `amm_client_quote` or `wire::quote_json`. Except `protocol_constants`,
|
|
`create_pool`, and `prepare_create_pool`, every operation below also includes the existing-pool
|
|
quote state described above.
|
|
|
|
| `operation` | Additional fields |
|
|
|---|---|
|
|
| `protocol_constants` | none; returns decimal-string `minimumLiquidity`, `feeBpsDenominator`, `slippageBpsDenominator`, and `supportedFeeTiers` |
|
|
| `pair_order` | `firstTokenDefinitionId`, `secondTokenDefinitionId` |
|
|
| `create_pool` | `ammProgramId`, `config`, `tokenADefinition`, `tokenBDefinition`, `tokenAAmount`, `tokenBAmount`, `feeBps` |
|
|
| `prepare_create_pool` | same fields as `create_pool`; returns quote plus `NewDefinition` instruction arguments |
|
|
| `preview_add_liquidity` | `maxAmountA`, `maxAmountB` |
|
|
| `prepare_add_liquidity` | `maxAmountA`, `maxAmountB`, `slippageBps` |
|
|
| `add_liquidity` | `maxAmountA`, `maxAmountB`, `minimumLiquidity` |
|
|
| `preview_remove_liquidity` | `userLiquidityHolding`, `removeLiquidityAmount` |
|
|
| `prepare_remove_liquidity` | `userLiquidityHolding`, `removeLiquidityAmount`, `slippageBps` |
|
|
| `remove_liquidity` | `userLiquidityHolding`, `removeLiquidityAmount`, `minimumAmountA`, `minimumAmountB` |
|
|
| `preview_swap_exact_input` | `userInputHolding`, `userOutputHolding`, `inputTokenDefinitionId`, `amountIn` |
|
|
| `prepare_swap_exact_input` | `userInputHolding`, `userOutputHolding`, `inputTokenDefinitionId`, `amountIn`, `slippageBps` |
|
|
| `swap_exact_input` | `userInputHolding`, `userOutputHolding`, `inputTokenDefinitionId`, `amountIn`, `minimumAmountOut` |
|
|
| `preview_swap_exact_output` | `userInputHolding`, `userOutputHolding`, `inputTokenDefinitionId`, `exactAmountOut` |
|
|
| `prepare_swap_exact_output` | `userInputHolding`, `userOutputHolding`, `inputTokenDefinitionId`, `exactAmountOut`, `slippageBps` |
|
|
| `swap_exact_output` | `userInputHolding`, `userOutputHolding`, `inputTokenDefinitionId`, `exactAmountOut`, `maximumAmountIn` |
|
|
| `sync_reserves` | no additional fields |
|
|
| `create_oracle_price_account` | `windowDuration` |
|
|
|
|
Quote values use these result shapes:
|
|
|
|
- pool creation: `pool`, `lockedLiquidity`, `userLiquidity`;
|
|
- add liquidity: `actualAmountA`, `actualAmountB`, `liquidityToMint`, `pool`;
|
|
- remove liquidity: `withdrawAmountA`, `withdrawAmountB`, `liquidityToBurn`, `pool`;
|
|
- swaps: `direction`, `amountIn`, `effectiveAmountIn`, `feeAmount`, `amountOut`, `pool`;
|
|
- reserve sync: `donatedAmountA`, `donatedAmountB`, `pool`;
|
|
- oracle price: `baseAsset`, `quoteAsset`, `initialPriceQ64_64`, `windowDuration`; and
|
|
- pair order: `order` (`stored` or `reversed`).
|
|
|
|
A `pool` result contains decimal-string `liquidityPoolSupply`, `reserveA`, `reserveB`, and
|
|
`spotPriceQ64_64` fields.
|
|
|
|
## Prepared instruction arguments
|
|
|
|
The five `prepare_*` operations return the economic result under `quote` and decimal-string chain
|
|
arguments under `instructionArgs`. Those fields map directly to the matching plan operation:
|
|
|
|
- `prepare_create_pool`: `tokenAAmount`, `tokenBAmount`, `fees`;
|
|
- `prepare_add_liquidity`: `minAmountLiquidity`, `maxAmountToAddTokenA`,
|
|
`maxAmountToAddTokenB`;
|
|
- `prepare_remove_liquidity`: `removeLiquidityAmount`, `minAmountToRemoveTokenA`,
|
|
`minAmountToRemoveTokenB`;
|
|
- `prepare_swap_exact_input`: `swapAmountIn`, `minAmountOut`; and
|
|
- `prepare_swap_exact_output`: `exactAmountOut`, `maxAmountIn`.
|
|
|
|
`slippageBps` accepts `0` through `slippageBpsDenominator` (`10,000`) as an unsigned decimal
|
|
string. Minimum guards use integer floor rounding and stay at least one raw unit for positive
|
|
quotes. Maximum guards use integer ceil rounding. A maximum above `u128` returns
|
|
`slippage_bound_overflow`; an out-of-range tolerance returns `slippage_tolerance_out_of_range`.
|
|
This calculation runs only in the Rust client, never in JavaScript or QML.
|
|
|
|
Prepared add-liquidity maximums are the quote's `actualAmountA` and `actualAmountB`, not the original
|
|
possibly lopsided caps. The exact quote is rerun with those fields before they are returned. This
|
|
keeps the eventual plan from spending above the displayed/current quoted deposits.
|
|
|
|
## Ownership and failures
|
|
|
|
The client validates account decoding, configured owners, canonical PDAs, pool/vault/token/LP
|
|
relationships, swap input/output pairing, and required input balances. Quote arithmetic failures
|
|
retain the stable `amm_program::quote::QuoteError` code.
|
|
|
|
No request performs network I/O or checks an ImageID, release version, compatibility manifest, or
|
|
program allowlist. Deployment configuration is expected to select the corresponding AMM build.
|