@rougechain/sdk 0.8.3 → 0.9.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
@@ -8,7 +8,7 @@
8
8
 
9
9
  <p align="center">
10
10
  <strong>Build quantum-safe dApps on RougeChain</strong><br />
11
- Transfers · DEX · NFTs · Shielded Transactions · Bridge · Rollups · Mail · Messenger
11
+ Transfers · DEX · NFTs · Shielded Transactions · Bridge · Rollups · Dynamic Fees · Finality Proofs · WebSocket · Mail · Messenger
12
12
  </p>
13
13
 
14
14
  <p align="center">
@@ -67,6 +67,10 @@ const { balance } = await rc.getBalance(wallet.publicKey);
67
67
  | **Address Resolution** | `rc` | O(1) rouge1↔pubkey resolution via on-chain index |
68
68
  | **Push Notifications** | `rc` | PQC-signed push token registration (Expo) |
69
69
  | **Token Freeze** | `rc` | Creator-only token freeze/pause |
70
+ | **Mintable Tokens** | `rc` | Ongoing token minting with supply cap enforcement |
71
+ | **Dynamic Fees** | `rc` | EIP-1559 base fee, priority tips, fee burning |
72
+ | **Finality Proofs** | `rc` | BFT finality certificates with ≥2/3 validator stake |
73
+ | **WebSocket** | `rc` | Real-time event streaming with topic subscriptions |
70
74
 
71
75
  ## Wallet & Addresses
72
76
 
