@donezone/client 0.1.51 → 0.1.55

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,128 +1,599 @@
1
1
  # @donezone/client
2
2
 
3
- Client-side helpers for interacting with the Done execution stack from browsers or Node. The package mirrors the structure of the backend `Done` API—contract calls are described as HTTP-style requests, wrapped into CosmWasm messages, packed into auth envelopes, and finally submitted to the Done HTTP gateway.
3
+ Client library for interacting with Done contracts from JavaScript/TypeScript (browser, Node, Bun). Handles envelope construction, signing, transport to the Done HTTP gateway, and SSE event subscriptions.
4
4
 
5
- ## Features
5
+ ---
6
6
 
7
- - Envelope utilities (`buildEnvelope`, `toSignDoc`, `signDocDigest`) that follow the router’s signing rules.
8
- - Done HTTP-aware transport via `DoneBackendClient` for `/query`, `/tx`, and quota inspection.
9
- - Contract helpers for building `WasmMsg::Execute` payloads from HTTP-like routes, reusing the ergonomics of the `Done` runtime.
7
+ ## Table of Contents
10
8
 
11
- ## Usage
9
+ 1. [Concepts](#concepts)
10
+ 2. [Installation](#installation)
11
+ 3. [The `Done` Facade](#the-done-facade)
12
+ 4. [DoneContractClient](#donecontractclient)
13
+ 5. [DoneBackendClient](#donebackendclient)
14
+ 6. [Envelope Builders](#envelope-builders)
15
+ 7. [Low-Level Primitives](#low-level-primitives)
16
+ 8. [Message Builders](#message-builders)
17
+ 9. [Types Reference](#types-reference)
12
18
 
13
- ### High-level Done facade
19
+ ---
20
+
21
+ ## Concepts
22
+
23
+ Every write operation on a Done contract requires an **auth envelope** — a signed payload that wraps one or more CosmWasm messages with identity, nonce, expiry, and signatures. This package handles building those envelopes, signing them (via pluggable signer callbacks), and submitting them to `POST /tx` on the Done HTTP gateway. Read operations are plain `GET /query/{contract}?msg=...` calls with no signing required.
24
+
25
+ **Call flow for a transaction:**
26
+
27
+ ```
28
+ Done.run(url, opts)
29
+ → buildTransactionMessage (produces WasmMsg::Execute)
30
+ → EnvelopeBuilder callback (user provides signing logic)
31
+ → backend.executeEnvelope (POST /tx)
32
+ ```
33
+
34
+ **Call flow for a query:**
35
+
36
+ ```
37
+ Done.query(url, opts)
38
+ → buildQueryMessage (serialises path/body/query)
39
+ → GET /query/{contract}?msg=...
40
+ ```
41
+
42
+ **Call flow for events:**
43
+
44
+ ```
45
+ Done.subscribe(eventsUrl, topic, handler)
46
+ → EventSource SSE connection
47
+ → JSON-parsed events forwarded to handler
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Installation
53
+
54
+ ```bash
55
+ bun add @donezone/client
56
+ # or
57
+ npm install @donezone/client
58
+ ```
59
+
60
+ ---
61
+
62
+ ## The `Done` Facade
63
+
64
+ `Done` is a pre-configured singleton exported from the package. Most applications only need this.
14
65
 
15
66
  ```ts
16
- import {
17
- Done,
18
- createPasskeyEnvelopeBuilder,
19
- signDocDigest,
20
- } from "@donezone/client";
67
+ import { Done, signDocDigest } from "@donezone/client";
68
+ ```
69
+
70
+ ### `Done.config(options)`
71
+
72
+ Mutates the global `Done` instance. Call once at app startup. Omitted fields keep their existing values.
21
73
 
74
+ ```ts
22
75
  Done.config({
23
- doneHttp: "https://doneHttp.done.zone",
24
- doneEvents: "https://doneEvents.done.zone",
25
- signer: createPasskeyEnvelopeBuilder({
26
- userId: "user-1",
27
- nonce: async () => Number(new Date()),
28
- expiresAt: () => Math.floor(Date.now() / 1000) + 300,
29
- publicKey: () => storedPasskey.publicKey,
30
- sign: async (signDoc) => {
31
- const digest = signDocDigest(signDoc);
32
- return await signWithPasskeyHardware(digest); // returns Uint8Array or base64
33
- },
34
- }),
76
+ doneHttp: "https://doneHttp.done.zone", // Done HTTP gateway base URL
77
+ doneEvents: "https://doneEvents.done.zone", // Done Events SSE base URL
78
+ signer: myEnvelopeBuilder, // EnvelopeBuilder (see Envelope Builders)
79
+ fetch: customFetch, // optional custom fetch implementation
80
+ eventSource: customEventSourceFactory, // optional custom EventSource factory
35
81
  });
82
+ ```
83
+
84
+ ### `Done.run(url, options?)`
85
+
86
+ Executes an authenticated transaction. Returns `Promise<ExecuteResponse>`.
87
+
88
+ `url` is resolved against `doneHttp`. The first path segment after the base must be the contract address, followed by the route path:
36
89
 
37
- await Done.run("/done1contract123/buy", {
90
+ ```ts
91
+ const result = await Done.run("/done1contract.../buy", {
38
92
  body: { minAmountOut: "1" },
39
- funds: { uusd: "100" },
40
- memo: "demo purchase",
93
+ funds: { uusd: "100" }, // or [{ denom: "uusd", amount: "100" }]
94
+ memo: "optional memo",
95
+ gasLimit: 500_000,
96
+ traceId: "abc-123",
97
+ signal: abortController.signal,
41
98
  });
99
+ // result: { transactionHash, height, gasUsed }
100
+ ```
42
101
 
43
- const price = await Done.query("/done1contract123/price");
102
+ Requires `signer` to be configured on the `Done` instance.
103
+
104
+ ### `Done.query<T>(url, options?)`
105
+
106
+ Issues a read-only query. Returns `Promise<T>`.
107
+
108
+ ```ts
109
+ const price = await Done.query<{ amount: string }>("/done1contract.../price");
44
110
 
111
+ const orders = await Done.query("/done1contract.../orders", {
112
+ search: { limit: 10, offset: 0 }, // merged into querystring
113
+ });
114
+ ```
115
+
116
+ ### `Done.subscribe(eventsUrl, topic, handler, options?)`
117
+
118
+ Opens an SSE stream. Returns an `() => void` cleanup function.
119
+
120
+ `eventsUrl` is resolved against `doneEvents`. The path must include the contract address (e.g. `/done1contract.../events` or just the address segment the events server expects).
121
+
122
+ ```ts
45
123
  const stop = Done.subscribe(
46
- "/done1contract123/events",
47
- "PriceChange",
124
+ "/done1contract.../events",
125
+ "PriceChange", // topic string; also accepts string[] for nested paths
48
126
  (event) => {
49
- console.log("new price", event.newPrice);
50
- }
127
+ console.log(event); // parsed JSON; raw string if parsing fails
128
+ },
129
+ {
130
+ rawEvent: true, // forward the raw MessageEvent instead of parsing
131
+ signal: ac.signal, // AbortSignal closes the subscription automatically
132
+ onError: (e) => {}, // called on EventSource error events
133
+ },
51
134
  );
52
135
 
53
- // later
136
+ // later:
54
137
  stop();
55
-
56
- // Contract-specific helper using just the address
57
- const sale = Done.contract("done1contract123");
58
- await sale.run("/buy", { body: { minAmountOut: "1" }, funds: { uusd: "100" } });
59
- const priceAgain = await sale.query("/price");
60
138
  ```
61
139
 
62
- Need a scoped client or different signer? Spawn another instance:
140
+ ### `Done.create(options?)`
141
+
142
+ Returns a new isolated `DoneInstance` with its own settings, inheriting from the current `Done` configuration. Useful for multi-tenant dashboards or per-request contexts.
63
143
 
64
144
  ```ts
65
145
  const staging = Done.create({
66
146
  doneHttp: "https://doneHttp.staging.zone",
67
147
  doneEvents: "https://doneEvents.staging.zone",
68
- signer: createPasskeyEnvelopeBuilder({...}),
148
+ signer: stagingSigner,
69
149
  });
70
150
 
71
- await staging.run("/done1contractABC/buy", { body: { minAmountOut: "5" }, funds: { uusd: "250" } });
151
+ await staging.run("/done1contract.../buy", { body: { minAmountOut: "5" } });
72
152
  ```
73
153
 
74
- You can still work with contract handles when you need per-contract hooks:
154
+ The returned instance has the same `run`, `query`, `subscribe`, `config`, `create`, and `contract` methods as the global `Done`.
155
+
156
+ ### `Done.contract(address)` / `Done.contract(config)`
157
+
158
+ Returns a `DoneContractClient` (or `DoneContractHandle`) scoped to a specific contract. The instance inherits `signer`, `fetch`, and `eventSource` from the `Done` configuration.
75
159
 
76
160
  ```ts
161
+ // Simple: address string — inherits everything from Done config
162
+ const sale = Done.contract("done1contract123");
163
+ await sale.run("/buy", { body: { minAmountOut: "1" } });
164
+ const price = await sale.query<{ amount: string }>("/price");
165
+
166
+ // Advanced: full config object
77
167
  const sale = Done.contract({
78
168
  baseUrl: "https://doneHttp.done.zone",
79
169
  address: "done1contract123",
170
+ buildEnvelope: customSigner,
171
+ eventsPath: "/events",
80
172
  });
173
+ ```
81
174
 
82
- const recent = await sale.get("/orders", { query: { limit: 10 } }).json();
175
+ ### `Done.buildEnvelope(draft)` / `Done.signDocDigest(envelope)` / `Done.toSignDoc(envelope)`
176
+
177
+ Convenience re-exports of the low-level primitives (see [Low-Level Primitives](#low-level-primitives)).
178
+
179
+ ---
180
+
181
+ ## DoneContractClient
182
+
183
+ A strongly typed, contract-scoped client. Instantiate directly when you need per-contract configuration (e.g. a different signer or events URL).
184
+
185
+ ```ts
186
+ import { DoneContractClient } from "@donezone/client";
187
+
188
+ const client = new DoneContractClient({
189
+ baseUrl: "https://doneHttp.done.zone",
190
+ address: "done1contract123",
191
+ buildEnvelope: myEnvelopeBuilder, // required to call execute/run/post
192
+ eventsPath: "/events", // default: "/events"
193
+ eventSource: myEventSourceFactory,
194
+ fetch: customFetch,
195
+ defaultMetadata: { gas_limit: 500_000 },
196
+ });
83
197
  ```
84
198
 
85
- ### Lower-level building blocks
199
+ ### Type Safety for Transactions
200
+
201
+ `execute`, `run`, and `post` require `buildEnvelope` to be present in the config. If it is absent, TypeScript will give a compile-time error (`Argument of type 'string' is not assignable to parameter of type 'never'`) rather than a runtime throw. Clients without `buildEnvelope` are limited to `query`, `get`, `subscribe`, and `transaction`.
202
+
203
+ ### Methods
204
+
205
+ #### `client.query<T>(path, request?, init?)`
206
+
207
+ Read-only query. Returns `Promise<T>`.
86
208
 
87
209
  ```ts
88
- import {
89
- DoneBackendClient,
90
- buildEnvelope,
91
- signDocDigest,
92
- toSignDoc,
93
- } from "@donezone/client";
210
+ const state = await client.query<{ count: number }>("/state");
211
+ const orders = await client.query("/orders", { query: { limit: "10" } });
212
+ ```
213
+
214
+ #### `client.get(path, request?, init?)`
215
+
216
+ Same as `query` but returns a `DoneRequest` (a `PromiseLike<Response>` with convenience `.json<T>()`, `.text()`, `.arrayBuffer()` methods). Useful when you need the raw `Response`.
217
+
218
+ ```ts
219
+ const res = await client.get("/orders", { query: { limit: "10" } });
220
+ const data = await res.json<Order[]>();
221
+ ```
222
+
223
+ #### `client.execute(path, request?, init?)` / `.run(...)` / `.post(...)`
224
+
225
+ Execute a transaction. All three are identical. Requires `buildEnvelope` in config (compile-time enforced). Returns `Promise<ExecuteResponse>`.
94
226
 
95
- const backend = new DoneBackendClient({ baseUrl: "https://doneHttp.example" });
96
- const contract = backend.contract("done1contract...");
97
- const call = contract.transaction("/buy", {
227
+ ```ts
228
+ const result = await client.execute("/buy", {
98
229
  body: { minAmountOut: "1" },
99
- gasLimit: 500_000,
230
+ funds: { uusd: "100" },
231
+ memo: "purchase",
232
+ gasLimit: 300_000,
233
+ traceId: "trace-xyz",
234
+ signal: ac.signal,
100
235
  });
236
+ // result: { transactionHash, height, gasUsed }
237
+ ```
238
+
239
+ #### `client.transaction(path, request?)`
240
+
241
+ Builds a `PreparedTransaction` (the `CosmosMsg` + optional metadata) without submitting it. Use this to batch multiple contract calls into a single envelope manually.
242
+
243
+ ```ts
244
+ const tx = client.transaction("/buy", { body: { minAmountOut: "1" } });
245
+ // tx: { msg: CosmosMsg, metadata?: EnvelopeMetadata }
246
+ ```
247
+
248
+ #### `client.subscribe(topic, handler, options?)`
249
+
250
+ Opens an SSE subscription to `{baseUrl}{eventsPath}/{address}?topic={topic}`. Returns `() => void`.
251
+
252
+ ```ts
253
+ const stop = client.subscribe("Pinged", (payload) => {
254
+ console.log(payload); // parsed JSON
255
+ });
256
+
257
+ // With options:
258
+ const stop = client.subscribe(
259
+ ["namespace", "event"], // string[] encodes as JSON topic
260
+ handler,
261
+ { onError: console.error, signal: ac.signal },
262
+ );
263
+ ```
264
+
265
+ #### `client.publishCode(request, init?)`
266
+
267
+ Publishes or updates contract code. Returns `Promise<PublishCodeResponse>`.
268
+
269
+ ```ts
270
+ await client.publishCode({ script: contractSourceCode, msg: initMsg });
271
+ ```
272
+
273
+ #### `client.buildEnvelope(draft)` / `client.signDocDigest(envelope)`
274
+
275
+ See [Low-Level Primitives](#low-level-primitives).
276
+
277
+ ---
278
+
279
+ ## DoneBackendClient
280
+
281
+ The raw transport layer. Use this when you need full control over envelope construction and submission.
282
+
283
+ ```ts
284
+ import { DoneBackendClient } from "@donezone/client";
285
+
286
+ const backend = new DoneBackendClient({
287
+ baseUrl: "https://doneHttp.done.zone",
288
+ fetch: customFetch, // optional
289
+ });
290
+ ```
291
+
292
+ ### Methods
293
+
294
+ #### `backend.contract(address)`
295
+
296
+ Returns a `DoneContractHandle` with `transaction`, `query`, `get`, and `publishCode` helpers. Does **not** include `execute`/`run` — use `backend.executeEnvelope` for submission.
297
+
298
+ ```ts
299
+ const handle = backend.contract("done1contract123");
300
+ const tx = handle.transaction("/buy", { body: { minAmountOut: "1" } });
301
+ // tx: PreparedTransaction — pass tx.msg into buildEnvelope
302
+ ```
303
+
304
+ #### `backend.executeEnvelope(envelope, options?, init?)`
305
+
306
+ Submit a fully-built `AuthEnvelope` to `POST /tx`. Returns `Promise<ExecuteResponse>`.
307
+
308
+ ```ts
309
+ await backend.executeEnvelope(envelope, {
310
+ passkey: { publicKey: "base64-encoded-public-key" },
311
+ memo: "tx memo",
312
+ signal: ac.signal,
313
+ });
314
+ ```
315
+
316
+ #### `backend.queryContract<T>(address, call, init?)`
317
+
318
+ ```ts
319
+ const result = await backend.queryContract<{ price: string }>(
320
+ "done1contract123",
321
+ { path: "/price" },
322
+ );
323
+ ```
324
+
325
+ #### `backend.queryContractRaw(address, call, init?)`
326
+
327
+ Same as `queryContract` but returns the raw `Response`.
328
+
329
+ #### `backend.publishCode(request, init?)`
330
+
331
+ ```ts
332
+ await backend.publishCode({
333
+ contract: "js", // or "wasm"
334
+ script: contractSource,
335
+ msg: optionalInitMsg,
336
+ });
337
+ ```
338
+
339
+ #### `backend.getAgentQuota(userId, agent)` / `backend.getForwarderQuota(address)`
340
+
341
+ Inspect quota usage for agent/forwarder authorization.
342
+
343
+ ---
344
+
345
+ ## Envelope Builders
346
+
347
+ Envelope builders are functions with the signature `(ctx: EnvelopeBuildContext) => Promise<EnvelopeBuildResult> | EnvelopeBuildResult`. Pass them as `signer` to `Done.config()` or `buildEnvelope` to `DoneContractClient`.
348
+
349
+ ### `createPasskeyEnvelopeBuilder(options)`
350
+
351
+ For WebAuthn / hardware passkey signing.
352
+
353
+ ```ts
354
+ import { createPasskeyEnvelopeBuilder, signDocDigest } from "@donezone/client";
355
+
356
+ const builder = createPasskeyEnvelopeBuilder({
357
+ userId: "user-abc", // or (ctx) => resolveUserId(ctx)
358
+ nonce: () => Date.now(),
359
+ expiresAt: () => Math.floor(Date.now() / 1000) + 300,
360
+ publicKey: () => storedPublicKey, // base64 string
361
+ sign: async (signDoc, ctx) => {
362
+ const digest = signDocDigest(signDoc); // SHA-256 Uint8Array
363
+ return await signWithHardware(digest); // return Uint8Array or base64 string
364
+ },
365
+ // Optional:
366
+ agent: "done1agent...",
367
+ forwarder: "done1forwarder...",
368
+ metadata: { gas_limit: 500_000 },
369
+ });
370
+
371
+ Done.config({ signer: builder });
372
+ ```
373
+
374
+ All option fields except `sign` can be a plain value **or** a `(ctx: EnvelopeBuildContext) => MaybePromise<T>` factory, giving per-call control.
375
+
376
+ ### `createSessionEnvelopeBuilder(options)`
377
+
378
+ For session key signing (e.g. a server-side HSM or stored keypair).
379
+
380
+ ```ts
381
+ import { createSessionEnvelopeBuilder } from "@donezone/client";
382
+
383
+ const builder = createSessionEnvelopeBuilder({
384
+ userId: "user-abc",
385
+ sessionId: "session-xyz",
386
+ nonce: () => Date.now(),
387
+ expiresAt: () => Math.floor(Date.now() / 1000) + 300,
388
+ sign: async (signDoc) => {
389
+ const digest = signDocDigest(signDoc);
390
+ return await signWithSessionKey(digest); // Uint8Array or base64
391
+ },
392
+ });
393
+ ```
394
+
395
+ ### `createDevEnvelopeBuilder(options?)`
396
+
397
+ Produces **unsigned** envelopes for local development and testing. Never use in production.
398
+
399
+ ```ts
400
+ import { createDevEnvelopeBuilder } from "@donezone/client";
401
+
402
+ const builder = createDevEnvelopeBuilder({
403
+ userId: "dev", // default: "dev"
404
+ ttlSeconds: 300, // default: 300
405
+ });
406
+ ```
407
+
408
+ ---
409
+
410
+ ## Low-Level Primitives
411
+
412
+ These are useful when implementing a custom envelope builder or doing manual envelope manipulation.
413
+
414
+ ### `buildEnvelope(draft)`
415
+
416
+ Constructs and validates an `AuthEnvelope` from a draft. Throws if `msgs` is empty.
417
+
418
+ ```ts
419
+ import { buildEnvelope } from "@donezone/client";
101
420
 
102
421
  const envelope = buildEnvelope({
103
- user_id: "user-1",
104
- msgs: [call.msg],
105
- nonce: 42,
422
+ user_id: "user-abc",
423
+ msgs: [cosmosMsg],
424
+ nonce: Date.now(),
106
425
  expires_at: Math.floor(Date.now() / 1000) + 300,
107
- role: "Passkey",
108
- metadata: call.metadata,
426
+ role: "Passkey", // or "Session"
427
+ signatures: { passkey: "base64sig" },
428
+ // Optional:
429
+ session_id: "...",
430
+ agent: "done1agent...",
431
+ forwarder: "done1forwarder...",
432
+ metadata: { trace_id: "...", memo: "...", gas_limit: 500_000 },
109
433
  });
434
+ ```
435
+
436
+ ### `toSignDoc(envelope)`
437
+
438
+ Strips signatures from an envelope (or draft) to produce the canonical `AuthEnvelopeSignDoc` that is actually signed.
439
+
440
+ ```ts
441
+ import { toSignDoc } from "@donezone/client";
110
442
 
111
443
  const signDoc = toSignDoc(envelope);
112
- const digest = signDocDigest(signDoc);
113
- // sign digest with passkey/session key, then attach to envelope.signatures
444
+ ```
114
445
 
115
- await backend.executeEnvelope(envelope, {
116
- passkey: { publicKey: "..." },
117
- memo: "demo tx",
118
- });
446
+ ### `signDocBytes(signDoc)`
447
+
448
+ Produces the canonical UTF-8 JSON bytes (keys sorted, no extra whitespace) of the sign doc. This is what gets hashed.
449
+
450
+ ```ts
451
+ import { signDocBytes } from "@donezone/client";
452
+
453
+ const bytes = signDocBytes(signDoc); // Uint8Array
119
454
  ```
120
455
 
121
- ### Server-friendly signing helpers
456
+ ### `signDocDigest(signDoc)`
122
457
 
123
- The exported builders (`createPasskeyEnvelopeBuilder`, `createSessionEnvelopeBuilder`) accept plain
124
- signing callbacks, so they work in Node, Bun, or browsers alike—the caller decides how to obtain
125
- signatures (WebAuthn, HSM, remote service, etc.). The helpers return the envelope plus any metadata
126
- the Done HTTP transport expects, keeping public/private key plumbing outside of the library.
458
+ SHA-256 of the canonical sign doc bytes. This is what passkey/session hardware actually signs.
127
459
 
128
- See `packages/done-client/test/envelope.test.ts` for more end-to-end examples and expected request payloads.
460
+ ```ts
461
+ import { signDocDigest } from "@donezone/client";
462
+
463
+ const digest = signDocDigest(signDoc); // Uint8Array (32 bytes)
464
+ ```
465
+
466
+ ### `encodeSignature(bytes)` / `decodeSignature(base64)`
467
+
468
+ Convert between raw signature bytes and the base64 strings stored in `AuthEnvelope.signatures`.
469
+
470
+ ```ts
471
+ import { encodeSignature, decodeSignature } from "@donezone/client";
472
+
473
+ const b64 = encodeSignature(rawSigBytes); // Uint8Array → base64 string
474
+ const raw = decodeSignature(b64); // base64 string → Uint8Array
475
+ ```
476
+
477
+ ---
478
+
479
+ ## Message Builders
480
+
481
+ These build the wire format for contract calls. Useful when constructing multi-message envelopes manually.
482
+
483
+ ### `buildTransactionMessage(contractAddr, call, options?)`
484
+
485
+ Builds a `WasmMsg::Execute` `CosmosMsg` in the shape the Done HTTP gateway expects.
486
+
487
+ ```ts
488
+ import { buildTransactionMessage } from "@donezone/client";
489
+
490
+ const msg = buildTransactionMessage(
491
+ "done1contract123",
492
+ { path: "/buy", body: { minAmountOut: "1" }, query: { mode: "fast" } },
493
+ { funds: { uusd: "100" } },
494
+ );
495
+ // { wasm: { execute: { contract_addr, msg: { msg: { path, body, query } }, funds } } }
496
+ ```
497
+
498
+ The `call.path` must start with `/`.
499
+
500
+ ### `buildQueryMessage(call)`
501
+
502
+ Builds the query message object that goes into `GET /query/{contract}?msg=...`.
503
+
504
+ ```ts
505
+ import { buildQueryMessage } from "@donezone/client";
506
+
507
+ const queryMsg = buildQueryMessage({ path: "/price", query: { verbose: "1" } });
508
+ // { msg: { path: "/price", query: { verbose: "1" } } }
509
+ ```
510
+
511
+ ---
512
+
513
+ ## Types Reference
514
+
515
+ Key types exported from the package:
516
+
517
+ ```ts
518
+ // Envelope core
519
+ AuthEnvelope // complete signed envelope sent to /tx
520
+ AuthEnvelopeSignDoc // envelope minus signatures — the thing that gets signed
521
+ EnvelopeDraft // input to buildEnvelope (signatures optional)
522
+ EnvelopeRole // "Passkey" | "Session"
523
+ EnvelopeSignatures // { passkey?: string; session?: string }
524
+ EnvelopeMetadata // { trace_id?: string; memo?: string; gas_limit?: number }
525
+
526
+ // Messages
527
+ CosmosMsg // WasmExecuteMsg | BankSendMsg | Record<string, unknown>
528
+ WasmExecuteMsg // { wasm: { execute: { contract_addr, msg, funds? } } }
529
+ BankSendMsg // { bank: { send: { to_address, amount } } }
530
+ Coin // { denom: string; amount: string }
531
+ FundsInput // Coin[] | Record<string, string | number> | undefined
532
+
533
+ // Client config
534
+ DoneContractConfig // config for DoneContractClient constructor
535
+ DoneClientConfig // config for DoneBackendClient constructor
536
+ DoneConfigOptions // config for Done.config() / Done.create()
537
+
538
+ // Request/response
539
+ ExecuteResponse // { transactionHash: string; height: number; gasUsed: number }
540
+ TransactionRequest // options for execute/run/post (body, query, funds, memo, etc.)
541
+ QueryRequest // options for query/get (body, query)
542
+ PreparedTransaction // { msg: CosmosMsg; metadata?: EnvelopeMetadata }
543
+ SubscriptionOptions // { onError?, signal?, rawEvent? }
544
+
545
+ // Builders
546
+ EnvelopeBuilder // (ctx: EnvelopeBuildContext) => Promise<EnvelopeBuildResult> | EnvelopeBuildResult
547
+ EnvelopeBuildContext // { msg, metadata?, path, request }
548
+ EnvelopeBuildResult // { envelope: AuthEnvelope; options?: ExecuteEnvelopeOptions }
549
+ EventSourceFactory // (url: string) => EventSource-compatible object
550
+
551
+ // Passkey/session builder options
552
+ PasskeyEnvelopeBuilderOptions
553
+ SessionEnvelopeBuilderOptions
554
+ DevEnvelopeBuilderOptions
555
+ ```
556
+
557
+ ---
558
+
559
+ ## Complete Example
560
+
561
+ ```ts
562
+ import {
563
+ Done,
564
+ createPasskeyEnvelopeBuilder,
565
+ signDocDigest,
566
+ } from "@donezone/client";
567
+
568
+ // Configure once at startup
569
+ Done.config({
570
+ doneHttp: "https://doneHttp.done.zone",
571
+ doneEvents: "https://doneEvents.done.zone",
572
+ signer: createPasskeyEnvelopeBuilder({
573
+ userId: () => currentUser.id,
574
+ nonce: () => Date.now(),
575
+ expiresAt: () => Math.floor(Date.now() / 1000) + 300,
576
+ publicKey: () => currentUser.passkeyPublicKey,
577
+ sign: async (signDoc) => {
578
+ const digest = signDocDigest(signDoc);
579
+ return await navigator.credentials.get(/* WebAuthn options using digest */);
580
+ },
581
+ }),
582
+ });
583
+
584
+ // Transaction
585
+ const { transactionHash } = await Done.run("/done1abc.../buy", {
586
+ body: { minAmountOut: "100" },
587
+ funds: { uusd: "1000" },
588
+ });
589
+
590
+ // Query
591
+ const price = await Done.query<{ amount: string }>("/done1abc.../price");
592
+
593
+ // Subscription
594
+ const stop = Done.subscribe(
595
+ "/done1abc.../events",
596
+ "PriceChange",
597
+ (event) => console.log("price changed:", event),
598
+ );
599
+ ```
package/dist/auth.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { toSignDoc } from "./envelope";
1
+ import { toSignDoc } from "./envelope-builder";
2
2
  import type { EnvelopeBuildContext, EnvelopeBuilder, EnvelopeMetadata, EnvelopeRole } from "./types";
3
3
  type MaybePromise<T> = T | Promise<T>;
4
4
  type ValueOrFactory<T> = T | ((ctx: EnvelopeBuildContext) => MaybePromise<T>);
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,SAAS,EAEV,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAEV,oBAAoB,EAEpB,eAAe,EACf,gBAAgB,EAChB,YAAY,EAGb,MAAM,SAAS,CAAC;AAEjB,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AACtC,KAAK,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,oBAAoB,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9E,UAAU,oBAAoB;IAC5B,KAAK,CAAC,EAAE,cAAc,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC3C,SAAS,CAAC,EAAE,cAAc,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,cAAc,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,6BAA8B,SAAQ,oBAAoB;IACzE,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9B,SAAS,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,SAAS,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,CACJ,OAAO,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,EACrC,GAAG,EAAE,oBAAoB,KACtB,YAAY,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,6BAA8B,SAAQ,oBAAoB;IACzE,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9B,SAAS,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,CACJ,OAAO,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,EACrC,GAAG,EAAE,oBAAoB,KACtB,YAAY,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;CACzC;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,6BAA6B,GACrC,eAAe,CA6CjB;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,6BAA6B,GACrC,eAAe,CA2CjB"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EAEV,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAEV,oBAAoB,EAEpB,eAAe,EACf,gBAAgB,EAChB,YAAY,EAGb,MAAM,SAAS,CAAC;AAEjB,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AACtC,KAAK,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,oBAAoB,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9E,UAAU,oBAAoB;IAC5B,KAAK,CAAC,EAAE,cAAc,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC3C,SAAS,CAAC,EAAE,cAAc,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,cAAc,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,6BAA8B,SAAQ,oBAAoB;IACzE,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9B,SAAS,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,SAAS,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,CACJ,OAAO,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,EACrC,GAAG,EAAE,oBAAoB,KACtB,YAAY,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,6BAA8B,SAAQ,oBAAoB;IACzE,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9B,SAAS,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,CACJ,OAAO,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,EACrC,GAAG,EAAE,oBAAoB,KACtB,YAAY,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;CACzC;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,6BAA6B,GACrC,eAAe,CA6CjB;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,6BAA6B,GACrC,eAAe,CA2CjB"}