@sodax/skills 2.0.0-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +18 -0
- package/AGENTS.md +83 -0
- package/LICENSE +21 -0
- package/README.md +49 -0
- package/package.json +58 -0
- package/skills/sodax-dapp-kit/SKILL.md +129 -0
- package/skills/sodax-dapp-kit/integration/knowledge/README.md +49 -0
- package/skills/sodax-dapp-kit/integration/knowledge/ai-rules.md +80 -0
- package/skills/sodax-dapp-kit/integration/knowledge/architecture.md +276 -0
- package/skills/sodax-dapp-kit/integration/knowledge/features/README.md +29 -0
- package/skills/sodax-dapp-kit/integration/knowledge/features/auxiliary-services.md +169 -0
- package/skills/sodax-dapp-kit/integration/knowledge/features/bitcoin.md +87 -0
- package/skills/sodax-dapp-kit/integration/knowledge/features/bridge.md +91 -0
- package/skills/sodax-dapp-kit/integration/knowledge/features/dex.md +152 -0
- package/skills/sodax-dapp-kit/integration/knowledge/features/migration.md +118 -0
- package/skills/sodax-dapp-kit/integration/knowledge/features/money-market.md +144 -0
- package/skills/sodax-dapp-kit/integration/knowledge/features/staking.md +123 -0
- package/skills/sodax-dapp-kit/integration/knowledge/features/swap.md +101 -0
- package/skills/sodax-dapp-kit/integration/knowledge/quickstart.md +188 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/README.md +136 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/backend-queries.md +157 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/bitcoin.md +193 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/bridge.md +174 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/dex.md +204 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/invalidations.md +115 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/migration.md +212 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/money-market.md +207 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/mutation-error-handling.md +118 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/observability.md +93 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/setup.md +168 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/staking.md +202 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/swap.md +272 -0
- package/skills/sodax-dapp-kit/integration/knowledge/recipes/wallet-connectivity.md +128 -0
- package/skills/sodax-dapp-kit/integration/knowledge/reference/README.md +12 -0
- package/skills/sodax-dapp-kit/integration/knowledge/reference/glossary.md +190 -0
- package/skills/sodax-dapp-kit/integration/knowledge/reference/hooks-index.md +190 -0
- package/skills/sodax-dapp-kit/integration/knowledge/reference/public-api.md +110 -0
- package/skills/sodax-dapp-kit/integration/knowledge/reference/querykey-conventions.md +179 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/README.md +60 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/ai-rules.md +81 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/breaking-changes/hook-signatures.md +233 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/breaking-changes/querykey-conventions.md +108 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/breaking-changes/result-handling.md +211 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/breaking-changes/sdk-leakage.md +167 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/checklist.md +89 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/features/README.md +34 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/features/auxiliary-services.md +114 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/features/bitcoin.md +88 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/features/bridge.md +160 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/features/dex.md +101 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/features/migration.md +120 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/features/money-market.md +139 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/features/staking.md +109 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/features/swap.md +133 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/recipes.md +185 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/reference/README.md +15 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/reference/deleted-hooks.md +110 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/reference/error-shape-crosswalk.md +144 -0
- package/skills/sodax-dapp-kit/migration-v1-to-v2/knowledge/reference/renamed-hooks.md +68 -0
- package/skills/sodax-sdk/SKILL.md +140 -0
- package/skills/sodax-sdk/backend-api/SKILL.md +52 -0
- package/skills/sodax-sdk/bridge/SKILL.md +49 -0
- package/skills/sodax-sdk/dex/SKILL.md +50 -0
- package/skills/sodax-sdk/integration/knowledge/README.md +43 -0
- package/skills/sodax-sdk/integration/knowledge/ai-rules.md +75 -0
- package/skills/sodax-sdk/integration/knowledge/architecture.md +517 -0
- package/skills/sodax-sdk/integration/knowledge/chain-specifics.md +189 -0
- package/skills/sodax-sdk/integration/knowledge/features/README.md +21 -0
- package/skills/sodax-sdk/integration/knowledge/features/backend-api.md +81 -0
- package/skills/sodax-sdk/integration/knowledge/features/bridge.md +172 -0
- package/skills/sodax-sdk/integration/knowledge/features/dex.md +182 -0
- package/skills/sodax-sdk/integration/knowledge/features/migration.md +181 -0
- package/skills/sodax-sdk/integration/knowledge/features/money-market.md +198 -0
- package/skills/sodax-sdk/integration/knowledge/features/partner.md +63 -0
- package/skills/sodax-sdk/integration/knowledge/features/recovery.md +50 -0
- package/skills/sodax-sdk/integration/knowledge/features/staking.md +171 -0
- package/skills/sodax-sdk/integration/knowledge/features/swap.md +273 -0
- package/skills/sodax-sdk/integration/knowledge/quickstart.md +213 -0
- package/skills/sodax-sdk/integration/knowledge/recipes/README.md +21 -0
- package/skills/sodax-sdk/integration/knowledge/recipes/backend-server-init.md +69 -0
- package/skills/sodax-sdk/integration/knowledge/recipes/chain-key-narrowing.md +65 -0
- package/skills/sodax-sdk/integration/knowledge/recipes/gas-estimation.md +33 -0
- package/skills/sodax-sdk/integration/knowledge/recipes/initialize-sodax.md +78 -0
- package/skills/sodax-sdk/integration/knowledge/recipes/raw-tx-flow.md +71 -0
- package/skills/sodax-sdk/integration/knowledge/recipes/result-and-errors.md +104 -0
- package/skills/sodax-sdk/integration/knowledge/recipes/signed-tx-flow.md +46 -0
- package/skills/sodax-sdk/integration/knowledge/recipes/testing.md +101 -0
- package/skills/sodax-sdk/integration/knowledge/reference/README.md +18 -0
- package/skills/sodax-sdk/integration/knowledge/reference/chain-keys.md +67 -0
- package/skills/sodax-sdk/integration/knowledge/reference/error-codes.md +165 -0
- package/skills/sodax-sdk/integration/knowledge/reference/glossary.md +32 -0
- package/skills/sodax-sdk/integration/knowledge/reference/public-api.md +138 -0
- package/skills/sodax-sdk/integration/knowledge/reference/wallet-providers.md +62 -0
- package/skills/sodax-sdk/migration/SKILL.md +65 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/README.md +58 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/ai-rules.md +76 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/breaking-changes/architecture.md +344 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/breaking-changes/result-and-errors.md +363 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/breaking-changes/type-system.md +341 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/checklist.md +67 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/README.md +37 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/backend-api.md +92 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/bridge.md +128 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/dex.md +143 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/migration.md +151 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/money-market.md +214 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/partner.md +59 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/recovery.md +35 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/staking.md +143 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/features/swap.md +198 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/recipes.md +350 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/reference/README.md +18 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/reference/deleted-exports.md +127 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/reference/error-code-crosswalk.md +104 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/reference/return-shapes.md +49 -0
- package/skills/sodax-sdk/migration-v1-to-v2/knowledge/reference/sodax-config.md +145 -0
- package/skills/sodax-sdk/money-market/SKILL.md +52 -0
- package/skills/sodax-sdk/partner/SKILL.md +51 -0
- package/skills/sodax-sdk/recovery/SKILL.md +49 -0
- package/skills/sodax-sdk/staking/SKILL.md +49 -0
- package/skills/sodax-sdk/swap/SKILL.md +67 -0
- package/skills/sodax-wallet-sdk-core/SKILL.md +114 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/README.md +108 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/ai-rules.md +141 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/architecture.md +212 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/features/README.md +22 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/features/bitcoin.md +103 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/features/evm.md +102 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/features/icon.md +88 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/features/injective.md +92 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/features/near.md +92 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/features/solana.md +104 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/features/stacks.md +91 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/features/stellar.md +95 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/features/sui.md +96 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/quickstart.md +259 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/recipes/README.md +15 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/recipes/bridge-to-sdk.md +145 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/recipes/defaults-and-overrides.md +159 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/recipes/library-exports.md +129 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/recipes/setup-browser-extension.md +137 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/recipes/setup-private-key.md +115 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/recipes/sign-and-broadcast.md +201 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/recipes/testing.md +163 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/reference/README.md +13 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/reference/chain-support.md +65 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/reference/glossary.md +28 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/reference/interfaces.md +131 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/reference/provider-classes.md +54 -0
- package/skills/sodax-wallet-sdk-core/integration/knowledge/reference/public-api.md +128 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/README.md +84 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/ai-rules.md +139 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/breaking-changes/README.md +14 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/breaking-changes/base-wallet-provider.md +52 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/breaking-changes/defaults-config.md +57 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/breaking-changes/folder-layout.md +99 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/breaking-changes/library-exports.md +58 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/checklist.md +62 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/recipes/README.md +12 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/recipes/adopt-defaults.md +84 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/recipes/adopt-library-exports.md +99 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/reference/README.md +12 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/reference/added-fields.md +71 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/reference/deleted-exports.md +35 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/reference/renamed-symbols.md +31 -0
- package/skills/sodax-wallet-sdk-core/migration-v1-to-v2/knowledge/reference/return-shapes.md +23 -0
- package/skills/sodax-wallet-sdk-react/SKILL.md +154 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/README.md +103 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/ai-rules.md +136 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/architecture.md +185 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/examples/01-minimal-evm.tsx +75 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/examples/02-multi-chain-modal.tsx +169 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/examples/03-nextjs-app-router.tsx +99 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/examples/04-walletconnect-setup.tsx +89 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/examples/README.md +29 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/recipes/batch-operations.md +224 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/recipes/bridge-to-sdk.md +165 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/recipes/chain-detection.md +259 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/recipes/connect-button.md +159 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/recipes/multi-chain-modal.md +203 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/recipes/setup.md +163 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/recipes/sign-message.md +138 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/recipes/sub-path-imports.md +97 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/recipes/switch-chain.md +144 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/recipes/walletconnect-setup.md +139 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/reference/api-surface.md +176 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/reference/chain-support.md +79 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/reference/connectors.md +75 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/reference/hooks.md +212 -0
- package/skills/sodax-wallet-sdk-react/integration/knowledge/reference/wallet-brands.md +107 -0
- package/skills/sodax-wallet-sdk-react/migration-v1-to-v2/knowledge/README.md +49 -0
- package/skills/sodax-wallet-sdk-react/migration-v1-to-v2/knowledge/ai-rules.md +144 -0
- package/skills/sodax-wallet-sdk-react/migration-v1-to-v2/knowledge/breaking-changes.md +310 -0
- package/skills/sodax-wallet-sdk-react/migration-v1-to-v2/knowledge/checklist.md +159 -0
- package/skills/sodax-wallet-sdk-react/migration-v1-to-v2/knowledge/recipes/connect-button.md +170 -0
- package/skills/sodax-wallet-sdk-react/migration-v1-to-v2/knowledge/recipes/multi-chain-modal.md +245 -0
- package/skills/sodax-wallet-sdk-react/migration-v1-to-v2/knowledge/recipes/ssr-setup.md +165 -0
- package/skills/sodax-wallet-sdk-react/migration-v1-to-v2/knowledge/recipes/walletconnect-migration.md +170 -0
- package/skills/sodax-wallet-sdk-react/migration-v1-to-v2/knowledge/reference/components.md +75 -0
- package/skills/sodax-wallet-sdk-react/migration-v1-to-v2/knowledge/reference/config.md +339 -0
- package/skills/sodax-wallet-sdk-react/migration-v1-to-v2/knowledge/reference/hooks.md +336 -0
- package/skills/sodax-wallet-sdk-react/migration-v1-to-v2/knowledge/reference/imports.md +158 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Chain specifics — Non-EVM quirks
|
|
2
|
+
|
|
3
|
+
EVM chains (12 of them) work uniformly through `IEvmWalletProvider`. Non-EVM chains have particularities you need to handle. This file documents each chain family's quirks.
|
|
4
|
+
|
|
5
|
+
## Section index
|
|
6
|
+
|
|
7
|
+
1. [Stellar trustline](#1-stellar-trustline) — `STELLAR_MAINNET`. Required before receiving any non-XLM asset.
|
|
8
|
+
2. [Bitcoin PSBT and Radfi](#2-bitcoin-psbt-and-radfi) — `BITCOIN_MAINNET`. PSBT signing; trading wallet; Radfi auth/session.
|
|
9
|
+
3. [Solana PDA derivation](#3-solana-pda-derivation) — `SOLANA_MAINNET`. Deterministic addresses; one-time setup utilities.
|
|
10
|
+
4. [ICON Hana wallet](#4-icon-hana-wallet) — `ICON_MAINNET`. Low-level Hana-extension helpers; chain key string vs numeric ID.
|
|
11
|
+
5. [NEAR connector discovery](#5-near-connector-discovery) — `NEAR_MAINNET`. Account-id semantics; multiple wallet variants.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 1. Stellar trustline
|
|
16
|
+
|
|
17
|
+
**Requirement:** before a Stellar account can hold or receive a non-XLM asset, it must establish a trustline to the asset issuer. SODAX's bridge / swap / money-market deliver stablecoin assets to Stellar — the destination Stellar account must have an active trustline for the asset, or the operation fails.
|
|
18
|
+
|
|
19
|
+
### How v2 handles it
|
|
20
|
+
|
|
21
|
+
`BridgeService` and other feature services delegate Stellar trustline / allowance handling to the Stellar spoke service internally — there is **no** public `checkStellarTrustline` / `requestStellarTrustline` method on `BridgeService`. When you call `sodax.bridge.approve({ params, raw: false, walletProvider })` with a Stellar `walletProvider`, the spoke service handles the trustline operation for you.
|
|
22
|
+
|
|
23
|
+
For direct trustline interaction outside the standard `approve` flow, reach for the Stellar spoke service:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { ChainKeys, type StellarSpokeService } from '@sodax/sdk';
|
|
27
|
+
|
|
28
|
+
const stellarSpoke = sodax.spoke.getSpokeService(ChainKeys.STELLAR_MAINNET) as StellarSpokeService;
|
|
29
|
+
// Use the spoke service's typed methods for Stellar-specific operations.
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### When to gate
|
|
33
|
+
|
|
34
|
+
Before any swap / bridge / money-market operation that **delivers** a non-XLM asset to a Stellar destination, the destination wallet must already trust the asset. Failed trustline checks surface as `VALIDATION_FAILED` errors; use `error.context.reason` to disambiguate. The standard pattern for app code is to call `sodax.bridge.approve(...)` (or the matching feature's approve) on the Stellar wallet first, which establishes the trustline as a side effect.
|
|
35
|
+
|
|
36
|
+
### Pitfall
|
|
37
|
+
|
|
38
|
+
Stellar accounts that have never held the asset have **no** trustline — receiving will fail. The error surfaces as `VALIDATION_FAILED` with `context.reason: 'trustlineMissing'` (or similar). Treat the missing-trustline state as a one-time setup step gated by the standard `approve` flow.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 2. Bitcoin PSBT and Radfi
|
|
43
|
+
|
|
44
|
+
Bitcoin support uses Partially Signed Bitcoin Transactions (PSBT) — a different model than EVM tx signing. The wallet provider (`BTCWalletProvider`) handles PSBT construction and signing internally.
|
|
45
|
+
|
|
46
|
+
### Address types
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
type BtcAddressType = 'P2PKH' | 'P2SH' | 'P2WPKH' | 'P2TR';
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`BTCWalletProvider` config takes an `addressType`. `'P2WPKH'` (native SegWit) is the modern default; `'P2TR'` (Taproot) is supported but may have lower compatibility with some on-chain logic.
|
|
53
|
+
|
|
54
|
+
### Radfi (auth + trading wallet)
|
|
55
|
+
|
|
56
|
+
SODAX uses the Radfi infrastructure for Bitcoin. Each user gets a derived "trading wallet" funded from their main BTC address. Operations consume UTXOs from the trading wallet rather than directly from the user's main address.
|
|
57
|
+
|
|
58
|
+
The Radfi provider is owned by `BitcoinSpokeService`. Reach it via the spoke router:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { ChainKeys, type BitcoinSpokeService } from '@sodax/sdk';
|
|
62
|
+
|
|
63
|
+
const btcSpoke = sodax.spoke.getSpokeService(ChainKeys.BITCOIN_MAINNET) as BitcoinSpokeService;
|
|
64
|
+
const radfi = btcSpoke.radfi; // RadfiProvider instance
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Most consumer flows don't need to touch `radfi` directly — `sodax.bridge.bridge(...)`, `sodax.swaps.createIntent(...)`, etc. handle the Radfi auth + trading-wallet routing internally on the Bitcoin path. For explicit lifecycle management:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
// Authenticate against Radfi (the wallet signs an auth message):
|
|
71
|
+
await radfi.authenticateWithWallet(/* args per RadfiProvider source */);
|
|
72
|
+
|
|
73
|
+
// Fetch the trading wallet for an address (creating it if needed):
|
|
74
|
+
const tradingWallet = await radfi.getTradingWallet(personalAddress);
|
|
75
|
+
|
|
76
|
+
// Read the trading wallet's BTC + token balances:
|
|
77
|
+
const balance = await radfi.getBalance(tradingWallet.address);
|
|
78
|
+
|
|
79
|
+
// Check whether a trading wallet exists without provisioning one:
|
|
80
|
+
const exists = await radfi.checkIfTradingWalletExists(personalAddress);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Other public methods on `RadfiProvider` you may need: `setRadfiAccessToken`, `refreshAccessToken`, `createTradingWallet`, `createWithdrawTransaction`, `requestRadfiSignature`, `getExpiredUtxos`, `buildRenewUtxoTransaction`, `signAndBroadcastRenewUtxo`, `withdrawToUser`, `signAndBroadcastWithdraw`, `getMaxWithdrawable`. Read `RadfiProvider` source for argument shapes — the API surface is broader than typical chain providers.
|
|
84
|
+
|
|
85
|
+
### Pitfall
|
|
86
|
+
|
|
87
|
+
`BitcoinSpokeService.radfi` is what feature services use under the hood. Bypassing the feature services and driving Radfi yourself works but is rarely needed — and you have to wire token balances + UTXO state manually. Prefer the standard feature flows unless you specifically need lifecycle control.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 3. Solana PDA derivation
|
|
92
|
+
|
|
93
|
+
Program Derived Addresses (PDAs) are deterministic Solana addresses derived from a program ID + seeds. SODAX uses PDAs for the user's spoke-side state on Solana.
|
|
94
|
+
|
|
95
|
+
The SDK derives PDAs internally — consumers don't usually need to do this manually. For advanced use cases (preflight, off-chain state lookups), reach into the Solana spoke service via the router:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { ChainKeys, type SolanaSpokeService } from '@sodax/sdk';
|
|
99
|
+
|
|
100
|
+
const solanaSpoke = sodax.spoke.getSpokeService(ChainKeys.SOLANA_MAINNET) as SolanaSpokeService;
|
|
101
|
+
// Use the spoke service's typed methods for any PDA-related read or write.
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### `SolanaSpokeService` specifics
|
|
105
|
+
|
|
106
|
+
- Solana txs are different shape from EVM (multiple instructions per tx; signed once globally).
|
|
107
|
+
- `TxReturnType<typeof ChainKeys.SOLANA_MAINNET, false>` is the base58-encoded signature string (not `0x…`).
|
|
108
|
+
- `SolanaRawTransaction` is the raw-tx return for `raw: true` — base64-encoded message for downstream signing.
|
|
109
|
+
|
|
110
|
+
### Pitfall
|
|
111
|
+
|
|
112
|
+
Solana addresses are base58 PublicKey strings, not `0x…` hex. `GetAddressType<typeof ChainKeys.SOLANA_MAINNET>` resolves to a base58-typed string brand; passing a hex address is a TypeScript error.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 4. ICON Hana wallet
|
|
117
|
+
|
|
118
|
+
ICON uses the Hana browser-extension wallet for dApp signing. The SDK ships low-level helper functions (file: `HanaWalletConnector.ts`) that wrap the Hana extension's JSON-RPC interface; consumers compose them into an `IIconWalletProvider` implementation.
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import { requestAddress, requestSigning, requestJsonRpc } from '@sodax/sdk';
|
|
122
|
+
|
|
123
|
+
const result = await requestAddress(); // returns Result<IconAddress>
|
|
124
|
+
if (result.ok) {
|
|
125
|
+
const address = result.value; // 'hx…'
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
ICON spoke calls require an `IIconWalletProvider`. Implementations either compose the helper functions above into a class your app owns, or use the reference implementation that ships in `@sodax/wallet-sdk-core` (separate package, install separately).
|
|
130
|
+
|
|
131
|
+
### `ChainKeys.ICON_MAINNET` is a string `'0x1.icon'`
|
|
132
|
+
|
|
133
|
+
The ICON chain key is the **string** `'0x1.icon'`, not the legacy numeric chain id `0x1`. This trips up code that did `Number(chainId)` to coerce — that returns `NaN` for `'0x1.icon'`.
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
ChainKeys.ICON_MAINNET === '0x1.icon'; // true
|
|
137
|
+
Number(ChainKeys.ICON_MAINNET); // NaN
|
|
138
|
+
chainKey === ChainKeys.ICON_MAINNET; // works
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Address types
|
|
142
|
+
|
|
143
|
+
- `hx…` — externally-owned account (user wallet).
|
|
144
|
+
- `cx…` — contract account.
|
|
145
|
+
|
|
146
|
+
`GetAddressType<typeof ChainKeys.ICON_MAINNET>` accepts both via a string brand.
|
|
147
|
+
|
|
148
|
+
### Injective (similar pattern)
|
|
149
|
+
|
|
150
|
+
Injective is a separate chain family but uses a similar wallet-extension model. Wallet helper: `Injective20Token` (in `@sodax/sdk`'s injective utilities). `IInjectiveWalletProvider` implementations can use Keplr, Leap, or other Cosmos-ecosystem wallets.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 5. NEAR connector discovery
|
|
155
|
+
|
|
156
|
+
NEAR has multiple wallet variants (NEAR Wallet, MyNearWallet, Meteor, Sender, …). NEAR spoke calls require an `INearWalletProvider`. The interface is exported from `@sodax/sdk`; consumers supply an object satisfying it. A reference implementation ships in `@sodax/wallet-sdk-core` (separate package — install separately); browser-side connector discovery for the multiple NEAR wallet variants happens there, not in `@sodax/sdk` itself.
|
|
157
|
+
|
|
158
|
+
### Account ID semantics
|
|
159
|
+
|
|
160
|
+
NEAR addresses come in two forms:
|
|
161
|
+
|
|
162
|
+
- **Named accounts** — `alice.near`, `mybiz.near`. Human-readable.
|
|
163
|
+
- **Implicit accounts** — 64-character hex strings.
|
|
164
|
+
|
|
165
|
+
Both are valid. `GetAddressType<typeof ChainKeys.NEAR_MAINNET>` accepts both via a string type.
|
|
166
|
+
|
|
167
|
+
### Pitfall
|
|
168
|
+
|
|
169
|
+
`NearWalletProvider` requires the `accountId` field at construction (alongside `privateKey`). Unlike EVM, NEAR can't derive an account from a key alone — keys are scoped to accounts.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Other non-EVM chains
|
|
174
|
+
|
|
175
|
+
| Chain | Notes |
|
|
176
|
+
|---|---|
|
|
177
|
+
| **Sui** (`SUI_MAINNET`) | Address: 32-byte `0x…` (different from EVM addresses despite the prefix). Wallet provider `ISuiWalletProvider` uses `@mysten/sui` under the hood. |
|
|
178
|
+
| **Stacks** (`STACKS_MAINNET`) | Address: `SP…` (mainnet) / `ST…` (testnet). Uses `@stacks/transactions` for tx construction. |
|
|
179
|
+
| **Injective** (`INJECTIVE_MAINNET`) | Cosmos-ecosystem chain. Address: `inj1…`. Wallet provider uses `@injectivelabs/sdk-ts`. |
|
|
180
|
+
|
|
181
|
+
Each has its own `I*WalletProvider` interface with chain-specific signing methods. The `chainType` discriminant on every `I*WalletProvider` instance lets you narrow at runtime without `instanceof`.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Cross-references
|
|
186
|
+
|
|
187
|
+
- `WalletProviderSlot` and chain narrowing: [`architecture.md`](architecture.md) §§ 5, 6.
|
|
188
|
+
- Per-chain wallet provider interfaces: [`reference/`](reference/) § 2.
|
|
189
|
+
- Cast-at-boundary pattern for chain-narrowed providers: [`recipes/`](recipes/) § 5.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Features — `@sodax/sdk` v2
|
|
2
|
+
|
|
3
|
+
One file per feature service. Each file documents the v2 API surface, common call shapes, return types, and error codes you can expect.
|
|
4
|
+
|
|
5
|
+
| Feature | Service class | What it does |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| [`swap.md`](swap.md) | `SwapService` | Intent-based swaps via the solver. Market and limit orders. Cross-chain by default. |
|
|
8
|
+
| [`money-market.md`](money-market.md) | `MoneyMarketService` | Cross-chain lending/borrowing. Supply, borrow, withdraw, repay. Reserves and user-position reads. |
|
|
9
|
+
| [`staking.md`](staking.md) | `StakingService` | SODA → xSoda staking via ERC-4626 vault. Stake, unstake (with penalty curve), instant unstake (slippage), claim, cancel. |
|
|
10
|
+
| [`bridge.md`](bridge.md) | `BridgeService` | Cross-chain token transfer via vault. `bridge` returns `TxHashPair = { srcChainTxHash, dstChainTxHash }`. Bridgeable-amount queries respect vault deposit limits. |
|
|
11
|
+
| [`dex.md`](dex.md) | `ClService` + `AssetService` | Uniswap-V3-style concentrated liquidity positions. Asset deposit/withdraw. Increase/decrease/claim flows. |
|
|
12
|
+
| [`migration.md`](migration.md) | `MigrationService` (the SDK module — not v1→v2 porting) | Legacy ICON ecosystem token migration. ICX ↔ SODA, legacy bnUSD ↔ new bnUSD, BALN → SODA with lockup multipliers. |
|
|
13
|
+
| [`partner.md`](partner.md) | `PartnerService` | Partner-fee handling: token approval, auto-swap preferences, fee-claim flows. |
|
|
14
|
+
| [`recovery.md`](recovery.md) | `RecoveryService` | Withdraw stuck hub-wallet assets back to a spoke chain. |
|
|
15
|
+
| [`backend-api.md`](backend-api.md) | `BackendApiService` | HTTP client for backend services: swap-tx submission, intent / orderbook lookups, money-market reads. |
|
|
16
|
+
|
|
17
|
+
All feature services are constructed and wired by the `Sodax` facade. You don't instantiate them directly — access them via `sodax.swaps`, `sodax.moneyMarket`, etc. See [`../architecture.md`](../architecture.md) for the service graph.
|
|
18
|
+
|
|
19
|
+
## Cross-references to migration
|
|
20
|
+
|
|
21
|
+
For the v1 → v2 port playbook on each feature, see the matching file in [`features/`](../../../migration-v1-to-v2/knowledge/features/) — same filename, different angle.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Backend API — `BackendApiService`
|
|
2
|
+
|
|
3
|
+
HTTP client for backend services. Provides intent lookup, swap-tx submission, solver orderbook queries, money-market position/reserve reads, and (internally) config fetching. Most consumer-side code uses just `submitSwapTx`, `getIntentByHash` / `getIntentByTxHash`, and the money-market read methods.
|
|
4
|
+
|
|
5
|
+
Access: `sodax.backendApi`. Service class: `BackendApiService`. **Feature tag for errors:** appears under multiple features depending on the call site (`'swap'` for `submitSwapTx`, `'moneyMarket'` for MM-related reads, etc.); errors carry `error.context.api: 'backend'`.
|
|
6
|
+
|
|
7
|
+
## Methods
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
// Swap-related
|
|
11
|
+
sodax.backendApi.submitSwapTx(request, config?): Promise<Result<SubmitSwapTxResponse>>;
|
|
12
|
+
sodax.backendApi.getSubmitSwapTxStatus(...): Promise<Result<...>>;
|
|
13
|
+
sodax.backendApi.getOrderbook(...): Promise<Result<OrderbookEntry[]>>;
|
|
14
|
+
sodax.backendApi.getIntentByHash(intentHash, config?): Promise<Result<IntentResponse>>;
|
|
15
|
+
sodax.backendApi.getIntentByTxHash(txHash, config?): Promise<Result<IntentResponse>>;
|
|
16
|
+
sodax.backendApi.getUserIntents(...): Promise<Result<IntentResponse[]>>;
|
|
17
|
+
|
|
18
|
+
// Money-market reads (these are the canonical reads for MM positions/reserves;
|
|
19
|
+
// MoneyMarketService does NOT expose getReservesData / getUserReservesData / etc.)
|
|
20
|
+
sodax.backendApi.getMoneyMarketPosition(...): Promise<Result<...>>;
|
|
21
|
+
sodax.backendApi.getAllMoneyMarketAssets(config?): Promise<Result<MoneyMarketAsset[]>>;
|
|
22
|
+
sodax.backendApi.getMoneyMarketAsset(reserveAddress, config?): Promise<Result<MoneyMarketAsset>>;
|
|
23
|
+
sodax.backendApi.getMoneyMarketAssetBorrowers(...): Promise<Result<...>>;
|
|
24
|
+
sodax.backendApi.getMoneyMarketAssetSuppliers(...): Promise<Result<...>>;
|
|
25
|
+
sodax.backendApi.getAllMoneyMarketBorrowers(...): Promise<Result<...>>;
|
|
26
|
+
|
|
27
|
+
// Config-API methods (used internally by ConfigService — implements `IConfigApi`)
|
|
28
|
+
sodax.backendApi.getAllConfig(config?): Promise<Result<GetAllConfigApiResponse>>;
|
|
29
|
+
sodax.backendApi.getChains(config?): Promise<Result<GetChainsApiResponse>>;
|
|
30
|
+
sodax.backendApi.getSwapTokens(config?): Promise<Result<GetSwapTokensApiResponse>>;
|
|
31
|
+
sodax.backendApi.getSwapTokensByChainId(...): Promise<Result<XToken[]>>;
|
|
32
|
+
sodax.backendApi.getMoneyMarketTokens(config?): Promise<Result<GetMoneyMarketTokensApiResponse>>;
|
|
33
|
+
sodax.backendApi.getMoneyMarketReserveAssets(...): Promise<Result<...>>;
|
|
34
|
+
sodax.backendApi.getMoneyMarketTokensByChainId(...): Promise<Result<XToken[]>>;
|
|
35
|
+
sodax.backendApi.getRelayChainIdMap(config?): Promise<Result<GetRelayChainIdMapApiResponse>>;
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
All methods return `Result<T, SodaxError>` where the error carries `feature: 'swap' | 'moneyMarket' | …` (depending on call site) and `error.context.api === 'backend'`.
|
|
39
|
+
|
|
40
|
+
## Common call shape — `submitSwapTx`
|
|
41
|
+
|
|
42
|
+
After `sodax.swaps.createIntent({ params, raw: false, walletProvider })` returns:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
const submitResult = await sodax.backendApi.submitSwapTx({
|
|
46
|
+
txHash: spokeTxHash as string,
|
|
47
|
+
srcChainKey: src.chain,
|
|
48
|
+
walletAddress: '0x…',
|
|
49
|
+
intent: swapIntentData,
|
|
50
|
+
relayData: relayData.payload, // string, not the RelayExtraData object
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (!submitResult.ok) return;
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Custom backend (sandbox / fixtures)
|
|
57
|
+
|
|
58
|
+
`SodaxConfig` does not expose a typed slot to inject a custom `IConfigApi` implementation at construction. Two supported patterns:
|
|
59
|
+
|
|
60
|
+
1. **Point at a local mock backend** via `SodaxConfig.api.baseURL`:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
const sodax = new Sodax({
|
|
64
|
+
api: { baseURL: 'http://localhost:4000' },
|
|
65
|
+
});
|
|
66
|
+
await sodax.config.initialize();
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`SodaxConfig.api` is `ApiConfig` (`{ baseURL, timeout, headers }`) — pass any subset via `DeepPartial`.
|
|
70
|
+
|
|
71
|
+
2. **Inject your own `BackendApiService`-compatible mock at the app layer** (dependency-injected where you control the `Sodax` instance), rather than via the constructor.
|
|
72
|
+
|
|
73
|
+
The `IConfigApi` interface itself still matters for both patterns — every method returns `Promise<Result<T>>` in v2, so any mock or local server must conform. See [`../architecture.md`](../architecture.md) § 4 "Custom backend" for the authoritative reference.
|
|
74
|
+
|
|
75
|
+
## Cross-references
|
|
76
|
+
|
|
77
|
+
- v1 → v2 migration of `BackendApiService` (the load-bearing change: every method now returns `Promise<Result<T>>`): [`features/backend-api.md`](../../../migration-v1-to-v2/knowledge/features/backend-api.md).
|
|
78
|
+
- The full `submitSwapTx` flow with `createIntent` upstream: [`./swap.md`](swap.md) § "Backend submit-tx flow".
|
|
79
|
+
- Partner-fee handling (separate service): [`./partner.md`](partner.md).
|
|
80
|
+
- Stuck-asset recovery (separate service): [`./recovery.md`](recovery.md).
|
|
81
|
+
- Error model context fields (`error.context.api`, `error.context.method`): [`../reference/`](../reference/) § 3.
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Bridge — `BridgeService`
|
|
2
|
+
|
|
3
|
+
Cross-chain token transfer via the hub-and-spoke vault architecture. Tokens are bridgeable if they share the same hub-side vault. The flow: spoke deposit → relay to hub → vault balance moves → spoke withdrawal on the destination chain.
|
|
4
|
+
|
|
5
|
+
Access: `sodax.bridge`. Service class: `BridgeService`. Feature tag for errors: `'bridge'`.
|
|
6
|
+
|
|
7
|
+
## How it works
|
|
8
|
+
|
|
9
|
+
A bridge call deposits the source token into its vault on the hub, then triggers a withdrawal of the same vault's destination-chain wrapper. Different tokens that share the same vault (e.g. multiple wrappings of the same underlying) are bridgeable to each other; tokens with different vaults are not.
|
|
10
|
+
|
|
11
|
+
`bridge()` handles the full lifecycle in one call. For custom relay control, use `createBridgeIntent()` (spoke-only) and call the relay layer manually.
|
|
12
|
+
|
|
13
|
+
## Public methods
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
sodax.bridge.bridge<K>(action: BridgeAction<K, false>): Promise<Result<TxHashPair, SodaxError>>;
|
|
17
|
+
sodax.bridge.createBridgeIntent<K, Raw>(action): Promise<Result<CreateBridgeIntentResult<K, Raw>, SodaxError>>;
|
|
18
|
+
sodax.bridge.approve<K, Raw>(args): Promise<Result<TxReturnType<K, Raw>, SodaxError>>;
|
|
19
|
+
sodax.bridge.isAllowanceValid<K, Raw>(args): Promise<Result<boolean, SodaxError>>;
|
|
20
|
+
|
|
21
|
+
sodax.bridge.getBridgeableAmount(from: XToken, to: XToken): Promise<Result<BridgeLimit, SodaxError>>;
|
|
22
|
+
sodax.bridge.getBridgeableTokens(from: SpokeChainKey, to: SpokeChainKey, token: string): Result<XToken[], SodaxError>;
|
|
23
|
+
// Plus the sync helper:
|
|
24
|
+
sodax.bridge.isBridgeable({ from: XToken, to: XToken }): boolean;
|
|
25
|
+
sodax.bridge.getFee(inputAmount: bigint): bigint;
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Action params shape
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
type CreateBridgeParams<K extends SpokeChainKey> = {
|
|
32
|
+
srcChainKey: K;
|
|
33
|
+
srcAddress: GetAddressType<K>;
|
|
34
|
+
srcAsset: `0x${string}`; // source token address (spoke chain)
|
|
35
|
+
amount: bigint;
|
|
36
|
+
dstChainKey: SpokeChainKey;
|
|
37
|
+
dstAddress: string; // destination wallet (chain-specific format)
|
|
38
|
+
dstAsset: `0x${string}`; // destination token address (must share vault with srcAsset)
|
|
39
|
+
};
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Common call shapes
|
|
43
|
+
|
|
44
|
+
### Full bridge (recommended for most flows)
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
const result = await sodax.bridge.bridge({
|
|
48
|
+
params: {
|
|
49
|
+
srcChainKey: ChainKeys.ARBITRUM_MAINNET,
|
|
50
|
+
srcAddress: '0x…',
|
|
51
|
+
srcAsset: USDC_ARBITRUM.address,
|
|
52
|
+
amount: parseUnits('100', 6),
|
|
53
|
+
dstChainKey: ChainKeys.STELLAR_MAINNET,
|
|
54
|
+
dstAddress: 'G…',
|
|
55
|
+
dstAsset: USDC_STELLAR.address,
|
|
56
|
+
},
|
|
57
|
+
raw: false,
|
|
58
|
+
walletProvider: evmWp,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (!result.ok) return;
|
|
62
|
+
const { srcChainTxHash, dstChainTxHash } = result.value;
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Create-intent (custom relay control)
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const result = await sodax.bridge.createBridgeIntent({
|
|
69
|
+
params: { /* same as above */ },
|
|
70
|
+
raw: false,
|
|
71
|
+
walletProvider: evmWp,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (!result.ok) return;
|
|
75
|
+
const { tx, intent, relayData } = result.value;
|
|
76
|
+
// Submit relayData.payload via your own relay infrastructure if needed.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Hub as source (Sonic → spoke)
|
|
80
|
+
|
|
81
|
+
`srcChainKey` accepts `ChainKeys.SONIC_MAINNET` too — the SDK routes through the user's hub-wallet abstraction (instead of a spoke deposit) and then triggers the destination withdrawal. The call shape is the same; only the chain key changes:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
const sodaSonic = sodax.config.findSupportedTokenBySymbol(ChainKeys.SONIC_MAINNET, 'SODA');
|
|
85
|
+
const sodaBase = sodax.config.findSupportedTokenBySymbol(ChainKeys.BASE_MAINNET, 'SODA');
|
|
86
|
+
if (!sodaSonic || !sodaBase) throw new Error('SODA missing from config');
|
|
87
|
+
|
|
88
|
+
// 1. Confirm the pair is vault-bridgeable (synchronous, config-derived).
|
|
89
|
+
if (!sodax.bridge.isBridgeable({ from: sodaSonic, to: sodaBase })) {
|
|
90
|
+
// Fall back to swap if needed — different vaults aren't bridgeable.
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 2. (Optional) check the vault-side cap.
|
|
95
|
+
const limit = await sodax.bridge.getBridgeableAmount(sodaSonic, sodaBase);
|
|
96
|
+
|
|
97
|
+
// 3. Execute. srcChainKey is the hub.
|
|
98
|
+
const result = await sodax.bridge.bridge({
|
|
99
|
+
params: {
|
|
100
|
+
srcChainKey: ChainKeys.SONIC_MAINNET,
|
|
101
|
+
srcAddress: (await evmWp.getWalletAddress()) as `0x${string}`,
|
|
102
|
+
srcAsset: sodaSonic.address,
|
|
103
|
+
amount: parseUnits('1', sodaSonic.decimals),
|
|
104
|
+
dstChainKey: ChainKeys.BASE_MAINNET,
|
|
105
|
+
dstAddress: recipientOnBase,
|
|
106
|
+
dstAsset: sodaBase.address,
|
|
107
|
+
},
|
|
108
|
+
raw: false,
|
|
109
|
+
walletProvider: evmWp,
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Internally `bridge()` branches on `isHubChainKeyType(srcChainKey)` and uses the user's hub wallet abstraction as the spender (the assetManager spoke address is used for non-hub sources). For allowance and approval flows, treat Sonic-as-source the same as any other EVM source — `isAllowanceValid` and `approve` use the same parameter shape.
|
|
114
|
+
|
|
115
|
+
### Bridgeable-amount check
|
|
116
|
+
|
|
117
|
+
Respects vault deposit limits (spoke→hub) and asset-manager balance (hub→spoke). Pass the source and destination tokens as full `XToken` objects (each carries its own `chainKey`):
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
const result = await sodax.bridge.getBridgeableAmount(USDC_ARBITRUM, USDC_STELLAR);
|
|
121
|
+
if (result.ok) {
|
|
122
|
+
const { amount, decimals, type } = result.value; // BridgeLimit
|
|
123
|
+
console.log(`Up to ${amount} (${decimals} decimals) can be bridged`);
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Find compatible tokens
|
|
128
|
+
|
|
129
|
+
Synchronous (config-derived). Pass source-chain key, destination-chain key, and the source token address; the SDK filters the destination's supported tokens by matching vault:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
const result = sodax.bridge.getBridgeableTokens(
|
|
133
|
+
ChainKeys.ARBITRUM_MAINNET,
|
|
134
|
+
ChainKeys.STELLAR_MAINNET,
|
|
135
|
+
USDC_ARBITRUM.address,
|
|
136
|
+
);
|
|
137
|
+
if (result.ok) {
|
|
138
|
+
// result.value: XToken[] — Stellar-side tokens that share USDC_ARBITRUM's vault
|
|
139
|
+
for (const token of result.value) {
|
|
140
|
+
console.log(token.chainKey, token.symbol);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Return shapes
|
|
146
|
+
|
|
147
|
+
| Method | Success type |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `bridge` | `TxHashPair` |
|
|
150
|
+
| `createBridgeIntent` | `CreateBridgeIntentResult<K, Raw>` = `{ tx: TxReturnType<K, Raw>, intent, relayData }` |
|
|
151
|
+
| `approve` | `TxReturnType<K, Raw>` |
|
|
152
|
+
| `isAllowanceValid` | `boolean` |
|
|
153
|
+
| `getBridgeableAmount` | `BridgeLimit = { amount, decimals, type }` |
|
|
154
|
+
| `getBridgeableTokens` | `XToken[]` |
|
|
155
|
+
|
|
156
|
+
## Error codes
|
|
157
|
+
|
|
158
|
+
`feature: 'bridge'`. Per-method narrow unions:
|
|
159
|
+
|
|
160
|
+
| Method | Codes | `error.context` |
|
|
161
|
+
|---|---|---|
|
|
162
|
+
| `bridge` | full exec set | `action: 'bridge'` |
|
|
163
|
+
| `createBridgeIntent` | `VALIDATION_FAILED`, `INTENT_CREATION_FAILED`, `UNKNOWN` | `action: 'bridge'` |
|
|
164
|
+
| `approve` | `VALIDATION_FAILED`, `APPROVE_FAILED`, `UNKNOWN` | n/a |
|
|
165
|
+
| `isAllowanceValid` | `VALIDATION_FAILED`, `ALLOWANCE_CHECK_FAILED`, `UNKNOWN` | n/a |
|
|
166
|
+
| `getBridgeableAmount`, `getBridgeableTokens` | `VALIDATION_FAILED`, `LOOKUP_FAILED`, `UNKNOWN` | `method: 'getBridgeableAmount' \| 'getBridgeableTokens'` |
|
|
167
|
+
|
|
168
|
+
## Cross-references
|
|
169
|
+
|
|
170
|
+
- v1 → v2 bridge migration: [`features/bridge.md`](../../../migration-v1-to-v2/knowledge/features/bridge.md).
|
|
171
|
+
- Stellar destinations need a trustline first: [`../chain-specifics.md`](../chain-specifics.md).
|
|
172
|
+
- Hub-and-spoke vault architecture: [`../architecture.md`](../architecture.md) § 1.
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# DEX — `DexService` (`AssetService` + `ClService`)
|
|
2
|
+
|
|
3
|
+
Concentrated liquidity AMM, similar to Uniswap V3 / PancakeSwap V3. Two sub-services:
|
|
4
|
+
|
|
5
|
+
- **`AssetService`** — wraps/unwraps spoke assets into the hub-side pool tokens. `deposit` (spoke→hub), `withdraw` (hub→spoke).
|
|
6
|
+
- **`ClService`** — full concentrated-liquidity position lifecycle: mint, increase, decrease, claim rewards. Pool / position read methods. (Class lives in `ConcentratedLiquidityService.ts` but the exported class is named `ClService`.)
|
|
7
|
+
|
|
8
|
+
Access: `sodax.dex.assetService`, `sodax.dex.clService`. Class names: `AssetService`, `ClService`. Feature tag for errors: `'dex'`.
|
|
9
|
+
|
|
10
|
+
## How it works
|
|
11
|
+
|
|
12
|
+
To enter a position:
|
|
13
|
+
|
|
14
|
+
1. **`assetService.deposit({ asset, amount, poolToken, ... })`** — wraps the spoke token into the hub-side pool token (vault).
|
|
15
|
+
2. **`assetService.approve(...)`** — permit the CL contract to spend the wrapped token.
|
|
16
|
+
3. **`clService.supplyLiquidity({ poolKey, ..., liquidity, amount0Max, amount1Max })`** — mints a new position NFT.
|
|
17
|
+
|
|
18
|
+
To increase / decrease / claim:
|
|
19
|
+
|
|
20
|
+
- **`clService.increaseLiquidity({ tokenId, ... })`** — adds liquidity to an existing position.
|
|
21
|
+
- **`clService.decreaseLiquidity({ tokenId, liquidity, amount0Min, amount1Min })`** — removes a fraction of liquidity (no NFT burn).
|
|
22
|
+
- **`clService.claimRewards({ tokenId, poolKey, tickLower, tickUpper })`** — collects accrued fees/rewards for a position.
|
|
23
|
+
|
|
24
|
+
## Public methods
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
// AssetService
|
|
28
|
+
sodax.dex.assetService.deposit<K>(action: AssetDepositAction<K, false>): Promise<Result<TxHashPair, SodaxError>>;
|
|
29
|
+
sodax.dex.assetService.withdraw<K>(action: AssetWithdrawAction<K, false>): Promise<Result<TxHashPair, SodaxError>>;
|
|
30
|
+
sodax.dex.assetService.approve<K, Raw>(args): Promise<Result<TxReturnType<K, Raw>, SodaxError>>;
|
|
31
|
+
sodax.dex.assetService.isAllowanceValid<K, Raw>(args): Promise<Result<boolean, SodaxError>>;
|
|
32
|
+
sodax.dex.assetService.getDeposit(poolToken, walletAddress, chainKey): Promise<Result<bigint, SodaxError>>;
|
|
33
|
+
sodax.dex.assetService.executeDeposit<K, Raw>(args): /* spoke-only deposit; no relay */;
|
|
34
|
+
|
|
35
|
+
// ClService (concentrated liquidity)
|
|
36
|
+
sodax.dex.clService.supplyLiquidity<K>(action): Promise<Result<TxHashPair, SodaxError>>;
|
|
37
|
+
sodax.dex.clService.increaseLiquidity<K>(action): Promise<Result<TxHashPair, SodaxError>>;
|
|
38
|
+
sodax.dex.clService.decreaseLiquidity<K>(action): Promise<Result<TxHashPair, SodaxError>>;
|
|
39
|
+
sodax.dex.clService.claimRewards<K>(action): Promise<Result<TxHashPair, SodaxError>>;
|
|
40
|
+
|
|
41
|
+
sodax.dex.clService.getPools(): PoolKey[]; // synchronous in v2
|
|
42
|
+
sodax.dex.clService.getPoolData(poolKey, publicClient): Promise<Result<PoolData, SodaxError>>;
|
|
43
|
+
sodax.dex.clService.getPositionInfo(tokenId, poolKey, publicClient): Promise<Result<PositionInfo, SodaxError>>;
|
|
44
|
+
sodax.dex.clService.getAssetsForPool(srcChainKey, poolKey): { token0, token1 }; // chain-key-first; sync
|
|
45
|
+
|
|
46
|
+
// Static math helpers (still throw on error — utility class):
|
|
47
|
+
ClService.priceToTick(price): number;
|
|
48
|
+
ClService.calculateAmount0FromAmount1(...): bigint;
|
|
49
|
+
ClService.calculateAmount1FromAmount0(...): bigint;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Action params shape
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
type CreateAssetDepositParams<K extends SpokeChainKey> = {
|
|
56
|
+
srcChainKey: K;
|
|
57
|
+
srcAddress: GetAddressType<K>;
|
|
58
|
+
asset: `0x${string}`; // spoke-side token address
|
|
59
|
+
amount: bigint;
|
|
60
|
+
poolToken: `0x${string}`; // hub-side pool token (vault address)
|
|
61
|
+
dst?: { chainKey: SpokeChainKey; address: string }; // optional cross-chain delivery
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
type CreateAssetWithdrawParams<K> = { /* same shape */ };
|
|
65
|
+
|
|
66
|
+
type ClSupplyParams<K> = {
|
|
67
|
+
srcChainKey: K;
|
|
68
|
+
srcAddress: GetAddressType<K>;
|
|
69
|
+
poolKey: PoolKey;
|
|
70
|
+
tickLower: number;
|
|
71
|
+
tickUpper: number;
|
|
72
|
+
liquidity: bigint;
|
|
73
|
+
amount0Max: bigint;
|
|
74
|
+
amount1Max: bigint;
|
|
75
|
+
sqrtPriceX96: bigint;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
type ClIncreaseLiquidityParams<K> = ClSupplyParams<K> & { tokenId: bigint };
|
|
79
|
+
type ClDecreaseLiquidityParams<K> = {
|
|
80
|
+
srcChainKey: K;
|
|
81
|
+
srcAddress: GetAddressType<K>;
|
|
82
|
+
poolKey: PoolKey;
|
|
83
|
+
tokenId: bigint;
|
|
84
|
+
liquidity: bigint;
|
|
85
|
+
amount0Min: bigint;
|
|
86
|
+
amount1Min: bigint;
|
|
87
|
+
};
|
|
88
|
+
type ClClaimRewardsParams<K> = { srcChainKey, srcAddress, poolKey, tokenId, tickLower, tickUpper };
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Common call shapes
|
|
92
|
+
|
|
93
|
+
### Deposit (spoke asset → hub pool token)
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
const result = await sodax.dex.assetService.deposit({
|
|
97
|
+
params: {
|
|
98
|
+
srcChainKey: ChainKeys.ARBITRUM_MAINNET,
|
|
99
|
+
srcAddress: '0x…',
|
|
100
|
+
asset: USDC.address,
|
|
101
|
+
amount: parseUnits('100', 6),
|
|
102
|
+
poolToken: '0x…', // the hub-side pool token (XToken.vault)
|
|
103
|
+
},
|
|
104
|
+
raw: false,
|
|
105
|
+
walletProvider: evmWp,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
if (!result.ok) return;
|
|
109
|
+
const { srcChainTxHash, dstChainTxHash } = result.value;
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Mint a new concentrated-liquidity position
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
const result = await sodax.dex.clService.supplyLiquidity({
|
|
116
|
+
params: {
|
|
117
|
+
srcChainKey: ChainKeys.ARBITRUM_MAINNET,
|
|
118
|
+
srcAddress: '0x…',
|
|
119
|
+
poolKey: { /* { currency0, currency1, fee, tickSpacing, hooks } */ },
|
|
120
|
+
tickLower: -887220,
|
|
121
|
+
tickUpper: 887220,
|
|
122
|
+
liquidity: 1000000n,
|
|
123
|
+
amount0Max: parseUnits('100', 6),
|
|
124
|
+
amount1Max: parseUnits('100', 6),
|
|
125
|
+
sqrtPriceX96: /* current sqrtPrice */,
|
|
126
|
+
},
|
|
127
|
+
raw: false,
|
|
128
|
+
walletProvider: evmWp,
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Increase liquidity on an existing position
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
await sodax.dex.clService.increaseLiquidity({
|
|
136
|
+
params: { /* same as supplyLiquidity, plus tokenId: existingPositionTokenId */ },
|
|
137
|
+
raw: false,
|
|
138
|
+
walletProvider: evmWp,
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Allowance check (read-only)
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
const allowed = await sodax.dex.assetService.isAllowanceValid({
|
|
146
|
+
params: { srcChainKey, srcAddress, asset, amount, poolToken },
|
|
147
|
+
raw: true, // read-only — no walletProvider required
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The underlying read does not consult the wallet provider; pass `raw: true` to satisfy `WalletProviderSlot` without supplying a provider.
|
|
152
|
+
|
|
153
|
+
## Return shapes
|
|
154
|
+
|
|
155
|
+
| Method | Success type |
|
|
156
|
+
|---|---|
|
|
157
|
+
| `deposit`, `withdraw`, `supplyLiquidity`, `increaseLiquidity`, `decreaseLiquidity`, `claimRewards` | `TxHashPair` |
|
|
158
|
+
| `approve` | `TxReturnType<K, Raw>` |
|
|
159
|
+
| `isAllowanceValid` | `boolean` |
|
|
160
|
+
| `getDeposit` | `bigint` (user's balance in the pool's hub wallet) |
|
|
161
|
+
| `getPoolData` | `{ liquidity, sqrtPriceX96, tick, /* … */ }` |
|
|
162
|
+
| `getPositionInfo` | `{ poolKey, tickLower, tickUpper, liquidity, fees0, fees1, /* … */ }` |
|
|
163
|
+
| `getPools` | `PoolKey[]` (synchronous, returns from cached config) |
|
|
164
|
+
| `getAssetsForPool` | `{ token0: XToken, token1: XToken }` (synchronous; takes `srcChainKey` to filter by spoke availability) |
|
|
165
|
+
|
|
166
|
+
> `getPools()` is **synchronous** in v2 (was `Promise<PoolKey[]>` in v1). v2 reads from cached config — no I/O. `await sodax.dex.clService.getPools()` works (TS allows `await` on non-promise) but `.then(...)` is a runtime error.
|
|
167
|
+
|
|
168
|
+
## Error codes
|
|
169
|
+
|
|
170
|
+
`feature: 'dex'`. Per-method narrow unions:
|
|
171
|
+
|
|
172
|
+
| Method | Codes | Action |
|
|
173
|
+
|---|---|---|
|
|
174
|
+
| `deposit`, `withdraw`, `supplyLiquidity`, `increaseLiquidity`, `decreaseLiquidity`, `claimRewards` | full exec set | matches operation |
|
|
175
|
+
| `approve` | `VALIDATION_FAILED`, `APPROVE_FAILED`, `UNKNOWN` | matches operation |
|
|
176
|
+
| `isAllowanceValid` | `VALIDATION_FAILED`, `ALLOWANCE_CHECK_FAILED`, `UNKNOWN` | n/a |
|
|
177
|
+
| `getDeposit`, `getPoolData`, `getPositionInfo` | `VALIDATION_FAILED`, `LOOKUP_FAILED`, `UNKNOWN` | (use `error.context.method`) |
|
|
178
|
+
|
|
179
|
+
## Cross-references
|
|
180
|
+
|
|
181
|
+
- v1 → v2 DEX migration: [`features/dex.md`](../../../migration-v1-to-v2/knowledge/features/dex.md).
|
|
182
|
+
- The hub-side `EvmHubProvider.publicClient` is what `getPoolData` / `getPositionInfo` use internally — consumers can pass `sodax.hubProvider.publicClient`.
|