@sodax/skills 2.0.0-rc.4
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 +13 -0
- package/AGENTS.md +81 -0
- package/LICENSE +21 -0
- package/README.md +49 -0
- package/knowledge/dapp-kit/AGENTS.md +50 -0
- package/knowledge/dapp-kit/integration/README.md +49 -0
- package/knowledge/dapp-kit/integration/ai-rules.md +80 -0
- package/knowledge/dapp-kit/integration/architecture.md +276 -0
- package/knowledge/dapp-kit/integration/features/README.md +29 -0
- package/knowledge/dapp-kit/integration/features/auxiliary-services.md +169 -0
- package/knowledge/dapp-kit/integration/features/bitcoin.md +87 -0
- package/knowledge/dapp-kit/integration/features/bridge.md +91 -0
- package/knowledge/dapp-kit/integration/features/dex.md +152 -0
- package/knowledge/dapp-kit/integration/features/migration.md +118 -0
- package/knowledge/dapp-kit/integration/features/money-market.md +144 -0
- package/knowledge/dapp-kit/integration/features/staking.md +123 -0
- package/knowledge/dapp-kit/integration/features/swap.md +101 -0
- package/knowledge/dapp-kit/integration/quickstart.md +188 -0
- package/knowledge/dapp-kit/integration/recipes/README.md +136 -0
- package/knowledge/dapp-kit/integration/recipes/backend-queries.md +157 -0
- package/knowledge/dapp-kit/integration/recipes/bitcoin.md +193 -0
- package/knowledge/dapp-kit/integration/recipes/bridge.md +174 -0
- package/knowledge/dapp-kit/integration/recipes/dex.md +204 -0
- package/knowledge/dapp-kit/integration/recipes/invalidations.md +115 -0
- package/knowledge/dapp-kit/integration/recipes/migration.md +212 -0
- package/knowledge/dapp-kit/integration/recipes/money-market.md +207 -0
- package/knowledge/dapp-kit/integration/recipes/mutation-error-handling.md +118 -0
- package/knowledge/dapp-kit/integration/recipes/observability.md +93 -0
- package/knowledge/dapp-kit/integration/recipes/setup.md +168 -0
- package/knowledge/dapp-kit/integration/recipes/staking.md +202 -0
- package/knowledge/dapp-kit/integration/recipes/swap.md +272 -0
- package/knowledge/dapp-kit/integration/recipes/wallet-connectivity.md +128 -0
- package/knowledge/dapp-kit/integration/reference/README.md +12 -0
- package/knowledge/dapp-kit/integration/reference/glossary.md +190 -0
- package/knowledge/dapp-kit/integration/reference/hooks-index.md +190 -0
- package/knowledge/dapp-kit/integration/reference/public-api.md +110 -0
- package/knowledge/dapp-kit/integration/reference/querykey-conventions.md +179 -0
- package/knowledge/dapp-kit/migration/README.md +60 -0
- package/knowledge/dapp-kit/migration/ai-rules.md +81 -0
- package/knowledge/dapp-kit/migration/breaking-changes/hook-signatures.md +233 -0
- package/knowledge/dapp-kit/migration/breaking-changes/querykey-conventions.md +108 -0
- package/knowledge/dapp-kit/migration/breaking-changes/result-handling.md +211 -0
- package/knowledge/dapp-kit/migration/breaking-changes/sdk-leakage.md +167 -0
- package/knowledge/dapp-kit/migration/checklist.md +89 -0
- package/knowledge/dapp-kit/migration/features/README.md +34 -0
- package/knowledge/dapp-kit/migration/features/auxiliary-services.md +114 -0
- package/knowledge/dapp-kit/migration/features/bitcoin.md +88 -0
- package/knowledge/dapp-kit/migration/features/bridge.md +160 -0
- package/knowledge/dapp-kit/migration/features/dex.md +101 -0
- package/knowledge/dapp-kit/migration/features/migration.md +120 -0
- package/knowledge/dapp-kit/migration/features/money-market.md +139 -0
- package/knowledge/dapp-kit/migration/features/staking.md +109 -0
- package/knowledge/dapp-kit/migration/features/swap.md +133 -0
- package/knowledge/dapp-kit/migration/recipes.md +185 -0
- package/knowledge/dapp-kit/migration/reference/README.md +15 -0
- package/knowledge/dapp-kit/migration/reference/deleted-hooks.md +110 -0
- package/knowledge/dapp-kit/migration/reference/error-shape-crosswalk.md +144 -0
- package/knowledge/dapp-kit/migration/reference/renamed-hooks.md +68 -0
- package/knowledge/sdk/AGENTS.md +41 -0
- package/knowledge/sdk/integration/README.md +41 -0
- package/knowledge/sdk/integration/ai-rules.md +75 -0
- package/knowledge/sdk/integration/architecture.md +533 -0
- package/knowledge/sdk/integration/chain-specifics.md +189 -0
- package/knowledge/sdk/integration/features/README.md +19 -0
- package/knowledge/sdk/integration/features/auxiliary-services.md +189 -0
- package/knowledge/sdk/integration/features/bridge.md +136 -0
- package/knowledge/sdk/integration/features/dex.md +182 -0
- package/knowledge/sdk/integration/features/icx-bnusd-baln.md +181 -0
- package/knowledge/sdk/integration/features/money-market.md +198 -0
- package/knowledge/sdk/integration/features/staking.md +166 -0
- package/knowledge/sdk/integration/features/swap.md +207 -0
- package/knowledge/sdk/integration/quickstart.md +213 -0
- package/knowledge/sdk/integration/recipes/README.md +21 -0
- package/knowledge/sdk/integration/recipes/backend-server-init.md +69 -0
- package/knowledge/sdk/integration/recipes/chain-key-narrowing.md +65 -0
- package/knowledge/sdk/integration/recipes/gas-estimation.md +33 -0
- package/knowledge/sdk/integration/recipes/initialize-sodax.md +78 -0
- package/knowledge/sdk/integration/recipes/raw-tx-flow.md +71 -0
- package/knowledge/sdk/integration/recipes/result-and-errors.md +104 -0
- package/knowledge/sdk/integration/recipes/signed-tx-flow.md +46 -0
- package/knowledge/sdk/integration/recipes/testing.md +101 -0
- package/knowledge/sdk/integration/reference/README.md +18 -0
- package/knowledge/sdk/integration/reference/chain-keys.md +67 -0
- package/knowledge/sdk/integration/reference/error-codes.md +165 -0
- package/knowledge/sdk/integration/reference/glossary.md +32 -0
- package/knowledge/sdk/integration/reference/public-api.md +138 -0
- package/knowledge/sdk/integration/reference/wallet-providers.md +62 -0
- package/knowledge/sdk/migration/README.md +58 -0
- package/knowledge/sdk/migration/ai-rules.md +80 -0
- package/knowledge/sdk/migration/breaking-changes/architecture.md +344 -0
- package/knowledge/sdk/migration/breaking-changes/result-and-errors.md +363 -0
- package/knowledge/sdk/migration/breaking-changes/type-system.md +341 -0
- package/knowledge/sdk/migration/checklist.md +67 -0
- package/knowledge/sdk/migration/features/README.md +35 -0
- package/knowledge/sdk/migration/features/auxiliary-services.md +156 -0
- package/knowledge/sdk/migration/features/bridge.md +128 -0
- package/knowledge/sdk/migration/features/dex.md +143 -0
- package/knowledge/sdk/migration/features/icx-bnusd-baln.md +151 -0
- package/knowledge/sdk/migration/features/money-market.md +214 -0
- package/knowledge/sdk/migration/features/staking.md +138 -0
- package/knowledge/sdk/migration/features/swap.md +198 -0
- package/knowledge/sdk/migration/recipes.md +350 -0
- package/knowledge/sdk/migration/reference/README.md +18 -0
- package/knowledge/sdk/migration/reference/deleted-exports.md +127 -0
- package/knowledge/sdk/migration/reference/error-code-crosswalk.md +104 -0
- package/knowledge/sdk/migration/reference/return-shapes.md +49 -0
- package/knowledge/sdk/migration/reference/sodax-config.md +145 -0
- package/knowledge/wallet-sdk-core/AGENTS.md +43 -0
- package/knowledge/wallet-sdk-core/integration/README.md +108 -0
- package/knowledge/wallet-sdk-core/integration/ai-rules.md +141 -0
- package/knowledge/wallet-sdk-core/integration/architecture.md +212 -0
- package/knowledge/wallet-sdk-core/integration/features/README.md +22 -0
- package/knowledge/wallet-sdk-core/integration/features/bitcoin.md +103 -0
- package/knowledge/wallet-sdk-core/integration/features/evm.md +102 -0
- package/knowledge/wallet-sdk-core/integration/features/icon.md +88 -0
- package/knowledge/wallet-sdk-core/integration/features/injective.md +92 -0
- package/knowledge/wallet-sdk-core/integration/features/near.md +92 -0
- package/knowledge/wallet-sdk-core/integration/features/solana.md +104 -0
- package/knowledge/wallet-sdk-core/integration/features/stacks.md +91 -0
- package/knowledge/wallet-sdk-core/integration/features/stellar.md +95 -0
- package/knowledge/wallet-sdk-core/integration/features/sui.md +96 -0
- package/knowledge/wallet-sdk-core/integration/quickstart.md +259 -0
- package/knowledge/wallet-sdk-core/integration/recipes/README.md +15 -0
- package/knowledge/wallet-sdk-core/integration/recipes/bridge-to-sdk.md +145 -0
- package/knowledge/wallet-sdk-core/integration/recipes/defaults-and-overrides.md +159 -0
- package/knowledge/wallet-sdk-core/integration/recipes/library-exports.md +129 -0
- package/knowledge/wallet-sdk-core/integration/recipes/setup-browser-extension.md +137 -0
- package/knowledge/wallet-sdk-core/integration/recipes/setup-private-key.md +115 -0
- package/knowledge/wallet-sdk-core/integration/recipes/sign-and-broadcast.md +201 -0
- package/knowledge/wallet-sdk-core/integration/recipes/testing.md +163 -0
- package/knowledge/wallet-sdk-core/integration/reference/README.md +13 -0
- package/knowledge/wallet-sdk-core/integration/reference/chain-support.md +65 -0
- package/knowledge/wallet-sdk-core/integration/reference/glossary.md +28 -0
- package/knowledge/wallet-sdk-core/integration/reference/interfaces.md +131 -0
- package/knowledge/wallet-sdk-core/integration/reference/provider-classes.md +54 -0
- package/knowledge/wallet-sdk-core/integration/reference/public-api.md +128 -0
- package/knowledge/wallet-sdk-core/migration/README.md +84 -0
- package/knowledge/wallet-sdk-core/migration/ai-rules.md +139 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/README.md +14 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/base-wallet-provider.md +52 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/defaults-config.md +57 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/folder-layout.md +99 -0
- package/knowledge/wallet-sdk-core/migration/breaking-changes/library-exports.md +58 -0
- package/knowledge/wallet-sdk-core/migration/checklist.md +62 -0
- package/knowledge/wallet-sdk-core/migration/recipes/README.md +12 -0
- package/knowledge/wallet-sdk-core/migration/recipes/adopt-defaults.md +84 -0
- package/knowledge/wallet-sdk-core/migration/recipes/adopt-library-exports.md +99 -0
- package/knowledge/wallet-sdk-core/migration/reference/README.md +12 -0
- package/knowledge/wallet-sdk-core/migration/reference/added-fields.md +71 -0
- package/knowledge/wallet-sdk-core/migration/reference/deleted-exports.md +35 -0
- package/knowledge/wallet-sdk-core/migration/reference/renamed-symbols.md +31 -0
- package/knowledge/wallet-sdk-core/migration/reference/return-shapes.md +23 -0
- package/knowledge/wallet-sdk-react/AGENTS.md +46 -0
- package/knowledge/wallet-sdk-react/integration/README.md +103 -0
- package/knowledge/wallet-sdk-react/integration/ai-rules.md +136 -0
- package/knowledge/wallet-sdk-react/integration/architecture.md +185 -0
- package/knowledge/wallet-sdk-react/integration/examples/01-minimal-evm.tsx +75 -0
- package/knowledge/wallet-sdk-react/integration/examples/02-multi-chain-modal.tsx +169 -0
- package/knowledge/wallet-sdk-react/integration/examples/03-nextjs-app-router.tsx +99 -0
- package/knowledge/wallet-sdk-react/integration/examples/04-walletconnect-setup.tsx +89 -0
- package/knowledge/wallet-sdk-react/integration/examples/README.md +29 -0
- package/knowledge/wallet-sdk-react/integration/recipes/batch-operations.md +224 -0
- package/knowledge/wallet-sdk-react/integration/recipes/bridge-to-sdk.md +165 -0
- package/knowledge/wallet-sdk-react/integration/recipes/chain-detection.md +259 -0
- package/knowledge/wallet-sdk-react/integration/recipes/connect-button.md +159 -0
- package/knowledge/wallet-sdk-react/integration/recipes/multi-chain-modal.md +203 -0
- package/knowledge/wallet-sdk-react/integration/recipes/setup.md +163 -0
- package/knowledge/wallet-sdk-react/integration/recipes/sign-message.md +138 -0
- package/knowledge/wallet-sdk-react/integration/recipes/sub-path-imports.md +97 -0
- package/knowledge/wallet-sdk-react/integration/recipes/switch-chain.md +144 -0
- package/knowledge/wallet-sdk-react/integration/recipes/walletconnect-setup.md +139 -0
- package/knowledge/wallet-sdk-react/integration/reference/api-surface.md +176 -0
- package/knowledge/wallet-sdk-react/integration/reference/chain-support.md +79 -0
- package/knowledge/wallet-sdk-react/integration/reference/connectors.md +75 -0
- package/knowledge/wallet-sdk-react/integration/reference/hooks.md +212 -0
- package/knowledge/wallet-sdk-react/integration/reference/wallet-brands.md +107 -0
- package/knowledge/wallet-sdk-react/migration/README.md +49 -0
- package/knowledge/wallet-sdk-react/migration/ai-rules.md +144 -0
- package/knowledge/wallet-sdk-react/migration/breaking-changes.md +310 -0
- package/knowledge/wallet-sdk-react/migration/checklist.md +159 -0
- package/knowledge/wallet-sdk-react/migration/recipes/connect-button.md +170 -0
- package/knowledge/wallet-sdk-react/migration/recipes/multi-chain-modal.md +245 -0
- package/knowledge/wallet-sdk-react/migration/recipes/ssr-setup.md +165 -0
- package/knowledge/wallet-sdk-react/migration/recipes/walletconnect-migration.md +170 -0
- package/knowledge/wallet-sdk-react/migration/reference/components.md +75 -0
- package/knowledge/wallet-sdk-react/migration/reference/config.md +339 -0
- package/knowledge/wallet-sdk-react/migration/reference/hooks.md +336 -0
- package/knowledge/wallet-sdk-react/migration/reference/imports.md +158 -0
- package/package.json +59 -0
- package/skills/sodax-dapp-kit-integration/SKILL.md +71 -0
- package/skills/sodax-dapp-kit-migration/SKILL.md +58 -0
- package/skills/sodax-sdk-integration/SKILL.md +66 -0
- package/skills/sodax-sdk-migration/SKILL.md +75 -0
- package/skills/sodax-wallet-sdk-core-integration/SKILL.md +55 -0
- package/skills/sodax-wallet-sdk-core-migration/SKILL.md +56 -0
- package/skills/sodax-wallet-sdk-react-integration/SKILL.md +80 -0
- package/skills/sodax-wallet-sdk-react-migration/SKILL.md +71 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# Result and error model breaking changes — v1 → v2
|
|
2
|
+
|
|
3
|
+
The runtime contract of every async method changed. v1 threw on failure; v2 resolves `{ ok: false, error }`. v1 had per-module typed-error unions; v2 has a single canonical `SodaxError<C>` with a closed 13-code vocabulary.
|
|
4
|
+
|
|
5
|
+
This is the largest behavioral change in v2. A consumer that ignores it will compile against v2 (with help from the type system) but silently swallow failures — a v1-style `try { await sodax.<method>(...) } catch` does **not** catch SDK-level failures, because they don't throw.
|
|
6
|
+
|
|
7
|
+
Read after [`type-system.md`](type-system.md) and [`architecture.md`](architecture.md).
|
|
8
|
+
|
|
9
|
+
## Section index
|
|
10
|
+
|
|
11
|
+
1. [`Result<T>` — the new return contract](#1-resultt--the-new-return-contract)
|
|
12
|
+
2. [`SodaxError<C>` — the canonical error class](#2-sodaxerrorc--the-canonical-error-class)
|
|
13
|
+
3. [The 13-code vocabulary](#3-the-13-code-vocabulary)
|
|
14
|
+
4. [Reference tables — moved](#4-reference-tables--moved) (v1 ↔ v2 code crosswalk and per-method return-shape diffs)
|
|
15
|
+
5. [Carve-out: `BalnSwapService` still throws](#5-carve-out-balnswapservice-still-throws)
|
|
16
|
+
6. [Migration patterns](#6-migration-patterns)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 1. `Result<T>` — the new return contract
|
|
21
|
+
|
|
22
|
+
### Shape
|
|
23
|
+
|
|
24
|
+
`Result<T, E = Error | unknown>` is defined in `@sodax/types` (re-exported from `@sodax/sdk`):
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
type Result<T, E = Error | unknown> =
|
|
28
|
+
| { ok: true; value: T }
|
|
29
|
+
| { ok: false; error: E };
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Every async public method on every feature service in v2 returns `Promise<Result<T, SodaxError<C>>>`. There is no `throw` across a service boundary.
|
|
33
|
+
|
|
34
|
+
### Where it applies
|
|
35
|
+
|
|
36
|
+
The **complete list** of services whose public methods return `Result<T>`:
|
|
37
|
+
|
|
38
|
+
- `SwapService` (every async method)
|
|
39
|
+
- `MoneyMarketService` (every async method)
|
|
40
|
+
- `BridgeService` (every async method)
|
|
41
|
+
- `StakingService` (every async method except `StakingLogic.*` static helpers — see § 5)
|
|
42
|
+
- `MigrationService` (every async method except `BalnSwapService` lock-management methods — see § 5)
|
|
43
|
+
- `DexService` / `ClService` / `AssetService` (every async method)
|
|
44
|
+
- `PartnerService`
|
|
45
|
+
- `RecoveryService`
|
|
46
|
+
- `BackendApiService`
|
|
47
|
+
- `SpokeService` (router-level helpers)
|
|
48
|
+
- `IConfigApi` implementations (every method)
|
|
49
|
+
|
|
50
|
+
Private helpers may still throw; the outer `try/catch` at each public method's boundary absorbs those and converts them to `{ ok: false, error }`.
|
|
51
|
+
|
|
52
|
+
### Propagation pattern
|
|
53
|
+
|
|
54
|
+
The canonical pattern across the SDK:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
// Forward a sub-Result without re-wrapping.
|
|
58
|
+
// (TypeScript narrows the error union — narrower codes are structurally
|
|
59
|
+
// assignable to wider ones, so this typechecks even if `sub` returns a smaller
|
|
60
|
+
// code union than the outer method.)
|
|
61
|
+
const sub = await this.subOperation();
|
|
62
|
+
if (!sub.ok) return sub;
|
|
63
|
+
|
|
64
|
+
// Success
|
|
65
|
+
return { ok: true, value: /* … */ };
|
|
66
|
+
|
|
67
|
+
// Outer catch at every public method's boundary
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (isMethodError(error)) return { ok: false, error };
|
|
70
|
+
return {
|
|
71
|
+
ok: false,
|
|
72
|
+
error: new SodaxError('EXECUTION_FAILED', '<short message>', {
|
|
73
|
+
feature: 'swap',
|
|
74
|
+
cause: error,
|
|
75
|
+
context: { action: 'createIntent', phase: 'execution' },
|
|
76
|
+
}),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
There is **no** `toResult` / `tryCatch` / `safeCall` helper. Explicit `try/catch` at each method boundary is the deliberate convention.
|
|
82
|
+
|
|
83
|
+
### Branching
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
const result = await sodax.swaps.createIntent({ params, raw: false, walletProvider });
|
|
87
|
+
if (!result.ok) {
|
|
88
|
+
if (isSodaxError(result.error)) {
|
|
89
|
+
if (result.error.code === 'RELAY_TIMEOUT') { /* retry */ }
|
|
90
|
+
if (result.error.code === 'INTENT_CREATION_FAILED') { /* show input error */ }
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const { tx, intent, relayData } = result.value;
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Migration mechanics
|
|
98
|
+
|
|
99
|
+
```diff
|
|
100
|
+
- try {
|
|
101
|
+
- const result = await sodax.swaps.createIntent({ intentParams, spokeProvider });
|
|
102
|
+
- const [spokeTxHash, intent, relayData] = result;
|
|
103
|
+
- /* … */
|
|
104
|
+
- } catch (e) {
|
|
105
|
+
- if (e instanceof IntentError && e.code === 'CREATE_INTENT_FAILED') { /* … */ }
|
|
106
|
+
- }
|
|
107
|
+
|
|
108
|
+
+ const result = await sodax.swaps.createIntent({ params, raw: false, walletProvider });
|
|
109
|
+
+ if (!result.ok) {
|
|
110
|
+
+ if (isSodaxError(result.error) && result.error.code === 'INTENT_CREATION_FAILED') { /* … */ }
|
|
111
|
+
+ return;
|
|
112
|
+
+ }
|
|
113
|
+
+ const { tx: spokeTxHash, intent, relayData } = result.value; // object, not tuple — see ../reference/return-shapes.md
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Pitfall
|
|
117
|
+
|
|
118
|
+
A `try { await sodax.<method>(...) } catch` block in v2 only catches **exceptions** thrown from inside the call (e.g. a bug, a missing argument, a synchronous validation thrown from the wrapper). It does **not** catch SDK-level failures like `RELAY_TIMEOUT` — those resolve to `{ ok: false, error }` and skip your `catch` entirely. The legacy `try/catch` can stay as defense-in-depth, but you **must** also branch on `result.ok`.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 2. `SodaxError<C>` — the canonical error class
|
|
123
|
+
|
|
124
|
+
### Shape
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
class SodaxError<C extends SodaxErrorCode = SodaxErrorCode> extends Error {
|
|
128
|
+
readonly code: C; // closed 13-code reason union
|
|
129
|
+
readonly feature: SodaxFeature; // 'swap' | 'moneyMarket' | 'bridge' | 'staking' | 'migration' | 'dex' | 'partner' | 'recovery'
|
|
130
|
+
readonly cause?: unknown;
|
|
131
|
+
readonly context?: SodaxErrorContext;
|
|
132
|
+
|
|
133
|
+
toJSON(): SodaxErrorJSON<C>; // canonical logger surface (Sentry/Pino/Datadog)
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Discrimination contract
|
|
138
|
+
|
|
139
|
+
The `(feature, code)` pair is the canonical discriminator. Loggers emit it as a tag pair; consumer switch statements branch on it. **Do not** string-match on `error.message` — messages are short prose and may change between releases. Codes are closed and stable.
|
|
140
|
+
|
|
141
|
+
### `isSodaxError` over `instanceof`
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import { isSodaxError } from '@sodax/sdk';
|
|
145
|
+
|
|
146
|
+
if (isSodaxError(e)) {
|
|
147
|
+
// e: SodaxError<SodaxErrorCode>
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
`isSodaxError` walks `e.name === 'SodaxError'` + a `code: string` + `feature: string` shape check. Prefer it over bare `instanceof SodaxError` — `instanceof` returns `false` when `@sodax/sdk` is loaded twice in the same bundle (a real-world hazard with monorepos and dual ESM/CJS, especially in apps with mixed package resolution).
|
|
152
|
+
|
|
153
|
+
### `error.context`
|
|
154
|
+
|
|
155
|
+
A free-form metadata bag with reserved fields:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
type SodaxErrorContext = {
|
|
159
|
+
action?: string; // feature operation (e.g. 'supply', 'stake', 'migrateBaln')
|
|
160
|
+
phase?: SodaxPhase; // 'validate' | 'intentCreation' | 'verify' | 'submit' | 'relay' | 'destinationExecution' | 'execution' | 'postExecution' | 'approve' | 'allowanceCheck' | 'gasEstimation' | 'lookup'
|
|
161
|
+
srcChainKey?: string;
|
|
162
|
+
dstChainKey?: string;
|
|
163
|
+
relayCode?: 'SUBMIT_TX_FAILED' | 'RELAY_TIMEOUT' | 'RELAY_POLLING_FAILED' | 'UNKNOWN';
|
|
164
|
+
api?: 'solver' | 'backend';
|
|
165
|
+
method?: string; // names the read-only method on LOOKUP_FAILED
|
|
166
|
+
direction?: 'forward' | 'reverse'; // migration's bnUSD-only
|
|
167
|
+
field?: string; // VALIDATION_FAILED specifics
|
|
168
|
+
reason?: string;
|
|
169
|
+
[key: string]: unknown; // open at the index signature
|
|
170
|
+
};
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### `error.toJSON()` for logging
|
|
174
|
+
|
|
175
|
+
`JSON.stringify(error)` invokes `toJSON()` automatically. The serializer:
|
|
176
|
+
|
|
177
|
+
- Coerces `bigint` to string anywhere in `context`.
|
|
178
|
+
- Walks `cause` chains up to depth 3.
|
|
179
|
+
- Stringifies `Date`, `Map`, `Set`, `Error`, and class instances safely.
|
|
180
|
+
- Handles cycles (depth-bounded at 5).
|
|
181
|
+
|
|
182
|
+
Consumer-side logging integration:
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
// Sentry
|
|
186
|
+
Sentry.captureException(error, { tags: { feature: error.feature, code: error.code, action: error.context?.action } });
|
|
187
|
+
|
|
188
|
+
// Pino / Winston
|
|
189
|
+
logger.error({ err: error }, 'sodax operation failed');
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 3. The 13-code vocabulary
|
|
195
|
+
|
|
196
|
+
| Code | Meaning | Common context fields |
|
|
197
|
+
|---|---|---|
|
|
198
|
+
| `VALIDATION_FAILED` | Pre-flight invariant tripped (input shape, unsupported chain, etc.). | `field`, `reason`, `phase: 'validate'` |
|
|
199
|
+
| `INTENT_CREATION_FAILED` | Building the intent / payload failed. | `phase: 'intentCreation'` |
|
|
200
|
+
| `EXECUTION_FAILED` | Orchestrator-level catch-all (post-relay business logic). | `action`, `phase: 'execution'` or `'postExecution'` |
|
|
201
|
+
| `TX_VERIFICATION_FAILED` | Spoke-side `verifyTxHash` returned false / threw. | `phase: 'verify'`, `srcChainKey` |
|
|
202
|
+
| `TX_SUBMIT_FAILED` | Spoke tx landed; relay POST submit failed. | `phase: 'submit'`, `relayCode: 'SUBMIT_TX_FAILED'` |
|
|
203
|
+
| `RELAY_TIMEOUT` | Destination packet didn't reach `executed` within timeout. | `phase: 'relay'`, `srcChainKey`, `dstChainKey`, `relayCode: 'RELAY_TIMEOUT'` |
|
|
204
|
+
| `RELAY_FAILED` | Relay polling outage / unrecognised relay error. | `phase: 'relay'`, `relayCode` |
|
|
205
|
+
| `APPROVE_FAILED` | Token approval call failed. | `phase: 'approve'` |
|
|
206
|
+
| `ALLOWANCE_CHECK_FAILED` | Reading on-chain allowance failed. (Distinct from `LOOKUP_FAILED` for retry semantics.) | `phase: 'allowanceCheck'` |
|
|
207
|
+
| `GAS_ESTIMATION_FAILED` | Gas estimation returned an error. (Distinct for retry semantics.) | `phase: 'gasEstimation'` |
|
|
208
|
+
| `LOOKUP_FAILED` | Read-only on-chain query / off-chain config fetch. | `method`, `phase: 'lookup'` |
|
|
209
|
+
| `EXTERNAL_API_ERROR` | Upstream API call failed (solver, backend). | `api: 'solver' \| 'backend'`, plus `solverCode`/`solverDetail` for solver |
|
|
210
|
+
| `UNKNOWN` | Last-resort catch in an outer `try`. Should be rare in production. | (none guaranteed) |
|
|
211
|
+
|
|
212
|
+
### Per-method narrow unions
|
|
213
|
+
|
|
214
|
+
Every public method declares a `<MethodName>ErrorCode` narrow union built via `Extract<SodaxErrorCode, ...>`. Switch exhaustively over the narrow union when you know the method:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
type CreateSupplyIntentErrorCode = Extract<
|
|
218
|
+
SodaxErrorCode,
|
|
219
|
+
'VALIDATION_FAILED' | 'INTENT_CREATION_FAILED' | 'UNKNOWN'
|
|
220
|
+
>;
|
|
221
|
+
|
|
222
|
+
// In the queryFn or call site:
|
|
223
|
+
const result = await sodax.moneyMarket.createSupplyIntent({ params, raw: true });
|
|
224
|
+
if (!result.ok) {
|
|
225
|
+
switch (result.error.code) {
|
|
226
|
+
case 'VALIDATION_FAILED': /* show input error */ break;
|
|
227
|
+
case 'INTENT_CREATION_FAILED': /* show "couldn't build supply intent" */ break;
|
|
228
|
+
case 'UNKNOWN': /* fallback */ break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
The narrow unions are exported from each feature's `errors.ts` (e.g. `@sodax/sdk` re-exports `SupplyErrorCode`, `BorrowErrorCode`, `BridgeErrorCode`, `StakeErrorCode`, etc.). See [`../../integration/reference/`](../../integration/reference/) § "Error codes" for the full catalogue.
|
|
234
|
+
|
|
235
|
+
### Read-method partition
|
|
236
|
+
|
|
237
|
+
`LOOKUP_FAILED` is the catch-all for read-only methods. Its partition lives on `error.context.method`:
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
if (result.error.code === 'LOOKUP_FAILED') {
|
|
241
|
+
switch (result.error.context?.method) {
|
|
242
|
+
case 'getStakingInfo': /* … */ break;
|
|
243
|
+
case 'getBridgeableAmount': /* … */ break;
|
|
244
|
+
case 'getUnstakingInfoWithPenalty': /* … */ break;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
This avoids inflating the global code count (`getStakingInfoFailed`, `getBridgeableAmountFailed`, …) while keeping per-method retry semantics inspectable.
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## 4. Reference tables — moved
|
|
254
|
+
|
|
255
|
+
The two reference-grade tables that used to live in this file (the **v1 ↔ v2 code crosswalk** and the **per-method return-shape diffs**) have moved into `../reference/`:
|
|
256
|
+
|
|
257
|
+
- [`../reference/error-code-crosswalk.md`](../reference/error-code-crosswalk.md) — every v1 module-error code → v2 `(feature, code, context)` mapping, per feature.
|
|
258
|
+
- [`../reference/return-shapes.md`](../reference/return-shapes.md) — per-method return-shape diffs (`CreateIntentResult` tuple → object, every cross-chain mutation now returns `TxHashPair`, `getBridgeableAmount` returns `BridgeLimit`, `getStakeRatio` returns a tuple, etc.).
|
|
259
|
+
|
|
260
|
+
The prose on shape semantics stays here; the lookup tables live in `../reference/`.
|
|
261
|
+
|
|
262
|
+
## 5. Carve-out: `BalnSwapService` still throws
|
|
263
|
+
|
|
264
|
+
The lock-management methods on `BalnSwapService` (a sub-service of `MigrationService`) **do not** return `Result<T>` in v2. They keep the v1 throw-on-error contract:
|
|
265
|
+
|
|
266
|
+
- `BalnSwapService.claim()`
|
|
267
|
+
- `BalnSwapService.claimUnstaked()`
|
|
268
|
+
- `BalnSwapService.stake()`
|
|
269
|
+
- `BalnSwapService.unstake()`
|
|
270
|
+
- `BalnSwapService.cancelUnstake()`
|
|
271
|
+
- `BalnSwapService.getDetailedUserLocks()`
|
|
272
|
+
|
|
273
|
+
This is **technical debt**, marked for cleanup in a future release. Until then, your code must `try/catch` these specific calls. Every other public async method on every other service in v2 returns `Result<T>`.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## 6. Migration patterns
|
|
278
|
+
|
|
279
|
+
### Convert one call site (the typical pattern)
|
|
280
|
+
|
|
281
|
+
```diff
|
|
282
|
+
try {
|
|
283
|
+
- const result = await sodax.moneyMarket.supply({ params: supplyParams, spokeProvider });
|
|
284
|
+
- const txHash = result;
|
|
285
|
+
+ const result = await sodax.moneyMarket.supply({ params: supplyParams, raw: false, walletProvider });
|
|
286
|
+
+ if (!result.ok) {
|
|
287
|
+
+ setError(getMmErrorText(result.error));
|
|
288
|
+
+ return;
|
|
289
|
+
+ }
|
|
290
|
+
+ const { srcChainTxHash } = result.value;
|
|
291
|
+
+ /* … */
|
|
292
|
+
} catch (e) {
|
|
293
|
+
/* keep as defense-in-depth net for unexpected throws */
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Adapt a `getXxxErrorText` helper
|
|
298
|
+
|
|
299
|
+
If your v1 code has a helper that branches on `error.code`, the minimal change is to map v2 shape onto the v1 shape at the boundary:
|
|
300
|
+
|
|
301
|
+
```ts
|
|
302
|
+
// Module-scope helper
|
|
303
|
+
function adaptToV1Shape(error: unknown): { code?: string; message?: string; data?: { error?: unknown } } | null {
|
|
304
|
+
if (!error) return null;
|
|
305
|
+
if (isSodaxError(error)) {
|
|
306
|
+
return {
|
|
307
|
+
code: error.code,
|
|
308
|
+
message: error.message,
|
|
309
|
+
data: { error: error.cause },
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
if (error instanceof Error) return { code: error.message, message: error.message };
|
|
313
|
+
if (typeof error === 'object') return error as { code?: string; message?: string; data?: { error?: unknown } };
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Existing branches (sdkError.code === 'SUPPLY_FAILED') keep working — until you migrate
|
|
318
|
+
// them properly to (feature, code) tuples per ../reference/error-code-crosswalk.md.
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Use the per-feature guard factory for routing
|
|
322
|
+
|
|
323
|
+
```ts
|
|
324
|
+
const isSwapError = isFeatureError('swap');
|
|
325
|
+
const isMmError = isFeatureError('moneyMarket');
|
|
326
|
+
const isBridgeError = isFeatureError('bridge');
|
|
327
|
+
|
|
328
|
+
if (!result.ok) {
|
|
329
|
+
if (isSwapError(result.error)) router.push('/swap-error');
|
|
330
|
+
else if (isMmError(result.error)) router.push('/loan-error');
|
|
331
|
+
else if (isBridgeError(result.error)) router.push('/bridge-error');
|
|
332
|
+
else router.push('/error');
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### A `throwIfError` shim for incremental migration
|
|
337
|
+
|
|
338
|
+
If you can't refactor every call site in one pass:
|
|
339
|
+
|
|
340
|
+
```ts
|
|
341
|
+
// Drop into a shared lib
|
|
342
|
+
export function throwIfError<T>(result: Result<T, unknown>): T {
|
|
343
|
+
if (!result.ok) throw result.error;
|
|
344
|
+
return result.value;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Use at call sites where you haven't migrated the surrounding error handling yet:
|
|
348
|
+
const { tx, intent } = throwIfError(
|
|
349
|
+
await sodax.swaps.createIntent({ params, raw: false, walletProvider }),
|
|
350
|
+
);
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
This is **transitional**. Once your error-handling tree is updated, remove `throwIfError` and branch on `result.ok` directly. See [`../recipes.md`](../recipes.md) § "Result adapter" for a fuller version.
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Cross-references
|
|
358
|
+
|
|
359
|
+
- Type-level renames (deleted error types, return-type renames): [`type-system.md`](type-system.md) §§ 6, 10.
|
|
360
|
+
- Architecture reshape (relay layer, mapRelayFailure, sodaxInvariant, isSodaxError): [`architecture.md`](architecture.md) §§ 3, 4.
|
|
361
|
+
- v2 design context (Result propagation, error model): [`../../integration/architecture.md`](../../integration/architecture.md) and [`../../integration/recipes/`](../../integration/recipes/) § "Result handling".
|
|
362
|
+
- Per-feature narrow code unions: [`../../integration/reference/`](../../integration/reference/) § "Error codes".
|
|
363
|
+
- Per-feature playbooks (with `getXxxErrorText` adapters in context): [`../features/`](../features/).
|