@@ -122,6 +126,56 @@ await rc.updateTokenMetadata(wallet, {
122
126
 
123
127
  // Burn tokens
124
128
  await rc.burn(wallet, 500);
129
+
130
+ // Create a mintable token with supply cap
131
+ await rc.createToken(wallet, {
132
+ name: "Inflation Token",
133
+ symbol: "INFT",
134
+ totalSupply: 100_000,
135
+ mintable: true,
136
+ maxSupply: 1_000_000,
137
+ });
138
+
139
+ // Mint additional tokens (creator only)
140
+ await rc.mintTokens(wallet, { symbol: "INFT", amount: 50_000 });
141
+ ```
142
+
143
+ ## Dynamic Fees (EIP-1559)
144
+
145
+ ```typescript
146
+ // Get current fee info — base fee adjusts per block
147
+ const fee = await rc.getFeeInfo();
148
+ console.log(`Base fee: ${fee.base_fee} XRGE`);
149
+ console.log(`Suggested total: ${fee.total_fee_suggestion} XRGE`);
150
+ console.log(`Total burned: ${fee.total_fees_burned} XRGE`);
151
+ ```
152
+
153
+ ## Finality Proofs
154
+
155
+ ```typescript
156
+ // Get a BFT finality proof for a block height
157
+ const { proof } = await rc.getFinalityProof(42);
158
+ if (proof) {
159
+ console.log(`Block ${proof.height} finalized with ${proof.voting_stake}/${proof.total_stake} stake`);
160
+ console.log(`${proof.precommit_votes.length} precommit signatures`);
161
+ }
162
+ ```
163
+
164
+ ## WebSocket Subscriptions
165
+
166
+ ```typescript
167
+ // Subscribe to specific topics for real-time events
168
+ const ws = rc.connectWebSocket(["blocks", `account:${wallet.publicKey}`]);
169
+
170
+ ws.onmessage = (event) => {
171
+ const data = JSON.parse(event.data);
172
+ if (data.type === "new_block") {
173
+ console.log(`New block #${data.height}`);
174
+ }
175
+ };
176
+
177
+ // Available topics: "blocks", "transactions", "stats",
178
+ // "account:<pubkey>", "token:<symbol>"
125
179
  ```
126
180
 
127
181
  ## DEX (`rc.dex`)
@@ -283,11 +337,41 @@ const batch = await rc.getRollupBatch(1);
283
337
 
284
338
  ## Mail (`rc.mail`)
285
339
 
286
- On-chain encrypted email with `@rouge.quant` addresses.
340
+ On-chain encrypted email with `@rouge.quant` / `@qwalla.mail` addresses. All write operations require a `wallet` parameter for ML-DSA-65 request signing — requests are authenticated via `/api/v2/` endpoints with anti-replay nonce protection.
341
+
342
+ ### Name Registry
343
+
344
+ Register a mail name so other users can send you encrypted email. Third-party apps (QWALLA, qRougee, etc.) should call these on wallet creation.
287
345
 
288
346
  ```typescript
289
- // Send an encrypted email
290
- await rc.mail.send({
347
+ // Step 1: Register wallet on the node (required for encryption keys)
348
+ await rc.messenger.registerWallet(wallet, {
349
+ id: wallet.publicKey,
350
+ displayName: "Alice",
351
+ signingPublicKey: wallet.publicKey,
352
+ encryptionPublicKey: encPubKey,
353
+ });
354
+
355
+ // Step 2: Register a mail name (signed request)
356
+ await rc.mail.registerName(wallet, "alice", wallet.publicKey);
357
+
358
+ // Resolve a name → wallet info (includes encryption key, public data only)
359
+ const resolved = await rc.mail.resolveName("alice");
360
+ // { entry: { name, wallet_id }, wallet: { id, signing_public_key, encryption_public_key } }
361
+
362
+ // Reverse lookup: wallet ID → name
363
+ const name = await rc.mail.reverseLookup(wallet.publicKey);
364
+ // "alice"
365
+
366
+ // Release a name (signed request)
367
+ await rc.mail.releaseName(wallet, "alice", wallet.publicKey);
368
+ ```
369
+
370
+ ### Sending & Reading Mail
371
+
372
+ ```typescript
373
+ // Send an encrypted email (signed, multi-recipient CEK encryption)
374
+ await rc.mail.send(wallet, {
291
375
  from: wallet.publicKey,
292
376
  to: recipientPubKey,
293
377
  subject: "Hello",
@@ -296,52 +380,55 @@ await rc.mail.send({
296
380
  encrypted_body: encryptedBody,
297
381
  });
298
382
 
299
- // Read inbox
300
- const inbox = await rc.mail.getInbox(wallet.publicKey);
383
+ // Read inbox (signed request)
384
+ const inbox = await rc.mail.getInbox(wallet);
385
+
386
+ // Move to trash (signed request)
387
+ await rc.mail.move(wallet, messageId, "trash");
301
388
 
302
- // Move to trash
303
- await rc.mail.move(messageId, "trash");
389
+ // Mark as read (signed request)
390
+ await rc.mail.markRead(wallet, messageId);
304
391
 
305
- // Mark as read
306
- await rc.mail.markRead(messageId);
392
+ // Delete (signed request)
393
+ await rc.mail.delete(wallet, messageId);
307
394
  ```
308
395
 
309
396
  ## Messenger (`rc.messenger`)
310
397
 
311
- End-to-end encrypted messaging with media and self-destruct support.
398
+ End-to-end encrypted messaging with media and self-destruct support. All operations use ML-DSA-65 signed requests via `/api/v2/` endpoints with nonce-based anti-replay protection.
312
399
 
313
400
  ```typescript
314
- // Register wallet for messaging
315
- await rc.messenger.registerWallet({
401
+ // Register wallet for messaging (signed request)
402
+ await rc.messenger.registerWallet(wallet, {
316
403
  id: wallet.publicKey,
317
404
  displayName: "Alice",
318
405
  signingPublicKey: wallet.publicKey,
319
406
  encryptionPublicKey: encPubKey,
320
407
  });
321
408
 
322
- // Create a conversation
323
- const result = await rc.messenger.createConversation([
409
+ // Create a conversation (signed request)
410
+ const result = await rc.messenger.createConversation(wallet, [
324
411
  wallet.publicKey,
325
412
  recipientPubKey,
326
413
  ]);
327
414
 
328
- // Fetch conversations (with extended key matching)
329
- const convos = await rc.messenger.getConversations(wallet.publicKey, {
330
- signingPublicKey: wallet.publicKey,
331
- encryptionPublicKey: encPubKey,
332
- });
415
+ // Fetch conversations (signed request)
416
+ const convos = await rc.messenger.getConversations(wallet);
333
417
 
334
- // Send an encrypted message (with optional self-destruct)
335
- await rc.messenger.sendMessage(conversationId, wallet.publicKey, encryptedContent, {
418
+ // Send an encrypted message (signed, with optional self-destruct)
419
+ await rc.messenger.sendMessage(wallet, conversationId, encryptedContent, {
336
420
  selfDestruct: true,
337
421
  destructAfterSeconds: 30,
338
422
  });
339
423
 
340
- // Read messages
341
- const messages = await rc.messenger.getMessages(conversationId);
424
+ // Read messages (signed request)
425
+ const messages = await rc.messenger.getMessages(wallet, conversationId);
426
+
427
+ // Delete a message (signed request)
428
+ await rc.messenger.deleteMessage(wallet, messageId);
342
429
 
343
- // Delete a message
344
- await rc.messenger.deleteMessage(messageId);
430
+ // Delete a conversation (signed request)
431
+ await rc.messenger.deleteConversation(wallet, conversationId);
345
432
  ```
346
433
 
347
434
  ## Shielded Transactions (`rc.shielded`)
@@ -460,6 +547,7 @@ import type {
460
547
  ShieldParams, ShieldedTransferParams, UnshieldParams, ShieldedStats,
461
548
  ShieldedNote,
462
549
  RollupStatus, RollupBatchResult, RollupSubmitParams, RollupSubmitResult,
550
+ FeeInfo, FinalityProof, MintTokenParams, VoteMessage, WsSubscribeMessage,
463
551
  } from "@rougechain/sdk";
464
552
  ```
465
553
 
@@ -468,6 +556,9 @@ import type {
468
556
  - **Post-quantum cryptography** — All signatures use ML-DSA-65 (CRYSTALS-Dilithium), resistant to quantum computer attacks
469
557
  - **Client-side signing** — Private keys never leave your application
470
558
  - **No key storage** — The SDK does not store or transmit keys
559
+ - **Signed API requests** — All mail, messenger, and name registry operations use ML-DSA-65 signed requests with timestamp validation and nonce-based anti-replay protection
560
+ - **Multi-recipient CEK encryption** — Mail content is encrypted once with a random AES-256 key, KEM-wrapped individually per recipient via ML-KEM-768
561
+ - **TOFU key verification** — Public key fingerprints (SHA-256) are tracked for key change detection
471
562
 
472
563
  ## Links
473
564
 
package/dist/index.cjs CHANGED
@@ -286,6 +286,9 @@ function createSignedPushUnregister(wallet) {
286
286
  type: "push_unregister"
287
287
  });
288
288
  }
289
+ function signRequest(wallet, payload) {
290
+ return buildAndSign(wallet, payload);
291
+ }
289
292
  var COMMITMENT_DOMAIN = new TextEncoder().encode("ROUGECHAIN_COMMITMENT_V1");
290
293
  var NULLIFIER_DOMAIN = new TextEncoder().encode("ROUGECHAIN_NULLIFIER_V1");
291
294
  function generateRandomness() {
@@ -468,6 +471,19 @@ var RougeChain = class {
468
471
  async getFinality() {
469
472
  return this.get("/finality");
470
473
  }
474
+ // ===== EIP-1559 Fee Info =====
475
+ /** Get current EIP-1559 fee information including base fee and suggestions. */
476
+ async getFeeInfo() {
477
+ return this.get("/fee");
478
+ }
479
+ // ===== BFT Finality Proofs =====
480
+ /**
481
+ * Get a BFT finality proof for a specific block height.
482
+ * Returns the aggregated precommit votes that prove ≥2/3 validator stake agreed.
483
+ */
484
+ async getFinalityProof(height) {
485
+ return this.get(`/finality/${height}`);
486
+ }
471
487
  // ===== Peers =====
472
488
  async getPeers() {
473
489
  const data = await this.get("/peers");
@@ -553,6 +569,39 @@ var RougeChain = class {
553
569
  const tx = createSignedTokenMetadataClaim(wallet, tokenSymbol);
554
570
  return this.submitTx("/v2/token/metadata/claim", tx);
555
571
  }
572
+ /**
573
+ * Mint additional tokens for a mintable token (creator only).
574
+ * The token must have been created with `mintable: true`.
575
+ */
576
+ async mintTokens(wallet, params) {
577
+ return this.post("/v2/token/mint", {
578
+ public_key: wallet.publicKey,
579
+ symbol: params.symbol,
580
+ amount: params.amount,
581
+ fee: params.fee ?? 1,
582
+ signature: ""
583
+ // Will be signed server-side via PQC verification
584
+ });
585
+ }
586
+ // ===== WebSocket =====
587
+ /**
588
+ * Connect to the node's WebSocket and optionally subscribe to specific topics.
589
+ * Topics: "blocks", "transactions", "stats", "account:<pubkey>", "token:<symbol>"
590
+ *
591
+ * @example
592
+ * const ws = client.connectWebSocket(["blocks", "account:abc123"]);
593
+ * ws.onmessage = (e) => console.log(JSON.parse(e.data));
594
+ */
595
+ connectWebSocket(topics) {
596
+ const wsUrl = this.baseUrl.replace(/^http/, "ws") + "/ws";
597
+ const ws = new WebSocket(wsUrl);
598
+ if (topics && topics.length > 0) {
599
+ ws.addEventListener("open", () => {
600
+ ws.send(JSON.stringify({ subscribe: topics }));
601
+ });
602
+ }
603
+ return ws;
604
+ }
556
605
  // ===== Rollup =====
557
606
  /** Get the current rollup accumulator status. */
558
607
  async getRollupStatus() {
@@ -913,68 +962,97 @@ var MailClient = class {
913
962
  constructor(rc) {
914
963
  this.rc = rc;
915
964
  }
916
- async send(params) {
965
+ // --- Name Registry (signed) ---
966
+ async registerName(wallet, name, walletId) {
967
+ const signed = signRequest(wallet, { name, walletId });
968
+ return this.rc.submitTx("/v2/names/register", signed);
969
+ }
970
+ async resolveName(name) {
917
971
  try {
918
- const data = await this.rc.post("/mail/send", params);
919
- return { success: data.success === true, error: data.error, data };
920
- } catch (e) {
921
- return { success: false, error: e instanceof Error ? e.message : String(e) };
972
+ const data = await this.rc.get(
973
+ `/names/resolve/${encodeURIComponent(name.toLowerCase())}`
974
+ );
975
+ if (!data.success) return null;
976
+ return { entry: data.entry, wallet: data.wallet };
977
+ } catch {
978
+ return null;
922
979
  }
923
980
  }
924
- async getInbox(walletId) {
925
- const data = await this.rc.get(
926
- `/mail/inbox?walletId=${encodeURIComponent(walletId)}`
927
- );
928
- return data.messages ?? [];
929
- }
930
- async getSent(walletId) {
931
- const data = await this.rc.get(
932
- `/mail/sent?walletId=${encodeURIComponent(walletId)}`
933
- );
934
- return data.messages ?? [];
981
+ async reverseLookup(walletId) {
982
+ try {
983
+ const data = await this.rc.get(
984
+ `/names/reverse/${encodeURIComponent(walletId)}`
985
+ );
986
+ return data.name || null;
987
+ } catch {
988
+ return null;
989
+ }
935
990
  }
936
- async getTrash(walletId) {
937
- const data = await this.rc.get(
938
- `/mail/trash?walletId=${encodeURIComponent(walletId)}`
939
- );
940
- return data.messages ?? [];
991
+ async releaseName(wallet, name) {
992
+ const signed = signRequest(wallet, { name });
993
+ return this.rc.submitTx("/v2/names/release", signed);
994
+ }
995
+ // --- Mail (signed) ---
996
+ async send(wallet, params) {
997
+ const signed = signRequest(wallet, {
998
+ fromWalletId: params.from,
999
+ toWalletIds: [params.to],
1000
+ subjectEncrypted: params.encrypted_subject,
1001
+ bodyEncrypted: params.encrypted_body,
1002
+ contentSignature: params.body,
1003
+ replyToId: params.reply_to_id,
1004
+ hasAttachment: false
1005
+ });
1006
+ return this.rc.submitTx("/v2/mail/send", signed);
941
1007
  }
942
- async getMessage(id) {
943
- return this.rc.get(`/mail/message/${encodeURIComponent(id)}`);
1008
+ async getInbox(wallet) {
1009
+ const signed = signRequest(wallet, { folder: "inbox" });
1010
+ try {
1011
+ const data = await this.rc.post("/v2/mail/folder", signed);
1012
+ return data.messages ?? [];
1013
+ } catch {
1014
+ return [];
1015
+ }
944
1016
  }
945
- async move(messageId, folder) {
1017
+ async getSent(wallet) {
1018
+ const signed = signRequest(wallet, { folder: "sent" });
946
1019
  try {
947
- const data = await this.rc.post("/mail/move", {
948
- messageId,
949
- folder
950
- });
951
- return { success: data.success === true, error: data.error };
952
- } catch (e) {
953
- return { success: false, error: e instanceof Error ? e.message : String(e) };
1020
+ const data = await this.rc.post("/v2/mail/folder", signed);
1021
+ return data.messages ?? [];
1022
+ } catch {
1023
+ return [];
954
1024
  }
955
1025
  }
956
- async markRead(messageId) {
1026
+ async getTrash(wallet) {
1027
+ const signed = signRequest(wallet, { folder: "trash" });
957
1028
  try {
958
- const data = await this.rc.post("/mail/read", {
959
- messageId
960
- });
961
- return { success: data.success === true, error: data.error };
962
- } catch (e) {
963
- return { success: false, error: e instanceof Error ? e.message : String(e) };
1029
+ const data = await this.rc.post("/v2/mail/folder", signed);
1030
+ return data.messages ?? [];
1031
+ } catch {
1032
+ return [];
964
1033
  }
965
1034
  }
966
- async delete(id) {
1035
+ async getMessage(wallet, messageId) {
1036
+ const signed = signRequest(wallet, { messageId });
967
1037
  try {
968
- const res = await this.rc.fetchFn(
969
- `${this.rc.baseUrl}/mail/${encodeURIComponent(id)}`,
970
- { method: "DELETE", headers: this.rc.headers }
971
- );
972
- const data = await res.json();
973
- return { success: data.success === true, error: data.error };
974
- } catch (e) {
975
- return { success: false, error: e instanceof Error ? e.message : String(e) };
1038
+ const data = await this.rc.post("/v2/mail/message", signed);
1039
+ return data.message ?? null;
1040
+ } catch {
1041
+ return null;
976
1042
  }
977
1043
  }
1044
+ async move(wallet, messageId, folder) {
1045
+ const signed = signRequest(wallet, { messageId, folder });
1046
+ return this.rc.submitTx("/v2/mail/move", signed);
1047
+ }
1048
+ async markRead(wallet, messageId) {
1049
+ const signed = signRequest(wallet, { messageId });
1050
+ return this.rc.submitTx("/v2/mail/read", signed);
1051
+ }
1052
+ async delete(wallet, messageId) {
1053
+ const signed = signRequest(wallet, { messageId });
1054
+ return this.rc.submitTx("/v2/mail/delete", signed);
1055
+ }
978
1056
  };
979
1057
  var MessengerClient = class {
980
1058
  constructor(rc) {
@@ -984,77 +1062,71 @@ var MessengerClient = class {
984
1062
  const data = await this.rc.get("/messenger/wallets");
985
1063
  return data.wallets ?? [];
986
1064
  }
987
- async registerWallet(opts) {
1065
+ async registerWallet(wallet, opts) {
1066
+ const signed = signRequest(wallet, {
1067
+ id: opts.id,
1068
+ displayName: opts.displayName,
1069
+ signingPublicKey: opts.signingPublicKey,
1070
+ encryptionPublicKey: opts.encryptionPublicKey,
1071
+ discoverable: opts.discoverable ?? true
1072
+ });
1073
+ return this.rc.submitTx("/v2/messenger/wallets/register", signed);
1074
+ }
1075
+ async getConversations(wallet) {
1076
+ const signed = signRequest(wallet, {});
988
1077
  try {
989
- const data = await this.rc.post("/messenger/wallets/register", opts);
990
- return { success: data.success === true, error: data.error, data };
991
- } catch (e) {
992
- return { success: false, error: e instanceof Error ? e.message : String(e) };
1078
+ const data = await this.rc.post(
1079
+ "/v2/messenger/conversations/list",
1080
+ signed
1081
+ );
1082
+ return data.conversations ?? [];
1083
+ } catch {
1084
+ return [];
993
1085
  }
994
1086
  }
995
- async getConversations(walletId, opts = {}) {
996
- const params = new URLSearchParams({ walletId });
997
- if (opts.signingPublicKey) params.set("signingPublicKey", opts.signingPublicKey);
998
- if (opts.encryptionPublicKey) params.set("encryptionPublicKey", opts.encryptionPublicKey);
999
- const data = await this.rc.get(
1000
- `/messenger/conversations?${params.toString()}`
1001
- );
1002
- return data.conversations ?? [];
1087
+ async createConversation(wallet, participantIds, opts = {}) {
1088
+ const signed = signRequest(wallet, {
1089
+ participantIds,
1090
+ name: opts.name,
1091
+ isGroup: opts.isGroup ?? false
1092
+ });
1093
+ return this.rc.submitTx("/v2/messenger/conversations", signed);
1003
1094
  }
1004
- async createConversation(participants) {
1095
+ async getMessages(wallet, conversationId) {
1096
+ const signed = signRequest(wallet, { conversationId });
1005
1097
  try {
1006
- const data = await this.rc.post("/messenger/conversations", {
1007
- participants
1008
- });
1009
- return { success: data.success === true, error: data.error, data };
1010
- } catch (e) {
1011
- return { success: false, error: e instanceof Error ? e.message : String(e) };
1098
+ const data = await this.rc.post(
1099
+ "/v2/messenger/messages/list",
1100
+ signed
1101
+ );
1102
+ return data.messages ?? [];
1103
+ } catch {
1104
+ return [];
1012
1105
  }
1013
1106
  }
1014
- async getMessages(conversationId) {
1015
- const data = await this.rc.get(
1016
- `/messenger/messages?conversationId=${encodeURIComponent(conversationId)}`
1017
- );
1018
- return data.messages ?? [];
1107
+ async sendMessage(wallet, conversationId, encryptedContent, opts = {}) {
1108
+ const signed = signRequest(wallet, {
1109
+ conversationId,
1110
+ encryptedContent,
1111
+ contentSignature: opts.contentSignature ?? "",
1112
+ messageType: opts.messageType ?? "text",
1113
+ selfDestruct: opts.selfDestruct ?? false,
1114
+ destructAfterSeconds: opts.destructAfterSeconds,
1115
+ spoiler: opts.spoiler ?? false
1116
+ });
1117
+ return this.rc.submitTx("/v2/messenger/messages", signed);
1019
1118
  }
1020
- async sendMessage(conversationId, senderWalletId, encryptedContent, opts = {}) {
1021
- try {
1022
- const data = await this.rc.post("/messenger/messages", {
1023
- conversationId,
1024
- senderWalletId,
1025
- encryptedContent,
1026
- signature: opts.signature ?? "",
1027
- messageType: opts.messageType ?? "text",
1028
- selfDestruct: opts.selfDestruct ?? false,
1029
- destructAfterSeconds: opts.destructAfterSeconds,
1030
- spoiler: opts.spoiler ?? false
1031
- });
1032
- return { success: data.success === true, error: data.error, data };
1033
- } catch (e) {
1034
- return { success: false, error: e instanceof Error ? e.message : String(e) };
1035
- }
1119
+ async deleteMessage(wallet, messageId, conversationId) {
1120
+ const signed = signRequest(wallet, { messageId, conversationId });
1121
+ return this.rc.submitTx("/v2/messenger/messages/delete", signed);
1036
1122
  }
1037
- async deleteMessage(messageId) {
1038
- try {
1039
- const res = await this.rc.fetchFn(
1040
- `${this.rc.baseUrl}/messenger/messages/${encodeURIComponent(messageId)}`,
1041
- { method: "DELETE", headers: this.rc.headers }
1042
- );
1043
- const data = await res.json();
1044
- return { success: data.success === true, error: data.error };
1045
- } catch (e) {
1046
- return { success: false, error: e instanceof Error ? e.message : String(e) };
1047
- }
1123
+ async deleteConversation(wallet, conversationId) {
1124
+ const signed = signRequest(wallet, { conversationId });
1125
+ return this.rc.submitTx("/v2/messenger/conversations/delete", signed);
1048
1126
  }
1049
- async markRead(messageId) {
1050
- try {
1051
- const data = await this.rc.post("/messenger/messages/read", {
1052
- messageId
1053
- });
1054
- return { success: data.success === true, error: data.error };
1055
- } catch (e) {
1056
- return { success: false, error: e instanceof Error ? e.message : String(e) };
1057
- }
1127
+ async markRead(wallet, messageId, conversationId) {
1128
+ const signed = signRequest(wallet, { messageId, conversationId });
1129
+ return this.rc.submitTx("/v2/messenger/messages/read", signed);
1058
1130
  }
1059
1131
  };
1060
1132
  var ShieldedClient = class {
@@ -1113,6 +1185,33 @@ var ShieldedClient = class {
1113
1185
  );
1114
1186
  return this.rc.submitTx("/v2/shielded/unshield", tx);
1115
1187
  }
1188
+ // ─── WASM Smart Contracts ──────────────────────────────────────────
1189
+ /** Deploy a WASM smart contract */
1190
+ async deployContract(params) {
1191
+ return this.rc.post("/v2/contract/deploy", params);
1192
+ }
1193
+ /** Call a WASM smart contract method (mutating) */
1194
+ async callContract(params) {
1195
+ return this.rc.post("/v2/contract/call", params);
1196
+ }
1197
+ /** Get contract metadata */
1198
+ async getContract(addr) {
1199
+ return this.rc.get(`/contract/${addr}`);
1200
+ }
1201
+ /** Read contract storage. Omit key for full state dump. */
1202
+ async getContractState(addr, key) {
1203
+ const q = key ? `?key=${encodeURIComponent(key)}` : "";
1204
+ return this.rc.get(`/contract/${addr}/state${q}`);
1205
+ }
1206
+ /** Get contract events */
1207
+ async getContractEvents(addr, limit) {
1208
+ const q = limit ? `?limit=${limit}` : "";
1209
+ return this.rc.get(`/contract/${addr}/events${q}`);
1210
+ }
1211
+ /** List all deployed contracts */
1212
+ async listContracts() {
1213
+ return this.rc.get("/contracts");
1214
+ }
1116
1215
  };
1117
1216
 
1118
1217
  // src/address.ts
@@ -1269,9 +1368,9 @@ var Wallet = class _Wallet {
1269
1368
  /**
1270
1369
  * Generate a new ML-DSA-65 keypair with a BIP-39 mnemonic.
1271
1370
  * The mnemonic is stored on the wallet for backup/recovery.
1272
- * @param strength 128 = 12 words (default), 256 = 24 words
1371
+ * @param strength 256 = 24 words (default, post-quantum safe), 128 = 12 words
1273
1372
  */
1274
- static generate(strength = 128) {
1373
+ static generate(strength = 256) {
1275
1374
  const mnemonic = generateMnemonic(strength);
1276
1375
  const { publicKey, secretKey } = keypairFromMnemonic(mnemonic);
1277
1376
  return new _Wallet(publicKey, secretKey, mnemonic);
@@ -1363,6 +1462,7 @@ exports.keypairFromMnemonic = keypairFromMnemonic;
1363
1462
  exports.mnemonicToMLDSASeed = mnemonicToMLDSASeed;
1364
1463
  exports.pubkeyToAddress = pubkeyToAddress;
1365
1464
  exports.serializePayload = serializePayload;
1465
+ exports.signRequest = signRequest;
1366
1466
  exports.signTransaction = signTransaction;
1367
1467
  exports.validateMnemonic = validateMnemonic;
1368
1468
  exports.verifyTransaction = verifyTransaction;