@usearete/sdk 0.1.5 → 0.3.0

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.
Files changed (39) hide show
  1. package/README.md +331 -56
  2. package/dist/index.cjs +6664 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.ts +1521 -260
  5. package/dist/index.esm.js +4603 -1085
  6. package/dist/index.esm.js.map +1 -1
  7. package/dist/ssr/handlers.cjs +794 -0
  8. package/dist/ssr/handlers.cjs.map +1 -0
  9. package/dist/ssr/handlers.esm.js +523 -4
  10. package/dist/ssr/handlers.esm.js.map +1 -1
  11. package/dist/ssr/index.cjs +795 -0
  12. package/dist/ssr/index.cjs.map +1 -0
  13. package/dist/ssr/index.esm.js +523 -4
  14. package/dist/ssr/index.esm.js.map +1 -1
  15. package/dist/ssr/nextjs-app.cjs +859 -0
  16. package/dist/ssr/nextjs-app.cjs.map +1 -0
  17. package/dist/ssr/nextjs-app.esm.js +523 -4
  18. package/dist/ssr/nextjs-app.esm.js.map +1 -1
  19. package/dist/ssr/tanstack-start.cjs +881 -0
  20. package/dist/ssr/tanstack-start.cjs.map +1 -0
  21. package/dist/ssr/tanstack-start.esm.js +523 -4
  22. package/dist/ssr/tanstack-start.esm.js.map +1 -1
  23. package/dist/ssr/vite.cjs +887 -0
  24. package/dist/ssr/vite.cjs.map +1 -0
  25. package/dist/ssr/vite.esm.js +523 -4
  26. package/dist/ssr/vite.esm.js.map +1 -1
  27. package/package.json +10 -8
  28. package/dist/index.js +0 -3074
  29. package/dist/index.js.map +0 -1
  30. package/dist/ssr/handlers.js +0 -294
  31. package/dist/ssr/handlers.js.map +0 -1
  32. package/dist/ssr/index.js +0 -295
  33. package/dist/ssr/index.js.map +0 -1
  34. package/dist/ssr/nextjs-app.js +0 -359
  35. package/dist/ssr/nextjs-app.js.map +0 -1
  36. package/dist/ssr/tanstack-start.js +0 -381
  37. package/dist/ssr/tanstack-start.js.map +0 -1
  38. package/dist/ssr/vite.js +0 -387
  39. package/dist/ssr/vite.js.map +0 -1
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Arete TypeScript SDK
2
2
 
3
- Pure TypeScript SDK for the Arete Solana streaming platform. Framework-agnostic core with AsyncIterable-based streaming.
3
+ Pure TypeScript SDK for generated stack definitions, program SDKs, prepared operation execution, and chain reads.
4
+
5
+ Connected clients expose the typed six-route transaction relay as `client.transactions`. Wallet adapters receive it per invocation from `client.transaction` and `client.inspectOperation`, so a shared wallet can safely serve multiple clients. Sessions expose `session.transactions` and accept a `transactions` override. HTTP `u64` fields are decimal strings on the wire and `bigint` in the SDK; sends are never automatically retried.
4
6
 
5
7
  ## Installation
6
8
 
@@ -8,104 +10,377 @@ Pure TypeScript SDK for the Arete Solana streaming platform. Framework-agnostic
8
10
  npm install @usearete/sdk
9
11
  ```
10
12
 
11
- ## Usage
13
+ ## Quick Start
14
+
15
+ ```ts
16
+ import { createSession } from '@usearete/sdk';
17
+ import { MY_STACK } from './generated/my-stack';
18
+
19
+ const session = await createSession({
20
+ stacks: { myStack: MY_STACK },
21
+ });
22
+
23
+ for await (const item of session.stacks.myStack.views.MyEntity.list.use()) {
24
+ console.log(item);
25
+ }
26
+ ```
27
+
28
+ ## SDK Shapes
29
+
30
+ ### Mental Model
31
+
32
+ Think of a generated stack as a **cartridge**: it packages one domain's typed views, queries, programs, reads, and flows, plus any cross-program addresses, constants, defaults, or math. "Cartridge" is only a mental model; the public API continues to use the existing generated stack objects and types.
33
+
34
+ An Arete session is the **console**. Insert one or more generated stacks under `session.stacks`, optionally add standalone programs, and use the console's shared `session.programs`, `session.chain`, and `session.execute(...)` surfaces. Programs packaged by a stack are automatically promoted to `session.programs` without creating another connection or runtime.
35
+
36
+ Every semantic operation has an explicit cardinality:
37
+
38
+ - `instruction` - exactly one Solana instruction
39
+ - `transaction` - exactly one atomic transaction with one or more instructions
40
+ - `flow` - one or more sequential transactions
41
+
42
+ Every semantic operation exposes one pure entrypoint:
12
43
 
13
- ### Setup
44
+ - `.prepare(input)`
14
45
 
15
- ```typescript
16
- import { Arete } from '@usearete/sdk';
17
- import { SETTLEMENT_GAME_STACK } from './generated/settlement-game-stack';
46
+ Every connected client or session exposes one semantic execution entrypoint:
18
47
 
