@kynesyslabs/demosdk 4.0.11 → 4.0.13

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 (82) hide show
  1. package/build/abstraction/Identities.js +10 -2
  2. package/build/abstraction/Identities.js.map +1 -1
  3. package/build/l2ps/channel/finalize.d.ts +63 -0
  4. package/build/l2ps/channel/finalize.js +85 -0
  5. package/build/l2ps/channel/finalize.js.map +1 -0
  6. package/build/l2ps/channel/index.d.ts +3 -0
  7. package/build/l2ps/channel/index.js +3 -0
  8. package/build/l2ps/channel/index.js.map +1 -1
  9. package/build/l2ps/channel/negotiate.d.ts +106 -0
  10. package/build/l2ps/channel/negotiate.js +206 -0
  11. package/build/l2ps/channel/negotiate.js.map +1 -0
  12. package/build/l2ps/channel/transport.d.ts +117 -0
  13. package/build/l2ps/channel/transport.js +178 -0
  14. package/build/l2ps/channel/transport.js.map +1 -0
  15. package/build/websdk/BroadcastFailedError.js.map +1 -1
  16. package/build/websdk/DemosTransactions.d.ts +2 -2
  17. package/build/websdk/DemosTransactions.js +3 -3
  18. package/build/websdk/TransportError.js.map +1 -1
  19. package/build/websdk/demosclass.d.ts +81 -1
  20. package/build/websdk/demosclass.js +84 -1
  21. package/build/websdk/demosclass.js.map +1 -1
  22. package/build/websdk/index.d.ts +1 -0
  23. package/build/websdk/index.js +3 -0
  24. package/build/websdk/index.js.map +1 -1
  25. package/build/websdk/programmatic/ProgrammaticTx.d.ts +118 -0
  26. package/build/websdk/programmatic/ProgrammaticTx.js +56 -0
  27. package/build/websdk/programmatic/ProgrammaticTx.js.map +1 -0
  28. package/build/websdk/programmatic/attest.d.ts +396 -0
  29. package/build/websdk/programmatic/attest.js +398 -0
  30. package/build/websdk/programmatic/attest.js.map +1 -0
  31. package/build/websdk/programmatic/bridge.d.ts +36 -0
  32. package/build/websdk/programmatic/bridge.js +37 -0
  33. package/build/websdk/programmatic/bridge.js.map +1 -0
  34. package/build/websdk/programmatic/context.d.ts +26 -0
  35. package/build/websdk/programmatic/context.js +9 -0
  36. package/build/websdk/programmatic/context.js.map +1 -0
  37. package/build/websdk/programmatic/contracts.d.ts +79 -0
  38. package/build/websdk/programmatic/contracts.js +81 -0
  39. package/build/websdk/programmatic/contracts.js.map +1 -0
  40. package/build/websdk/programmatic/d402.d.ts +33 -0
  41. package/build/websdk/programmatic/d402.js +35 -0
  42. package/build/websdk/programmatic/d402.js.map +1 -0
  43. package/build/websdk/programmatic/demoswork.d.ts +37 -0
  44. package/build/websdk/programmatic/demoswork.js +38 -0
  45. package/build/websdk/programmatic/demoswork.js.map +1 -0
  46. package/build/websdk/programmatic/errors.d.ts +20 -0
  47. package/build/websdk/programmatic/errors.js +24 -0
  48. package/build/websdk/programmatic/errors.js.map +1 -0
  49. package/build/websdk/programmatic/escrow.d.ts +75 -0
  50. package/build/websdk/programmatic/escrow.js +74 -0
  51. package/build/websdk/programmatic/escrow.js.map +1 -0
  52. package/build/websdk/programmatic/governance.d.ts +59 -0
  53. package/build/websdk/programmatic/governance.js +44 -0
  54. package/build/websdk/programmatic/governance.js.map +1 -0
  55. package/build/websdk/programmatic/index.d.ts +30 -0
  56. package/build/websdk/programmatic/index.js +31 -0
  57. package/build/websdk/programmatic/index.js.map +1 -0
  58. package/build/websdk/programmatic/ipfs.d.ts +74 -0
  59. package/build/websdk/programmatic/ipfs.js +103 -0
  60. package/build/websdk/programmatic/ipfs.js.map +1 -0
  61. package/build/websdk/programmatic/pay.d.ts +36 -0
  62. package/build/websdk/programmatic/pay.js +37 -0
  63. package/build/websdk/programmatic/pay.js.map +1 -0
  64. package/build/websdk/programmatic/runner.d.ts +30 -0
  65. package/build/websdk/programmatic/runner.js +186 -0
  66. package/build/websdk/programmatic/runner.js.map +1 -0
  67. package/build/websdk/programmatic/storage.d.ts +49 -0
  68. package/build/websdk/programmatic/storage.js +49 -0
  69. package/build/websdk/programmatic/storage.js.map +1 -0
  70. package/build/websdk/programmatic/tokens.d.ts +155 -0
  71. package/build/websdk/programmatic/tokens.js +157 -0
  72. package/build/websdk/programmatic/tokens.js.map +1 -0
  73. package/build/websdk/programmatic/types.d.ts +95 -0
  74. package/build/websdk/programmatic/types.js +8 -0
  75. package/build/websdk/programmatic/types.js.map +1 -0
  76. package/build/websdk/programmatic/validator.d.ts +63 -0
  77. package/build/websdk/programmatic/validator.js +64 -0
  78. package/build/websdk/programmatic/validator.js.map +1 -0
  79. package/build/websdk/programmatic/xm.d.ts +36 -0
  80. package/build/websdk/programmatic/xm.js +37 -0
  81. package/build/websdk/programmatic/xm.js.map +1 -0
  82. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"negotiate.js","sourceRoot":"","sources":["../../../../src/l2ps/channel/negotiate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * SR-4 WI-A — Channel-over-L2PS transport adapter.
3
+ *
4
+ * The DACS channel layer (`ChannelSession`) is transport-agnostic: it
5
+ * produces signed `ChannelMessage` envelopes and verifies incoming ones,
6
+ * but does not move bytes. The L2PS instant-messaging layer
7
+ * (`L2PSMessagingPeer`) moves encrypted bytes between subnet members but
8
+ * knows nothing about channel envelopes. This adapter bridges the two:
9
+ * it serialises + encrypts an outgoing envelope onto the messaging
10
+ * transport, and on the receive side decrypts, deserialises, and feeds
11
+ * envelopes into the session **in strict sequence order**.
12
+ *
13
+ * Why a reorder buffer is mandatory:
14
+ * `ChannelSession.receiveIncoming` accepts any sequence strictly greater
15
+ * than the highest it has seen and then advances its counter to that
16
+ * value — so a *gap* (seq N+2 arriving before N+1) is not rejected, it
17
+ * permanently skips the missing messages. The L2PS transport delivers by
18
+ * timestamp and replays an offline queue, so out-of-order arrival is
19
+ * normal. This adapter therefore only hands the session the next
20
+ * contiguous sequence and buffers anything ahead of the gap until it
21
+ * fills.
22
+ *
23
+ * Scope / assumptions:
24
+ * - The shared per-channel sequence counter assumes turn-based messaging
25
+ * (DACS negotiation is offer → counter → accept; a party waits for the
26
+ * counter before replying). Two parties emitting the same sequence
27
+ * concurrently is out of scope for SR-4 v1; such a colliding inbound
28
+ * message (seq <= already-applied) is dropped as a duplicate.
29
+ * - Membership is the channel's `members`; the transport sends to every
30
+ * member except self. Confidentiality is the subnet AES key (only
31
+ * members hold it) — CH-2.
32
+ */
33
+ import type { ChannelMessage, ChannelMessageType } from "./types";
34
+ /**
35
+ * Minimal surface of `ChannelSession` the adapter depends on. Declared
36
+ * structurally so tests can inject a fake without real signing keys.
37
+ */
38
+ export interface ChannelSessionLike {
39
+ readonly channelId: string;
40
+ sendOutgoing(opts: {
41
+ type: ChannelMessageType;
42
+ body: unknown;
43
+ sentAt?: number;
44
+ repliesTo?: number;
45
+ }): Promise<ChannelMessage>;
46
+ receiveIncoming(msg: ChannelMessage): Promise<void>;
47
+ }
48
+ /** Wire shape the L2PS messaging transport carries (ciphertext + nonce, base64). */
49
+ export interface SerializedEncryptedMessage {
50
+ ciphertext: string;
51
+ nonce: string;
52
+ ephemeralKey?: string;
53
+ }
54
+ /** Incoming payload the messaging peer hands to an onMessage handler. */
55
+ export interface IncomingMessagePayload {
56
+ from: string;
57
+ encrypted: SerializedEncryptedMessage;
58
+ messageHash: string;
59
+ offline?: boolean;
60
+ }
61
+ /**
62
+ * Minimal surface of `L2PSMessagingPeer` the adapter depends on.
63
+ * Declared structurally for the same reason as `ChannelSessionLike`.
64
+ */
65
+ export interface L2PSMessagingPeerLike {
66
+ send(to: string, encrypted: SerializedEncryptedMessage, messageHash: string): Promise<unknown>;
67
+ onMessage(handler: (payload: IncomingMessagePayload) => void): void;
68
+ }
69
+ export interface L2PSChannelTransportOpts {
70
+ session: ChannelSessionLike;
71
+ peer: L2PSMessagingPeerLike;
72
+ /** Subnet AES-256 key (raw 32 bytes) — only members hold it (CH-2). */
73
+ sharedKey: Uint8Array;
74
+ /**
75
+ * Recipient public keys to deliver to (every channel member except
76
+ * self), in the format the messaging peer routes on.
77
+ */
78
+ recipients: string[];
79
+ /** Called with each envelope once it has been applied in order. */
80
+ onMessage?: (msg: ChannelMessage) => void;
81
+ /** Called on a decrypt / parse / verification failure. */
82
+ onError?: (err: Error) => void;
83
+ }
84
+ export declare class L2PSChannelTransport {
85
+ private readonly session;
86
+ private readonly peer;
87
+ private readonly sharedKey;
88
+ private readonly recipients;
89
+ private readonly onMessage?;
90
+ private readonly onError?;
91
+ /** Sequences seen ahead of the gap, awaiting contiguous application. */
92
+ private readonly buffer;
93
+ /** Highest contiguous sequence applied locally (sent or received). */
94
+ private appliedSeq;
95
+ /** Serialises drain() so concurrent inbound frames can't interleave. */
96
+ private draining;
97
+ private started;
98
+ constructor(opts: L2PSChannelTransportOpts);
99
+ /** Wire the peer's inbound handler. Call once. */
100
+ start(): void;
101
+ /**
102
+ * Build + sign the next outgoing envelope via the session, encrypt
103
+ * it under the subnet key, and deliver to every recipient.
104
+ */
105
+ send(opts: {
106
+ type: ChannelMessageType;
107
+ body: unknown;
108
+ repliesTo?: number;
109
+ }): Promise<ChannelMessage>;
110
+ private ingest;
111
+ /** Apply every buffered message that is now contiguous with appliedSeq. */
112
+ private drain;
113
+ /** Count of out-of-order messages currently held awaiting the gap. */
114
+ get bufferedCount(): number;
115
+ private encrypt;
116
+ private decrypt;
117
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * SR-4 WI-A — Channel-over-L2PS transport adapter.
3
+ *
4
+ * The DACS channel layer (`ChannelSession`) is transport-agnostic: it
5
+ * produces signed `ChannelMessage` envelopes and verifies incoming ones,
6
+ * but does not move bytes. The L2PS instant-messaging layer
7
+ * (`L2PSMessagingPeer`) moves encrypted bytes between subnet members but
8
+ * knows nothing about channel envelopes. This adapter bridges the two:
9
+ * it serialises + encrypts an outgoing envelope onto the messaging
10
+ * transport, and on the receive side decrypts, deserialises, and feeds
11
+ * envelopes into the session **in strict sequence order**.
12
+ *
13
+ * Why a reorder buffer is mandatory:
14
+ * `ChannelSession.receiveIncoming` accepts any sequence strictly greater
15
+ * than the highest it has seen and then advances its counter to that
16
+ * value — so a *gap* (seq N+2 arriving before N+1) is not rejected, it
17
+ * permanently skips the missing messages. The L2PS transport delivers by
18
+ * timestamp and replays an offline queue, so out-of-order arrival is
19
+ * normal. This adapter therefore only hands the session the next
20
+ * contiguous sequence and buffers anything ahead of the gap until it
21
+ * fills.
22
+ *
23
+ * Scope / assumptions:
24
+ * - The shared per-channel sequence counter assumes turn-based messaging
25
+ * (DACS negotiation is offer → counter → accept; a party waits for the
26
+ * counter before replying). Two parties emitting the same sequence
27
+ * concurrently is out of scope for SR-4 v1; such a colliding inbound
28
+ * message (seq <= already-applied) is dropped as a duplicate.
29
+ * - Membership is the channel's `members`; the transport sends to every
30
+ * member except self. Confidentiality is the subnet AES key (only
31
+ * members hold it) — CH-2.
32
+ */
33
+ /**
34
+ * Max number of sequences a buffered inbound frame may sit ahead of the
35
+ * current contiguous point before it is dropped, bounding reorder-buffer
36
+ * memory. Turn-based negotiation never legitimately exceeds this.
37
+ */
38
+ const MAX_REORDER_AHEAD = 256;
39
+ export class L2PSChannelTransport {
40
+ constructor(opts) {
41
+ /** Sequences seen ahead of the gap, awaiting contiguous application. */
42
+ this.buffer = new Map();
43
+ /** Highest contiguous sequence applied locally (sent or received). */
44
+ this.appliedSeq = 0;
45
+ /** Serialises drain() so concurrent inbound frames can't interleave. */
46
+ this.draining = Promise.resolve();
47
+ this.started = false;
48
+ this.session = opts.session;
49
+ this.peer = opts.peer;
50
+ this.sharedKey = opts.sharedKey;
51
+ this.recipients = opts.recipients;
52
+ this.onMessage = opts.onMessage;
53
+ this.onError = opts.onError;
54
+ }
55
+ /** Wire the peer's inbound handler. Call once. */
56
+ start() {
57
+ if (this.started)
58
+ throw new Error("L2PSChannelTransport: already started");
59
+ this.started = true;
60
+ this.peer.onMessage(payload => {
61
+ // Chain onto `draining` so frames are processed one at a time
62
+ // in arrival order; each appends to the buffer then drains.
63
+ this.draining = this.draining
64
+ .then(() => this.ingest(payload))
65
+ .catch(err => this.onError?.(err));
66
+ });
67
+ }
68
+ /**
69
+ * Build + sign the next outgoing envelope via the session, encrypt
70
+ * it under the subnet key, and deliver to every recipient.
71
+ */
72
+ async send(opts) {
73
+ const signed = await this.session.sendOutgoing(opts);
74
+ const encrypted = await this.encrypt(JSON.stringify(signed));
75
+ const messageHash = signed.signature.signature; // unique per signed envelope
76
+ // Deliver to every recipient BEFORE committing the sequence locally.
77
+ // If any send rejects, the throw propagates here and appliedSeq is
78
+ // left untouched, so a retry re-emits the same sequence rather than
79
+ // skipping ahead and stranding peers behind a reorder gap. (Recipients
80
+ // that did receive it will drop the duplicate on resend — seq <=
81
+ // appliedSeq — so at-least-once delivery is safe.)
82
+ for (const to of this.recipients) {
83
+ await this.peer.send(to, encrypted, messageHash);
84
+ }
85
+ // Our own send advances the shared per-channel counter; record it
86
+ // so we expect the peer's reply at appliedSeq + 1.
87
+ if (signed.sequence > this.appliedSeq)
88
+ this.appliedSeq = signed.sequence;
89
+ return signed;
90
+ }
91
+ async ingest(payload) {
92
+ let msg;
93
+ try {
94
+ const json = await this.decrypt(payload.encrypted);
95
+ msg = JSON.parse(json);
96
+ }
97
+ catch (e) {
98
+ throw new Error(`L2PSChannelTransport: failed to decrypt/parse inbound frame from ${payload.from}: ${e.message}`);
99
+ }
100
+ // Ignore traffic for other channels sharing the same subnet.
101
+ if (msg.channelId !== this.session.channelId)
102
+ return;
103
+ // Duplicate / already-applied (or a colliding concurrent send): drop.
104
+ if (msg.sequence <= this.appliedSeq)
105
+ return;
106
+ // Bound the reorder window: a member could otherwise stream many
107
+ // validly-encrypted frames at far-future sequences without ever
108
+ // filling the gap, growing `buffer` without limit. Drop anything
109
+ // beyond MAX_REORDER_AHEAD of the current contiguous point — a
110
+ // legitimate turn-based negotiation never runs that far ahead, and
111
+ // a dropped frame is re-deliverable (the offline queue replays it
112
+ // once the gap closes and appliedSeq advances).
113
+ if (msg.sequence > this.appliedSeq + MAX_REORDER_AHEAD) {
114
+ this.onError?.(new Error(`L2PSChannelTransport: dropping seq ${msg.sequence} — ` +
115
+ `more than ${MAX_REORDER_AHEAD} ahead of applied ${this.appliedSeq}`));
116
+ return;
117
+ }
118
+ // Buffer; a later sequence with the same value would be a protocol
119
+ // error — keep the first seen.
120
+ if (!this.buffer.has(msg.sequence))
121
+ this.buffer.set(msg.sequence, msg);
122
+ await this.drain();
123
+ }
124
+ /** Apply every buffered message that is now contiguous with appliedSeq. */
125
+ async drain() {
126
+ // Sequence counter is shared across both directions, so the next
127
+ // expected inbound is appliedSeq + 1.
128
+ let next = this.buffer.get(this.appliedSeq + 1);
129
+ while (next) {
130
+ this.buffer.delete(next.sequence);
131
+ // Throws on tamper (bad signature, wrong sender, channelId
132
+ // mismatch) — propagate as channel-fatal per §8.12.
133
+ await this.session.receiveIncoming(next);
134
+ this.appliedSeq = next.sequence;
135
+ this.onMessage?.(next);
136
+ next = this.buffer.get(this.appliedSeq + 1);
137
+ }
138
+ }
139
+ /** Count of out-of-order messages currently held awaiting the gap. */
140
+ get bufferedCount() {
141
+ return this.buffer.size;
142
+ }
143
+ // ── AES-256-GCM (Web Crypto) — matches the messaging wire format:
144
+ // ciphertext (with auth tag) + 12-byte nonce, both base64. ──
145
+ async encrypt(plaintext) {
146
+ const nonce = crypto.getRandomValues(new Uint8Array(12));
147
+ const key = await crypto.subtle.importKey("raw", keyBytes(this.sharedKey), "AES-GCM", false, ["encrypt"]);
148
+ const cipher = await crypto.subtle.encrypt({ name: "AES-GCM", iv: nonce }, key, new TextEncoder().encode(plaintext));
149
+ return {
150
+ ciphertext: bytesToBase64(new Uint8Array(cipher)),
151
+ nonce: bytesToBase64(nonce),
152
+ };
153
+ }
154
+ async decrypt(enc) {
155
+ const key = await crypto.subtle.importKey("raw", keyBytes(this.sharedKey), "AES-GCM", false, ["decrypt"]);
156
+ const plain = await crypto.subtle.decrypt({ name: "AES-GCM", iv: base64ToBytes(enc.nonce) }, key, base64ToBytes(enc.ciphertext));
157
+ return new TextDecoder().decode(plain);
158
+ }
159
+ }
160
+ /**
161
+ * Return a standalone `ArrayBuffer` holding exactly the bytes of `view`.
162
+ * `view.buffer` exposes the whole backing buffer, which for a `subarray`
163
+ * (e.g. a 32-byte key sliced out of a larger buffer) is longer than the
164
+ * view — Web Crypto would then see the wrong length / wrong bytes and
165
+ * reject or mis-key the AES import. Copying the exact `[byteOffset,
166
+ * byteOffset+byteLength)` window guarantees the key import sees only the
167
+ * intended bytes.
168
+ */
169
+ function keyBytes(view) {
170
+ return view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);
171
+ }
172
+ function bytesToBase64(bytes) {
173
+ return Buffer.from(bytes).toString("base64");
174
+ }
175
+ function base64ToBytes(b64) {
176
+ return new Uint8Array(Buffer.from(b64, "base64"));
177
+ }
178
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../../src/l2ps/channel/transport.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"BroadcastFailedError.js","sourceRoot":"","sources":["../../../src/websdk/BroadcastFailedError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAI3C,YAAY,IAA0D;QAClE,MAAM,YAAY,GACb,IAAI,CAAC,KAAa,EAAE,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,CAAA;QACnE,KAAK,CACD,IAAI,CAAC,OAAO;YACR,iEAAiE,IAAI,CAAC,MAAM,MAAM,YAAY,EAAE,CACvG,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;QAClC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;IAC3B,CAAC;CACJ"}
1
+ {"version":3,"file":"BroadcastFailedError.js","sourceRoot":"","sources":["../../../src/websdk/BroadcastFailedError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAM3C,YAAY,IAA0D;QAClE,MAAM,YAAY,GACb,IAAI,CAAC,KAAa,EAAE,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,CAAA;QACnE,KAAK,CACD,IAAI,CAAC,OAAO;YACR,iEAAiE,IAAI,CAAC,MAAM,MAAM,YAAY,EAAE,CACvG,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;QAClC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;IAC3B,CAAC;CACJ"}
@@ -98,7 +98,7 @@ export declare const DemosTransactions: {
98
98
  * Broadcast a confirmed transaction and wait for inclusion.
99
99
  *
100
100
  * Polls the node's `getTransactionStatus` RPC until the tx is observed
101
- * `included` or `failed`, or until `opts.timeoutMs` elapses (default 30s).
101
+ * `included` or `failed`, or until `opts.timeoutMs` elapses (default 60s).
102
102
  *
103
103
  * Use this when you want a single call with a deterministic outcome.
104
104
  * Use plain `broadcast()` when you want to handle async confirmation
@@ -117,7 +117,7 @@ export declare const DemosTransactions: {
117
117
  *
118
118
  * @param validationData - The validity data of the transaction (from `confirm`)
119
119
  * @param demos - The demos instance
120
- * @param opts.timeoutMs - Total time to wait for inclusion. Defaults to 30_000.
120
+ * @param opts.timeoutMs - Total time to wait for inclusion. Defaults to 60_000.
121
121
  * @param opts.pollIntervalMs - Delay between status polls. Defaults to 500.
122
122
  * @param opts.failFastOnBroadcastError - If true, throw `BroadcastFailedError`
123
123
  * immediately when the broadcast can't contact the node. Defaults to false.
@@ -271,7 +271,7 @@ export const DemosTransactions = {
271
271
  * Broadcast a confirmed transaction and wait for inclusion.
272
272
  *
273
273
  * Polls the node's `getTransactionStatus` RPC until the tx is observed
274
- * `included` or `failed`, or until `opts.timeoutMs` elapses (default 30s).
274
+ * `included` or `failed`, or until `opts.timeoutMs` elapses (default 60s).
275
275
  *
276
276
  * Use this when you want a single call with a deterministic outcome.
277
277
  * Use plain `broadcast()` when you want to handle async confirmation
@@ -290,7 +290,7 @@ export const DemosTransactions = {
290
290
  *
291
291
  * @param validationData - The validity data of the transaction (from `confirm`)
292
292
  * @param demos - The demos instance
293
- * @param opts.timeoutMs - Total time to wait for inclusion. Defaults to 30_000.
293
+ * @param opts.timeoutMs - Total time to wait for inclusion. Defaults to 60_000.
294
294
  * @param opts.pollIntervalMs - Delay between status polls. Defaults to 500.
295
295
  * @param opts.failFastOnBroadcastError - If true, throw `BroadcastFailedError`
296
296
  * immediately when the broadcast can't contact the node. Defaults to false.
@@ -298,7 +298,7 @@ export const DemosTransactions = {
298
298
  * @returns The original broadcast response and the terminal status.
299
299
  */
300
300
  broadcastAndWait: async function (validationData, demos, opts) {
301
- const timeout = opts?.timeoutMs ?? 30000;
301
+ const timeout = opts?.timeoutMs ?? 60000;
302
302
  const pollInterval = opts?.pollIntervalMs ?? 500;
303
303
  const failFast = opts?.failFastOnBroadcastError ?? false;
304
304
  // Extract the tx hash from the validity data before broadcasting so
@@ -1 +1 @@
1
- {"version":3,"file":"TransportError.js","sourceRoot":"","sources":["../../../src/websdk/TransportError.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,OAAO,cAAe,SAAQ,KAAK;IAIrC,YAAY,OAAe,EAAE,IAA0C;QACnE,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAA;QAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;QAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;IAC3B,CAAC;CACJ"}
1
+ {"version":3,"file":"TransportError.js","sourceRoot":"","sources":["../../../src/websdk/TransportError.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,OAAO,cAAe,SAAQ,KAAK;IAMrC,YAAY,OAAe,EAAE,IAA0C;QACnE,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAA;QAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;QAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;IAC3B,CAAC;CACJ"}
@@ -7,6 +7,7 @@ import type { ValidatorInfo } from "../types/validator/ValidatorTypes";
7
7
  import type { NetworkParameters, NetworkUpgradeProposal, ProposalVoteInfo } from "../types/blockchain/NetworkParameters";
8
8
  import { RPCRequest, RPCResponse, RPCResponseWithValidityData } from "../types/communication/rpc";
9
9
  import { IKeyPair } from "./types/KeyPair";
10
+ import { type ProgrammaticTx } from "./programmatic";
10
11
  import { UnifiedCrypto } from "../encryption/unifiedCrypto";
11
12
  import { type NetworkInfo } from "../denomination/networkInfo";
12
13
  import { TweetSimplified } from "../types";
@@ -67,6 +68,50 @@ export declare class Demos {
67
68
  * @returns Whether the connection was successful
68
69
  */
69
70
  connect(rpc_url: string): Promise<boolean>;
71
+ /**
72
+ * One-call bootstrap: connect to a node and (optionally) a wallet, then
73
+ * return the ready instance for immediate use with `demos.run.*`.
74
+ *
75
+ * Convenience wrapper over {@link connect} + {@link connectWallet} — no
76
+ * new behaviour, just the two-step setup collapsed into one. Omit
77
+ * `wallet` to connect read-only.
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * import { Demos } from "@kynesyslabs/demosdk/websdk"
82
+ * const demos = await Demos.start("https://node2.demos.sh", mnemonic)
83
+ * await demos.run.pay("0x...", 100n)
84
+ * ```
85
+ *
86
+ * @param rpc_url - The URL of the demos node.
87
+ * @param wallet - Master seed / mnemonic (string) or raw seed bytes.
88
+ * Omit to connect without a wallet.
89
+ * @param walletOptions - Forwarded to {@link connectWallet}.
90
+ * @returns This connected Demos instance.
91
+ */
92
+ start(rpc_url: string, wallet?: string | Uint8Array, walletOptions?: {
93
+ algorithm?: SigningAlgorithm;
94
+ dual_sign?: boolean;
95
+ }): Promise<this>;
96
+ /**
97
+ * Static one-call bootstrap over the shared singleton — starts
98
+ * {@link Demos.instance} and returns it ready for `demos.run.*`.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * const demos = await Demos.start("https://node2.demos.sh", mnemonic)
103
+ * await demos.run.pay("0x...", 100n)
104
+ * ```
105
+ *
106
+ * @param rpc_url - The URL of the demos node.
107
+ * @param wallet - Master seed / mnemonic (string) or raw seed bytes.
108
+ * @param walletOptions - Forwarded to {@link connectWallet}.
109
+ * @returns The started shared Demos instance.
110
+ */
111
+ static start(rpc_url: string, wallet?: string | Uint8Array, walletOptions?: {
112
+ algorithm?: SigningAlgorithm;
113
+ dual_sign?: boolean;
114
+ }): Promise<Demos>;
70
115
  /**
71
116
  * Connects to a Demos wallet using the provided master seed.
72
117
  *
@@ -202,7 +247,7 @@ export declare class Demos {
202
247
  * handle async confirmation yourself.
203
248
  *
204
249
  * @param validationData - The validity data of the transaction
205
- * @param opts.timeoutMs - Total time to wait. Defaults to 30_000.
250
+ * @param opts.timeoutMs - Total time to wait. Defaults to 60_000.
206
251
  * @param opts.pollIntervalMs - Delay between polls. Defaults to 500.
207
252
  */
208
253
  broadcastAndWait(validationData: RPCResponseWithValidityData, opts?: {
@@ -654,6 +699,41 @@ export declare class Demos {
654
699
  }, demos: Demos): Promise<Transaction>;
655
700
  voteOnUpgrade(proposalId: string, approve: boolean, demos: Demos): Promise<Transaction>;
656
701
  };
702
+ private _run?;
703
+ /**
704
+ * Programmatic transaction facade — one call per transaction type.
705
+ *
706
+ * Collapses the classic `build → sign → confirm → broadcast` flow into a
707
+ * single method per operation (`run.pay`, `run.attest.*`, `run.tokens.*`,
708
+ * …) that auto-broadcasts within a configurable fee ceiling (default
709
+ * 5 DEM). Additive: the classic `pay`/`confirm`/`broadcast` methods are
710
+ * unchanged.
711
+ *
712
+ * Built lazily on first access (and memoised) rather than in the
713
+ * constructor. Two reasons: (1) the singleton `demos = Demos.instance` is
714
+ * created at import time, so eagerly *constructing* the namespaces during
715
+ * `new Demos()` — which reach into `@/abstraction`, tokens, contracts — is
716
+ * the part that risked tripping the websdk↔abstraction import cycle;
717
+ * deferring construction removes that crash vector. (2) it avoids building
718
+ * ~6 objects on every `new Demos()` that many callers never touch.
719
+ *
720
+ * Note: the programmatic module graph is still *loaded* when this file is
721
+ * imported (a static `import` cannot be deferred in ESM). That residual
722
+ * cycle is benign — no module reads a cross-cycle binding at evaluation
723
+ * time, only inside functions — and has been narrowed by importing
724
+ * `Identities` directly from `@/abstraction/Identities` rather than via the
725
+ * `@/abstraction` barrel.
726
+ *
727
+ * @example
728
+ * ```ts
729
+ * // one-call payment, auto-broadcast within the 5 DEM fee cap
730
+ * await demos.run.pay("0x...", 100n)
731
+ * // build + confirm only, broadcast yourself later
732
+ * const r = await demos.run.pay("0x...", 100n, { confirm: "manual" })
733
+ * await demos.broadcast(r.validityData)
734
+ * ```
735
+ */
736
+ get run(): ProgrammaticTx;
657
737
  DemosTransactions: {
658
738
  empty: () => Transaction;
659
739
  prepare: (data?: any) => Promise<Transaction>;
@@ -12,6 +12,7 @@ import { DemosWebAuth } from "./DemosWebAuth.js";
12
12
  import { prepareXMPayload } from "./XMTransactions.js";
13
13
  import { _required as required } from "./utils/required.js";
14
14
  import { web2Calls } from "./Web2Calls.js";
15
+ import { createProgrammaticTx, } from "./programmatic/index.js";
15
16
  import { hexToUint8Array, uint8ArrayToHex, UnifiedCrypto, } from "../encryption/unifiedCrypto.js";
16
17
  import { GCRGeneration } from "./GCRGeneration.js";
17
18
  import { Hashing } from "../encryption/Hashing.js";
@@ -276,6 +277,52 @@ export class Demos {
276
277
  this.connected = true;
277
278
  return this.connected;
278
279
  }
280
+ /**
281
+ * One-call bootstrap: connect to a node and (optionally) a wallet, then
282
+ * return the ready instance for immediate use with `demos.run.*`.
283
+ *
284
+ * Convenience wrapper over {@link connect} + {@link connectWallet} — no
285
+ * new behaviour, just the two-step setup collapsed into one. Omit
286
+ * `wallet` to connect read-only.
287
+ *
288
+ * @example
289
+ * ```ts
290
+ * import { Demos } from "@kynesyslabs/demosdk/websdk"
291
+ * const demos = await Demos.start("https://node2.demos.sh", mnemonic)
292
+ * await demos.run.pay("0x...", 100n)
293
+ * ```
294
+ *
295
+ * @param rpc_url - The URL of the demos node.
296
+ * @param wallet - Master seed / mnemonic (string) or raw seed bytes.
297
+ * Omit to connect without a wallet.
298
+ * @param walletOptions - Forwarded to {@link connectWallet}.
299
+ * @returns This connected Demos instance.
300
+ */
301
+ async start(rpc_url, wallet, walletOptions) {
302
+ await this.connect(rpc_url);
303
+ if (wallet !== undefined) {
304
+ await this.connectWallet(wallet, walletOptions);
305
+ }
306
+ return this;
307
+ }
308
+ /**
309
+ * Static one-call bootstrap over the shared singleton — starts
310
+ * {@link Demos.instance} and returns it ready for `demos.run.*`.
311
+ *
312
+ * @example
313
+ * ```ts
314
+ * const demos = await Demos.start("https://node2.demos.sh", mnemonic)
315
+ * await demos.run.pay("0x...", 100n)
316
+ * ```
317
+ *
318
+ * @param rpc_url - The URL of the demos node.
319
+ * @param wallet - Master seed / mnemonic (string) or raw seed bytes.
320
+ * @param walletOptions - Forwarded to {@link connectWallet}.
321
+ * @returns The started shared Demos instance.
322
+ */
323
+ static async start(rpc_url, wallet, walletOptions) {
324
+ return Demos.instance.start(rpc_url, wallet, walletOptions);
325
+ }
279
326
  /**
280
327
  * Connects to a Demos wallet using the provided master seed.
281
328
  *
@@ -454,7 +501,7 @@ export class Demos {
454
501
  * handle async confirmation yourself.
455
502
  *
456
503
  * @param validationData - The validity data of the transaction
457
- * @param opts.timeoutMs - Total time to wait. Defaults to 30_000.
504
+ * @param opts.timeoutMs - Total time to wait. Defaults to 60_000.
458
505
  * @param opts.pollIntervalMs - Delay between polls. Defaults to 500.
459
506
  */
460
507
  broadcastAndWait(validationData, opts) {
@@ -1417,6 +1464,42 @@ export class Demos {
1417
1464
  }
1418
1465
  return tlsn;
1419
1466
  }
1467
+ /**
1468
+ * Programmatic transaction facade — one call per transaction type.
1469
+ *
1470
+ * Collapses the classic `build → sign → confirm → broadcast` flow into a
1471
+ * single method per operation (`run.pay`, `run.attest.*`, `run.tokens.*`,
1472
+ * …) that auto-broadcasts within a configurable fee ceiling (default
1473
+ * 5 DEM). Additive: the classic `pay`/`confirm`/`broadcast` methods are
1474
+ * unchanged.
1475
+ *
1476
+ * Built lazily on first access (and memoised) rather than in the
1477
+ * constructor. Two reasons: (1) the singleton `demos = Demos.instance` is
1478
+ * created at import time, so eagerly *constructing* the namespaces during
1479
+ * `new Demos()` — which reach into `@/abstraction`, tokens, contracts — is
1480
+ * the part that risked tripping the websdk↔abstraction import cycle;
1481
+ * deferring construction removes that crash vector. (2) it avoids building
1482
+ * ~6 objects on every `new Demos()` that many callers never touch.
1483
+ *
1484
+ * Note: the programmatic module graph is still *loaded* when this file is
1485
+ * imported (a static `import` cannot be deferred in ESM). That residual
1486
+ * cycle is benign — no module reads a cross-cycle binding at evaluation
1487
+ * time, only inside functions — and has been narrowed by importing
1488
+ * `Identities` directly from `@/abstraction/Identities` rather than via the
1489
+ * `@/abstraction` barrel.
1490
+ *
1491
+ * @example
1492
+ * ```ts
1493
+ * // one-call payment, auto-broadcast within the 5 DEM fee cap
1494
+ * await demos.run.pay("0x...", 100n)
1495
+ * // build + confirm only, broadcast yourself later
1496
+ * const r = await demos.run.pay("0x...", 100n, { confirm: "manual" })
1497
+ * await demos.broadcast(r.validityData)
1498
+ * ```
1499
+ */
1500
+ get run() {
1501
+ return (this._run ?? (this._run = createProgrammaticTx(this)));
1502
+ }
1420
1503
  }
1421
1504
  Demos._instance = null;
1422
1505
  /**