@rougechain/sdk 0.3.7 → 0.4.1
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 +45 -3
- package/dist/index.cjs +148 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +142 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/index.d.cts +0 -592
- package/dist/index.d.ts +0 -592
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 · Bridge · Mail · Messenger
|
|
11
|
+
Transfers · DEX · NFTs · Shielded Transactions · Bridge · Mail · Messenger
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
14
|
<p align="center">
|
|
@@ -58,7 +58,8 @@ const { balance } = await rc.getBalance(wallet.publicKey);
|
|
|
58
58
|
| **Staking** | `rc` | Stake/unstake XRGE for validation |
|
|
59
59
|
| **DEX** | `rc.dex` | AMM pools, swaps with slippage protection, liquidity |
|
|
60
60
|
| **NFTs** | `rc.nft` | RC-721 collections, mint, batch mint, royalties, freeze |
|
|
61
|
-
| **
|
|
61
|
+
| **Shielded** | `rc.shielded` | Private transfers with zk-STARK proofs, shield/unshield XRGE |
|
|
62
|
+
| **Bridge** | `rc.bridge` | ETH ↔ qETH, USDC ↔ qUSDC, XRGE bridge (Base Sepolia) |\r
|
|
62
63
|
| **Mail** | `rc.mail` | On-chain encrypted email (`@rouge.quant`) |
|
|
63
64
|
| **Messenger** | `rc.messenger` | E2E encrypted messaging with self-destruct |
|
|
64
65
|
|
|
@@ -306,6 +307,45 @@ const messages = await rc.messenger.getMessages(conversationId);
|
|
|
306
307
|
await rc.messenger.deleteMessage(messageId);
|
|
307
308
|
```
|
|
308
309
|
|
|
310
|
+
## Shielded Transactions (`rc.shielded`)
|
|
311
|
+
|
|
312
|
+
Private value transfers using zk-STARK proofs. Shield XRGE into private notes, transfer privately, and unshield back to public balance.
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
import { createShieldedNote, computeCommitment, computeNullifier } from "@rougechain/sdk";
|
|
316
|
+
|
|
317
|
+
// Shield 100 XRGE into a private note
|
|
318
|
+
const { note } = await rc.shielded.shield(wallet, { amount: 100 });
|
|
319
|
+
// ⚠️ Save `note` securely — losing it means losing the funds!
|
|
320
|
+
// note = { commitment, nullifier, value, randomness, ownerPubKey }
|
|
321
|
+
|
|
322
|
+
// Check pool stats
|
|
323
|
+
const stats = await rc.shielded.getStats();
|
|
324
|
+
// { commitment_count, nullifier_count, active_notes }
|
|
325
|
+
|
|
326
|
+
// Check if a nullifier has been spent
|
|
327
|
+
const { spent } = await rc.shielded.isNullifierSpent(note.nullifier);
|
|
328
|
+
|
|
329
|
+
// Private transfer (requires STARK proof from Rust prover)
|
|
330
|
+
await rc.shielded.transfer(wallet, {
|
|
331
|
+
nullifiers: [note.nullifier],
|
|
332
|
+
outputCommitments: [recipientCommitment],
|
|
333
|
+
proof: starkProofHex,
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// Unshield back to public balance
|
|
337
|
+
await rc.shielded.unshield(wallet, {
|
|
338
|
+
nullifiers: [note.nullifier],
|
|
339
|
+
amount: 100,
|
|
340
|
+
proof: starkProofHex,
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
// Client-side crypto primitives
|
|
344
|
+
const randomness = generateRandomness();
|
|
345
|
+
const commitment = computeCommitment(100, wallet.publicKey, randomness);
|
|
346
|
+
const nullifier = computeNullifier(randomness, commitment);
|
|
347
|
+
```
|
|
348
|
+
|
|
309
349
|
## Low-Level Signing
|
|
310
350
|
|
|
311
351
|
For advanced use cases:
|
|
@@ -347,6 +387,8 @@ import type {
|
|
|
347
387
|
NftToken, LiquidityPool, BalanceResponse, Validator,
|
|
348
388
|
BridgeConfig, MailMessage, MessengerMessage, WalletKeys,
|
|
349
389
|
PriceSnapshot, PoolEvent, PoolStats, SwapQuote,
|
|
390
|
+
ShieldParams, ShieldedTransferParams, UnshieldParams, ShieldedStats,
|
|
391
|
+
ShieldedNote,
|
|
350
392
|
} from "@rougechain/sdk";
|
|
351
393
|
```
|
|
352
394
|
|
|
@@ -360,7 +402,7 @@ import type {
|
|
|
360
402
|
|
|
361
403
|
- [Website](https://rougechain.io)
|
|
362
404
|
- [Documentation](https://docs.rougechain.io)
|
|
363
|
-
- [Chrome Extension](https://chromewebstore.google.com/detail/rougechain-wallet)
|
|
405
|
+
- [Chrome Extension](https://chromewebstore.google.com/detail/rougechain-wallet/ilkbgjgphhaolfdjkfefdfiifipmhakj)
|
|
364
406
|
- [GitHub](https://github.com/cyberdreadx/quantum-vault)
|
|
365
407
|
|
|
366
408
|
## License
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var mlDsa_js = require('@noble/post-quantum/ml-dsa.js');
|
|
4
|
+
var sha2 = require('@noble/hashes/sha2');
|
|
4
5
|
|
|
5
6
|
// src/signer.ts
|
|
6
7
|
|
|
@@ -228,6 +229,88 @@ function createSignedNftFreezeCollection(wallet, collectionId, frozen) {
|
|
|
228
229
|
fee: 0.1
|
|
229
230
|
});
|
|
230
231
|
}
|
|
232
|
+
function createSignedShield(wallet, amount, commitment) {
|
|
233
|
+
return buildAndSign(wallet, {
|
|
234
|
+
type: "shield",
|
|
235
|
+
amount,
|
|
236
|
+
commitment
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
function createSignedShieldedTransfer(wallet, nullifiers, outputCommitments, proof, shieldedFee) {
|
|
240
|
+
return buildAndSign(wallet, {
|
|
241
|
+
type: "shielded_transfer",
|
|
242
|
+
nullifiers,
|
|
243
|
+
output_commitments: outputCommitments,
|
|
244
|
+
proof,
|
|
245
|
+
fee: shieldedFee ?? 0
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
function createSignedUnshield(wallet, nullifiers, amount, proof) {
|
|
249
|
+
return buildAndSign(wallet, {
|
|
250
|
+
type: "unshield",
|
|
251
|
+
nullifiers,
|
|
252
|
+
amount,
|
|
253
|
+
proof
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
var COMMITMENT_DOMAIN = new TextEncoder().encode("ROUGECHAIN_COMMITMENT_V1");
|
|
257
|
+
var NULLIFIER_DOMAIN = new TextEncoder().encode("ROUGECHAIN_NULLIFIER_V1");
|
|
258
|
+
function generateRandomness() {
|
|
259
|
+
const buf = new Uint8Array(32);
|
|
260
|
+
crypto.getRandomValues(buf);
|
|
261
|
+
return bytesToHex(buf);
|
|
262
|
+
}
|
|
263
|
+
function u64ToBytes(value) {
|
|
264
|
+
const buf = new Uint8Array(8);
|
|
265
|
+
const view = new DataView(buf.buffer);
|
|
266
|
+
view.setBigUint64(0, BigInt(value), false);
|
|
267
|
+
return buf;
|
|
268
|
+
}
|
|
269
|
+
function hexToU8(hex) {
|
|
270
|
+
const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
271
|
+
const bytes = new Uint8Array(clean.length / 2);
|
|
272
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
273
|
+
bytes[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
274
|
+
}
|
|
275
|
+
return bytes;
|
|
276
|
+
}
|
|
277
|
+
function computeCommitment(value, ownerPubKey, randomness) {
|
|
278
|
+
const valueBytes = u64ToBytes(value);
|
|
279
|
+
const pubkeyBytes = hexToU8(ownerPubKey);
|
|
280
|
+
const randBytes = hexToU8(randomness);
|
|
281
|
+
const input = new Uint8Array(
|
|
282
|
+
COMMITMENT_DOMAIN.length + valueBytes.length + pubkeyBytes.length + randBytes.length
|
|
283
|
+
);
|
|
284
|
+
let offset = 0;
|
|
285
|
+
input.set(COMMITMENT_DOMAIN, offset);
|
|
286
|
+
offset += COMMITMENT_DOMAIN.length;
|
|
287
|
+
input.set(valueBytes, offset);
|
|
288
|
+
offset += valueBytes.length;
|
|
289
|
+
input.set(pubkeyBytes, offset);
|
|
290
|
+
offset += pubkeyBytes.length;
|
|
291
|
+
input.set(randBytes, offset);
|
|
292
|
+
return bytesToHex(sha2.sha256(input));
|
|
293
|
+
}
|
|
294
|
+
function computeNullifier(randomness, commitment) {
|
|
295
|
+
const randBytes = hexToU8(randomness);
|
|
296
|
+
const commitBytes = hexToU8(commitment);
|
|
297
|
+
const input = new Uint8Array(
|
|
298
|
+
NULLIFIER_DOMAIN.length + randBytes.length + commitBytes.length
|
|
299
|
+
);
|
|
300
|
+
let offset = 0;
|
|
301
|
+
input.set(NULLIFIER_DOMAIN, offset);
|
|
302
|
+
offset += NULLIFIER_DOMAIN.length;
|
|
303
|
+
input.set(randBytes, offset);
|
|
304
|
+
offset += randBytes.length;
|
|
305
|
+
input.set(commitBytes, offset);
|
|
306
|
+
return bytesToHex(sha2.sha256(input));
|
|
307
|
+
}
|
|
308
|
+
function createShieldedNote(value, ownerPubKey) {
|
|
309
|
+
const randomness = generateRandomness();
|
|
310
|
+
const commitment = computeCommitment(value, ownerPubKey, randomness);
|
|
311
|
+
const nullifier = computeNullifier(randomness, commitment);
|
|
312
|
+
return { commitment, nullifier, value, randomness, ownerPubKey };
|
|
313
|
+
}
|
|
231
314
|
|
|
232
315
|
// src/client.ts
|
|
233
316
|
var RougeChain = class {
|
|
@@ -243,6 +326,7 @@ var RougeChain = class {
|
|
|
243
326
|
this.bridge = new BridgeClient(this);
|
|
244
327
|
this.mail = new MailClient(this);
|
|
245
328
|
this.messenger = new MessengerClient(this);
|
|
329
|
+
this.shielded = new ShieldedClient(this);
|
|
246
330
|
}
|
|
247
331
|
// ===== Internal helpers =====
|
|
248
332
|
/** @internal */
|
|
@@ -898,6 +982,63 @@ var MessengerClient = class {
|
|
|
898
982
|
}
|
|
899
983
|
}
|
|
900
984
|
};
|
|
985
|
+
var ShieldedClient = class {
|
|
986
|
+
constructor(rc) {
|
|
987
|
+
this.rc = rc;
|
|
988
|
+
}
|
|
989
|
+
// Queries
|
|
990
|
+
async getStats() {
|
|
991
|
+
return this.rc.get("/shielded/stats");
|
|
992
|
+
}
|
|
993
|
+
async isNullifierSpent(nullifierHex) {
|
|
994
|
+
return this.rc.get(
|
|
995
|
+
`/shielded/nullifier/${encodeURIComponent(nullifierHex)}`
|
|
996
|
+
);
|
|
997
|
+
}
|
|
998
|
+
// Write operations
|
|
999
|
+
/**
|
|
1000
|
+
* Shield public XRGE into a private note.
|
|
1001
|
+
* Creates the commitment client-side, submits to the chain.
|
|
1002
|
+
*
|
|
1003
|
+
* @returns The ShieldedNote (keep this locally — it's the only way to spend the note)
|
|
1004
|
+
*/
|
|
1005
|
+
async shield(wallet, params) {
|
|
1006
|
+
const note = createShieldedNote(params.amount, wallet.publicKey);
|
|
1007
|
+
const tx = createSignedShield(wallet, params.amount, note.commitment);
|
|
1008
|
+
const result = await this.rc.submitTx("/v2/shielded/shield", tx);
|
|
1009
|
+
if (result.success) {
|
|
1010
|
+
return { ...result, note };
|
|
1011
|
+
}
|
|
1012
|
+
return result;
|
|
1013
|
+
}
|
|
1014
|
+
/**
|
|
1015
|
+
* Transfer between shielded notes (private → private).
|
|
1016
|
+
* Requires a pre-generated STARK proof.
|
|
1017
|
+
*/
|
|
1018
|
+
async transfer(wallet, params) {
|
|
1019
|
+
const tx = createSignedShieldedTransfer(
|
|
1020
|
+
wallet,
|
|
1021
|
+
params.nullifiers,
|
|
1022
|
+
params.outputCommitments,
|
|
1023
|
+
params.proof,
|
|
1024
|
+
params.shieldedFee
|
|
1025
|
+
);
|
|
1026
|
+
return this.rc.submitTx("/v2/shielded/transfer", tx);
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Unshield a private note back to public XRGE.
|
|
1030
|
+
* Requires a STARK proof of note ownership.
|
|
1031
|
+
*/
|
|
1032
|
+
async unshield(wallet, params) {
|
|
1033
|
+
const tx = createSignedUnshield(
|
|
1034
|
+
wallet,
|
|
1035
|
+
params.nullifiers,
|
|
1036
|
+
params.amount,
|
|
1037
|
+
params.proof
|
|
1038
|
+
);
|
|
1039
|
+
return this.rc.submitTx("/v2/shielded/unshield", tx);
|
|
1040
|
+
}
|
|
1041
|
+
};
|
|
901
1042
|
var Wallet = class _Wallet {
|
|
902
1043
|
constructor(publicKey, privateKey) {
|
|
903
1044
|
this.publicKey = publicKey;
|
|
@@ -944,10 +1085,17 @@ exports.BURN_ADDRESS = BURN_ADDRESS;
|
|
|
944
1085
|
exports.RougeChain = RougeChain;
|
|
945
1086
|
exports.Wallet = Wallet;
|
|
946
1087
|
exports.bytesToHex = bytesToHex;
|
|
1088
|
+
exports.computeCommitment = computeCommitment;
|
|
1089
|
+
exports.computeNullifier = computeNullifier;
|
|
1090
|
+
exports.createShieldedNote = createShieldedNote;
|
|
947
1091
|
exports.createSignedBridgeWithdraw = createSignedBridgeWithdraw;
|
|
1092
|
+
exports.createSignedShield = createSignedShield;
|
|
1093
|
+
exports.createSignedShieldedTransfer = createSignedShieldedTransfer;
|
|
948
1094
|
exports.createSignedTokenMetadataClaim = createSignedTokenMetadataClaim;
|
|
949
1095
|
exports.createSignedTokenMetadataUpdate = createSignedTokenMetadataUpdate;
|
|
1096
|
+
exports.createSignedUnshield = createSignedUnshield;
|
|
950
1097
|
exports.generateNonce = generateNonce;
|
|
1098
|
+
exports.generateRandomness = generateRandomness;
|
|
951
1099
|
exports.hexToBytes = hexToBytes;
|
|
952
1100
|
exports.isBurnAddress = isBurnAddress;
|
|
953
1101
|
exports.serializePayload = serializePayload;
|