@buildaureon/sdk 0.1.0 → 0.1.1
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/README.md +353 -245
- package/dist/index.d.ts +15 -6
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/docs/architecture.md +139 -138
- package/docs/auth.md +127 -168
- package/docs/client-api.md +5 -4
- package/docs/data-contracts.md +7 -4
- package/docs/error-model.md +151 -116
- package/docs/integration-guide.md +173 -112
- package/docs/security.md +87 -41
- package/docs/transport.md +91 -77
- package/examples/e2e-policy-rebalance/main.ts +24 -36
- package/examples/e2e-policy-rebalance/underrun.ts +28 -24
- package/examples/e2e-policy-rebalance/verify-sizing.ts +29 -26
- package/examples/e2e-vault-flow/main.ts +36 -90
- package/examples/market-event/main.ts +9 -9
- package/examples/quickstart/main.ts +17 -16
- package/examples/sdk-demo-terminal/main.ts +171 -0
- package/package.json +5 -8
package/docs/error-model.md
CHANGED
|
@@ -1,182 +1,217 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Error Model and Diagnostics
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Error classification, payloads, recovery patterns, and live failure modes for `@buildaureon/sdk`.
|
|
4
|
+
|
|
5
|
+
**Automation note:** Examples assume **Automatic** objectives. Manual Approve error paths are out of scope for SDK agents.
|
|
4
6
|
|
|
5
7
|
---
|
|
6
8
|
|
|
7
|
-
## 1.
|
|
9
|
+
## 1. Exception hierarchy
|
|
8
10
|
|
|
9
|
-
All
|
|
11
|
+
All SDK failures that represent API/client faults extend `AureonError`.
|
|
10
12
|
|
|
11
13
|
```mermaid
|
|
12
14
|
graph TD
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
Native[Error] --> Base[AureonError]
|
|
16
|
+
Base --> Val[AureonValidationError_400]
|
|
17
|
+
Base --> NotFound[AureonNotFoundError_404]
|
|
18
|
+
Base --> Conflict[AureonConflictError_409]
|
|
19
|
+
Base --> Net[AureonNetworkError]
|
|
20
|
+
Base --> Timeout[AureonTimeoutError]
|
|
19
21
|
```
|
|
20
22
|
|
|
21
|
-
###
|
|
23
|
+
### Properties
|
|
24
|
+
|
|
25
|
+
| Field | Meaning |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| `code` | Stable string for branching (`UNAUTHORIZED`, `VALIDATION_ERROR`, …) |
|
|
28
|
+
| `status` | HTTP status, or `null` for pure network failures |
|
|
29
|
+
| `details` | Optional structured metadata from the API |
|
|
30
|
+
| `retryable` | Whether an immediate retry is reasonable |
|
|
31
|
+
| `message` | Human-readable summary |
|
|
22
32
|
|
|
23
33
|
```ts
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
/** Indicates whether the request can be retried immediately. */
|
|
32
|
-
readonly retryable: boolean;
|
|
33
|
-
|
|
34
|
-
constructor(
|
|
35
|
-
message: string,
|
|
36
|
-
code: AureonErrorCode,
|
|
37
|
-
status: number | null = null,
|
|
38
|
-
details: Record<string, unknown> | null = null
|
|
39
|
-
) {
|
|
40
|
-
super(message);
|
|
41
|
-
this.name = this.constructor.name;
|
|
42
|
-
this.code = code;
|
|
43
|
-
this.status = status;
|
|
44
|
-
this.details = details;
|
|
45
|
-
this.retryable = isRetryableCode(code);
|
|
46
|
-
|
|
47
|
-
// Capture stack trace, preserving original V8 exception stack where supported
|
|
48
|
-
if (Error.captureStackTrace) {
|
|
49
|
-
Error.captureStackTrace(this, this.constructor);
|
|
50
|
-
}
|
|
34
|
+
import { isAureonError } from "@buildaureon/sdk";
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
await aureon.restoreObjective(id);
|
|
38
|
+
} catch (err) {
|
|
39
|
+
if (isAureonError(err)) {
|
|
40
|
+
console.error(err.code, err.status, err.details);
|
|
51
41
|
}
|
|
42
|
+
throw err;
|
|
52
43
|
}
|
|
53
44
|
```
|
|
54
45
|
|
|
55
46
|
---
|
|
56
47
|
|
|
57
|
-
## 2. API
|
|
48
|
+
## 2. Common API payloads
|
|
58
49
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
### 2.1 Validation Error Payload (HTTP 400)
|
|
62
|
-
Returned when objective creation weights, names, or tolerances violate system rules.
|
|
50
|
+
### Validation (400)
|
|
63
51
|
|
|
64
52
|
```json
|
|
65
53
|
{
|
|
66
54
|
"code": "VALIDATION_ERROR",
|
|
67
|
-
"message": "Create objective parameters failed validation
|
|
55
|
+
"message": "Create objective parameters failed validation",
|
|
68
56
|
"details": {
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"tolerance": "Tolerance must be a number between 0.0 and 0.5"
|
|
57
|
+
"targetWeight": "must be between 0 and 1",
|
|
58
|
+
"tolerance": "must be between 0 and 0.5"
|
|
72
59
|
}
|
|
73
60
|
}
|
|
74
61
|
```
|
|
75
62
|
|
|
76
|
-
|
|
77
|
-
|
|
63
|
+
Also covers locked-field updates (e.g. attempting to change `targetSymbol` / `automationMode` after create).
|
|
64
|
+
|
|
65
|
+
### Unauthorized (401)
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"message": "Invalid API key",
|
|
70
|
+
"details": null
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Or, when an env bootstrap key is used without wallet identity:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"message": "Wallet session required (env API keys cannot identify a wallet; use an issued developer key or Bearer)",
|
|
79
|
+
"details": null
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Not found (404)
|
|
84
|
+
|
|
85
|
+
Missing objective / key id / resource.
|
|
86
|
+
|
|
87
|
+
### Conflict (409)
|
|
78
88
|
|
|
79
89
|
```json
|
|
80
90
|
{
|
|
81
91
|
"code": "CONFLICT",
|
|
82
|
-
"message": "Cannot modify objective
|
|
92
|
+
"message": "Cannot modify objective while restore is in flight",
|
|
83
93
|
"details": {
|
|
84
|
-
"objectiveId": "
|
|
85
|
-
"executionId": "exec_01h8v5t7p8p3z2v1q45r3m2e99",
|
|
94
|
+
"objectiveId": "obj_...",
|
|
86
95
|
"status": "pending_confirmation"
|
|
87
96
|
}
|
|
88
97
|
}
|
|
89
98
|
```
|
|
90
99
|
|
|
91
|
-
|
|
92
|
-
|
|
100
|
+
Also appears when restore is rejected because capital / plan / vault state conflicts with the request.
|
|
101
|
+
|
|
102
|
+
### Rate limit (429)
|
|
93
103
|
|
|
94
104
|
```json
|
|
95
105
|
{
|
|
96
106
|
"code": "RATE_LIMITED",
|
|
97
|
-
"message": "Too many requests
|
|
98
|
-
"details": {
|
|
99
|
-
"retryAfterSeconds": 15,
|
|
100
|
-
"limit": 100,
|
|
101
|
-
"windowMs": 60000
|
|
102
|
-
}
|
|
107
|
+
"message": "Too many requests",
|
|
108
|
+
"details": { "retryAfterSeconds": 15 }
|
|
103
109
|
}
|
|
104
110
|
```
|
|
105
111
|
|
|
112
|
+
### Server (5xx)
|
|
113
|
+
|
|
114
|
+
Retryable when `maxRetries` > 0. Alert ops if persistent.
|
|
115
|
+
|
|
106
116
|
---
|
|
107
117
|
|
|
108
|
-
## 3.
|
|
118
|
+
## 3. Operational recovery map
|
|
119
|
+
|
|
120
|
+
```mermaid
|
|
121
|
+
flowchart TD
|
|
122
|
+
Catch[Catch_AureonError] --> Code{error.code_or_status}
|
|
123
|
+
|
|
124
|
+
Code -->|UNAUTHORIZED| Auth[Rotate_issued_key_or_refresh_Bearer]
|
|
125
|
+
Code -->|VALIDATION_ERROR| ValFix[Fix_inputs_recreate_if_locked_fields]
|
|
126
|
+
Code -->|NOT_FOUND| Missing[Refresh_lists_check_ids]
|
|
127
|
+
Code -->|CONFLICT| Wait[Backoff_recheck_health_and_plan]
|
|
128
|
+
Code -->|RATE_LIMITED| Sleep[Sleep_retryAfter_or_retryDelayMs]
|
|
129
|
+
Code -->|TIMEOUT_NETWORK| Retry[Increase_timeoutMs_enable_maxRetries]
|
|
130
|
+
Code -->|5xx| Alert[Alert_ops_retry_bounded]
|
|
131
|
+
```
|
|
109
132
|
|
|
110
|
-
|
|
133
|
+
| Situation | Agent action |
|
|
134
|
+
| --- | --- |
|
|
135
|
+
| Invalid / paused key | Stop loop; operator rotates Developers key |
|
|
136
|
+
| Bootstrap key alone | Switch to issued key |
|
|
137
|
+
| Vault empty on restore | Prepare deposit → broadcast → sync → retry |
|
|
138
|
+
| Locked field on update | Recreate objective |
|
|
139
|
+
| Conflict mid-restore | Back off; read timeline / executions |
|
|
140
|
+
| Staged settlement returned | Do not treat as on-chain success |
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 4. Logging hooks
|
|
111
145
|
|
|
112
146
|
```ts
|
|
113
|
-
import { createAureonClient
|
|
114
|
-
|
|
115
|
-
const productionLogger: AureonLogger = {
|
|
116
|
-
debug(msg, ctx) { console.debug(`[DEBUG] ${msg}`, ctx || ""); },
|
|
117
|
-
info(msg, ctx) { console.info(`[INFO] ${msg}`, ctx || ""); },
|
|
118
|
-
warn(msg, ctx) { console.warn(`[WARN] ${msg}`, ctx || ""); },
|
|
119
|
-
error(msg, ctx) {
|
|
120
|
-
// Send critical anomalies to third-party alert services
|
|
121
|
-
if (ctx?.code === "SERVER_ERROR" || ctx?.code === "CONFLICT") {
|
|
122
|
-
sendToSentry(msg, ctx);
|
|
123
|
-
}
|
|
124
|
-
console.error(`[ERROR] ${msg}`, ctx || "");
|
|
125
|
-
}
|
|
126
|
-
};
|
|
147
|
+
import { createAureonClient } from "@buildaureon/sdk";
|
|
127
148
|
|
|
128
149
|
const aureon = createAureonClient({
|
|
129
|
-
apiKey: process.env.AUREON_API_KEY
|
|
130
|
-
logger:
|
|
150
|
+
apiKey: process.env.AUREON_API_KEY!,
|
|
151
|
+
logger: {
|
|
152
|
+
debug: (msg, ctx) => console.debug(msg, ctx),
|
|
153
|
+
info: (msg, ctx) => console.info(msg, ctx),
|
|
154
|
+
warn: (msg, ctx) => console.warn(msg, ctx),
|
|
155
|
+
error: (msg, ctx) => {
|
|
156
|
+
// forward to your APM — never include secrets from ctx
|
|
157
|
+
console.error(msg, ctx);
|
|
158
|
+
},
|
|
159
|
+
},
|
|
131
160
|
});
|
|
132
161
|
```
|
|
133
162
|
|
|
134
163
|
---
|
|
135
164
|
|
|
136
|
-
##
|
|
165
|
+
## 5. Client-side validation vs server errors
|
|
137
166
|
|
|
138
|
-
|
|
139
|
-
flowchart TD
|
|
140
|
-
Catch[Catch AureonError] --> CodeBranch{Switch error.code}
|
|
141
|
-
|
|
142
|
-
CodeBranch -->|UNAUTHORIZED| HandleAuth[Clear storage and restart EIP-191 signature challenge]
|
|
143
|
-
CodeBranch -->|VALIDATION_ERROR| HandleValidation[Parse details dictionary and highlight fields in UI]
|
|
144
|
-
CodeBranch -->|NOT_FOUND| HandleNotFound[Redirect to list and show warning toast]
|
|
145
|
-
CodeBranch -->|RATE_LIMITED| HandleRate[Wait retryAfterSeconds or exponential backoff then retry]
|
|
146
|
-
CodeBranch -->|TIMEOUT| HandleTimeout[Increase timeoutMs client configuration and retry]
|
|
147
|
-
CodeBranch -->|SERVER_ERROR| HandleServer[Alert ops team and fallback to staged settlement]
|
|
148
|
-
```
|
|
167
|
+
The SDK normalizes create/update inputs before HTTP (weights, locked fields, automation defaults). Failures can therefore happen:
|
|
149
168
|
|
|
150
|
-
|
|
169
|
+
1. **Preflight** in the SDK (no network), or
|
|
170
|
+
2. **Gateway** after HTTP (allowlists, vault state, conflicts).
|
|
171
|
+
|
|
172
|
+
Always catch with `isAureonError` and inspect `code` + `details`.
|
|
151
173
|
|
|
152
|
-
|
|
174
|
+
---
|
|
153
175
|
|
|
154
|
-
|
|
176
|
+
## 6. Unit test sketch
|
|
155
177
|
|
|
156
178
|
```ts
|
|
157
|
-
import
|
|
158
|
-
import
|
|
159
|
-
import {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
targetWeight: 0.2,
|
|
170
|
-
tolerance: 0.02
|
|
171
|
-
});
|
|
172
|
-
assert.fail("Should have failed pre-flight validation");
|
|
173
|
-
} catch (err) {
|
|
174
|
-
assert.ok(isAureonError(err));
|
|
175
|
-
assert.strictEqual(err.code, "VALIDATION_ERROR");
|
|
176
|
-
assert.ok(err instanceof AureonValidationError);
|
|
177
|
-
assert.match(err.message, /length/);
|
|
178
|
-
}
|
|
179
|
+
import assert from "node:assert/strict";
|
|
180
|
+
import test from "node:test";
|
|
181
|
+
import {
|
|
182
|
+
createAureonClient,
|
|
183
|
+
isAureonError,
|
|
184
|
+
AureonValidationError,
|
|
185
|
+
} from "@buildaureon/sdk";
|
|
186
|
+
|
|
187
|
+
test("empty objective name fails validation", async () => {
|
|
188
|
+
const client = createAureonClient({
|
|
189
|
+
baseUrl: "https://api.aureonlabs.network",
|
|
190
|
+
apiKey: "test",
|
|
179
191
|
});
|
|
192
|
+
|
|
193
|
+
await assert.rejects(
|
|
194
|
+
() =>
|
|
195
|
+
client.createObjective({
|
|
196
|
+
name: " ",
|
|
197
|
+
kind: "balanced_portfolio",
|
|
198
|
+
targetWeight: 0.2,
|
|
199
|
+
tolerance: 0.02,
|
|
200
|
+
targetSymbol: "WETH",
|
|
201
|
+
}),
|
|
202
|
+
(err: unknown) =>
|
|
203
|
+
isAureonError(err) &&
|
|
204
|
+
err instanceof AureonValidationError &&
|
|
205
|
+
err.code === "VALIDATION_ERROR"
|
|
206
|
+
);
|
|
180
207
|
});
|
|
181
208
|
```
|
|
182
|
-
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## 7. Related docs
|
|
213
|
+
|
|
214
|
+
- [Transport](./transport.md)
|
|
215
|
+
- [Auth](./auth.md)
|
|
216
|
+
- [Integration guide](./integration-guide.md)
|
|
217
|
+
- [Client API](./client-api.md)
|