19
- const a4 = await Arete.connect('wss://mainnet.arete.xyz', {
20
- stack: SETTLEMENT_GAME_STACK,
48
+ - `.execute(prepared, options?)`
49
+
50
+ There is no semantic `.resolve()`, `.build()`, `.stage()`, `.plan()`, or `.send()` projection surface anymore.
51
+
52
+ ### Connected Stack Cartridges
53
+
54
+ Access a connected generated stack through `session.stacks.<name>`. Its stable namespaces are:
55
+
56
+ - `views` - typed streaming, list, and state views
57
+ - `queries` - stack-level HTTP queries
58
+ - `programs` - owner-scoped program SDKs; the same connected objects are promoted to `session.programs`
59
+ - `addresses` - domain address derivations, when defined
60
+ - `constants` - domain constants and enums, when defined
61
+ - `defaults` - reusable domain defaults, when defined
62
+ - `math` - pure domain calculations, when defined
63
+ - `read` - connected, domain-oriented reads, when defined
64
+ - `flows` - stack-level multi-transaction operations, when defined
65
+
66
+ These are namespaces on the existing connected stack object; no separate cartridge class or type is introduced.
67
+
68
+ ### Program SDKs
69
+
70
+ Each packaged, attached, or standalone program is canonically available under `session.programs.<name>` and exposes these stable namespaces. The owner-scoped `session.stacks.<name>.programs.<program>` path remains available when disambiguation is needed.
71
+
72
+ - `programId` - the deployed Solana program address
73
+ - `schemas` - generated validation schemas
74
+ - `pdas` - exact generated PDA definitions
75
+ - `addresses` - semantic address derivations, when defined
76
+ - `accounts` - typed point reads for program accounts
77
+ - `queries` - program-level HTTP queries
78
+ - `raw` - exact IDL instruction builders with synchronous `.build(...)`
79
+ - `instructions` - semantic one-instruction operations with `.prepare(...)`
80
+ - `transactions` - semantic one-transaction operations with `.prepare(...)`
81
+ - `flows` - program-local multi-transaction operations with `.prepare(...)`
82
+ - `constants` - program constants and enums
83
+ - `defaults` - reusable program defaults
84
+ - `math` - pure protocol calculations
85
+
86
+ ### Raw Instructions
87
+
88
+ Use raw handlers when you want exact wire control and will compose the transaction yourself:
89
+
90
+ ```ts
91
+ const ix = session.programs.splToken.raw.InitializeMint2.build({
92
+ mint,
93
+ decimals: 6,
94
+ mint_authority: authority,
95
+ freeze_authority: null,
21
96
  });
97
+
98
+ await session.transaction([ix]);
22
99
  ```
23
100
 
24
- ### Streaming with AsyncIterable
101
+ Raw builders are the exact IDL escape hatch. Instruction names, account names, argument names, and nested objects retain the generated IDL shape, including snake_case where the IDL uses it.
25
102
 
26
- ```typescript
27
- for await (const update of a4.views.settlementGame.list.watch()) {
28
- if (update.type === 'upsert') {
29
- console.log('Game updated:', update.key, update.data);
30
- } else if (update.type === 'delete') {
31
- console.log('Game deleted:', update.key);
103
+ ### Semantic Operations
104
+
105
+ Use semantic operations for normal application code. Their `.prepare(...)` methods accept semantic, camelCase object inputs, derive routine addresses, normalize amounts, and return prepared artifacts. Use `raw` only when you deliberately need the exact IDL surface.
106
+
107
+ Instruction example:
108
+
109
+ ```ts
110
+ const prepared = await session.programs.tokenMetadata.instructions.createMetadataAccountV3.prepare({
111
+ mint,
112
+ mintAuthority,
113
+ payer,
114
+ updateAuthority,
115
+ name,
116
+ symbol,
117
+ uri,
118
+ });
119
+
120
+ console.log(prepared.kind); // 'instruction'
121
+ console.log(prepared.instruction);
122
+ console.log(prepared.artifacts);
123
+
124
+ await session.execute(prepared);
125
+ ```
126
+
127
+ Transaction example:
128
+
129
+ ```ts
130
+ const prepared = await session.programs.cpAmm.transactions.swap.exactIn.prepare({
131
+ pool,
132
+ payer,
133
+ inputTokenMint,
134
+ amountIn: { ui: '1.25' },
135
+ minimumAmountOut: 1n,
136
+ });
137
+
138
+ console.log(prepared.kind); // 'transaction'
139
+ console.log(prepared.transaction.instructions.length);
140
+
141
+ await session.execute(prepared);
142
+ ```
143
+
144
+ Flow example:
145
+
146
+ ```ts
147
+ const prepared = await session.programs.presale.flows.escrow.depositPermissionless.prepare({
148
+ presale,
149
+ owner,
150
+ maxAmount: { ui: '1000' },
151
+ });
152
+
153
+ console.log(prepared.kind); // 'flow'
154
+ console.log(prepared.plan.transactions.length);
155
+
156
+ await session.execute(prepared);
157
+ ```
158
+
159
+ ### Prepared Shapes
160
+
161
+ Prepared values are immutable and discriminated:
162
+
163
+ - `PreparedInstruction`
164
+ - `PreparedTransaction`
165
+ - `PreparedFlow`
166
+
167
+ All prepared values include:
168
+
169
+ - `kind`
170
+ - `name`
171
+ - `artifacts`
172
+ - `plan.transactions`
173
+
174
+ Instruction values also include `.instruction`, and transaction values include `.transaction`.
175
+
176
+ Prepared instructions can be composed directly into a transaction without
177
+ extracting `.instruction`:
178
+
179
+ ```ts
180
+ const transaction = createPreparedTransaction({
181
+ name: 'configureMint',
182
+ instructions: [initializeMint, setAuthority],
183
+ artifacts: { mint },
184
+ });
185
+ ```
186
+
187
+ Prepared instructions and prepared transactions can also be flattened into one
188
+ atomic transaction without reaching into their transaction bodies:
189
+
190
+ ```ts
191
+ const transaction = createPreparedTransaction({
192
+ name: 'createAndConfigureMint',
193
+ operations: [createMint, createMetadata, setAuthority],
194
+ artifacts: { mint },
195
+ });
196
+ ```
197
+
198
+ Only single-transaction operations are accepted by `operations`. A
199
+ `PreparedFlow` must retain its ordered transaction boundaries.
200
+
201
+ Child signer and error metadata is inherited unless the transaction explicitly
202
+ provides `requiredSignerAddresses` or `errors`.
203
+
204
+ Every successful execution receipt exposes its signatures in transaction order:
205
+
206
+ ```ts
207
+ const receipt = await session.execute(prepared);
208
+ console.log(receipt.signatures);
209
+ ```
210
+
211
+ Instruction and transaction receipts contain one signature. Flow receipts
212
+ contain one signature for each executed transaction.
213
+
214
+ Use `describePreparedOperation(prepared)` for a typed, JSON-safe description, or
215
+ `formatPreparedOperation(prepared)` for human-readable text.
216
+
217
+ ```ts
218
+ const description = describePreparedOperation(prepared);
219
+ console.log(JSON.stringify(description, null, 2));
220
+ ```
221
+
222
+ ## Sessions
223
+
224
+ Use a session as the console for one or more generated stack cartridges and/or standalone programs behind one execution surface. Stack programs are promoted by reference; `session.programs.presale === session.stacks.presale.programs.presale`.
225
+
226
+ ```ts
227
+ import { createSession, createSignerRegistry } from '@usearete/sdk';
228
+
229
+ const signerRegistry = createSignerRegistry([
230
+ [creatorAddress, creatorSigner],
231
+ ]);
232
+
233
+ const session = await createSession(
234
+ {
235
+ stacks: {
236
+ squads: SQUADS_V4_STREAM_STACK,
237
+ presale: METEORA_PRESALE_STREAM_STACK,
238
+ },
239
+ programs: {
240
+ splToken: SPL_TOKEN_PROGRAM,
241
+ },
242
+ },
243
+ {
244
+ transport: 'http',
245
+ endpoints: { http: 'http://127.0.0.1:8081' },
246
+ wallet,
247
+ signerRegistry,
32
248
  }
33
- }
249
+ );
34
250
 
35
- for await (const update of a4.views.settlementGame.state.watch('game-123')) {
36
- console.log('Game 123 updated:', update.data);
37
- }
251
+ const prepared = await session.stacks.squads.flows.vaultProposal.prepare(...);
252
+ await session.execute(prepared);
253
+
254
+ // Signers can also be managed after session creation.
255
+ session.signerRegistry.register(memberAddress, memberSigner);
256
+ ```
257
+
258
+ Equivalent entrypoints:
38
259
 
39
- for await (const update of a4.views.settlementGame.list.watchRich()) {
40
- if (update.type === 'updated') {
41
- console.log('Changed from:', update.before);
42
- console.log('Changed to:', update.after);
260
+ - `createSession(...)`
261
+ - `Arete.session(...)`
262
+
263
+ Session surface:
264
+
265
+ - `session.stacks.<name>` - connected generated stacks
266
+ - `session.programs.<name>` - connected packaged, attached, or standalone programs
267
+ - `session.chain` - canonical generic chain reads
268
+ - `session.signerRegistry`
269
+ - `session.transaction(...)`
270
+ - `session.execute(...)`
271
+
272
+ Prefer these connected paths in application code. `Arete.connect(STACK, ...)` remains available when a direct single-stack client is more convenient.
273
+
274
+ If multiple stacks package the same program key, the first stack in the session definition owns the promoted alias and the session emits a warning. Both owner-scoped stack paths remain available. An explicitly declared standalone program always owns its top-level key.
275
+
276
+ ## Chain Reads
277
+
278
+ Generic chain reads use the console-level `session.chain` surface.
279
+
280
+ Available reads include:
281
+
282
+ - `exists(address)`
283
+ - `lamports(address)`
284
+ - `minimumBalanceForRentExemption(space)`
285
+ - `clock()`
286
+ - `account(address)`
287
+ - `mint(address)`
288
+ - `tokenAccount(address)`
289
+ - `balance({ owner, mint, tokenProgram? })`
290
+
291
+ Example:
292
+
293
+ ```ts
294
+ const rentLamports = await session.chain.minimumBalanceForRentExemption(82);
295
+ const mintInfo = await session.chain.mint(mintAddress);
296
+ ```
297
+
298
+ ## Streaming Views
299
+
300
+ Views are still the main streaming surface.
301
+
302
+ ```ts
303
+ for await (const update of session.stacks.myStack.views.settlementGame.list.watch()) {
304
+ if (update.type === 'upsert') {
305
+ console.log(update.key, update.data);
43
306
  }
44
307
  }
308
+
309
+ const game = await session.stacks.myStack.views.settlementGame.state.get('game-123');
45
310
  ```
46
311
 
47
- ### One-Shot Queries
312
+ Every options object is a protocol v2 query with independent ordered membership. Different windows and filters on the same view can run concurrently, while equivalent normalized queries share one reference-counted wire subscription:
313
+
314
+ ```ts
315
+ const rounds = session.stacks.ore.views.OreRound.latest;
48
316
 
49
- ```typescript
50
- const games = await a4.views.settlementGame.list.get();
317
+ const firstPage = rounds.watch({ take: 10 });
318
+ const secondPage = rounds.watch({ take: 10, skip: 10 });
51
319
 
52
- const game = await a4.views.settlementGame.state.get('game-123');
320
+ for await (const update of firstPage) {
321
+ if (update.type === 'remove') {
322
+ console.log(`${update.key} left the first-page window`);
323
+ }
324
+ }
53
325
  ```
54
326
 
55
- ### Connection Management
327
+ Completed authoritative snapshots replace membership for their exact query after reconnect. Cursor queries created with `after` receive incremental snapshots and merge without pruning.
56
328
 
57
- ```typescript
58
- console.log(a4.connectionState);
329
+ Low-level `QueryLease.refresh()` returns a `Promise<void>` that resolves after the refreshed subscription's next complete snapshot is committed. Registration, send, and subscription failures reject and are published on the lease's `QuerySnapshot.error`, with `isRefreshing` cleared. Subscriptions created with snapshots disabled resolve after the refresh request is sent.
59
330
 
60
- const unsubscribe = a4.onConnectionStateChange((state) => {
61
- console.log('Connection state:', state);
62
- });
331
+ ### Connection recovery
63
332
 
64
- await a4.disconnect();
333
+ `autoConnect` and `autoReconnect` default to `true` and control separate lifecycle phases. Set `autoConnect: false` to create a disconnected client that the application connects later. Set `autoReconnect: false` when the application wants to handle post-disconnect recovery itself:
334
+
335
+ ```ts
336
+ const client = await Arete.connect(MY_STACK, {
337
+ autoConnect: false,
338
+ autoReconnect: false,
339
+ });
65
340
  ```
66
341
 
67
- ## API
342
+ The same independent options are available per stack member in `createSession(...)` and on React's `AreteProvider`.
343
+
344
+ ### Caller-supplied schema diagnostics
68
345
 
69
- ### Arete
346
+ Core view schemas continue to filter rejected entities. React view hooks additionally accept `onSchemaValidationError`, which reports `{ view, key?, entity, error }` without changing accepted data.
70
347
 
71
- Main client class with typed view accessors.
348
+ ## Safe amount parsing
72
349
 
73
- - `Arete.connect(url, options)` - Connect to a Arete server
74
- - `views` - Typed view accessors based on your stack definition
75
- - `connectionState` - Current connection state
76
- - `onConnectionStateChange(callback)` - Listen for connection changes
77
- - `disconnect()` - Disconnect from the server
350
+ `toRawAmount(input, decimals)` throws when user input is invalid. Form and API boundaries can use `safeToRawAmount(input, decimals)` instead:
78
351
 
79
- ### Views
352
+ ```ts
353
+ import { safeToRawAmount } from '@usearete/sdk';
80
354
 
81
- Each view provides:
355
+ const result = safeToRawAmount({ ui: amountText }, 9);
356
+ if (!result.success) {
357
+ console.error(result.error);
358
+ return;
359
+ }
82
360
 
83
- **StateView (keyed entities)**
84
- - `watch(key)` - AsyncIterable of updates for a specific key
85
- - `watchRich(key)` - AsyncIterable with before/after diffs
86
- - `get(key)` - Get entity by key
87
- - `getSync(key)` - Get entity synchronously (if available)
361
+ console.log(result.data); // bigint in raw base units
362
+ ```
88
363
 
89
- **ListView (collections)**
90
- - `watch()` - AsyncIterable of all updates
91
- - `watchRich()` - AsyncIterable with before/after diffs
92
- - `get()` - Get all entities
93
- - `getSync()` - Get all entities synchronously (if available)
364
+ It returns `{ success: true, data } | { success: false, error }` and never throws for an invalid amount input.
94
365
 
95
- ### Update Types
366
+ ## Update Types
96
367
 
97
- ```typescript
368
+ ```ts
98
369
  type Update<T> =
99
370
  | { type: 'upsert'; key: string; data: T }
100
371
  | { type: 'patch'; key: string; data: Partial<T> }
372
+ | { type: 'remove'; key: string }
101
373
  | { type: 'delete'; key: string };
102
374
 
103
375
  type RichUpdate<T> =
104
376
  | { type: 'created'; key: string; data: T }
105
377
  | { type: 'updated'; key: string; before: T; after: T; patch?: unknown }
378
+ | { type: 'removed'; key: string; lastKnown?: T }
106
379
  | { type: 'deleted'; key: string; lastKnown?: T };
107
380
  ```
108
381
 
382
+ `remove` means an entity left only this query's filter or window. `delete` means the source entity was deleted and is removed from every query for that view.
383
+
109
384
  ## License
110
385
 
111
386
  MIT