@usearete/sdk 0.1.5 → 0.2.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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
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
4
 
5
5
  ## Installation
6
6
 
@@ -8,93 +8,308 @@ Pure TypeScript SDK for the Arete Solana streaming platform. Framework-agnostic
8
8
  npm install @usearete/sdk
9
9
  ```
10
10
 
11
- ## Usage
11
+ ## Quick Start
12
12
 
13
- ### Setup
13
+ ```ts
14
+ import { createSession } from '@usearete/sdk';
15
+ import { MY_STACK } from './generated/my-stack';
14
16
 
15
- ```typescript
16
- import { Arete } from '@usearete/sdk';
17
- import { SETTLEMENT_GAME_STACK } from './generated/settlement-game-stack';
17
+ const session = await createSession({
18
+ stacks: { myStack: MY_STACK },
19
+ });
20
+
21
+ for await (const item of session.stacks.myStack.views.MyEntity.list.use()) {
22
+ console.log(item);
23
+ }
24
+ ```
25
+
26
+ ## SDK Shapes
27
+
28
+ ### Mental Model
29
+
30
+ 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.
31
+
32
+ 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.
33
+
34
+ Every semantic operation has an explicit cardinality:
35
+
36
+ - `instruction` - exactly one Solana instruction
37
+ - `transaction` - exactly one atomic transaction with one or more instructions
38
+ - `flow` - one or more sequential transactions
39
+
40
+ Every semantic operation exposes one pure entrypoint:
41
+
42
+ - `.prepare(input)`
43
+
44
+ Every connected client or session exposes one semantic execution entrypoint:
45
+
46
+ - `.execute(prepared, options?)`
47
+
48
+ There is no semantic `.resolve()`, `.build()`, `.stage()`, `.plan()`, or `.send()` projection surface anymore.
49
+
50
+ ### Connected Stack Cartridges
51
+
52
+ Access a connected generated stack through `session.stacks.<name>`. Its stable namespaces are:
53
+
54
+ - `views` - typed streaming, list, and state views
55
+ - `queries` - stack-level HTTP queries
56
+ - `programs` - owner-scoped program SDKs; the same connected objects are promoted to `session.programs`
57
+ - `addresses` - domain address derivations, when defined
58
+ - `constants` - domain constants and enums, when defined
59
+ - `defaults` - reusable domain defaults, when defined
60
+ - `math` - pure domain calculations, when defined
61
+ - `read` - connected, domain-oriented reads, when defined
62
+ - `flows` - stack-level multi-transaction operations, when defined
63
+
64
+ These are namespaces on the existing connected stack object; no separate cartridge class or type is introduced.
65
+
66
+ ### Program SDKs
67
+
68
+ 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.
18
69
 
19
- const a4 = await Arete.connect('wss://mainnet.arete.xyz', {
20
- stack: SETTLEMENT_GAME_STACK,
70
+ - `programId` - the deployed Solana program address
71
+ - `schemas` - generated validation schemas
72
+ - `pdas` - exact generated PDA definitions
73
+ - `addresses` - semantic address derivations, when defined
74
+ - `accounts` - typed point reads for program accounts
75
+ - `queries` - program-level HTTP queries
76
+ - `raw` - exact IDL instruction builders with synchronous `.build(...)`
77
+ - `instructions` - semantic one-instruction operations with `.prepare(...)`
78
+ - `transactions` - semantic one-transaction operations with `.prepare(...)`
79
+ - `flows` - program-local multi-transaction operations with `.prepare(...)`
80
+ - `constants` - program constants and enums
81
+ - `defaults` - reusable program defaults
82
+ - `math` - pure protocol calculations
83
+
84
+ ### Raw Instructions
85
+
86
+ Use raw handlers when you want exact wire control and will compose the transaction yourself:
87
+
88
+ ```ts
89
+ const ix = session.programs.splToken.raw.InitializeMint2.build({
90
+ mint,
91
+ decimals: 6,
92
+ mint_authority: authority,
93
+ freeze_authority: null,
21
94
  });
95
+
96
+ await session.transaction([ix]);
22
97
  ```
23
98
 
24
- ### Streaming with AsyncIterable
99
+ 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
100
 
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);
32
- }
33
- }
101
+ ### Semantic Operations
34
102
 
