@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 +117 -26
- package/dist/index.cjs +210 -110
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +210 -111
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
//
|
|
290
|
-
await rc.
|
|
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
|
|
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
|
-
//
|
|
303
|
-
await rc.mail.
|
|
389
|
+
// Mark as read (signed request)
|
|
390
|
+
await rc.mail.markRead(wallet, messageId);
|
|
304
391
|
|
|
305
|
-
//
|
|
306
|
-
await rc.mail.
|
|
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 (
|
|
329
|
-
const convos = await rc.messenger.getConversations(wallet
|
|
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(
|
|
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
|
|
344
|
-
await rc.messenger.
|
|
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
|
-
|
|
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.
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
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
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
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
|
|
937
|
-
const
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
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
|
|
943
|
-
|
|
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
|
|
1017
|
+
async getSent(wallet) {
|
|
1018
|
+
const signed = signRequest(wallet, { folder: "sent" });
|
|
946
1019
|
try {
|
|
947
|
-
const data = await this.rc.post("/mail/
|
|
948
|
-
|
|
949
|
-
|
|
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
|
|
1026
|
+
async getTrash(wallet) {
|
|
1027
|
+
const signed = signRequest(wallet, { folder: "trash" });
|
|
957
1028
|
try {
|
|
958
|
-
const data = await this.rc.post("/mail/
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
return
|
|
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
|
|
1035
|
+
async getMessage(wallet, messageId) {
|
|
1036
|
+
const signed = signRequest(wallet, { messageId });
|
|
967
1037
|
try {
|
|
968
|
-
const
|
|
969
|
-
|
|
970
|
-
|
|
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(
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
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
|
|
996
|
-
const
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
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
|
|
1095
|
+
async getMessages(wallet, conversationId) {
|
|
1096
|
+
const signed = signRequest(wallet, { conversationId });
|
|
1005
1097
|
try {
|
|
1006
|
-
const data = await this.rc.post(
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
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
|
|
1015
|
-
const
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
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
|
|
1021
|
-
|
|
1022
|
-
|
|
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
|
|
1038
|
-
|
|
1039
|
-
|
|
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
|
-
|
|
1051
|
-
|
|
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
|
|
1371
|
+
* @param strength 256 = 24 words (default, post-quantum safe), 128 = 12 words
|
|
1273
1372
|
*/
|
|
1274
|
-
static generate(strength =
|
|
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;
|