@buildaureon/sdk 0.1.2 → 0.1.8
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/LICENSE +21 -21
- package/README.md +21 -3
- package/config/network.json +20 -10
- package/dist/index.d.ts +706 -100
- package/dist/index.js +1813 -205
- package/dist/index.js.map +1 -1
- package/docs/architecture.md +11 -9
- package/docs/auth.md +5 -3
- package/docs/client-api.md +187 -4
- package/docs/data-contracts.md +81 -6
- package/docs/error-model.md +2 -2
- package/docs/integration-guide.md +169 -26
- package/docs/receipt-validation.md +66 -0
- package/docs/security.md +1 -1
- package/docs/transport.md +2 -1
- package/examples/ai-to-objective-to-portfolio/main.ts +130 -0
- package/examples/audit-trail/main.ts +55 -0
- package/examples/drift-detect-restore/main.ts +99 -0
- package/examples/e2e-policy-rebalance/main.ts +13 -8
- package/examples/e2e-policy-rebalance/underrun.ts +13 -8
- package/examples/e2e-policy-rebalance/verify-sizing.ts +13 -8
- package/examples/e2e-vault-flow/main.ts +13 -8
- package/examples/full-aureon-loop/main.ts +86 -0
- package/examples/green-vs-plan/main.ts +142 -0
- package/examples/market-event/main.ts +8 -3
- package/examples/portfolio-watch/main.ts +87 -0
- package/examples/quickstart/main.ts +8 -5
- package/examples/receipt-verification/main.ts +90 -0
- package/examples/sdk-demo-terminal/main.ts +6 -4
- package/fixtures/reference-objectives.json +18 -18
- package/fixtures/reference-portfolio.json +10 -10
- package/package.json +70 -61
package/docs/architecture.md
CHANGED
|
@@ -127,7 +127,7 @@ sequenceDiagram
|
|
|
127
127
|
|
|
128
128
|
- **Capital Book** — gateway portfolio used for weight math (`syncPortfolio`).
|
|
129
129
|
- **Vault balances** — on-chain capital Automatic restores trade against.
|
|
130
|
-
- Empty vault ⇒ Automatic
|
|
130
|
+
- Empty vault ⇒ Automatic restore returns 409. It does not stage a fake success or edit the capital book.
|
|
131
131
|
|
|
132
132
|
---
|
|
133
133
|
|
|
@@ -184,16 +184,18 @@ flowchart TD
|
|
|
184
184
|
|
|
185
185
|
---
|
|
186
186
|
|
|
187
|
-
## 8. Network
|
|
187
|
+
## 8. Network
|
|
188
188
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
|
192
|
-
|
|
|
193
|
-
|
|
|
194
|
-
|
|
|
189
|
+
Default omitted SDK/MCP options are the **isolated mainnet stack** (4663 + local 8788). Public `api.aureonlabs.network` is still **testnet 46630**.
|
|
190
|
+
|
|
191
|
+
| Item | Mainnet (default) | Testnet (opt-in) |
|
|
192
|
+
| --- | --- | --- |
|
|
193
|
+
| Chain | Robinhood Chain mainnet | Robinhood Chain testnet |
|
|
194
|
+
| Chain ID | `4663` | `46630` |
|
|
195
|
+
| API | `http://127.0.0.1:8788` | `https://api.aureonlabs.network` |
|
|
196
|
+
| Explorer | `https://robinhoodchain.blockscout.com` | `https://explorer.testnet.chain.robinhood.com` |
|
|
195
197
|
|
|
196
|
-
|
|
198
|
+
Production does **not** already sync 4663. Confirm live addresses from the API you actually call.
|
|
197
199
|
|
|
198
200
|
---
|
|
199
201
|
|
package/docs/auth.md
CHANGED
|
@@ -40,8 +40,9 @@ Control-plane calls (sync, objectives, health, restore, vault reads, prepare-*)
|
|
|
40
40
|
import { createAureonClient } from "@buildaureon/sdk";
|
|
41
41
|
|
|
42
42
|
const aureon = createAureonClient({
|
|
43
|
-
baseUrl: "https://api.aureonlabs.network",
|
|
44
43
|
apiKey: process.env.AUREON_API_KEY!, // issued key from Developers
|
|
44
|
+
// omit network → mainnet 4663 / http://127.0.0.1:8788
|
|
45
|
+
// network: "testnet" → public host (still 46630)
|
|
45
46
|
});
|
|
46
47
|
|
|
47
48
|
const me = await aureon.me();
|
|
@@ -88,7 +89,7 @@ import { createAureonClient, createSessionTokenProvider } from "@buildaureon/sdk
|
|
|
88
89
|
|
|
89
90
|
const session = createSessionTokenProvider(null);
|
|
90
91
|
const aureon = createAureonClient({
|
|
91
|
-
|
|
92
|
+
network: "testnet", // public host, still chain 46630
|
|
92
93
|
apiKey: process.env.AUREON_API_KEY,
|
|
93
94
|
getAccessToken: session.getAccessToken,
|
|
94
95
|
});
|
|
@@ -143,7 +144,8 @@ session.clear();
|
|
|
143
144
|
| Variable | Required | Description |
|
|
144
145
|
| --- | --- | --- |
|
|
145
146
|
| `AUREON_API_KEY` | Recommended | Issued developer key |
|
|
146
|
-
| `
|
|
147
|
+
| `AUREON_NETWORK` | No | Omit for mainnet 4663 / `http://127.0.0.1:8788`. Set `testnet` for the public host (still 46630). |
|
|
148
|
+
| `AUREON_API_URL` | No | Optional override. Must match `AUREON_NETWORK` if both are set. |
|
|
147
149
|
| `AUREON_TOKEN` | No | Optional Bearer for CLI / scripts |
|
|
148
150
|
|
|
149
151
|
CLI example:
|
package/docs/client-api.md
CHANGED
|
@@ -32,7 +32,8 @@ import {
|
|
|
32
32
|
} from "@buildaureon/sdk";
|
|
33
33
|
|
|
34
34
|
const aureon = createAureonClient({
|
|
35
|
-
//
|
|
35
|
+
// network defaults to mainnet (4663 / http://127.0.0.1:8788)
|
|
36
|
+
// network: "testnet" → public host (still chain 46630)
|
|
36
37
|
apiKey: process.env.AUREON_API_KEY,
|
|
37
38
|
getAccessToken: () => sessionToken,
|
|
38
39
|
timeoutMs: 30_000,
|
|
@@ -44,7 +45,8 @@ const aureon = createAureonClient({
|
|
|
44
45
|
|
|
45
46
|
| Option | Required | Default | Description |
|
|
46
47
|
|--------|----------|---------|-------------|
|
|
47
|
-
| `
|
|
48
|
+
| `network` | no | `mainnet` | `mainnet` = 4663 / `http://127.0.0.1:8788`. `testnet` = public host (still 46630). |
|
|
49
|
+
| `baseUrl` | no | mainnet local API | Absolute `http://` or `https://` URL. Wins when set; mismatch with `network` throws. |
|
|
48
50
|
| `apiKey` | SDK / CLI | N/A | Sent as `X-Aureon-Api-Key`. Issued developer keys also identify the bound wallet (no Bearer required). Env bootstrap keys are product-gate only. Utility uses wallet Bearer only. |
|
|
49
51
|
| `getAccessToken` | no | N/A | Optional Bearer getter. Wins over API-key identity when present. |
|
|
50
52
|
| `authToken` | no | N/A | Static Bearer string when `getAccessToken` is omitted. |
|
|
@@ -59,8 +61,12 @@ const aureon = createAureonClient({
|
|
|
59
61
|
|
|
60
62
|
| Rule | Behavior |
|
|
61
63
|
|------|----------|
|
|
62
|
-
| Omitted `baseUrl` |
|
|
64
|
+
| Omitted `network` and `baseUrl` | Local mainnet `http://127.0.0.1:8788`, chain 4663 |
|
|
65
|
+
| `network: "testnet"` | Public `https://api.aureonlabs.network` (still 46630) |
|
|
66
|
+
| Explicit `baseUrl` | Wins; infer network from known hosts |
|
|
67
|
+
| `network` + disagreeing `baseUrl` | Throws |
|
|
63
68
|
| Invalid `baseUrl` scheme | Throws via `assertBaseUrl` |
|
|
69
|
+
| `aureon.network` / `aureon.chainId` | Resolved bundle |
|
|
64
70
|
| Both `authToken` and `getAccessToken` | Transport uses `getAccessToken` only |
|
|
65
71
|
| `aureon.baseUrl` getter | Returns resolved base (no trailing slash) |
|
|
66
72
|
|
|
@@ -365,6 +371,172 @@ async getOverview(): Promise<DashboardOverview>
|
|
|
365
371
|
| HTTP | `GET /overview` |
|
|
366
372
|
| Contains | Health counts, global score, 24h portfolio change (daily snapshots), evaluation schedule, recent executions + events |
|
|
367
373
|
|
|
374
|
+
### `getAllocationVsTarget()`
|
|
375
|
+
|
|
376
|
+
```ts
|
|
377
|
+
async getAllocationVsTarget(): Promise<{
|
|
378
|
+
rows: AllocationComparisonRow[];
|
|
379
|
+
paradox: PlanParadoxResult;
|
|
380
|
+
overview: DashboardOverview;
|
|
381
|
+
}>
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
| | |
|
|
385
|
+
|--|--|
|
|
386
|
+
| Auth | Required |
|
|
387
|
+
| HTTP | Composite — parallel `GET /overview`, `GET /objectives`, `GET /health` |
|
|
388
|
+
| Returns | Per-objective current vs target weights plus a green-book/off-plan paradox flag |
|
|
389
|
+
| Use | demo — objective vs actual portfolio without stitching JSON yourself |
|
|
390
|
+
|
|
391
|
+
Helpers `buildAllocationComparison()` and `detectPlanParadox()` are exported for custom integrators. See `pnpm example:green-vs-plan`.
|
|
392
|
+
|
|
393
|
+
### `applyFinancialIntent(intent)`
|
|
394
|
+
|
|
395
|
+
```ts
|
|
396
|
+
async applyFinancialIntent(intent: FinancialIntent): Promise<ObjectivePortfolioFlow>
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
| | |
|
|
400
|
+
|--|--|
|
|
401
|
+
| Auth | Required |
|
|
402
|
+
| HTTP | Composite — `POST /objectives` + watchdog refresh + `GET /health` + `GET /portfolio` |
|
|
403
|
+
| Returns | Intent summary, created objective, health, portfolio snapshot, teaching message |
|
|
404
|
+
| Use | AI → objective → portfolio in one call |
|
|
405
|
+
|
|
406
|
+
### `getObjectivePortfolioFlow(objectiveId?)`
|
|
407
|
+
|
|
408
|
+
```ts
|
|
409
|
+
async getObjectivePortfolioFlow(objectiveId?: string): Promise<ObjectivePortfolioFlow[]>
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
| | |
|
|
413
|
+
|--|--|
|
|
414
|
+
| Auth | Required |
|
|
415
|
+
| HTTP | Composite — objectives + health + portfolio |
|
|
416
|
+
| Returns | Flow snapshots for active objectives (or one id) |
|
|
417
|
+
|
|
418
|
+
Helpers `parseFinancialIntent()`, `resolveObjectiveFromIntent()`, and `buildObjectivePortfolioFlow()` are exported. See `pnpm example:ai-to-objective-to-portfolio`.
|
|
419
|
+
|
|
420
|
+
### `runDriftRestoreDemo()`
|
|
421
|
+
|
|
422
|
+
```ts
|
|
423
|
+
async runDriftRestoreDemo(): Promise<DriftRestoreFlow>
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
| | |
|
|
427
|
+
|--|--|
|
|
428
|
+
| Auth | Required |
|
|
429
|
+
| HTTP | Composite — portfolio seed, objective create, market event (`autoRestore: false`), restore plan, manual restore |
|
|
430
|
+
| Returns | Three-beat `DriftRestoreFlow` — aligned → drift → restored |
|
|
431
|
+
| Use | drift → detection → restore teaching demo |
|
|
432
|
+
|
|
433
|
+
### `getDriftRestoreFlow(objectiveId?)`
|
|
434
|
+
|
|
435
|
+
```ts
|
|
436
|
+
async getDriftRestoreFlow(objectiveId?: string): Promise<DriftRestoreFlow[]>
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
| | |
|
|
440
|
+
|--|--|
|
|
441
|
+
| Auth | Required |
|
|
442
|
+
| HTTP | Composite — objectives + health + allocation + executions (+ restore plan when off-plan) |
|
|
443
|
+
| Returns | Inferred drift-restore flows for active objectives |
|
|
444
|
+
|
|
445
|
+
Helpers `buildDriftRestoreFlow()`, `buildDriftRestoreFlowFromSnapshot()`, and `inferDriftPhase()` are exported. See `pnpm example:drift-detect-restore`.
|
|
446
|
+
|
|
447
|
+
### `runReceiptVerificationDemo()`
|
|
448
|
+
|
|
449
|
+
```ts
|
|
450
|
+
async runReceiptVerificationDemo(): Promise<ReceiptVerificationFlow>
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
| | |
|
|
454
|
+
|--|--|
|
|
455
|
+
| Auth | Required |
|
|
456
|
+
| HTTP | Composite — `runDriftRestoreDemo()` + local validation + settlement lookup + timeline |
|
|
457
|
+
| Returns | Three-beat `ReceiptVerificationFlow` — claim → validate → verify |
|
|
458
|
+
| Use | receipt → verification teaching demo |
|
|
459
|
+
|
|
460
|
+
### `getReceiptVerificationFlow(executionId?)`
|
|
461
|
+
|
|
462
|
+
```ts
|
|
463
|
+
async getReceiptVerificationFlow(executionId?: string): Promise<ReceiptVerificationFlow[]>
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
| | |
|
|
467
|
+
|--|--|
|
|
468
|
+
| Auth | Required |
|
|
469
|
+
| HTTP | Composite — executions + validation + settlement + timeline |
|
|
470
|
+
| Returns | Verification flows for recent or specified execution(s) |
|
|
471
|
+
|
|
472
|
+
Helpers `buildReceiptVerificationFlow()`, `inferProofTier()`, and `validateExecutionReceipt()` are exported. See `pnpm example:receipt-verification`.
|
|
473
|
+
|
|
474
|
+
### `runPortfolioWatchDemo(input?)`
|
|
475
|
+
|
|
476
|
+
```ts
|
|
477
|
+
async runPortfolioWatchDemo(input?: {
|
|
478
|
+
brief?: string;
|
|
479
|
+
host?: "cursor" | "claude" | "mcp";
|
|
480
|
+
}): Promise<PortfolioWatchFlow>
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
| | |
|
|
484
|
+
|--|--|
|
|
485
|
+
| Auth | Required |
|
|
486
|
+
| HTTP | Composite — `applyFinancialIntent` + market event (`autoRestore: true`) + timeline |
|
|
487
|
+
| Returns | Portfolio watch flow — register → while away → return briefing |
|
|
488
|
+
| Use | agent-in-host demo |
|
|
489
|
+
|
|
490
|
+
### `getPortfolioWatchFlow(input?)`
|
|
491
|
+
|
|
492
|
+
```ts
|
|
493
|
+
async getPortfolioWatchFlow(input?: {
|
|
494
|
+
objectiveId?: string;
|
|
495
|
+
brief?: string;
|
|
496
|
+
host?: "cursor" | "claude" | "mcp";
|
|
497
|
+
}): Promise<PortfolioWatchFlow[]>
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
| | |
|
|
501
|
+
|--|--|
|
|
502
|
+
| Auth | Required |
|
|
503
|
+
| HTTP | Composite — Automatic objectives + health + allocation + timeline |
|
|
504
|
+
| Returns | Read-only briefing for active Automatic objectives |
|
|
505
|
+
|
|
506
|
+
Helpers `buildPortfolioWatchFlow()`, `DEFAULT_PORTFOLIO_WATCH_BRIEF`, and `inferPortfolioWatchPhase()` are exported. See `pnpm example:portfolio-watch`.
|
|
507
|
+
|
|
508
|
+
### `runFullAureonLoopDemo(input?)`
|
|
509
|
+
|
|
510
|
+
```ts
|
|
511
|
+
async runFullAureonLoopDemo(input?: {
|
|
512
|
+
brief?: string;
|
|
513
|
+
}): Promise<FullAureonLoopFlow>
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
| | |
|
|
517
|
+
|--|--|
|
|
518
|
+
| Auth | Required |
|
|
519
|
+
| HTTP | Composite — intent + allocation paradox + restore (`autoRestore: false`) + receipt verification |
|
|
520
|
+
| Returns | Full loop — intent → plan check → restore → verify |
|
|
521
|
+
| Use | Content Arc — full AUREON loop positioning demo |
|
|
522
|
+
|
|
523
|
+
### `getFullAureonLoopFlow(input?)`
|
|
524
|
+
|
|
525
|
+
```ts
|
|
526
|
+
async getFullAureonLoopFlow(input?: {
|
|
527
|
+
objectiveId?: string;
|
|
528
|
+
brief?: string;
|
|
529
|
+
}): Promise<FullAureonLoopFlow[]>
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
| | |
|
|
533
|
+
|--|--|
|
|
534
|
+
| Auth | Required |
|
|
535
|
+
| HTTP | Composite — objectives + allocation + latest receipt + validation |
|
|
536
|
+
| Returns | Read-only full-loop flows for active objectives with receipts |
|
|
537
|
+
|
|
538
|
+
Helpers `buildFullAureonLoopFlow()`, `DEFAULT_FULL_LOOP_BRIEF`, and `inferFullAureonLoopPhase()` are exported. See `pnpm example:full-aureon-loop`.
|
|
539
|
+
|
|
368
540
|
---
|
|
369
541
|
|
|
370
542
|
## 6. Vault
|
|
@@ -478,7 +650,7 @@ async applyMarketEvent(input: ApplyMarketEventInput): Promise<{
|
|
|
478
650
|
|--|--|
|
|
479
651
|
| Auth | Required |
|
|
480
652
|
| HTTP | `POST /market/events` |
|
|
481
|
-
| Normalization | Uppercases symbol; `autoRestore` defaults **
|
|
653
|
+
| Normalization | Uppercases symbol; `autoRestore` defaults **false** (must opt in to restore) |
|
|
482
654
|
| Validation | Symbol required; finite `priceChangeRatio`; rejects extreme ≤ -0.95 |
|
|
483
655
|
|
|
484
656
|
### `getRestorePlan(objectiveId)`
|
|
@@ -578,6 +750,17 @@ session.clear();
|
|
|
578
750
|
| `syncPortfolio` | POST | `/portfolio/sync` | **yes** |
|
|
579
751
|
| `refreshWatchdog` | POST | `/watchdog/refresh` | **yes** |
|
|
580
752
|
| `getOverview` | GET | `/overview` | **yes** |
|
|
753
|
+
| `getAllocationVsTarget` | composite | overview + objectives + health | **yes** |
|
|
754
|
+
| `applyFinancialIntent` | composite | create objective + health + portfolio | **yes** |
|
|
755
|
+
| `getObjectivePortfolioFlow` | composite | objectives + health + portfolio | **yes** |
|
|
756
|
+
| `runDriftRestoreDemo` | composite | seed + drift + manual restore | **yes** |
|
|
757
|
+
| `getDriftRestoreFlow` | composite | objectives + health + allocation + executions | **yes** |
|
|
758
|
+
| `runReceiptVerificationDemo` | composite | drift-restore + validate + settlement | **yes** |
|
|
759
|
+
| `getReceiptVerificationFlow` | composite | executions + validation + settlement | **yes** |
|
|
760
|
+
| `runPortfolioWatchDemo` | composite | intent + auto-restore market event + briefing | **yes** |
|
|
761
|
+
| `getPortfolioWatchFlow` | composite | Automatic objectives + health + timeline | **yes** |
|
|
762
|
+
| `runFullAureonLoopDemo` | composite | intent + plan paradox + restore + verify | **yes** |
|
|
763
|
+
| `getFullAureonLoopFlow` | composite | objectives + allocation + receipt validation | **yes** |
|
|
581
764
|
| `listMarketPresets` | GET | `/market/presets` | **yes** |
|
|
582
765
|
| `applyMarketEvent` | POST | `/market/events` | **yes** |
|
|
583
766
|
| `getRestorePlan` | GET | `/objectives/:id/restore-plan` | **yes** |
|
package/docs/data-contracts.md
CHANGED
|
@@ -402,14 +402,84 @@ export interface ExecutionReceipt {
|
|
|
402
402
|
result: string;
|
|
403
403
|
createdAt: string;
|
|
404
404
|
confirmedAt: string | null;
|
|
405
|
-
/**
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
405
|
+
/** Required. vault = on-chain keeper path; staged = capital-book update only. */
|
|
406
|
+
settlement: "staged" | "vault";
|
|
407
|
+
/** Block explorer link when vault tx is confirmed (`0x…`); null for staged. */
|
|
408
|
+
explorerUrl?: string | null;
|
|
409
|
+
/** Present when the objective is registered on ObjectiveRegistry. */
|
|
410
|
+
registryRef?: RegistryRef;
|
|
411
|
+
/** True when a settlement record exists for this execution (vault only). */
|
|
412
|
+
verifiedOnChain?: boolean;
|
|
413
|
+
/** Populated when `verifiedOnChain` is true. */
|
|
414
|
+
settlementRecord?: SettlementRecord;
|
|
410
415
|
}
|
|
411
416
|
```
|
|
412
417
|
|
|
418
|
+
### SettlementRecord (Day 8)
|
|
419
|
+
|
|
420
|
+
Independent on-chain proof from AureonVault `Rebalanced` events:
|
|
421
|
+
|
|
422
|
+
```ts
|
|
423
|
+
export interface SettlementRecord {
|
|
424
|
+
id: string;
|
|
425
|
+
executionId: string | null;
|
|
426
|
+
objectiveId: string | null;
|
|
427
|
+
walletAddress: string;
|
|
428
|
+
settlement: "vault";
|
|
429
|
+
transactionHash: string;
|
|
430
|
+
blockNumber: number;
|
|
431
|
+
logIndex: number;
|
|
432
|
+
vaultAddress: string;
|
|
433
|
+
tokenSell: string;
|
|
434
|
+
tokenBuy: string;
|
|
435
|
+
amountIn: string;
|
|
436
|
+
amountOut: string;
|
|
437
|
+
explorerUrl: string;
|
|
438
|
+
verifiedAt: string;
|
|
439
|
+
status: "confirmed" | "orphan";
|
|
440
|
+
registryRef?: RegistryRef;
|
|
441
|
+
}
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
Client methods: `getExecutionSettlement`, `listSettlements`, `confirmExecutionSettlement`.
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## 6.1 Receipt validation (Day 9)
|
|
449
|
+
|
|
450
|
+
Validate receipts locally before trusting them in automation:
|
|
451
|
+
|
|
452
|
+
```ts
|
|
453
|
+
import {
|
|
454
|
+
validateExecutionReceipt,
|
|
455
|
+
assertValidExecutionReceipt,
|
|
456
|
+
} from "@buildaureon/sdk";
|
|
457
|
+
|
|
458
|
+
const result = validateExecutionReceipt(receipt);
|
|
459
|
+
if (!result.valid) {
|
|
460
|
+
console.error(result.issues);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
assertValidExecutionReceipt(receipt); // throws AureonValidationError
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
`ReceiptValidationResult`:
|
|
467
|
+
|
|
468
|
+
```ts
|
|
469
|
+
export type ReceiptValidationIssue = {
|
|
470
|
+
code: string;
|
|
471
|
+
message: string;
|
|
472
|
+
path?: string;
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
export type ReceiptValidationResult = {
|
|
476
|
+
valid: boolean;
|
|
477
|
+
issues: ReceiptValidationIssue[];
|
|
478
|
+
};
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
Enforces required fields, `vault` vs `staged` honesty, explorer rules, and `verifiedOnChain` / `settlementRecord` consistency. See [receipt-validation.md](./receipt-validation.md).
|
|
482
|
+
|
|
413
483
|
#### JSON Representation Example
|
|
414
484
|
```json
|
|
415
485
|
{
|
|
@@ -422,7 +492,12 @@ export interface ExecutionReceipt {
|
|
|
422
492
|
"result": "Exchanged stock tokens for 3750.0 USDG on Robinhood Chain",
|
|
423
493
|
"createdAt": "2026-07-15T22:46:00.000Z",
|
|
424
494
|
"confirmedAt": "2026-07-15T22:46:05.000Z",
|
|
425
|
-
"settlement": "vault"
|
|
495
|
+
"settlement": "vault",
|
|
496
|
+
"explorerUrl": "https://explorer.testnet.chain.robinhood.com/tx/0xe295c2763f0d4681a8b54dfd38a0f8bfd21051515fcd9185a494ff3c8a99478f",
|
|
497
|
+
"registryRef": {
|
|
498
|
+
"objectiveKey": "0xabc…",
|
|
499
|
+
"contractAddress": "0x76d8f088d2abba3c73ff93f92308f8b59b250ea5"
|
|
500
|
+
}
|
|
426
501
|
}
|
|
427
502
|
```
|
|
428
503
|
|
package/docs/error-model.md
CHANGED
|
@@ -134,7 +134,7 @@ flowchart TD
|
|
|
134
134
|
| --- | --- |
|
|
135
135
|
| Invalid / paused key | Stop loop; operator rotates Developers key |
|
|
136
136
|
| Bootstrap key alone | Switch to issued key |
|
|
137
|
-
| Vault empty on restore |
|
|
137
|
+
| Vault empty on restore | Expected first use. Call `prepareVaultDeposit`, return unsigned steps, wait for the **user/host** to broadcast. Agents do not fund the vault. |
|
|
138
138
|
| Locked field on update | Recreate objective |
|
|
139
139
|
| Conflict mid-restore | Back off; read timeline / executions |
|
|
140
140
|
| Staged settlement returned | Do not treat as on-chain success |
|
|
@@ -186,7 +186,7 @@ import {
|
|
|
186
186
|
|
|
187
187
|
test("empty objective name fails validation", async () => {
|
|
188
188
|
const client = createAureonClient({
|
|
189
|
-
|
|
189
|
+
network: "testnet",
|
|
190
190
|
apiKey: "test",
|
|
191
191
|
});
|
|
192
192
|
|
|
@@ -11,8 +11,11 @@ Integrate `@buildaureon/sdk` into server-side agents and automated rebalancing l
|
|
|
11
11
|
```mermaid
|
|
12
12
|
flowchart TD
|
|
13
13
|
Init[1_issued_API_key_client] --> Sync[2_sync_Capital_Book]
|
|
14
|
-
Sync -->
|
|
15
|
-
|
|
14
|
+
Sync --> Empty{vault empty?}
|
|
15
|
+
Empty -->|yes| FourOhNine[restore 409]
|
|
16
|
+
FourOhNine --> Prep[prepareVaultDeposit unsigned]
|
|
17
|
+
Prep --> User[user/host signs when they use it]
|
|
18
|
+
Empty -->|no| Obj[create Auto objective]
|
|
16
19
|
Obj --> Loop[5_watchdog_heartbeat]
|
|
17
20
|
Loop -->|breach| Plan[6_restore_plan]
|
|
18
21
|
Plan --> Restore[7_restoreObjective]
|
|
@@ -22,10 +25,12 @@ flowchart TD
|
|
|
22
25
|
### Step 1 — Client
|
|
23
26
|
|
|
24
27
|
```ts
|
|
25
|
-
import { createAureonClient } from "@buildaureon/sdk";
|
|
28
|
+
import { createAureonClient, resolveAureonNetworkFromEnv } from "@buildaureon/sdk";
|
|
26
29
|
|
|
30
|
+
const resolved = resolveAureonNetworkFromEnv();
|
|
27
31
|
export const aureon = createAureonClient({
|
|
28
|
-
|
|
32
|
+
network: resolved.network,
|
|
33
|
+
baseUrl: resolved.baseUrl,
|
|
29
34
|
apiKey: process.env.AUREON_API_KEY!, // issued Developers key
|
|
30
35
|
timeoutMs: 30_000,
|
|
31
36
|
maxRetries: 2,
|
|
@@ -39,11 +44,17 @@ console.log("operating as", me.walletAddress);
|
|
|
39
44
|
Optional Bearer (usually unnecessary with an issued key):
|
|
40
45
|
|
|
41
46
|
```ts
|
|
42
|
-
import {
|
|
47
|
+
import {
|
|
48
|
+
createAureonClient,
|
|
49
|
+
createSessionTokenProvider,
|
|
50
|
+
resolveAureonNetworkFromEnv,
|
|
51
|
+
} from "@buildaureon/sdk";
|
|
43
52
|
|
|
53
|
+
const resolved = resolveAureonNetworkFromEnv();
|
|
44
54
|
const session = createSessionTokenProvider(process.env.AUREON_TOKEN ?? null);
|
|
45
55
|
export const aureon = createAureonClient({
|
|
46
|
-
|
|
56
|
+
network: resolved.network,
|
|
57
|
+
baseUrl: resolved.baseUrl,
|
|
47
58
|
apiKey: process.env.AUREON_API_KEY ?? null,
|
|
48
59
|
getAccessToken: session.getAccessToken,
|
|
49
60
|
});
|
|
@@ -62,28 +73,19 @@ console.log({
|
|
|
62
73
|
|
|
63
74
|
Prefer `syncPortfolio()` over hand-seeded books in production. Use `setPortfolio` only for controlled rehearsals.
|
|
64
75
|
|
|
65
|
-
### Step 3 —
|
|
76
|
+
### Step 3 — Empty vault is first use (do not fund for the user)
|
|
66
77
|
|
|
67
|
-
Automatic
|
|
78
|
+
Automatic restore on an empty vault must **409**. That is the same path as testnet. The SDK/MCP process does **not** broadcast a deposit. When the user actually uses the product, their host wallet signs `prepareVaultDeposit` steps.
|
|
68
79
|
|
|
69
80
|
```ts
|
|
70
81
|
import type { VaultPrepareResult } from "@buildaureon/sdk";
|
|
71
82
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (!status.empty && status.canRestore) return status;
|
|
79
|
-
|
|
80
|
-
const prep = await aureon.prepareVaultDeposit({ symbol, amount });
|
|
81
|
-
for (const step of prep.steps) {
|
|
82
|
-
const hash = await broadcast(step);
|
|
83
|
-
console.log(step.label, hash);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return aureon.getVaultStatus();
|
|
83
|
+
const status = await aureon.getVaultStatus();
|
|
84
|
+
if (status.empty) {
|
|
85
|
+
// restoreObjective must 409 here — do not treat that as a bug
|
|
86
|
+
const prep = await aureon.prepareVaultDeposit({ symbol: "USDG", amount: "0.05" });
|
|
87
|
+
// prep.steps are UNSIGNED. Return them. The user broadcasts when they fund.
|
|
88
|
+
return prep;
|
|
87
89
|
}
|
|
88
90
|
```
|
|
89
91
|
|
|
@@ -163,7 +165,147 @@ Start with one Automatic `balanced_portfolio` objective and a funded vault befor
|
|
|
163
165
|
|
|
164
166
|
---
|
|
165
167
|
|
|
166
|
-
##
|
|
168
|
+
## 2b. Green vs plan paradox demo (Update 2)
|
|
169
|
+
|
|
170
|
+
Most dashboards celebrate green PnL. AUREON separates book performance from plan adherence:
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
// Baseline
|
|
174
|
+
const before = await aureon.getAllocationVsTarget();
|
|
175
|
+
console.log(before.rows); // current vs target per objective
|
|
176
|
+
|
|
177
|
+
// Controlled shock — keep violation visible
|
|
178
|
+
await aureon.applyMarketEvent({
|
|
179
|
+
symbol: "NVDA",
|
|
180
|
+
priceChangeRatio: 0.45,
|
|
181
|
+
autoRestore: false,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const after = await aureon.getAllocationVsTarget();
|
|
185
|
+
console.log(after.paradox.message);
|
|
186
|
+
// "Book is up (5.0%), but 1 objective is off-plan."
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Run the full script: `pnpm example:green-vs-plan` (requires `AUREON_API_KEY`).
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 2c. AI → objective → portfolio (Update 3)
|
|
194
|
+
|
|
195
|
+
Most AI agents can transact but forget what the user wanted. AUREON registers intent as a persistent objective, then reads the portfolio through that policy:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
const flow = await aureon.applyFinancialIntent({
|
|
199
|
+
brief: "Keep about 20% of the portfolio in stable assets",
|
|
200
|
+
kind: "stable_allocation",
|
|
201
|
+
targetWeight: 0.2,
|
|
202
|
+
tolerance: 0.02,
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
console.log(flow.intent.policySummary);
|
|
206
|
+
console.log(flow.objective.id);
|
|
207
|
+
console.log(flow.health?.state);
|
|
208
|
+
console.log(flow.message);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
For demos, `parseFinancialIntent(brief)` converts a user sentence into structured fields (rule-based, not production NLU).
|
|
212
|
+
|
|
213
|
+
Run the full script: `pnpm example:ai-to-objective-to-portfolio`.
|
|
214
|
+
|
|
215
|
+
Then use `getAllocationVsTarget()` (Update 2) to compare objective vs actual over time.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 2d. Drift → detection → restore (Update 4)
|
|
220
|
+
|
|
221
|
+
Update 2 stops at the paradox — book up, plan off-target, no restore. Update 4 closes the loop:
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
const flow = await aureon.runDriftRestoreDemo();
|
|
225
|
+
|
|
226
|
+
console.log(flow.rule.summary);
|
|
227
|
+
console.log(flow.phases.aligned.health.state);
|
|
228
|
+
console.log(flow.phases.drift.health.state);
|
|
229
|
+
console.log(flow.phases.restored?.receipt?.settlement);
|
|
230
|
+
console.log(flow.message);
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
For read-only monitoring without mutating the book, use `getDriftRestoreFlow()` — it joins objectives, health, allocation rows, restore plans (when off-plan), and the latest execution receipt.
|
|
234
|
+
|
|
235
|
+
Run the full script: `pnpm example:drift-detect-restore`.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## 2e. Receipt → verification (Update 5)
|
|
240
|
+
|
|
241
|
+
Update 4 returns a receipt after restore. Update 5 teaches that **"transaction successful" is a claim**, not proof:
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
const flow = await aureon.runReceiptVerificationDemo();
|
|
245
|
+
|
|
246
|
+
console.log(flow.phases.claimed.result);
|
|
247
|
+
console.log(flow.phases.validation.valid);
|
|
248
|
+
console.log(flow.proofTier);
|
|
249
|
+
console.log(flow.phases.settlement?.verifiedOnChain);
|
|
250
|
+
console.log(flow.message);
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Proof tiers: **claim_only** (validation failed) → **schema_valid** (honest receipt shape) → **chain_verified** (independent settlement record for vault).
|
|
254
|
+
|
|
255
|
+
For read-only checks on existing executions, use `getReceiptVerificationFlow(executionId?)`.
|
|
256
|
+
|
|
257
|
+
Run the full script: `pnpm example:receipt-verification`.
|
|
258
|
+
|
|
259
|
+
Forward link: Update 6 — Claude/Cursor + AUREON agent-in-host demo.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 2f. Portfolio watch while away (Update 6)
|
|
264
|
+
|
|
265
|
+
Consumer hook: *“Imagine telling your AI: watch my portfolio while I'm away.”*
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
const flow = await aureon.runPortfolioWatchDemo({ host: "cursor" });
|
|
269
|
+
|
|
270
|
+
console.log(flow.userBrief);
|
|
271
|
+
console.log(flow.phases.register.automationMode);
|
|
272
|
+
console.log(flow.phases.whileAway?.autoRestored);
|
|
273
|
+
for (const line of flow.phases.briefing.summaryLines) {
|
|
274
|
+
console.log(line);
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Update 4 uses `autoRestore: false` (manual restore demo). Update 6 uses **`autoRestore: true`** — Automatic mode acts while the operator is away.
|
|
279
|
+
|
|
280
|
+
For read-only briefing on existing Automatic objectives: `getPortfolioWatchFlow()`.
|
|
281
|
+
|
|
282
|
+
Run the full script: `pnpm example:portfolio-watch`.
|
|
283
|
+
|
|
284
|
+
Forward link: Update 7 — full AUREON loop.
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## 2g. Full AUREON loop (Update 7)
|
|
289
|
+
|
|
290
|
+
Positioning hook: *"We're not building another portfolio tracker."*
|
|
291
|
+
|
|
292
|
+
```ts
|
|
293
|
+
const flow = await aureon.runFullAureonLoopDemo();
|
|
294
|
+
|
|
295
|
+
console.log(flow.phases.intent.policySummary);
|
|
296
|
+
console.log(flow.phases.planCheck.afterShock.paradox.detected);
|
|
297
|
+
console.log(flow.phases.driftRestore.settlement);
|
|
298
|
+
console.log(flow.phases.verification.proofTier);
|
|
299
|
+
console.log(flow.message);
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
One composite closes the content arc: **intent → plan check → restore → receipt verification**. A tracker stops at marks; AUREON registers policy, exposes green-vs-plan failure (`autoRestore: false`), restores, then validates the receipt.
|
|
303
|
+
|
|
304
|
+
For read-only joins on existing objectives with receipts: `getFullAureonLoopFlow()`.
|
|
305
|
+
|
|
306
|
+
Run the full script: `pnpm example:full-aureon-loop`.
|
|
307
|
+
|
|
308
|
+
---
|
|
167
309
|
|
|
168
310
|
### PM2
|
|
169
311
|
|
|
@@ -177,7 +319,8 @@ module.exports = {
|
|
|
177
319
|
autorestart: true,
|
|
178
320
|
env: {
|
|
179
321
|
NODE_ENV: "production",
|
|
180
|
-
AUREON_API_URL
|
|
322
|
+
// omit AUREON_API_URL for local mainnet 8788 / 4663
|
|
323
|
+
// AUREON_NETWORK: "testnet" // public host, still 46630
|
|
181
324
|
// AUREON_API_KEY from secret store / PM2 ecosystem secrets
|
|
182
325
|
},
|
|
183
326
|
},
|
|
@@ -240,7 +383,7 @@ Never log API keys, Bearer tokens, or private keys.
|
|
|
240
383
|
| --- | --- | --- |
|
|
241
384
|
| 401 invalid key | Wrong / paused / revoked key | Rotate in Developers |
|
|
242
385
|
| 401 need issued key | Env bootstrap key alone | Use an issued Developers key |
|
|
243
|
-
| Vault empty / cannot restore |
|
|
386
|
+
| Vault empty / cannot restore | First use — no user deposit yet | `prepareVaultDeposit` (unsigned). User/host broadcasts when they fund. Agents do not. |
|
|
244
387
|
| Update rejects symbol/mode | Locked at create | Recreate objective |
|
|
245
388
|
| Restore receipt `staged` | Ledger-local path | Do not claim on-chain |
|
|
246
389
|
| Health still violated after restore | Prices / sizing / liquidity | Re-read plan, vault balances, timeline |
|