@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.
@@ -1,20 +1,16 @@
1
1
  /**
2
- * @fileoverview Live SDK e2e against local AUREON API + Robinhood testnet vault.
2
+ * @fileoverview Live vault deposit/withdraw + Automatic objective against the AUREON API.
3
3
  *
4
- * Exercises: wallet auth sync vault prepare deposit/withdraw (signed)
5
- * createObjective (Automatic) → restore plan.
4
+ * Env (integrators only no local repo files):
5
+ * AUREON_API_KEY issued developer key (required)
6
+ * AUREON_API_URL optional (default https://api.aureonlabs.network)
7
+ * AUREON_WALLET_PRIVATE_KEY 0x… key used to sign auth + broadcast vault txs (required)
8
+ * AUREON_RPC_URL optional (default Robinhood testnet RPC)
9
+ * AUREON_CHAIN_ID optional (default 46630)
6
10
  *
7
- * Env (loaded from backend/.env + .secrets automatically when unset):
8
- * AUREON_API_URL default http://127.0.0.1:8787
9
- * AUREON_API_KEY from backend/.env AUREON_API_KEYS (first key)
10
- * AUREON_E2E_KEY hex private key (defaults to vault-deployer.key)
11
- *
12
- * pnpm --filter @buildaureon/sdk exec tsx examples/e2e-vault-flow/main.ts
11
+ * pnpm --filter @buildaureon/sdk example:e2e
13
12
  */
14
13
 