35
- for await (const update of a4.views.settlementGame.state.watch('game-123')) {
36
- console.log('Game 123 updated:', update.data);
37
- }
103
+ 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.
38
104
 
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);
43
- }
44
- }
105
+ Instruction example:
106
+
107
+ ```ts
108
+ const prepared = await session.programs.tokenMetadata.instructions.createMetadataAccountV3.prepare({
109
+ mint,
110
+ mintAuthority,
111
+ payer,
112
+ updateAuthority,
113
+ name,
114
+ symbol,
115
+ uri,
116
+ });
117
+
118
+ console.log(prepared.kind); // 'instruction'
119
+ console.log(prepared.instruction);
120
+ console.log(prepared.artifacts);
121
+
122
+ await session.execute(prepared);
123
+ ```
124
+
125
+ Transaction example:
126
+
127
+ ```ts
128
+ const prepared = await session.programs.cpAmm.transactions.swap.exactIn.prepare({
129
+ pool,
130
+ payer,
131
+ inputTokenMint,
132
+ amountIn: { ui: '1.25' },
133
+ minimumAmountOut: 1n,
134
+ });
135
+
136
+ console.log(prepared.kind); // 'transaction'
137
+ console.log(prepared.transaction.instructions.length);
138
+
139
+ await session.execute(prepared);
45
140
  ```
46
141
 
47
- ### One-Shot Queries
142
+ Flow example:
48
143
 
49
- ```typescript
50
- const games = await a4.views.settlementGame.list.get();
144
+ ```ts
145
+ const prepared = await session.programs.presale.flows.escrow.depositPermissionless.prepare({
146
+ presale,
147
+ owner,
148
+ maxAmount: { ui: '1000' },
149
+ });
150
+
151
+ console.log(prepared.kind); // 'flow'
152
+ console.log(prepared.plan.transactions.length);
51
153
 
52
- const game = await a4.views.settlementGame.state.get('game-123');
154
+ await session.execute(prepared);
53
155
  ```
54
156
 
55
- ### Connection Management
157
+ ### Prepared Shapes
158
+
159
+ Prepared values are immutable and discriminated:
160
+
161
+ - `PreparedInstruction`
162
+ - `PreparedTransaction`
163
+ - `PreparedFlow`
164
+
165
+ All prepared values include:
166
+
167
+ - `kind`
168
+ - `name`
169
+ - `artifacts`
170
+ - `plan.transactions`
56
171
 
57
- ```typescript
58
- console.log(a4.connectionState);
172
+ Instruction values also include `.instruction`, and transaction values include `.transaction`.
59
173
 
