diff --git a/SUMMARY.md b/SUMMARY.md index 698183d..b327f58 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -28,11 +28,13 @@ * [Tooling Modules](developers/packages/foundation/sdk/tooling-modules/README.md) * [Backend API](developers/packages/foundation/sdk/tooling-modules/backend_api.md) * [Intent Relay API](developers/packages/foundation/sdk/tooling-modules/intent_relay_api.md) + * [@sodax/swaps-api](developers/packages/foundation/swaps-api.md) * [2. The Connection Layer](developers/packages/connection/README.md) * [@sodax/wallet-sdk-core](developers/packages/connection/wallet-sdk-core.md) * [@sodax/wallet-sdk-react](developers/packages/connection/wallet-sdk-react.md) * [3. The Experience Layer](developers/packages/experience/README.md) * [@sodax/dapp-kit](developers/packages/experience/dapp-kit.md) + * [@sodax/skills](developers/packages/experience/skills.md) * [Technical Overview](developers/technical-overview/README.md) * [Asset Manager](developers/technical-overview/asset-manager.md) * [Vault Token](developers/technical-overview/vault-token.md) @@ -47,6 +49,7 @@ * [Estimate Gas](developers/packages/sdk/docs/ESTIMATE_GAS.md) * [Handle Stellar Trustline](developers/packages/sdk/docs/STELLAR_TRUSTLINE.md) * [Bitcoin Integration](developers/how-to/bitcoin-integration.md) + * [Is SODAX on Testnet?](developers/how-to/testnet.md) * [AI Integration](developers/ai-integration/README.md) * [FAQ](developers/faq.md) diff --git a/developers/faq.md b/developers/faq.md index 9b35e26..dd2a5e1 100644 --- a/developers/faq.md +++ b/developers/faq.md @@ -6,23 +6,29 @@ icon: comment-question #### 1. Which chains does SODAX support? -SODAX runs on 20 chains across two families. EVM (12): Sonic (hub), Ethereum, Arbitrum, Base, BSC, Optimism, Polygon, Avalanche, HyperEVM, Lightlink, Redbelly, Kaia. Non-EVM (8): Solana, Sui, Stellar, ICON, Injective, NEAR, Stacks, Bitcoin. Reference any chain via `ChainKeys.*`. The legacy `*_CHAIN_ID` constants are deprecated. +SODAX runs on a hub-and-spoke network of **mainnet** chains. Sonic is the hub; spokes span EVM chains (Ethereum, Arbitrum, Base, BSC, Optimism, Polygon, Avalanche, HyperEVM, Lightlink, Redbelly, Kaia, Hedera) and non-EVM chains (Solana, Sui, Stellar, ICON, Injective, NEAR, Stacks, Bitcoin). Reference any chain via `ChainKeys.*`, which — together with the backend config — is the source of truth. The legacy `*_CHAIN_ID` constants are deprecated. Full list with relay IDs: [Relayer API endpoints](https://docs.sodax.com/developers/deployments/relayer_api_endpoints). -#### 2. What is the difference between the hub and a spoke chain? +#### 2. Is SODAX available on a testnet? + +No — SODAX is **mainnet-only**. Every chain in the canonical `@sodax/types` config is a `*_MAINNET` entry; there are no testnet chain configs, RPC endpoints, or a network toggle, because SODAX's cross-chain intents settle against real deployed contracts and live solver liquidity that only exist on mainnet. To build and test, use small amounts on mainnet and drive flows with the private-key wallet providers (see `apps/node`) rather than a testnet. + +Full explanation and next steps: [Is SODAX on Testnet?](https://docs.sodax.com/developers/how-to/testnet). + +#### 3. What is the difference between the hub and a spoke chain? Sonic is the hub. All swap, lend, borrow, bridge and stake actions are coordinated by hub contracts (Intents, Asset Manager, Hub Wallet Factory). Spoke chains hold user funds and act as deposit and execution venues. The SODAX relayer carries cross-chain messages between them. Deep dives: [Technical Overview](https://docs.sodax.com/developers/technical-overview), [Asset Manager](https://docs.sodax.com/developers/technical-overview/asset-manager), [Generalized Messaging Protocol](https://docs.sodax.com/developers/technical-overview/generalized-messaging-protocol). -#### 3. Do I need to call `sodax.initialize()` before using the SDK? +#### 4. Do I need to call `sodax.initialize()` before using the SDK? Not strictly. The constructor uses defaults packaged with the SDK version you installed. `await sodax.initialize()` fetches the latest tokens and chains from the backend API. Recommended for production, optional for prototypes. If it fails, the SDK falls back to packaged defaults rather than throwing. See [Configure SDK](https://docs.sodax.com/developers/how-to/configure_sdk). -#### 4. How do I override the hub RPC or contract addresses? +#### 5. How do I override the hub RPC or contract addresses? Pass a partial `hub` block to the constructor: @@ -36,25 +42,25 @@ Full config reference: [Configure SDK](https://docs.sodax.com/developers/how-to/ ### SDK behaviour -#### 5. Why don't SDK methods throw? +#### 6. Why don't SDK methods throw? Every public method returns `Result` shaped as `{ ok: true, value }` or `{ ok: false, error }`. Do not wrap SDK calls in try/catch. Check `result.ok` first, then discriminate on `result.error.code`. The pattern is canonical across modules: [Backend API](https://docs.sodax.com/developers/packages/foundation/sdk/tooling-modules/backend_api). -#### 6. How should I handle errors properly? +#### 7. How should I handle errors properly? Switch on the narrow `error.code` union (for example `VALIDATION_FAILED`, `RELAY_TIMEOUT`, `TX_SUBMIT_FAILED`). Never branch on `error.message`, it is human-readable and may change. The original lower-level error is preserved on `error.cause`, structured metadata on `error.context`. Use the exported guards (`isSwapError`, `isStakeOrchestrationError`, `isMigrateOrchestrationError`, `isPartnerError`) in dapp code for cross-bundle type safety. Per-module code tables: [Swaps](https://docs.sodax.com/developers/packages/foundation/sdk/functional-modules/swaps), [Money Market](https://docs.sodax.com/developers/packages/foundation/sdk/functional-modules/money_market), [Bridge](https://docs.sodax.com/developers/packages/foundation/sdk/functional-modules/bridge), [Staking](https://docs.sodax.com/developers/packages/foundation/sdk/functional-modules/staking), [Migration](https://docs.sodax.com/developers/packages/foundation/sdk/functional-modules/migration). -#### 7. What should I do when a swap returns `RELAY_TIMEOUT`? +#### 8. What should I do when a swap returns `RELAY_TIMEOUT`? The spoke transaction landed but the hub packet has not arrived within the timeout window. The relay may still complete. Persist the spoke tx hash and poll the relayer API. Do not re-submit from the user side. Error semantics: [Make a Swap](https://docs.sodax.com/developers/how-to/how_to_make_a_swap), [Relayer API endpoints](https://docs.sodax.com/developers/deployments/relayer_api_endpoints). -#### 8. What does `TX_SUBMIT_FAILED` mean? +#### 9. What does `TX_SUBMIT_FAILED` mean? The critical case. The spoke tx landed but the relay submission itself failed. Funds may be in flight. Persist the user's input plus spoke tx hash and retry submission against the relay API. Do not retry the user-facing transaction. @@ -62,7 +68,7 @@ Full code reference: [Make a Swap](https://docs.sodax.com/developers/how-to/how_ ### Swaps and intents -#### 9. What is the difference between `swap()`, `createIntent()` and `createLimitOrder()`? +#### 10. What is the difference between `swap()`, `createIntent()` and `createLimitOrder()`? `swap()` is the recommended end-to-end path. It handles approval, intent creation, relay submission and solver notification automatically (signed execution only). @@ -72,19 +78,19 @@ Full code reference: [Make a Swap](https://docs.sodax.com/developers/how-to/how_ Full method list: [Swaps (Solver)](https://docs.sodax.com/developers/packages/foundation/sdk/functional-modules/swaps). -#### 10. How do I get a swap quote and feed it into `minOutputAmount`? +#### 11. How do I get a swap quote and feed it into `minOutputAmount`? Call `sodax.swaps.getQuote(payload)` with `token_src`, `token_dst`, source and destination `ChainKeys`, an amount in the token's smallest unit, and `quote_type: 'exact_input'`. Use `quoted_amount` from the response to set `minOutputAmount` on the intent. Walkthrough with code: [Make a Swap](https://docs.sodax.com/developers/how-to/how_to_make_a_swap). -#### 11. Can I cancel an intent? +#### 12. Can I cancel an intent? Yes. Call `cancelIntent(intent)` on the Intents contract. The caller must be the creator, or the deadline must have passed. Intents with pending fills cannot be cancelled. Limit orders (`deadline = 0`) always require manual cancellation. Contract interface: [Intents](https://docs.sodax.com/developers/technical-overview/intents). -#### 12. Are intents trustless? Can a solver run off with funds? +#### 13. Are intents trustless? Can a solver run off with funds? No. Solvers cannot exit with user funds. They lock collateral in the `IntentFiller` contract on the destination spoke when filling. The hub is the source of truth for intent state and settlement, spokes act only as escrow and execution venues. Settlement reconciles cross-chain via the relay. @@ -92,7 +98,7 @@ Detailed flow: [Intents](https://docs.sodax.com/developers/technical-overview/in ### Lend, borrow, bridge, stake -#### 13. Which actions actually need on-chain approval? +#### 14. Which actions actually need on-chain approval? EVM spokes: `supply` and `repay` approve the Asset Manager contract. @@ -104,13 +110,13 @@ Borrow and withdraw on EVM and hub do not require approval. Most non-EVM chains Full matrix: [Money Market](https://docs.sodax.com/developers/packages/foundation/sdk/functional-modules/money_market). -#### 14. How is the bridge different from a swap? +#### 15. How is the bridge different from a swap? Bridge moves the same asset across chains using the hub vault, with no price discovery. Swap routes through the solver network for cross-chain price execution. The bridge supports three directions: spoke to hub, hub to spoke, and spoke to spoke. See [Bridge](https://docs.sodax.com/developers/packages/foundation/sdk/functional-modules/bridge) and [Swaps (Solver)](https://docs.sodax.com/developers/packages/foundation/sdk/functional-modules/swaps). -#### 15. How do I estimate gas across different chain families? +#### 16. How do I estimate gas across different chain families? Build a raw tx with `raw: true` from any `createIntent`, `createSupplyIntent`, `approve`, etc. Then call the matching module's `estimateGas({ tx, chainKey })`. The return shape depends on the chain family. @@ -118,7 +124,7 @@ EVM, ICON, Stellar, Bitcoin, NEAR return a `bigint`. Sui returns `{ computationC Examples per chain: [Estimate Gas](https://docs.sodax.com/developers/how-to/estimate_gas). -#### 16. Can I stake SODA from a non-EVM chain like Sui or Stellar? +#### 17. Can I stake SODA from a non-EVM chain like Sui or Stellar? Yes. Every `StakingService` method accepts any `SpokeChainKey` as the source. If you pass `ChainKeys.SONIC_MAINNET`, the spoke and hub tx hashes are identical. Approval is required only on EVM spokes, the hub, and Stellar. @@ -126,25 +132,25 @@ See [Staking](https://docs.sodax.com/developers/packages/foundation/sdk/function ### Monetization, integration, tooling -#### 17. How do partner fees work and how do I claim them? +#### 18. How do partner fees work and how do I claim them? Set `swaps.partnerFee`, `moneyMarket.partnerFee` and `bridge.partnerFee` independently on `SodaxConfig`. `getQuote` deducts the swap partner fee from the input amount before forwarding to the solver, so no fee field appears in the request payload. Claim accrued fees via `sodax.partners.feeClaim*` methods, which return `Result`. Setup and claim flows: [Monetize SDK](https://docs.sodax.com/developers/how-to/monetize_sdk). -#### 18. When do I need the `IntentRelayChainId` versus `ChainKeys`? +#### 19. When do I need the `IntentRelayChainId` versus `ChainKeys`? The relay API identifies chains by a numeric `IntentRelayChainId` (for example `BASE_MAINNET = 30n`, `SOLANA_MAINNET = 1n`, `BITCOIN_MAINNET = 627463n`). The SDK converts internally. You only need `getIntentRelayChainId(chainKey)` when constructing raw relay requests directly, which is advanced usage. Full mapping: [Relayer API endpoints](https://docs.sodax.com/developers/deployments/relayer_api_endpoints). -#### 19. How do I wire SODAX into my AI coding agent (Claude Code, Cursor, Codex)? +#### 20. How do I wire SODAX into my AI coding agent (Claude Code, Cursor, Codex)? From your project root run `npx skills@latest add icon-project/sodax-sdks/packages/skills`. The CLI detects your tool (Claude Code, Cursor, Codex, Copilot) and installs `AGENTS.md` plus per-feature `SKILL.md` files into the conventional location. Point your agent rules at the installed `AGENTS.md`, not the GitHub main branch, so version drift does not corrupt the routing. See [AI Integration](https://docs.sodax.com/developers/ai-integration). -#### 20. What is hub wallet abstraction and when do I touch it directly? +#### 21. What is hub wallet abstraction and when do I touch it directly? The hub generates a deterministic user wallet on Sonic for every spoke address. For spoke chains with limited calldata, the SDK supports hashed calls: send a 32-byte `keccak256` payload to the hub, then execute the stored call later with the same data. The relayer handles this in normal flows. You only touch it directly when building custom orchestration or recovering stuck cross-chain executions. diff --git a/developers/how-to/testnet.md b/developers/how-to/testnet.md new file mode 100644 index 0000000..5496baf --- /dev/null +++ b/developers/how-to/testnet.md @@ -0,0 +1,39 @@ +--- +description: >- + SODAX is mainnet-only. Here's why there is no testnet, and how to test and + explore SODAX safely on mainnet instead. +icon: flask +--- + +# Is SODAX on Testnet? + +**Short answer: no.** The SODAX SDKs and protocol run on **mainnet only**. There is no SODAX testnet, and the SDK has no testnet mode or network toggle. + +## Is SODAX available on a testnet? + +No. Every chain the SDK supports is a mainnet. The canonical chain list in `@sodax/types` (`ChainKeys`) contains only `*_MAINNET` entries — there are no testnet chain configs, no testnet RPC endpoints, and no `testnet` switch anywhere in the SDK. + +{% hint style="info" %} +Any `testnet` / `TESTNET` value you may see in wallet configuration (for example a Bitcoin or Sui wallet provider's `network` field) is an **upstream parameter of that wallet library** — it does not enable a SODAX testnet. +{% endhint %} + +## Why is SODAX not available on testnets? + +SODAX is a cross-chain **intents** system. Swaps, lending, borrowing, staking and bridging are settled through the Sonic hub against **real, deployed contracts** and **live, solver-provided liquidity**. Those primitives have no meaning without production liquidity and deployed spoke contracts, so there is no parallel testnet deployment to point the SDK at. + +For how settlement works, see [Intents](https://docs.sodax.com/developers/technical-overview/intents) and the [Technical Overview](https://docs.sodax.com/developers/technical-overview). + +## Can I integrate SODAX on testnet? + +No — integrate against mainnet. To build and test safely: + +* **Use small amounts on mainnet.** Every flow is real, so start with minimal values while you wire things up. +* **Drive flows headlessly** with the private-key wallet providers — see the mainnet smoke scripts in [`apps/node`](https://github.com/icon-project/sodax-sdks/tree/main/apps/node) to exercise integrations without a browser wallet. +* **Point your AI coding agent at the SODAX skills** for per-chain, v2-correct integration guidance — see [AI Integration](https://docs.sodax.com/developers/ai-integration). + +## Keep exploring + +* [Make a Swap](https://docs.sodax.com/developers/how-to/how_to_make_a_swap) — end-to-end swap walkthrough. +* [Configure the SDK](https://docs.sodax.com/developers/how-to/configure_sdk) — initialization and configuration. +* [SDKs overview](https://docs.sodax.com/developers/packages) — the full package stack (Foundation, Connection, Experience). +* [FAQ](https://docs.sodax.com/developers/faq) — common questions. diff --git a/developers/packages/experience/skills.md b/developers/packages/experience/skills.md new file mode 100644 index 0000000..5775a60 --- /dev/null +++ b/developers/packages/experience/skills.md @@ -0,0 +1,58 @@ +--- +description: >- + Consumer-facing AI skills and knowledge so coding agents (Claude Code, Cursor, Copilot, Codex) write v2-correct @sodax/* SDK code. +icon: robot +--- + +# @sodax/skills + +AI-agent skills and knowledge for building on the **SODAX** cross-chain DeFi platform. Drop this into your repo and your AI coding agent writes v2-correct `@sodax/*` SDK code on the first try. + +**Full setup** (skills CLI, npm, monorepo/local install, wiring agents to `AGENTS.md`): [docs/ai-integration-guide.md](https://github.com/icon-project/sodax-sdks/blob/main/docs/ai-integration-guide.md). + +## Install + +Using the [`skills` CLI](https://github.com/vercel-labs/skills) from Vercel Labs — the open agent-skills ecosystem CLI (supports Claude Code, Cursor, Codex, GitHub Copilot, and 50+ other agents): + +```bash +# From the root of your consumer repo +npx skills@latest add icon-project/sodax-sdks/packages/skills +``` + +The installable skills listed in `.claude-plugin/plugin.json` land in your repo — the `sodax-build` front-door / ideation skill plus the mode-gated per-SDK-package skills (each with two knowledge subtrees: `integration/` for new v2 code, `migration-v1-to-v2/` for v1→v2 porting) — alongside a router `AGENTS.md`. Re-running the command picks up the latest content. + +> **npm fallback** (web chats or when you prefer a devDependency): `pnpm add -D @sodax/skills`, then point your agent at `node_modules/@sodax/skills/AGENTS.md`. See the [integration guide](https://github.com/icon-project/sodax-sdks/blob/main/docs/ai-integration-guide.md#wire-your-agent). + +## What you get + +| Bundle | Contains | +|---|---| +| **Front-door skill** at `skills/sodax-build/SKILL.md` | A cross-cutting ideation skill for when you don't know what to build yet. It interviews you, turns the idea into a product brief, and hands off to the right developer skill(s). Writes no app code; flat `knowledge/` tree (no integration/migration split). | +| **Mode-gated per-SDK-package skills** under `skills/sodax-/SKILL.md` | One skill per SODAX SDK package. `` ∈ `sdk`, `wallet-sdk-core`, `wallet-sdk-react`, `dapp-kit`. Each SKILL.md gates by mode (integration vs migration) at the top of the body. | +| **Granular skills** bundled inside each broad skill at `skills/sodax-//SKILL.md` | Every broad skill ships focused single-domain children: `sodax-sdk` / `sodax-dapp-kit` per feature (swap, money-market, bridge, staking, dex, …); `sodax-wallet-sdk-core` per chain (evm, solana, sui, bitcoin, stellar, icon, injective, near, stacks); `sodax-wallet-sdk-react` per connectivity concern (connect, wallet-modal, bridge-to-sdk, switch-chain, sign-message, walletconnect). They install **with** their parent broad skill (not as separate packages); once installed, load one when the task is already scoped to a single sub-domain — it points at exactly the knowledge files for it instead of the whole broad skill. | +| **Knowledge** under `skills/sodax-/{integration,migration-v1-to-v2}/knowledge/` | Long-form supporting docs — features, recipes, reference tables, breaking-change writeups, code examples. Each skill ships both mode subtrees so `npx skills add` copies the full reference together. | +| **`AGENTS.md`** at the package root | Tool-neutral router: maps the consumer's stated task to the right skill + mode. | + +Skills are short and action-oriented (workflow + anti-patterns + links). Knowledge is the lookup material. Don't read knowledge files top-to-bottom — the skill tells the agent which file is relevant for the current task. + +## Which skill applies? + +After install, your agent picks based on what you're building. Quick guide: + +| You're building | Load these skills (mode) | +|---|---| +| Not sure what to build yet / not a developer | `sodax-build` — it interviews you, writes a product brief, and names the skill to load next | +| Backend / Node app (no React) using `@sodax/sdk` | `sodax-sdk` (integration) + `sodax-wallet-sdk-core` (integration; if signing) | +| React dapp using `@sodax/dapp-kit` | `sodax-dapp-kit` (integration) + `sodax-wallet-sdk-react` (integration; always) + `sodax-sdk` (integration; for any unwrapped operations) | +| React app calling the SDK directly (no `dapp-kit`) | `sodax-sdk` (integration) + `sodax-wallet-sdk-react` (integration) | +| **Porting v1 code** | Same skills, switched to migration mode (each SKILL.md mode-gates by consumer signal). | + +`AGENTS.md` says the same thing in router form — your agent reads it first and picks. + +## Why this exists + +LLM training data drifts: snippets from chat often use stale method names, reshaped types, or outdated error codes. Public docs help humans, not agents — an agent only reads what's in its context window. This package ships the right material in agent-native form so the agent reads it before generating code. The content is version-locked to the SDK — upgrade `@sodax/skills`, the docs upgrade with it. + +## Feedback + +If your agent generates wrong code despite reading the docs, that's a doc bug — please open an issue on the [Sodax SDKs repo](https://github.com/icon-project/sodax-sdks/issues) with the prompt and the incorrect output. The per-skill `knowledge/` subtrees are structurally CI-guarded (frontmatter, link resolution); prose claims benefit from real-world feedback. diff --git a/developers/packages/foundation/swaps-api.md b/developers/packages/foundation/swaps-api.md new file mode 100644 index 0000000..22eeb5a --- /dev/null +++ b/developers/packages/foundation/swaps-api.md @@ -0,0 +1,143 @@ +--- +description: >- + Minimal, type-safe HTTP client for the SODAX backend Swaps API v2 — the wire client that @sodax/sdk's sodax.api.swaps wraps. +icon: plug +--- + +# @sodax/swaps-api + +Minimal, type-safe HTTP client for the SODAX backend **Swaps API v2**. + +- Implements the `ISwapsApiV2` contract from `@sodax/types` over `fetch`. +- Validates every response at runtime with [valibot](https://valibot.dev), and + transforms each chain-specific unsigned `tx` back to its domain shape + (decimal-string → `bigint`, Injective index-object bytes → `Uint8Array`). +- Zero dependency on `@sodax/sdk`, viem, or wallet providers — only + `@sodax/types` (types) and `valibot`. + +It is the single source of the swaps wire client: `@sodax/sdk`'s `SwapsApiService` +(`sodax.api.swaps`) is a thin adapter over this package, adding the SDK's +`Result` contract, logger, and config resolution on top. Use `@sodax/swaps-api` +directly when you want just the swaps backend without pulling in the full SDK. + +## Install + +```bash +pnpm add @sodax/swaps-api +``` + +`valibot` is a bundled runtime dependency, not a peer — you don't need to install +it separately. + +## Usage + +```ts +import { SwapsApi, SwapsApiError } from '@sodax/swaps-api'; + +const api = new SwapsApi({ baseUrl: 'https://' }); + +const tokens = await api.getTokens(); +const quote = await api.getQuote({ + tokenSrc, + tokenSrcChainKey, + tokenDst, + tokenDstChainKey, + amount, + quoteType: 'exact_input', +}); +``` + +`baseUrl` is required and injected by the caller — the package never hardcodes +environment URLs. Optionally set `timeout` (ms — an overall per-call deadline that +includes retries; on expiry the call throws `TIMEOUT_ERROR`), a custom `fetch` (for +tests or non-standard runtimes; it receives the timeout `AbortSignal`), and extra `headers`. + +> Note: `quoteType: 'exact_input'` is currently the only supported quote type — the +> `QuoteTypeV2` union in `@sodax/types` has no other member yet. + +## Configuration + +The `SwapsApi` constructor takes a `SwapsApiConfig`: + +| Option | Type | Required | Description | +| --------- | ------------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `baseUrl` | `string` | Yes | Base URL of the Swaps API host, including any version prefix (e.g. `https://canary-api.sodax.com/v1`). The package never hardcodes environment URLs. | +| `timeout` | `number` | No | Overall per-call deadline in ms, enforced with an `AbortController` across the entire call **including retries** — a hard ceiling on total latency. Omit for no timeout. On expiry the call rejects with a `TIMEOUT_ERROR`. | +| `fetch` | `typeof globalThis.fetch`| No | `fetch` implementation to use. Defaults to the global `fetch`. Inject a custom one for tests or non-standard runtimes; it receives the timeout `AbortSignal`, so it should forward `init.signal`. | +| `headers` | `Record` | No | Extra headers merged over the defaults on every request. | + +## Methods + +Each method maps one-to-one to an `ISwapsApiV2` endpoint. Path params are +`encodeURIComponent`-escaped by the client. + +| Method | HTTP | Path | +| -------------------------------------------- | ------ | ------------------------------------- | +| `getTokens()` | GET | `/swaps/tokens` | +| `getTokensByChain(chainKey)` | GET | `/swaps/tokens/{chainKey}` | +| `getQuote(body, query?)` | POST | `/swaps/quote` | +| `getDeadline(query?)` | GET | `/swaps/deadline` | +| `checkAllowance(body)` | POST | `/swaps/allowance/check` | +| `approve(body)` | POST | `/swaps/approve` | +| `createIntent(body)` | POST | `/swaps/intents` | +| `submitIntent(body)` | POST | `/swaps/intents/submit` | +| `getStatus(body)` | POST | `/swaps/intents/status` | +| `cancelIntent(body)` | POST | `/swaps/intents/cancel` | +| `getIntentHash(body)` | POST | `/swaps/intents/hash` | +| `getSolvedIntentPacket(body)` | POST | `/swaps/intents/packet` | +| `getIntentSubmitTxExtraData(body)` | POST | `/swaps/intents/extra-data` | +| `getFilledIntent(txHash)` | GET | `/swaps/intents/{txHash}/fill` | +| `getIntent(txHash)` | GET | `/swaps/intents/{txHash}` | +| `createLimitOrderIntent(body)` | POST | `/swaps/limit-orders` | +| `estimateGas(body)` | POST | `/swaps/gas/estimate` | +| `getPartnerFee(query)` | GET | `/swaps/fees/partner` | +| `getSolverFee(query)` | GET | `/swaps/fees/solver` | +| `submitTx(body)` | POST | `/swaps/submit-tx` | +| `getSubmitTxStatus(query)` | GET | `/swaps/submit-tx/status` | + +## Errors + +Every method **throws** a `SwapsApiError` on failure — a single typed error whose +`code` is one of `NETWORK_ERROR` / `TIMEOUT_ERROR` / `HTTP_ERROR` / `PARSE_ERROR` / +`VALIDATION_ERROR`, with diagnostic `context` (endpoint, method, path, HTTP status, +validation issues) and the underlying failure on `.cause`. Idempotent calls (reads, +polls, pure-compute POSTs like `getQuote`) are retried a few times on transient HTTP / +network failures; a `timeout` and mutating calls are never retried. + +> Note: this throwing contract is intentional and distinct from `@sodax/sdk`'s +> `sodax.api.swaps`, which wraps these calls and returns `Result` instead of throwing. + +### `SwapsApiError.code` + +`code` is one of the following `SwapsApiErrorCode` values: + +| Code | Meaning | +| ------------------ | -------------------------------------------------------------- | +| `NETWORK_ERROR` | `fetch` threw (offline, DNS). | +| `TIMEOUT_ERROR` | The request exceeded the configured `timeout` (aborted). | +| `HTTP_ERROR` | Server returned a non-2xx status. | +| `PARSE_ERROR` | 2xx body was missing or not valid JSON. | +| `VALIDATION_ERROR` | Body did not match the expected schema (or a request was malformed). | + +### `SwapsApiError.context` + +`context` carries best-effort diagnostics (`SwapsApiErrorContext`). All fields are optional: + +| Field | Type | Description | +| ---------- | --------- | -------------------------------------------------------------------------------------------- | +| `endpoint` | `string` | The `ISwapsApiV2` method that failed, e.g. `'getQuote'`. | +| `method` | `string` | HTTP method actually sent, e.g. `'POST'`. | +| `path` | `string` | Request path actually sent, e.g. `'/swaps/quote'`. | +| `status` | `number` | HTTP status, for `HTTP_ERROR`. | +| `body` | `unknown` | Best-effort parsed backend response body (JSON if possible, else text), so the backend's message surfaces to the caller. | +| `issues` | `unknown` | valibot issues, for `VALIDATION_ERROR`. | + +The underlying failure is available on `.cause`. + +## Reference app + +For a full end-to-end flow — including wallet signing, which this package +deliberately leaves to the caller — see the +[`apps/swap-api-example`](https://github.com/icon-project/sodax-sdks/tree/main/apps/swap-api-example) reference app. It drives +`@sodax/swaps-api` through the complete quote → approve → create-intent → +sign → submit lifecycle. diff --git a/sync-sodax-sdks.sh b/sync-sodax-sdks.sh index e227f50..9edf7d5 100755 --- a/sync-sodax-sdks.sh +++ b/sync-sodax-sdks.sh @@ -108,6 +108,12 @@ inject_frontmatter "$DST/packages/foundation/sdk/README.md" "cup-straw" \ "The SODAX SDK provides a comprehensive interface for interacting with the SODAX protocol, enabling cross-chain swaps, money market, cross-chain bridging, migration and staking SODA token." fix_synced_links "$DST/packages/foundation/sdk/README.md" +# 4b) swaps-api README → Foundation layer (standalone Swaps API v2 wire client) +copy_file "$SRC/packages/swaps-api/README.md" "$DST/packages/foundation/swaps-api.md" +inject_frontmatter "$DST/packages/foundation/swaps-api.md" "plug" \ + "Minimal, type-safe HTTP client for the SODAX backend Swaps API v2 — the wire client that @sodax/sdk's sodax.api.swaps wraps." +fix_synced_links "$DST/packages/foundation/swaps-api.md" + # 5) Functional modules (sdk/docs → foundation/sdk/functional-modules, lowercased) copy_file "$SRC/packages/sdk/docs/SWAPS.md" "$DST/packages/foundation/sdk/functional-modules/swaps.md" copy_file "$SRC/packages/sdk/docs/MONEY_MARKET.md" "$DST/packages/foundation/sdk/functional-modules/money_market.md" @@ -174,6 +180,12 @@ inject_frontmatter "$DST/packages/experience/dapp-kit.md" "browser" fix_relative_repo_links "$DST/packages/experience/dapp-kit.md" +# 9b) skills README → Experience layer (AI-agent skills bundle) +copy_file "$SRC/packages/skills/README.md" "$DST/packages/experience/skills.md" +inject_frontmatter "$DST/packages/experience/skills.md" "robot" \ + "Consumer-facing AI skills and knowledge so coding agents (Claude Code, Cursor, Copilot, Codex) write v2-correct @sodax/* SDK code." +fix_relative_repo_links "$DST/packages/experience/skills.md" + # 10) Audits (Markdown + PDF files, preserving directory structure) AUDITS_SRC="$SRC/Audits" AUDITS_DST="$DST/audits"