15
- import { readFileSync, existsSync } from "node:fs";
16
- import { dirname, join } from "node:path";
17
- import { fileURLToPath } from "node:url";
18
14
  import {
19
15
  createPublicClient,
20
16
  createWalletClient,
@@ -25,48 +21,22 @@ import { privateKeyToAccount } from "viem/accounts";
25
21
  import {
26
22
  createAureonClient,
27
23
  createSessionTokenProvider,
24
+ DEFAULT_API_BASE_URL,
28
25
  isAureonError,
29
- LOCAL_API_BASE_URL,
30
26
  } from "../../src/index.js";
31
27
 
32
- const __dirname = dirname(fileURLToPath(import.meta.url));
33
- const ROOT = join(__dirname, "../../..");
34
- const BACKEND = join(ROOT, "backend");
35
-
36
- function loadDotEnv(path: string): Record<string, string> {
37
- if (!existsSync(path)) return {};
38
- const out: Record<string, string> = {};
39
- for (const line of readFileSync(path, "utf8").split(/\r?\n/)) {
40
- const trimmed = line.trim();
41
- if (!trimmed || trimmed.startsWith("#")) continue;
42
- const i = trimmed.indexOf("=");
43
- if (i < 0) continue;
44
- out[trimmed.slice(0, i)] = trimmed.slice(i + 1).trim();
45
- }
46
- return out;
47
- }
48
-
49
- function firstApiKey(raw: string | undefined): string | null {
50
- if (!raw) return null;
51
- const key = raw.split(",")[0]?.trim();
52
- return key || null;
28
+ function requireEnv(name: string): string {
29
+ const value = process.env[name]?.trim();
30
+ if (!value) throw new Error(`Set ${name}`);
31
+ return value;
53
32
  }
54
33
 
55
34
  function loadPrivateKey(): Hex {
56
- if (process.env.AUREON_E2E_KEY?.startsWith("0x")) {
57
- return process.env.AUREON_E2E_KEY as Hex;
35
+ const key = requireEnv("AUREON_WALLET_PRIVATE_KEY");
36
+ if (!/^0x[0-9a-fA-F]{64}$/.test(key)) {
37
+ throw new Error("AUREON_WALLET_PRIVATE_KEY must be a 0x-prefixed 32-byte hex key");
58
38
  }
59
- const fromEnv = loadDotEnv(join(BACKEND, ".env")).AUREON_VAULT_DEPLOYER_KEY;
60
- if (fromEnv?.startsWith("0x")) return fromEnv as Hex;
61
- const keyPath = join(BACKEND, ".secrets/vault-deployer.key");
62
- if (!existsSync(keyPath)) {
63
- throw new Error("Missing AUREON_E2E_KEY / vault-deployer.key");
64
- }
65
- const hex = readFileSync(keyPath, "utf8").trim();
66
- if (!/^0x[0-9a-fA-F]{64}$/.test(hex)) {
67
- throw new Error("vault-deployer.key must be a 32-byte hex private key");
68
- }
69
- return hex as Hex;
39
+ return key as Hex;
70
40
  }
71
41
 
72
42
  function log(step: string, data?: unknown): void {
@@ -78,15 +48,12 @@ function log(step: string, data?: unknown): void {
78
48
  }
79
49
 
80
50
  async function main(): Promise<void> {
81
- const env = loadDotEnv(join(BACKEND, ".env"));
82
- const baseUrl =
83
- process.env.AUREON_API_URL ?? env.AUREON_API_URL ?? LOCAL_API_BASE_URL;
84
- const apiKey =
85
- process.env.AUREON_API_KEY ?? firstApiKey(env.AUREON_API_KEYS);
86
- const rpcUrl = env.AUREON_RPC_URL ?? "https://rpc.testnet.chain.robinhood.com";
87
- const chainId = Number(env.AUREON_CHAIN_ID ?? 46630);
88
-
89
- if (!apiKey) throw new Error("AUREON_API_KEY / AUREON_API_KEYS missing");
51
+ const baseUrl = process.env.AUREON_API_URL?.trim() || DEFAULT_API_BASE_URL;
52
+ const apiKey = requireEnv("AUREON_API_KEY");
53
+ const rpcUrl =
54
+ process.env.AUREON_RPC_URL?.trim() ||
55
+ "https://rpc.testnet.chain.robinhood.com";
56
+ const chainId = Number(process.env.AUREON_CHAIN_ID ?? 46630);
90
57
 
91
58
  const account = privateKeyToAccount(loadPrivateKey());
92
59
  const publicClient = createPublicClient({ transport: http(rpcUrl) });
@@ -94,6 +61,12 @@ async function main(): Promise<void> {
94
61
  account,
95
62
  transport: http(rpcUrl),
96
63
  });
64
+ const chain = {
65
+ id: chainId,
66
+ name: "Robinhood Chain Testnet",
67
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
68
+ rpcUrls: { default: { http: [rpcUrl] } },
69
+ } as const;
97
70
 
98
71
  const session = createSessionTokenProvider(null);
99
72
  const aureon = createAureonClient({
@@ -106,10 +79,7 @@ async function main(): Promise<void> {
106
79
  log("ping", ping);
107
80
 
108
81
  const { message } = await aureon.getAuthNonce(account.address);
109
- const signature = await walletClient.signMessage({
110
- account,
111
- message,
112
- });
82
+ const signature = await walletClient.signMessage({ account, message });
113
83
  const login = await aureon.verifyWallet({
114
84
  address: account.address,
115
85
  message,
@@ -118,11 +88,6 @@ async function main(): Promise<void> {
118
88
  session.setToken(login.token);
119
89
  log("auth", { wallet: login.walletAddress });
120
90
 
121
- const me = await aureon.me();
122
- if (me.walletAddress.toLowerCase() !== account.address.toLowerCase()) {
123
- throw new Error("session wallet mismatch");
124
- }
125
-
126
91
  const synced = await aureon.syncPortfolio();
127
92
  log("syncPortfolio", {
128
93
  chainId: synced.chainId,
@@ -162,12 +127,7 @@ async function main(): Promise<void> {
162
127
  for (const step of deposit.steps) {
163
128
  const hash = await walletClient.sendTransaction({
164
129
  account,
165
- chain: {
166
- id: chainId,
167
- name: "Robinhood Chain Testnet",
168
- nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
169
- rpcUrls: { default: { http: [rpcUrl] } },
170
- },
130
+ chain,
171
131
  to: step.to as `0x${string}`,
172
132
  data: step.data as Hex,
173
133
  value: BigInt(step.value),
@@ -185,19 +145,11 @@ async function main(): Promise<void> {
185
145
  throw new Error("expected vault WETH to increase after depositETH");
186
146
  }
187
147
 
188
- const withdrawAmount = "0.00005";
189
- const withdraw = await aureon.prepareVaultWithdraw({
190
- amount: withdrawAmount,
191
- });
148
+ const withdraw = await aureon.prepareVaultWithdraw({ amount: "0.00005" });
192
149
  for (const step of withdraw.steps) {
193
150
  const hash = await walletClient.sendTransaction({
194
151
  account,
195
- chain: {
196
- id: chainId,
197
- name: "Robinhood Chain Testnet",
198
- nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
199
- rpcUrls: { default: { http: [rpcUrl] } },
200
- },
152
+ chain,
201
153
  to: step.to as `0x${string}`,
202
154
  data: step.data as Hex,
203
155
  value: BigInt(step.value),
@@ -211,9 +163,6 @@ async function main(): Promise<void> {
211
163
  vaultAfterWithdraw.balances.find((b) => b.symbol.toUpperCase() === "WETH")
212
164
  ?.quantity ?? 0;
213
165
  log("vault after withdraw", { weth: wethAfterWithdraw });
214
- if (!(wethAfterWithdraw < wethAfterDeposit)) {
215
- throw new Error("expected vault WETH to decrease after withdraw");
216
- }
217
166
 
218
167
  await aureon.syncPortfolio();
219
168
 
@@ -228,12 +177,9 @@ async function main(): Promise<void> {
228
177
  log("createObjective", {
229
178
  id: objective.id,
230
179
  automationMode: objective.automationMode,
231
- summary: objective.policy.summary,
232
180
  });
233
181
  if (objective.automationMode !== "auto") {
234
- throw new Error(
235
- `SDK create must default to auto, got ${objective.automationMode}`
236
- );
182
+ throw new Error(`expected automationMode auto, got ${objective.automationMode}`);
237
183
  }
238
184
 
239
185
  const health = await aureon.getHealth(objective.id);
@@ -248,7 +194,7 @@ async function main(): Promise<void> {
248
194
  });
249
195
  } catch (err) {
250
196
  if (isAureonError(err)) {
251
- log("getRestorePlan (expected if already in band)", {
197
+ log("getRestorePlan (ok if already in band)", {
252
198
  code: err.code,
253
199
  message: err.message,
254
200
  });
@@ -257,7 +203,7 @@ async function main(): Promise<void> {
257
203
  }
258
204
  }
259
205
 
260
- console.log("\nE2E OK : vault up/down + Automatic objective via SDK");
206
+ console.log("\nE2E OK vault deposit/withdraw + Automatic objective");
261
207
  }
262
208
 
263
209
  main().catch((error) => {
@@ -1,28 +1,28 @@
1
1
  /**
2
- * @fileoverview Controlled market event example (simulation helper).
2
+ * @fileoverview Controlled market-event rehearsal against the live AUREON API.
3
3
  *
4
- * Env: AUREON_API_KEY, AUREON_TOKEN, optional AUREON_API_URL
4
+ * Env:
5
+ * AUREON_API_KEY issued developer key (required)
6
+ * AUREON_API_URL optional (default https://api.aureonlabs.network)
5
7
  *
6
8
  * pnpm --filter @buildaureon/sdk example:market
7
9
  */
8
10
 
9
11
  import {
10
12
  createAureonClient,
11
- createSessionTokenProvider,
12
13
  DEFAULT_API_BASE_URL,
13
14
  isAureonError,
14
15
  } from "../../src/index.js";
15
16
 
16
17
  async function main(): Promise<void> {
17
- const session = createSessionTokenProvider(process.env.AUREON_TOKEN ?? null);
18
- if (!session.getAccessToken()) {
19
- throw new Error("Set AUREON_TOKEN from a wallet verify session.");
18
+ const apiKey = process.env.AUREON_API_KEY?.trim();
19
+ if (!apiKey) {
20
+ throw new Error("Set AUREON_API_KEY to an issued developer key.");
20
21
  }
21
22
 
22
23
  const aureon = createAureonClient({
23
- baseUrl: process.env.AUREON_API_URL ?? DEFAULT_API_BASE_URL,
24
- apiKey: process.env.AUREON_API_KEY ?? null,
25
- getAccessToken: session.getAccessToken,
24
+ baseUrl: process.env.AUREON_API_URL?.trim() || DEFAULT_API_BASE_URL,
25
+ apiKey,
26
26
  });
27
27
 
28
28
  const objective = await aureon.createObjective({
@@ -1,39 +1,36 @@
1
1
  /**
2
- * @fileoverview Quickstart example for @buildaureon/sdk against the AUREON API.
2
+ * @fileoverview Quickstart control-plane calls with an issued developer API key.
3
3
  *
4
- * Env:
5
- * AUREON_API_KEY : product key (required on hosted API)
6
- * AUREON_TOKEN : wallet Bearer session
7
- * AUREON_API_URL : optional override (defaults to https://api.aureonlabs.network)
4
+ * Env (required for integrators — nothing else):
5
+ * AUREON_API_KEY issued key from https://app.aureonlabs.network Developers
6
+ * AUREON_API_URL optional (default https://api.aureonlabs.network)
8
7
  *
9
8
  * pnpm --filter @buildaureon/sdk example:quickstart
10
9
  */
11
10
 
12
11
  import {
13
12
  createAureonClient,
14
- createSessionTokenProvider,
15
13
  DEFAULT_API_BASE_URL,
16
14
  formatWeight,
17
15
  isAureonError,
18
16
  } from "../../src/index.js";
19
17
 
20
18
  async function main(): Promise<void> {
21
- const session = createSessionTokenProvider(process.env.AUREON_TOKEN ?? null);
19
+ const apiKey = process.env.AUREON_API_KEY?.trim();
20
+ if (!apiKey) {
21
+ throw new Error(
22
+ "Set AUREON_API_KEY to an issued developer key from the AUREON Developers page."
23
+ );
24
+ }
25
+
22
26
  const aureon = createAureonClient({
23
- baseUrl: process.env.AUREON_API_URL ?? DEFAULT_API_BASE_URL,
24
- apiKey: process.env.AUREON_API_KEY ?? null,
25
- getAccessToken: session.getAccessToken,
27
+ baseUrl: process.env.AUREON_API_URL?.trim() || DEFAULT_API_BASE_URL,
28
+ apiKey,
26
29
  });
27
30
 
28
31
  const ping = await aureon.ping();
29
32
  console.log("connected", ping);
30
33
 
31
- if (!session.getAccessToken()) {
32
- throw new Error(
33
- "Set AUREON_TOKEN from a wallet verify session (nonce → sign → verifyWallet)."
34
- );
35
- }
36
-
37
34
  const me = await aureon.me();
38
35
  console.log("wallet", me.walletAddress);
39
36
 
@@ -59,6 +56,10 @@ async function main(): Promise<void> {
59
56
  automationMode: o.automationMode,
60
57
  }))
61
58
  );
59
+
60
+ console.log(
61
+ "hint: private key is only needed later to broadcast prepare-deposit / prepare-withdraw steps"
62
+ );
62
63
  }
63
64
 
64
65
  main().catch((error) => {
@@ -0,0 +1,171 @@
1
+ /**
2
+ * @fileoverview Console demo of an Automatic SDK loop against the live API.
3
+ *
4
+ * Env:
5
+ * AUREON_API_KEY issued developer key (required)
6
+ * AUREON_API_URL optional (default https://api.aureonlabs.network)
7
+ *
8
+ * pnpm --filter @buildaureon/sdk example:sdk-demo-terminal
9
+ * pnpm --filter @buildaureon/sdk example:sdk-demo-terminal -- --create-only
10
+ */
11
+
12
+ import {
13
+ createAureonClient,
14
+ DEFAULT_API_BASE_URL,
15
+ formatWeight,
16
+ isAureonError,
17
+ type PortfolioPositionInput,
18
+ } from "../../src/index.js";
19
+
20
+ const CREATE_ONLY = process.argv.includes("--create-only");
21
+
22
+ const DEMO_POSITIONS: PortfolioPositionInput[] = [
23
+ {
24
+ symbol: "USDG",
25
+ name: "Paxos USDG",
26
+ category: "stable",
27
+ quantity: 24_000,
28
+ markPriceUsd: 1,
29
+ },
30
+ {
31
+ symbol: "NVDA",
32
+ name: "NVIDIA Stock Token",
33
+ category: "stock_token",
34
+ quantity: 45,
35
+ markPriceUsd: 920,
36
+ },
37
+ {
38
+ symbol: "AAPL",
39
+ name: "Apple Stock Token",
40
+ category: "stock_token",
41
+ quantity: 80,
42
+ markPriceUsd: 210,
43
+ },
44
+ {
45
+ symbol: "GOOGL",
46
+ name: "Alphabet Stock Token",
47
+ category: "stock_token",
48
+ quantity: 60,
49
+ markPriceUsd: 175,
50
+ },
51
+ {
52
+ symbol: "ETH",
53
+ name: "Ether",
54
+ category: "gas",
55
+ quantity: 8.5,
56
+ markPriceUsd: 3400,
57
+ },
58
+ ];
59
+
60
+ function shortHash(hash: string, head = 10, tail = 6): string {
61
+ if (hash.length <= head + tail + 1) return hash;
62
+ return `${hash.slice(0, head)}…${hash.slice(-tail)}`;
63
+ }
64
+
65
+ function line(kind: "cmd" | "out" | "err" | "meta", text: string): void {
66
+ const prefix =
67
+ kind === "cmd" ? "$ " : kind === "err" ? "! " : kind === "meta" ? "# " : " ";
68
+ console.log(`${prefix}${text}`);
69
+ }
70
+
71
+ async function main(): Promise<void> {
72
+ const apiKey = process.env.AUREON_API_KEY?.trim();
73
+ if (!apiKey) {
74
+ throw new Error("Set AUREON_API_KEY to an issued developer key.");
75
+ }
76
+
77
+ const baseUrl = process.env.AUREON_API_URL?.trim() || DEFAULT_API_BASE_URL;
78
+ line(
79
+ "meta",
80
+ CREATE_ONLY
81
+ ? `@buildaureon/sdk · create-only · ${baseUrl}`
82
+ : `@buildaureon/sdk · Automatic demo loop · ${baseUrl}`
83
+ );
84
+
85
+ const aureon = createAureonClient({ baseUrl, apiKey });
86
+
87
+ line("cmd", "aureon.ping()");
88
+ const ping = await aureon.ping();
89
+ line(
90
+ "out",
91
+ `connected ok=${String(ping.ok)} service=${ping.service} version=${ping.version}`
92
+ );
93
+
94
+ line("cmd", "aureon.me()");
95
+ const me = await aureon.me();
96
+ line("out", `me wallet=${me.walletAddress}`);
97
+
98
+ line("cmd", "aureon.setPortfolio(/* rehearsal book */)");
99
+ const book = await aureon.setPortfolio(DEMO_POSITIONS);
100
+ line(
101
+ "out",
102
+ `portfolio notional=${book.totalNotionalUsd.toFixed(0)} stable=${formatWeight(book.stableWeight)} positions=${book.positions.length}`
103
+ );
104
+
105
+ line(
106
+ "cmd",
107
+ 'aureon.createObjective({ kind: "stable_allocation", targetWeight: 0.2, … })'
108
+ );
109
+ const objective = await aureon.createObjective({
110
+ name: "Maintain 20% Stable Assets",
111
+ kind: "stable_allocation",
112
+ targetWeight: 0.2,
113
+ tolerance: 0.02,
114
+ priority: "high",
115
+ });
116
+ line(
117
+ "out",
118
+ `objective id=${objective.id} status=${objective.status} mode=${objective.automationMode}`
119
+ );
120
+
121
+ if (CREATE_ONLY) {
122
+ line("meta", "create-only complete");
123
+ return;
124
+ }
125
+
126
+ line(
127
+ "cmd",
128
+ 'aureon.applyMarketEvent({ symbol: "NVDA", priceChangeRatio: 0.45, autoRestore: true })'
129
+ );
130
+ const market = await aureon.applyMarketEvent({
131
+ name: "NVDA Stock Token Rally",
132
+ description: "Controlled mark appreciation on NVIDIA Stock Token",
133
+ symbol: "NVDA",
134
+ priceChangeRatio: 0.45,
135
+ autoRestore: true,
136
+ });
137
+ line(
138
+ "out",
139
+ `market event=${market.event.id} ${market.event.symbol} ${(market.event.priceChangeRatio * 100).toFixed(0)}%`
140
+ );
141
+
142
+ const executions =
143
+ market.executions.length > 0
144
+ ? market.executions
145
+ : await aureon.listExecutions(objective.id);
146
+ for (const receipt of executions) {
147
+ line(
148
+ "out",
149
+ `execution id=${receipt.id} status=${receipt.status} settlement=${receipt.settlement ?? "n/a"} hash=${shortHash(receipt.transactionHash)}`
150
+ );
151
+ }
152
+
153
+ const finalHealth = (await aureon.getHealth(objective.id))[0];
154
+ if (finalHealth) {
155
+ line(
156
+ "out",
157
+ `health state=${finalHealth.state} current=${formatWeight(finalHealth.currentMetric)} target=${formatWeight(finalHealth.targetMetric)}`
158
+ );
159
+ }
160
+
161
+ line("meta", "done — check settlement field before claiming on-chain");
162
+ }
163
+
164
+ main().catch((error) => {
165
+ if (isAureonError(error)) {
166
+ line("err", `${error.code}: ${error.message}`);
167
+ } else {
168
+ line("err", error instanceof Error ? error.message : String(error));
169
+ }
170
+ process.exitCode = 1;
171
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buildaureon/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Official TypeScript SDK for AUREON Financial Compass on Robinhood Chain",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -29,6 +29,7 @@
29
29
  "bench": "tsx benchmarks/client-throughput.ts",
30
30
  "example:quickstart": "tsx examples/quickstart/main.ts",
31
31
  "example:market": "tsx examples/market-event/main.ts",
32
+ "example:sdk-demo-terminal": "tsx examples/sdk-demo-terminal/main.ts",
32
33
  "example:e2e": "tsx examples/e2e-vault-flow/main.ts",
33
34
  "example:e2e-policy": "tsx examples/e2e-policy-rebalance/main.ts",
34
35
  "cli": "tsx cli/aureon-cli.ts",
@@ -47,18 +48,14 @@
47
48
  "url": "https://github.com/buildaureon/aureon-sdk"
48
49
  },
49
50
  "license": "MIT",
50
- "author": "AUREON Labs (https://github.com/buildaureon)",
51
- "publishConfig": {
52
- "access": "public"
53
- },
54
51
  "engines": {
55
52
  "node": ">=20"
56
53
  },
57
54
  "devDependencies": {
58
55
  "@types/node": "^22.13.10",
59
- "tsup": "^8.5.1",
60
- "tsx": "^4.23.1",
61
- "typescript": "^5.9.3",
56
+ "tsup": "^8.4.0",
57
+ "tsx": "^4.19.3",
58
+ "typescript": "^5.8.2",
62
59
  "viem": "^2.55.1"
63
60
  }
64
61
  }