60
- const unsubscribe = a4.onConnectionStateChange((state) => {
61
- console.log('Connection state:', state);
174
+ Prepared instructions can be composed directly into a transaction without
175
+ extracting `.instruction`:
176
+
177
+ ```ts
178
+ const transaction = createPreparedTransaction({
179
+ name: 'configureMint',
180
+ instructions: [initializeMint, setAuthority],
181
+ artifacts: { mint },
62
182
  });
183
+ ```
184
+
185
+ Prepared instructions and prepared transactions can also be flattened into one
186
+ atomic transaction without reaching into their transaction bodies:
63
187
 
64
- await a4.disconnect();
188
+ ```ts
189
+ const transaction = createPreparedTransaction({
190
+ name: 'createAndConfigureMint',
191
+ operations: [createMint, createMetadata, setAuthority],
192
+ artifacts: { mint },
193
+ });
65
194
  ```
66
195
 
67
- ## API
196
+ Only single-transaction operations are accepted by `operations`. A
197
+ `PreparedFlow` must retain its ordered transaction boundaries.
68
198
 
69
- ### Arete
199
+ Child signer and error metadata is inherited unless the transaction explicitly
200
+ provides `requiredSignerAddresses` or `errors`.
70
201
 
71
- Main client class with typed view accessors.
202
+ Every successful execution receipt exposes its signatures in transaction order:
72
203
 
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
204
+ ```ts
205
+ const receipt = await session.execute(prepared);
206
+ console.log(receipt.signatures);
207
+ ```
78
208
 
79
- ### Views
209
+ Instruction and transaction receipts contain one signature. Flow receipts
210
+ contain one signature for each executed transaction.
80
211
 
81
- Each view provides:
212
+ Use `describePreparedOperation(prepared)` for a typed, JSON-safe description, or
213
+ `formatPreparedOperation(prepared)` for human-readable text.
82
214
 
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)
215
+ ```ts
216
+ const description = describePreparedOperation(prepared);
217
+ console.log(JSON.stringify(description, null, 2));
218
+ ```
219
+
220
+ ## Sessions
221
+
222
+ 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`.
223
+
224
+ ```ts
225
+ import { createSession, createSignerRegistry } from '@usearete/sdk';
226
+
227
+ const signerRegistry = createSignerRegistry([
228
+ [creatorAddress, creatorSigner],
229
+ ]);
230
+
231
+ const session = await createSession(
232
+ {
233
+ stacks: {
234
+ squads: SQUADS_V4_STREAM_STACK,
235
+ presale: METEORA_PRESALE_STREAM_STACK,
236
+ },
237
+ programs: {
238
+ splToken: SPL_TOKEN_PROGRAM,
239
+ },
240
+ },
241
+ {
242
+ transport: 'http',
243
+ endpoints: { http: 'http://127.0.0.1:8081' },
244
+ wallet,
245
+ signerRegistry,
246
+ }
247
+ );
248
+
249
+ const prepared = await session.stacks.squads.flows.vaultProposal.prepare(...);
250
+ await session.execute(prepared);
251
+
252
+ // Signers can also be managed after session creation.
253
+ session.signerRegistry.register(memberAddress, memberSigner);
254
+ ```
88
255
 
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)
256
+ Equivalent entrypoints:
257
+
258
+ - `createSession(...)`
259
+ - `Arete.session(...)`
260
+
261
+ Session surface:
262
+
263
+ - `session.stacks.<name>` - connected generated stacks
264
+ - `session.programs.<name>` - connected packaged, attached, or standalone programs
265
+ - `session.chain` - canonical generic chain reads
266
+ - `session.signerRegistry`
267
+ - `session.transaction(...)`
268
+ - `session.execute(...)`
269
+
270
+ Prefer these connected paths in application code. `Arete.connect(STACK, ...)` remains available when a direct single-stack client is more convenient.
271
+
272
+ 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.
273
+
274
+ ## Chain Reads
275
+
276
+ Generic chain reads use the console-level `session.chain` surface.
277
+
278
+ Available reads include:
279
+
280
+ - `exists(address)`
281
+ - `lamports(address)`
282
+ - `minimumBalanceForRentExemption(space)`
283
+ - `clock()`
284
+ - `account(address)`
285
+ - `mint(address)`
286
+ - `tokenAccount(address)`
287
+ - `balance({ owner, mint, tokenProgram? })`
288
+
289
+ Example:
290
+
291
+ ```ts
292
+ const rentLamports = await session.chain.minimumBalanceForRentExemption(82);
293
+ const mintInfo = await session.chain.mint(mintAddress);
294
+ ```
295
+
296
+ ## Streaming Views
297
+
298
+ Views are still the main streaming surface.
299
+
300
+ ```ts
301
+ for await (const update of session.stacks.myStack.views.settlementGame.list.watch()) {
302
+ if (update.type === 'upsert') {
303
+ console.log(update.key, update.data);
304
+ }
305
+ }
306
+
307
+ const game = await session.stacks.myStack.views.settlementGame.state.get('game-123');
308
+ ```
94
309
 
95
- ### Update Types
310
+ ## Update Types
96
311
 
97
- ```typescript
312
+ ```ts
98
313
  type Update<T> =
99
314
  | { type: 'upsert'; key: string; data: T }
100
315
  | { type: 'patch'; key: string; data: Partial<T> }