@adelos/sdk 0.1.2 → 0.1.5
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/dist/index.d.mts +42 -470
- package/dist/index.d.ts +42 -470
- package/dist/index.js +138 -725
- package/dist/index.mjs +138 -725
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30,24 +30,20 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
ADELOS_CONFIG: () => ADELOS_CONFIG,
|
|
33
34
|
AdelosIndexer: () => AdelosIndexer,
|
|
34
35
|
AdelosSDK: () => AdelosSDK,
|
|
35
36
|
IDL: () => IDL,
|
|
36
|
-
LIGHT_PROGRAM_IDS: () => LIGHT_PROGRAM_IDS,
|
|
37
|
-
LightClient: () => LightClient,
|
|
38
37
|
MEMO_PREFIX: () => MEMO_PREFIX,
|
|
39
38
|
MEMO_PROGRAM_ID: () => MEMO_PROGRAM_ID,
|
|
40
39
|
PROGRAM_ID: () => PROGRAM_ID,
|
|
41
|
-
PROGRAM_IDS: () => PROGRAM_IDS,
|
|
42
|
-
REGISTRY_ACCOUNT_SIZE: () => REGISTRY_ACCOUNT_SIZE,
|
|
43
40
|
REGISTRY_SEED: () => REGISTRY_SEED,
|
|
44
|
-
|
|
41
|
+
RPC_URL: () => RPC_URL,
|
|
45
42
|
STEALTH_DOMAIN: () => STEALTH_DOMAIN,
|
|
46
43
|
bytesToHex: () => bytesToHex,
|
|
47
44
|
computeSharedSecret: () => computeSharedSecret,
|
|
48
45
|
computeSharedSecretAsRecipient: () => computeSharedSecretAsRecipient,
|
|
49
46
|
createIndexer: () => createIndexer,
|
|
50
|
-
createLightClient: () => createLightClient,
|
|
51
47
|
deriveRegistryPda: () => deriveRegistryPda,
|
|
52
48
|
deriveStealthPubkey: () => deriveStealthPubkey,
|
|
53
49
|
generateEphemeralKeypair: () => generateEphemeralKeypair,
|
|
@@ -55,41 +51,35 @@ __export(index_exports, {
|
|
|
55
51
|
generateStealthMemo: () => generateStealthMemo,
|
|
56
52
|
getDiscriminator: () => getDiscriminator,
|
|
57
53
|
hexToBytes: () => hexToBytes,
|
|
58
|
-
isStealthTransactionForMe: () => isStealthTransactionForMe,
|
|
59
54
|
isValidMetaPubkey: () => isValidMetaPubkey,
|
|
60
55
|
parseStealthMemo: () => parseStealthMemo,
|
|
61
56
|
recoverStealthSecretKey: () => recoverStealthSecretKey
|
|
62
57
|
});
|
|
63
58
|
module.exports = __toCommonJS(index_exports);
|
|
64
|
-
var
|
|
59
|
+
var import_web34 = require("@solana/web3.js");
|
|
65
60
|
|
|
66
61
|
// src/constants.ts
|
|
67
62
|
var import_web3 = require("@solana/web3.js");
|
|
68
|
-
var
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
devnet: (0, import_web3.clusterApiUrl)("devnet"),
|
|
76
|
-
"mainnet-beta": (0, import_web3.clusterApiUrl)("mainnet-beta"),
|
|
77
|
-
localnet: "http://localhost:8899"
|
|
63
|
+
var ADELOS_CONFIG = {
|
|
64
|
+
PROGRAM_ID: new import_web3.PublicKey("7T1UxHJ6psKiQheKZXxANu6mhgsmgaX55eNKZZL5u4Rp"),
|
|
65
|
+
RPC_URL: (0, import_web3.clusterApiUrl)("devnet"),
|
|
66
|
+
MEMO_PROGRAM_ID: new import_web3.PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"),
|
|
67
|
+
REGISTRY_SEED: "registry",
|
|
68
|
+
MEMO_PREFIX: "ADLSv1:",
|
|
69
|
+
STEALTH_DOMAIN: "adelos:stealth:v1"
|
|
78
70
|
};
|
|
79
|
-
var PROGRAM_ID =
|
|
80
|
-
var
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
var
|
|
84
|
-
var
|
|
85
|
-
var MEMO_PREFIX = "ADLSv1:";
|
|
86
|
-
var STEALTH_DOMAIN = "adelos:stealth:v1";
|
|
71
|
+
var PROGRAM_ID = ADELOS_CONFIG.PROGRAM_ID;
|
|
72
|
+
var RPC_URL = ADELOS_CONFIG.RPC_URL;
|
|
73
|
+
var MEMO_PROGRAM_ID = ADELOS_CONFIG.MEMO_PROGRAM_ID;
|
|
74
|
+
var REGISTRY_SEED = ADELOS_CONFIG.REGISTRY_SEED;
|
|
75
|
+
var MEMO_PREFIX = ADELOS_CONFIG.MEMO_PREFIX;
|
|
76
|
+
var STEALTH_DOMAIN = ADELOS_CONFIG.STEALTH_DOMAIN;
|
|
87
77
|
|
|
88
78
|
// src/utils.ts
|
|
89
79
|
var import_web32 = require("@solana/web3.js");
|
|
90
|
-
function deriveRegistryPda(owner, programId = PROGRAM_ID) {
|
|
80
|
+
function deriveRegistryPda(owner, programId = ADELOS_CONFIG.PROGRAM_ID) {
|
|
91
81
|
return import_web32.PublicKey.findProgramAddressSync(
|
|
92
|
-
[Buffer.from(REGISTRY_SEED), owner.toBuffer()],
|
|
82
|
+
[Buffer.from(ADELOS_CONFIG.REGISTRY_SEED), owner.toBuffer()],
|
|
93
83
|
programId
|
|
94
84
|
);
|
|
95
85
|
}
|
|
@@ -362,65 +352,52 @@ var IDL = {
|
|
|
362
352
|
|
|
363
353
|
// src/crypto.ts
|
|
364
354
|
var import_sha256 = require("@noble/hashes/sha256");
|
|
355
|
+
var import_sha512 = require("@noble/hashes/sha512");
|
|
365
356
|
var ed = __toESM(require("@noble/ed25519"));
|
|
357
|
+
ed.etc.sha512Sync = (...m) => {
|
|
358
|
+
const h = import_sha512.sha512.create();
|
|
359
|
+
m.forEach((msg) => h.update(msg));
|
|
360
|
+
return h.digest();
|
|
361
|
+
};
|
|
362
|
+
var encoder = new TextEncoder();
|
|
366
363
|
function generateEphemeralKeypair() {
|
|
367
364
|
const secretKey = ed.utils.randomPrivateKey();
|
|
368
|
-
|
|
369
|
-
return { secretKey, publicKey };
|
|
365
|
+
return { secretKey, publicKey: ed.getPublicKey(secretKey) };
|
|
370
366
|
}
|
|
371
|
-
|
|
372
|
-
const point = ed.ExtendedPoint.fromHex(
|
|
373
|
-
const scalar = ed.etc.mod(
|
|
374
|
-
|
|
375
|
-
ed.CURVE.n
|
|
376
|
-
);
|
|
377
|
-
const sharedPoint = point.multiply(scalar);
|
|
378
|
-
const sharedBytes = sharedPoint.toRawBytes();
|
|
379
|
-
return (0, import_sha256.sha256)(sharedBytes);
|
|
367
|
+
function computeSharedSecret(ephemeralSk, recipientMetaPk) {
|
|
368
|
+
const point = ed.ExtendedPoint.fromHex(bytesToHex(recipientMetaPk));
|
|
369
|
+
const scalar = ed.etc.mod(BigInt("0x" + bytesToHex(ephemeralSk)), ed.CURVE.n);
|
|
370
|
+
return (0, import_sha256.sha256)(point.multiply(scalar).toRawBytes());
|
|
380
371
|
}
|
|
381
|
-
function
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
);
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
);
|
|
389
|
-
const
|
|
390
|
-
const
|
|
391
|
-
const
|
|
372
|
+
function computeSharedSecretAsRecipient(metaSk, ephemeralPk) {
|
|
373
|
+
const secretKey = metaSk.length === 64 ? metaSk.slice(0, 32) : metaSk;
|
|
374
|
+
const point = ed.ExtendedPoint.fromHex(bytesToHex(ephemeralPk));
|
|
375
|
+
const scalar = ed.etc.mod(BigInt("0x" + bytesToHex(secretKey)), ed.CURVE.n);
|
|
376
|
+
return (0, import_sha256.sha256)(point.multiply(scalar).toRawBytes());
|
|
377
|
+
}
|
|
378
|
+
function deriveStealthPubkey(metaPk, sharedSecret) {
|
|
379
|
+
const domain = encoder.encode(ADELOS_CONFIG.STEALTH_DOMAIN);
|
|
380
|
+
const scalarBytes = (0, import_sha256.sha256)(new Uint8Array([...sharedSecret, ...domain]));
|
|
381
|
+
const scalar = ed.etc.mod(BigInt("0x" + bytesToHex(scalarBytes)), ed.CURVE.n);
|
|
382
|
+
const metaPoint = ed.ExtendedPoint.fromHex(bytesToHex(metaPk));
|
|
383
|
+
const stealthPoint = metaPoint.add(ed.ExtendedPoint.BASE.multiply(scalar));
|
|
392
384
|
return stealthPoint.toRawBytes();
|
|
393
385
|
}
|
|
394
386
|
function recoverStealthSecretKey(metaSk, sharedSecret) {
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
);
|
|
398
|
-
const
|
|
399
|
-
BigInt("0x" + bytesToHex(scalarBytes)),
|
|
400
|
-
ed.CURVE.n
|
|
401
|
-
);
|
|
402
|
-
const metaScalar = ed.etc.mod(
|
|
403
|
-
BigInt("0x" + bytesToHex(metaSk)),
|
|
404
|
-
ed.CURVE.n
|
|
405
|
-
);
|
|
387
|
+
const domain = encoder.encode(ADELOS_CONFIG.STEALTH_DOMAIN);
|
|
388
|
+
const scalarBytes = (0, import_sha256.sha256)(new Uint8Array([...sharedSecret, ...domain]));
|
|
389
|
+
const scalar = ed.etc.mod(BigInt("0x" + bytesToHex(scalarBytes)), ed.CURVE.n);
|
|
390
|
+
const metaScalar = ed.etc.mod(BigInt("0x" + bytesToHex(metaSk)), ed.CURVE.n);
|
|
406
391
|
const stealthScalar = ed.etc.mod(metaScalar + scalar, ed.CURVE.n);
|
|
407
392
|
const hex = stealthScalar.toString(16).padStart(64, "0");
|
|
408
393
|
return hexToBytes(hex);
|
|
409
394
|
}
|
|
410
|
-
async function computeSharedSecretAsRecipient(metaSk, ephemeralPubkey) {
|
|
411
|
-
const point = ed.ExtendedPoint.fromHex(ephemeralPubkey);
|
|
412
|
-
const scalar = ed.etc.mod(BigInt("0x" + bytesToHex(metaSk)), ed.CURVE.n);
|
|
413
|
-
const sharedPoint = point.multiply(scalar);
|
|
414
|
-
const sharedBytes = sharedPoint.toRawBytes();
|
|
415
|
-
return (0, import_sha256.sha256)(sharedBytes);
|
|
416
|
-
}
|
|
417
395
|
function generateStealthMemo(ephemeralPubkey) {
|
|
418
|
-
|
|
419
|
-
return `${MEMO_PREFIX}${pubkeyHex}`;
|
|
396
|
+
return `${ADELOS_CONFIG.MEMO_PREFIX}${bytesToHex(ephemeralPubkey)}`;
|
|
420
397
|
}
|
|
421
398
|
function parseStealthMemo(memo) {
|
|
422
|
-
if (!memo.startsWith(MEMO_PREFIX)) return null;
|
|
423
|
-
const pubkeyHex = memo.slice(MEMO_PREFIX.length);
|
|
399
|
+
if (!memo.startsWith(ADELOS_CONFIG.MEMO_PREFIX)) return null;
|
|
400
|
+
const pubkeyHex = memo.slice(ADELOS_CONFIG.MEMO_PREFIX.length);
|
|
424
401
|
if (pubkeyHex.length !== 64) return null;
|
|
425
402
|
try {
|
|
426
403
|
return hexToBytes(pubkeyHex);
|
|
@@ -428,613 +405,115 @@ function parseStealthMemo(memo) {
|
|
|
428
405
|
return null;
|
|
429
406
|
}
|
|
430
407
|
}
|
|
431
|
-
|
|
408
|
+
function generateStealthAddress(recipientMetaPk) {
|
|
432
409
|
const ephemeralKeypair = generateEphemeralKeypair();
|
|
433
|
-
const sharedSecret =
|
|
434
|
-
|
|
435
|
-
recipientMetaPubkey
|
|
436
|
-
);
|
|
437
|
-
const stealthPubkey = deriveStealthPubkey(recipientMetaPubkey, sharedSecret);
|
|
410
|
+
const sharedSecret = computeSharedSecret(ephemeralKeypair.secretKey, recipientMetaPk);
|
|
411
|
+
const stealthPubkey = deriveStealthPubkey(recipientMetaPk, sharedSecret);
|
|
438
412
|
const memo = generateStealthMemo(ephemeralKeypair.publicKey);
|
|
439
|
-
return {
|
|
440
|
-
stealthPubkey,
|
|
441
|
-
ephemeralKeypair,
|
|
442
|
-
sharedSecret,
|
|
443
|
-
memo
|
|
444
|
-
};
|
|
445
|
-
}
|
|
446
|
-
async function isStealthTransactionForMe(metaSk, metaPubkey, ephemeralPubkey, targetAddress) {
|
|
447
|
-
const sharedSecret = await computeSharedSecretAsRecipient(
|
|
448
|
-
metaSk,
|
|
449
|
-
ephemeralPubkey
|
|
450
|
-
);
|
|
451
|
-
const expectedStealth = deriveStealthPubkey(metaPubkey, sharedSecret);
|
|
452
|
-
return bytesToHex(expectedStealth) === bytesToHex(targetAddress);
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// src/light.ts
|
|
456
|
-
var import_web33 = require("@solana/web3.js");
|
|
457
|
-
var LIGHT_PROGRAM_IDS = {
|
|
458
|
-
LIGHT_SYSTEM_PROGRAM: new import_web33.PublicKey(
|
|
459
|
-
"SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7"
|
|
460
|
-
),
|
|
461
|
-
COMPRESSED_TOKEN_PROGRAM: new import_web33.PublicKey(
|
|
462
|
-
"cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m"
|
|
463
|
-
),
|
|
464
|
-
ACCOUNT_COMPRESSION_PROGRAM: new import_web33.PublicKey(
|
|
465
|
-
"compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq"
|
|
466
|
-
)
|
|
467
|
-
};
|
|
468
|
-
var LightClient = class _LightClient {
|
|
469
|
-
constructor(connection, config) {
|
|
470
|
-
this.connection = connection;
|
|
471
|
-
this.config = config;
|
|
472
|
-
}
|
|
473
|
-
/**
|
|
474
|
-
* Creates a new Light Protocol client
|
|
475
|
-
*
|
|
476
|
-
* @param rpcUrl - Solana RPC URL with Light Protocol support
|
|
477
|
-
* @returns LightClient instance
|
|
478
|
-
*/
|
|
479
|
-
static create(rpcUrl) {
|
|
480
|
-
const connection = new import_web33.Connection(rpcUrl, "confirmed");
|
|
481
|
-
return new _LightClient(connection, { rpcUrl });
|
|
482
|
-
}
|
|
483
|
-
/**
|
|
484
|
-
* Gets compressed SOL balance for an address
|
|
485
|
-
*
|
|
486
|
-
* @param owner - Owner public key
|
|
487
|
-
* @returns Compressed SOL balance in lamports
|
|
488
|
-
*/
|
|
489
|
-
async getCompressedSolBalance(owner) {
|
|
490
|
-
try {
|
|
491
|
-
const response = await fetch(this.config.rpcUrl, {
|
|
492
|
-
method: "POST",
|
|
493
|
-
headers: { "Content-Type": "application/json" },
|
|
494
|
-
body: JSON.stringify({
|
|
495
|
-
jsonrpc: "2.0",
|
|
496
|
-
id: 1,
|
|
497
|
-
method: "getCompressedAccountsByOwner",
|
|
498
|
-
params: [owner.toBase58()]
|
|
499
|
-
})
|
|
500
|
-
});
|
|
501
|
-
const data = await response.json();
|
|
502
|
-
if (data.error) {
|
|
503
|
-
console.warn("Light RPC error:", data.error);
|
|
504
|
-
return BigInt(0);
|
|
505
|
-
}
|
|
506
|
-
const accounts = data.result?.items || [];
|
|
507
|
-
let total = BigInt(0);
|
|
508
|
-
for (const acc of accounts) {
|
|
509
|
-
total += BigInt(acc.lamports || 0);
|
|
510
|
-
}
|
|
511
|
-
return total;
|
|
512
|
-
} catch (error) {
|
|
513
|
-
console.warn("Failed to get compressed balance:", error);
|
|
514
|
-
return BigInt(0);
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
/**
|
|
518
|
-
* Gets compressed token balances for an address
|
|
519
|
-
*
|
|
520
|
-
* @param owner - Owner public key
|
|
521
|
-
* @param mint - Optional token mint to filter
|
|
522
|
-
* @returns Array of compressed token balances
|
|
523
|
-
*/
|
|
524
|
-
async getCompressedTokenBalances(owner, mint) {
|
|
525
|
-
try {
|
|
526
|
-
const response = await fetch(this.config.rpcUrl, {
|
|
527
|
-
method: "POST",
|
|
528
|
-
headers: { "Content-Type": "application/json" },
|
|
529
|
-
body: JSON.stringify({
|
|
530
|
-
jsonrpc: "2.0",
|
|
531
|
-
id: 1,
|
|
532
|
-
method: "getCompressedTokenAccountsByOwner",
|
|
533
|
-
params: [owner.toBase58(), mint?.toBase58()]
|
|
534
|
-
})
|
|
535
|
-
});
|
|
536
|
-
const data = await response.json();
|
|
537
|
-
if (data.error) {
|
|
538
|
-
console.warn("Light RPC error:", data.error);
|
|
539
|
-
return [];
|
|
540
|
-
}
|
|
541
|
-
const balancesByMint = /* @__PURE__ */ new Map();
|
|
542
|
-
const accounts = data.result?.items || [];
|
|
543
|
-
for (const acc of accounts) {
|
|
544
|
-
const mintStr = acc.mint;
|
|
545
|
-
if (!balancesByMint.has(mintStr)) {
|
|
546
|
-
balancesByMint.set(mintStr, {
|
|
547
|
-
mint: new import_web33.PublicKey(mintStr),
|
|
548
|
-
amount: BigInt(0),
|
|
549
|
-
accounts: []
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
const balance = balancesByMint.get(mintStr);
|
|
553
|
-
balance.amount += BigInt(acc.amount || 0);
|
|
554
|
-
balance.accounts.push({
|
|
555
|
-
hash: acc.hash,
|
|
556
|
-
owner: new import_web33.PublicKey(acc.owner),
|
|
557
|
-
lamports: acc.lamports || 0,
|
|
558
|
-
data: new Uint8Array(acc.data || []),
|
|
559
|
-
tree: new import_web33.PublicKey(acc.tree),
|
|
560
|
-
leafIndex: acc.leafIndex
|
|
561
|
-
});
|
|
562
|
-
}
|
|
563
|
-
return Array.from(balancesByMint.values());
|
|
564
|
-
} catch (error) {
|
|
565
|
-
console.warn("Failed to get compressed token balances:", error);
|
|
566
|
-
return [];
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
/**
|
|
570
|
-
* Creates a compressed SOL transfer instruction
|
|
571
|
-
*
|
|
572
|
-
* Note: This creates the instruction data structure.
|
|
573
|
-
* Actual ZK proof generation requires Light Protocol SDK.
|
|
574
|
-
*
|
|
575
|
-
* @param from - Sender public key
|
|
576
|
-
* @param to - Recipient public key (can be stealth address)
|
|
577
|
-
* @param amount - Amount in lamports
|
|
578
|
-
* @returns Transaction instruction (placeholder)
|
|
579
|
-
*/
|
|
580
|
-
createCompressedTransferInstruction(from, to, amount) {
|
|
581
|
-
const data = Buffer.alloc(72);
|
|
582
|
-
data.write("compressed_transfer", 0);
|
|
583
|
-
data.writeBigUInt64LE(amount, 32);
|
|
584
|
-
return new import_web33.TransactionInstruction({
|
|
585
|
-
keys: [
|
|
586
|
-
{ pubkey: from, isSigner: true, isWritable: true },
|
|
587
|
-
{ pubkey: to, isSigner: false, isWritable: true },
|
|
588
|
-
{
|
|
589
|
-
pubkey: LIGHT_PROGRAM_IDS.LIGHT_SYSTEM_PROGRAM,
|
|
590
|
-
isSigner: false,
|
|
591
|
-
isWritable: false
|
|
592
|
-
}
|
|
593
|
-
],
|
|
594
|
-
programId: LIGHT_PROGRAM_IDS.LIGHT_SYSTEM_PROGRAM,
|
|
595
|
-
data
|
|
596
|
-
});
|
|
597
|
-
}
|
|
598
|
-
/**
|
|
599
|
-
* Compresses SOL from regular account to compressed account
|
|
600
|
-
*
|
|
601
|
-
* @param owner - Owner public key
|
|
602
|
-
* @param amount - Amount in lamports to compress
|
|
603
|
-
* @returns Transaction (unsigned)
|
|
604
|
-
*/
|
|
605
|
-
async createCompressSolTransaction(owner, amount) {
|
|
606
|
-
const instruction = this.createCompressedTransferInstruction(
|
|
607
|
-
owner,
|
|
608
|
-
owner,
|
|
609
|
-
// Compress to self
|
|
610
|
-
amount
|
|
611
|
-
);
|
|
612
|
-
const transaction = new import_web33.Transaction().add(instruction);
|
|
613
|
-
transaction.recentBlockhash = (await this.connection.getLatestBlockhash()).blockhash;
|
|
614
|
-
transaction.feePayer = owner;
|
|
615
|
-
return transaction;
|
|
616
|
-
}
|
|
617
|
-
/**
|
|
618
|
-
* Decompresses SOL from compressed account to regular account
|
|
619
|
-
*
|
|
620
|
-
* @param owner - Owner public key
|
|
621
|
-
* @param amount - Amount in lamports to decompress
|
|
622
|
-
* @returns Transaction (unsigned)
|
|
623
|
-
*/
|
|
624
|
-
async createDecompressSolTransaction(owner, amount) {
|
|
625
|
-
const instruction = this.createCompressedTransferInstruction(
|
|
626
|
-
owner,
|
|
627
|
-
owner,
|
|
628
|
-
amount
|
|
629
|
-
);
|
|
630
|
-
const transaction = new import_web33.Transaction().add(instruction);
|
|
631
|
-
transaction.recentBlockhash = (await this.connection.getLatestBlockhash()).blockhash;
|
|
632
|
-
transaction.feePayer = owner;
|
|
633
|
-
return transaction;
|
|
634
|
-
}
|
|
635
|
-
/**
|
|
636
|
-
* Creates a stealth compressed transfer
|
|
637
|
-
* Combines stealth addressing with ZK-compression
|
|
638
|
-
*
|
|
639
|
-
* @param from - Sender public key
|
|
640
|
-
* @param stealthPubkey - Derived stealth address for recipient
|
|
641
|
-
* @param amount - Amount in lamports
|
|
642
|
-
* @param memo - Stealth memo containing ephemeral pubkey
|
|
643
|
-
* @returns Transaction (unsigned)
|
|
644
|
-
*/
|
|
645
|
-
async createStealthCompressedTransfer(from, stealthPubkey, amount, memo) {
|
|
646
|
-
const stealthAddress = new import_web33.PublicKey(stealthPubkey);
|
|
647
|
-
const transferIx = this.createCompressedTransferInstruction(
|
|
648
|
-
from,
|
|
649
|
-
stealthAddress,
|
|
650
|
-
amount
|
|
651
|
-
);
|
|
652
|
-
const memoIx = new import_web33.TransactionInstruction({
|
|
653
|
-
keys: [],
|
|
654
|
-
programId: MEMO_PROGRAM_ID,
|
|
655
|
-
data: Buffer.from(memo, "utf-8")
|
|
656
|
-
});
|
|
657
|
-
const transaction = new import_web33.Transaction().add(transferIx).add(memoIx);
|
|
658
|
-
transaction.recentBlockhash = (await this.connection.getLatestBlockhash()).blockhash;
|
|
659
|
-
transaction.feePayer = from;
|
|
660
|
-
return transaction;
|
|
661
|
-
}
|
|
662
|
-
};
|
|
663
|
-
function createLightClient(rpcUrl) {
|
|
664
|
-
return LightClient.create(rpcUrl);
|
|
413
|
+
return { stealthPubkey, ephemeralKeypair, sharedSecret, memo };
|
|
665
414
|
}
|
|
666
415
|
|
|
667
416
|
// src/indexer.ts
|
|
668
|
-
var
|
|
417
|
+
var import_web33 = require("@solana/web3.js");
|
|
669
418
|
var AdelosIndexer = class _AdelosIndexer {
|
|
670
419
|
constructor(config) {
|
|
671
|
-
this.
|
|
672
|
-
this.
|
|
673
|
-
this.config = config;
|
|
674
|
-
this.connection = new import_web34.Connection(config.rpcUrl, "confirmed");
|
|
420
|
+
this.connection = new import_web33.Connection(config.rpcUrl, "confirmed");
|
|
421
|
+
this.heliusApiKey = config.heliusApiKey;
|
|
675
422
|
}
|
|
676
|
-
/**
|
|
677
|
-
* Creates an indexer instance
|
|
678
|
-
*/
|
|
679
423
|
static create(config) {
|
|
680
424
|
return new _AdelosIndexer(config);
|
|
681
425
|
}
|
|
682
|
-
/**
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
*
|
|
689
|
-
* @param metaSk - Recipient's meta secret key
|
|
690
|
-
* @param metaPubkey - Recipient's meta public key
|
|
691
|
-
* @param limit - Number of transactions to scan
|
|
692
|
-
* @returns Array of stealth transactions for this recipient
|
|
693
|
-
*/
|
|
694
|
-
async scanForStealthTransfers(metaSk, metaPubkey, limit = 100) {
|
|
695
|
-
const results = [];
|
|
696
|
-
try {
|
|
697
|
-
const signatures = await this.connection.getSignaturesForAddress(
|
|
698
|
-
MEMO_PROGRAM_ID,
|
|
699
|
-
{ limit }
|
|
700
|
-
);
|
|
701
|
-
for (const sigInfo of signatures) {
|
|
702
|
-
const tx = await this.connection.getParsedTransaction(
|
|
703
|
-
sigInfo.signature,
|
|
704
|
-
{ maxSupportedTransactionVersion: 0 }
|
|
705
|
-
);
|
|
706
|
-
if (!tx) continue;
|
|
707
|
-
const memo = this.extractMemo(tx);
|
|
708
|
-
if (!memo?.startsWith(MEMO_PREFIX)) continue;
|
|
709
|
-
const stealthTx = await this.parseStealthTransaction(
|
|
710
|
-
tx,
|
|
711
|
-
sigInfo.signature,
|
|
712
|
-
metaSk,
|
|
713
|
-
metaPubkey
|
|
714
|
-
);
|
|
715
|
-
if (stealthTx) {
|
|
716
|
-
results.push(stealthTx);
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
} catch (error) {
|
|
720
|
-
console.error("Error scanning transactions:", error);
|
|
721
|
-
}
|
|
722
|
-
return results;
|
|
723
|
-
}
|
|
724
|
-
/**
|
|
725
|
-
* Scans all transactions with ADLSv1 memo prefix
|
|
726
|
-
*
|
|
727
|
-
* @param metaSk - Recipient's meta secret key
|
|
728
|
-
* @param metaPubkey - Recipient's meta public key
|
|
729
|
-
* @param since - Scan transactions after this signature
|
|
730
|
-
* @returns Array of stealth transactions
|
|
731
|
-
*/
|
|
732
|
-
async scanByMemoPrefix(metaSk, metaPubkey, since) {
|
|
426
|
+
/** Scan for stealth transfers to this recipient */
|
|
427
|
+
async scanForStealthTransfers(metaSk, metaPk, limit = 100) {
|
|
428
|
+
const sigs = await this.connection.getSignaturesForAddress(
|
|
429
|
+
ADELOS_CONFIG.MEMO_PROGRAM_ID,
|
|
430
|
+
{ limit }
|
|
431
|
+
);
|
|
733
432
|
const results = [];
|
|
734
|
-
|
|
735
|
-
const
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
);
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
sigInfo.signature,
|
|
750
|
-
metaSk,
|
|
751
|
-
metaPubkey
|
|
752
|
-
);
|
|
753
|
-
if (stealthTx) {
|
|
754
|
-
results.push(stealthTx);
|
|
755
|
-
}
|
|
433
|
+
for (const s of sigs) {
|
|
434
|
+
const tx = await this.connection.getParsedTransaction(s.signature, {
|
|
435
|
+
maxSupportedTransactionVersion: 0
|
|
436
|
+
});
|
|
437
|
+
if (!tx) continue;
|
|
438
|
+
const memo = this.extractMemo(tx);
|
|
439
|
+
if (!memo?.startsWith(ADELOS_CONFIG.MEMO_PREFIX)) continue;
|
|
440
|
+
const detected = this.attemptDecryption(tx, metaSk, metaPk);
|
|
441
|
+
if (detected) {
|
|
442
|
+
results.push({
|
|
443
|
+
signature: s.signature,
|
|
444
|
+
blockTime: tx.blockTime ?? null,
|
|
445
|
+
stealthAddress: detected.stealthAddress,
|
|
446
|
+
amount: detected.amount
|
|
447
|
+
});
|
|
756
448
|
}
|
|
757
|
-
} catch (error) {
|
|
758
|
-
console.error("Error scanning by memo:", error);
|
|
759
449
|
}
|
|
760
450
|
return results;
|
|
761
451
|
}
|
|
762
|
-
/**
|
|
763
|
-
|
|
764
|
-
*/
|
|
765
|
-
extractMemo(tx) {
|
|
766
|
-
const memoProgram = "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr";
|
|
767
|
-
for (const ix of tx.transaction.message.instructions) {
|
|
768
|
-
if ("programId" in ix && ix.programId.toBase58() === memoProgram) {
|
|
769
|
-
if ("parsed" in ix && typeof ix.parsed === "string") {
|
|
770
|
-
return ix.parsed;
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
if (tx.meta?.innerInstructions) {
|
|
775
|
-
for (const inner of tx.meta.innerInstructions) {
|
|
776
|
-
for (const ix of inner.instructions) {
|
|
777
|
-
if ("programId" in ix && ix.programId.toBase58() === memoProgram) {
|
|
778
|
-
if ("parsed" in ix && typeof ix.parsed === "string") {
|
|
779
|
-
return ix.parsed;
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
return null;
|
|
786
|
-
}
|
|
787
|
-
/**
|
|
788
|
-
* Parses a transaction to extract stealth transfer info using Trial Decryption
|
|
789
|
-
*
|
|
790
|
-
* Trial Decryption: First compute expected stealth address, then find if it exists in tx accounts
|
|
791
|
-
*/
|
|
792
|
-
async parseStealthTransaction(tx, signature, metaSk, metaPubkey) {
|
|
452
|
+
/** Trial Decryption: Check if transaction is for this recipient */
|
|
453
|
+
attemptDecryption(tx, metaSk, metaPk) {
|
|
793
454
|
const memo = this.extractMemo(tx);
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
try {
|
|
799
|
-
const sharedSecret = await computeSharedSecretAsRecipient(
|
|
800
|
-
metaSk,
|
|
801
|
-
ephemeralPubkey
|
|
802
|
-
);
|
|
803
|
-
const expectedStealth = deriveStealthPubkey(metaPubkey, sharedSecret);
|
|
804
|
-
expectedStealthHex = bytesToHex(expectedStealth);
|
|
805
|
-
} catch (error) {
|
|
806
|
-
console.warn("Error computing expected stealth:", error);
|
|
807
|
-
return null;
|
|
808
|
-
}
|
|
455
|
+
const ephemeralPk = parseStealthMemo(memo || "");
|
|
456
|
+
if (!ephemeralPk) return null;
|
|
457
|
+
const secret = computeSharedSecretAsRecipient(metaSk, ephemeralPk);
|
|
458
|
+
const expectedStealthHex = bytesToHex(deriveStealthPubkey(metaPk, secret));
|
|
809
459
|
const accounts = tx.transaction.message.accountKeys;
|
|
460
|
+
const idx = accounts.findIndex(
|
|
461
|
+
(a) => bytesToHex(a.pubkey.toBytes()) === expectedStealthHex
|
|
462
|
+
);
|
|
463
|
+
if (idx === -1) return null;
|
|
810
464
|
const preBalances = tx.meta?.preBalances || [];
|
|
811
465
|
const postBalances = tx.meta?.postBalances || [];
|
|
812
|
-
|
|
813
|
-
for (let i = 0; i < accounts.length; i++) {
|
|
814
|
-
const accountHex = bytesToHex(accounts[i].pubkey.toBytes());
|
|
815
|
-
if (accountHex === expectedStealthHex) {
|
|
816
|
-
stealthIndex = i;
|
|
817
|
-
break;
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
if (stealthIndex === -1) return null;
|
|
821
|
-
const stealthAddress = accounts[stealthIndex].pubkey;
|
|
822
|
-
const change = (postBalances[stealthIndex] || 0) - (preBalances[stealthIndex] || 0);
|
|
823
|
-
const amount = BigInt(Math.max(change, 0));
|
|
824
|
-
let sender = null;
|
|
825
|
-
for (let i = 0; i < accounts.length; i++) {
|
|
826
|
-
const accChange = (postBalances[i] || 0) - (preBalances[i] || 0);
|
|
827
|
-
if (accChange < 0) {
|
|
828
|
-
sender = accounts[i].pubkey;
|
|
829
|
-
break;
|
|
830
|
-
}
|
|
831
|
-
}
|
|
466
|
+
const change = (postBalances[idx] || 0) - (preBalances[idx] || 0);
|
|
832
467
|
return {
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
slot: tx.slot,
|
|
836
|
-
sender,
|
|
837
|
-
stealthAddress,
|
|
838
|
-
amount,
|
|
839
|
-
ephemeralPubkey,
|
|
840
|
-
isForMe: true
|
|
841
|
-
// If we reach here, it's definitely for us
|
|
468
|
+
stealthAddress: accounts[idx].pubkey,
|
|
469
|
+
amount: BigInt(Math.max(change, 0))
|
|
842
470
|
};
|
|
843
471
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
*/
|
|
850
|
-
startScanning(metaSk, metaPubkey) {
|
|
851
|
-
if (this.isScanning) return;
|
|
852
|
-
this.isScanning = true;
|
|
853
|
-
let lastSignature;
|
|
854
|
-
const scanInterval = this.config.scanInterval || 1e4;
|
|
855
|
-
this.scanIntervalId = setInterval(async () => {
|
|
856
|
-
try {
|
|
857
|
-
const txs = await this.scanByMemoPrefix(
|
|
858
|
-
metaSk,
|
|
859
|
-
metaPubkey,
|
|
860
|
-
lastSignature
|
|
861
|
-
);
|
|
862
|
-
for (const tx of txs) {
|
|
863
|
-
if (tx.isForMe && this.onTransaction) {
|
|
864
|
-
this.onTransaction(tx);
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
if (txs.length > 0) {
|
|
868
|
-
lastSignature = txs[0].signature;
|
|
869
|
-
}
|
|
870
|
-
} catch (error) {
|
|
871
|
-
console.error("Scan error:", error);
|
|
872
|
-
}
|
|
873
|
-
}, scanInterval);
|
|
874
|
-
}
|
|
875
|
-
/**
|
|
876
|
-
* Stops continuous scanning
|
|
877
|
-
*/
|
|
878
|
-
stopScanning() {
|
|
879
|
-
this.isScanning = false;
|
|
880
|
-
if (this.scanIntervalId) {
|
|
881
|
-
clearInterval(this.scanIntervalId);
|
|
882
|
-
this.scanIntervalId = null;
|
|
883
|
-
}
|
|
884
|
-
}
|
|
885
|
-
/**
|
|
886
|
-
* Processes a Helius webhook payload
|
|
887
|
-
*
|
|
888
|
-
* @param payload - Webhook payload from Helius
|
|
889
|
-
* @param metaSk - Recipient's meta secret key
|
|
890
|
-
* @param metaPubkey - Recipient's meta public key
|
|
891
|
-
* @returns Stealth transaction if detected and for this recipient
|
|
892
|
-
*/
|
|
893
|
-
async processWebhook(payload, metaSk, metaPubkey) {
|
|
894
|
-
let memo = null;
|
|
895
|
-
const memoProgramStr = MEMO_PROGRAM_ID.toBase58();
|
|
896
|
-
for (const ix of payload.instructions) {
|
|
897
|
-
if (ix.programId === memoProgramStr) {
|
|
898
|
-
memo = Buffer.from(ix.data, "base64").toString("utf-8");
|
|
899
|
-
break;
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
if (!memo?.startsWith(MEMO_PREFIX)) return null;
|
|
903
|
-
const ephemeralPubkey = parseStealthMemo(memo);
|
|
904
|
-
if (!ephemeralPubkey) return null;
|
|
905
|
-
let stealthAddress = null;
|
|
906
|
-
let amount = BigInt(0);
|
|
907
|
-
for (const acc of payload.accountData) {
|
|
908
|
-
if (acc.nativeBalanceChange > 0) {
|
|
909
|
-
stealthAddress = new import_web34.PublicKey(acc.account);
|
|
910
|
-
amount = BigInt(acc.nativeBalanceChange);
|
|
911
|
-
break;
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
if (!stealthAddress) return null;
|
|
915
|
-
let isForMe = false;
|
|
916
|
-
try {
|
|
917
|
-
const sharedSecret = await computeSharedSecretAsRecipient(
|
|
918
|
-
metaSk,
|
|
919
|
-
ephemeralPubkey
|
|
920
|
-
);
|
|
921
|
-
const expectedStealth = deriveStealthPubkey(metaPubkey, sharedSecret);
|
|
922
|
-
isForMe = bytesToHex(expectedStealth) === bytesToHex(stealthAddress.toBytes());
|
|
923
|
-
} catch (error) {
|
|
924
|
-
console.warn("Error checking webhook tx:", error);
|
|
925
|
-
}
|
|
926
|
-
if (!isForMe) return null;
|
|
927
|
-
return {
|
|
928
|
-
signature: payload.signature,
|
|
929
|
-
blockTime: payload.timestamp,
|
|
930
|
-
slot: payload.slot,
|
|
931
|
-
sender: null,
|
|
932
|
-
stealthAddress,
|
|
933
|
-
amount,
|
|
934
|
-
ephemeralPubkey,
|
|
935
|
-
isForMe: true
|
|
936
|
-
};
|
|
937
|
-
}
|
|
938
|
-
/**
|
|
939
|
-
* Sets up Helius webhook for real-time notifications
|
|
940
|
-
*
|
|
941
|
-
* @param webhookUrl - Your server's webhook endpoint
|
|
942
|
-
* @returns Webhook ID
|
|
943
|
-
*/
|
|
944
|
-
async setupHeliusWebhook(webhookUrl) {
|
|
945
|
-
if (!this.config.heliusApiKey) {
|
|
946
|
-
console.warn("Helius API key not configured");
|
|
947
|
-
return null;
|
|
948
|
-
}
|
|
949
|
-
try {
|
|
950
|
-
const response = await fetch(
|
|
951
|
-
`https://api.helius.xyz/v0/webhooks?api-key=${this.config.heliusApiKey}`,
|
|
952
|
-
{
|
|
953
|
-
method: "POST",
|
|
954
|
-
headers: { "Content-Type": "application/json" },
|
|
955
|
-
body: JSON.stringify({
|
|
956
|
-
webhookURL: webhookUrl,
|
|
957
|
-
transactionTypes: ["TRANSFER"],
|
|
958
|
-
accountAddresses: [
|
|
959
|
-
MEMO_PROGRAM_ID.toBase58()
|
|
960
|
-
],
|
|
961
|
-
webhookType: "enhanced"
|
|
962
|
-
})
|
|
963
|
-
}
|
|
964
|
-
);
|
|
965
|
-
const data = await response.json();
|
|
966
|
-
return data.webhookID || null;
|
|
967
|
-
} catch (error) {
|
|
968
|
-
console.error("Failed to setup Helius webhook:", error);
|
|
969
|
-
return null;
|
|
970
|
-
}
|
|
472
|
+
extractMemo(tx) {
|
|
473
|
+
const ix = tx.transaction.message.instructions.find(
|
|
474
|
+
(i) => i.programId.equals(ADELOS_CONFIG.MEMO_PROGRAM_ID)
|
|
475
|
+
);
|
|
476
|
+
return ix?.parsed || null;
|
|
971
477
|
}
|
|
972
478
|
};
|
|
973
479
|
function createIndexer(config) {
|
|
974
|
-
return AdelosIndexer
|
|
480
|
+
return new AdelosIndexer(config);
|
|
975
481
|
}
|
|
976
482
|
|
|
977
483
|
// src/index.ts
|
|
978
484
|
var AdelosSDK = class {
|
|
979
485
|
constructor(options = {}) {
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
this.
|
|
983
|
-
this.programId = PROGRAM_IDS[this.cluster];
|
|
984
|
-
this.heliusApiKey = options.heliusApiKey;
|
|
486
|
+
const rpcUrl = options.rpcUrl ?? ADELOS_CONFIG.RPC_URL;
|
|
487
|
+
this.connection = new import_web34.Connection(rpcUrl, "confirmed");
|
|
488
|
+
this.programId = ADELOS_CONFIG.PROGRAM_ID;
|
|
985
489
|
}
|
|
986
|
-
|
|
987
|
-
* Derives the registry PDA for an owner
|
|
988
|
-
*/
|
|
490
|
+
// --- Registry Operations ---
|
|
989
491
|
deriveRegistryAddress(owner) {
|
|
990
492
|
return deriveRegistryPda(owner, this.programId);
|
|
991
493
|
}
|
|
992
|
-
/**
|
|
993
|
-
* Fetches a registry account by owner
|
|
994
|
-
*/
|
|
995
494
|
async getRegistry(owner) {
|
|
996
495
|
const [address] = this.deriveRegistryAddress(owner);
|
|
997
496
|
const accountInfo = await this.connection.getAccountInfo(address);
|
|
998
497
|
if (!accountInfo) {
|
|
999
|
-
return {
|
|
1000
|
-
address,
|
|
1001
|
-
exists: false,
|
|
1002
|
-
account: null
|
|
1003
|
-
};
|
|
498
|
+
return { address, exists: false, account: null };
|
|
1004
499
|
}
|
|
1005
500
|
const data = accountInfo.data.slice(8);
|
|
1006
501
|
const account = {
|
|
1007
|
-
owner: new
|
|
502
|
+
owner: new import_web34.PublicKey(data.slice(0, 32)),
|
|
1008
503
|
metaPubkey: new Uint8Array(data.slice(32, 64)),
|
|
1009
504
|
bump: data[64]
|
|
1010
505
|
};
|
|
1011
506
|
return { address, exists: true, account };
|
|
1012
507
|
}
|
|
1013
|
-
/**
|
|
1014
|
-
* Gets the meta pubkey for an owner
|
|
1015
|
-
* @returns The meta pubkey as Uint8Array, or null if not registered
|
|
1016
|
-
*/
|
|
1017
508
|
async getMetaPubkey(owner) {
|
|
1018
509
|
const registry = await this.getRegistry(owner);
|
|
1019
510
|
return registry.exists ? registry.account.metaPubkey : null;
|
|
1020
511
|
}
|
|
1021
|
-
/**
|
|
1022
|
-
* Gets the meta pubkey as hex string
|
|
1023
|
-
*/
|
|
1024
|
-
async getMetaPubkeyHex(owner) {
|
|
1025
|
-
const metaPubkey = await this.getMetaPubkey(owner);
|
|
1026
|
-
return metaPubkey ? bytesToHex(metaPubkey) : null;
|
|
1027
|
-
}
|
|
1028
|
-
/**
|
|
1029
|
-
* Checks if an owner has a registered identity
|
|
1030
|
-
*/
|
|
1031
512
|
async isRegistered(owner) {
|
|
1032
513
|
const registry = await this.getRegistry(owner);
|
|
1033
514
|
return registry.exists;
|
|
1034
515
|
}
|
|
1035
|
-
|
|
1036
|
-
* Creates a register identity instruction
|
|
1037
|
-
*/
|
|
516
|
+
// --- Instruction Builders ---
|
|
1038
517
|
createRegisterInstruction(owner, metaPubkey) {
|
|
1039
518
|
if (!isValidMetaPubkey(metaPubkey)) {
|
|
1040
519
|
throw new Error("Invalid meta pubkey: must be 32 bytes and not all zeros");
|
|
@@ -1044,19 +523,16 @@ var AdelosSDK = class {
|
|
|
1044
523
|
Buffer.from(getDiscriminator("register_identity")),
|
|
1045
524
|
Buffer.from(metaPubkey)
|
|
1046
525
|
]);
|
|
1047
|
-
return new
|
|
526
|
+
return new import_web34.TransactionInstruction({
|
|
1048
527
|
keys: [
|
|
1049
528
|
{ pubkey: owner, isSigner: true, isWritable: true },
|
|
1050
529
|
{ pubkey: registryPda, isSigner: false, isWritable: true },
|
|
1051
|
-
{ pubkey:
|
|
530
|
+
{ pubkey: import_web34.SystemProgram.programId, isSigner: false, isWritable: false }
|
|
1052
531
|
],
|
|
1053
532
|
programId: this.programId,
|
|
1054
533
|
data
|
|
1055
534
|
});
|
|
1056
535
|
}
|
|
1057
|
-
/**
|
|
1058
|
-
* Creates an update identity instruction
|
|
1059
|
-
*/
|
|
1060
536
|
createUpdateInstruction(owner, newMetaPubkey) {
|
|
1061
537
|
if (!isValidMetaPubkey(newMetaPubkey)) {
|
|
1062
538
|
throw new Error("Invalid meta pubkey: must be 32 bytes and not all zeros");
|
|
@@ -1066,22 +542,20 @@ var AdelosSDK = class {
|
|
|
1066
542
|
Buffer.from(getDiscriminator("update_identity")),
|
|
1067
543
|
Buffer.from(newMetaPubkey)
|
|
1068
544
|
]);
|
|
1069
|
-
return new
|
|
545
|
+
return new import_web34.TransactionInstruction({
|
|
1070
546
|
keys: [
|
|
1071
|
-
{ pubkey: owner, isSigner: true, isWritable:
|
|
1072
|
-
{ pubkey: registryPda, isSigner: false, isWritable: true }
|
|
547
|
+
{ pubkey: owner, isSigner: true, isWritable: true },
|
|
548
|
+
{ pubkey: registryPda, isSigner: false, isWritable: true },
|
|
549
|
+
{ pubkey: import_web34.SystemProgram.programId, isSigner: false, isWritable: false }
|
|
1073
550
|
],
|
|
1074
551
|
programId: this.programId,
|
|
1075
552
|
data
|
|
1076
553
|
});
|
|
1077
554
|
}
|
|
1078
|
-
/**
|
|
1079
|
-
* Creates a close registry instruction
|
|
1080
|
-
*/
|
|
1081
555
|
createCloseInstruction(owner) {
|
|
1082
556
|
const [registryPda] = this.deriveRegistryAddress(owner);
|
|
1083
557
|
const data = Buffer.from(getDiscriminator("close_registry"));
|
|
1084
|
-
return new
|
|
558
|
+
return new import_web34.TransactionInstruction({
|
|
1085
559
|
keys: [
|
|
1086
560
|
{ pubkey: owner, isSigner: true, isWritable: true },
|
|
1087
561
|
{ pubkey: registryPda, isSigner: false, isWritable: true }
|
|
@@ -1090,117 +564,57 @@ var AdelosSDK = class {
|
|
|
1090
564
|
data
|
|
1091
565
|
});
|
|
1092
566
|
}
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
*/
|
|
1096
|
-
async createRegisterTransaction(owner, metaPubkey) {
|
|
1097
|
-
const instruction = this.createRegisterInstruction(owner, metaPubkey);
|
|
1098
|
-
const transaction = new import_web35.Transaction().add(instruction);
|
|
1099
|
-
transaction.recentBlockhash = (await this.connection.getLatestBlockhash()).blockhash;
|
|
1100
|
-
transaction.feePayer = owner;
|
|
1101
|
-
return transaction;
|
|
1102
|
-
}
|
|
1103
|
-
/**
|
|
1104
|
-
* Creates a register transaction (unsigned) - Versioned format (v0)
|
|
1105
|
-
* Recommended for modern Solana applications
|
|
1106
|
-
*/
|
|
1107
|
-
async createRegisterTransactionV0(owner, metaPubkey) {
|
|
1108
|
-
const instruction = this.createRegisterInstruction(owner, metaPubkey);
|
|
567
|
+
// --- Transaction Builders ---
|
|
568
|
+
async buildTransaction(payer, instructions, version = "v0") {
|
|
1109
569
|
const { blockhash } = await this.connection.getLatestBlockhash();
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
recentBlockhash
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
* Creates an update transaction (unsigned) - Legacy format
|
|
1119
|
-
*/
|
|
1120
|
-
async createUpdateTransaction(owner, newMetaPubkey) {
|
|
1121
|
-
const instruction = this.createUpdateInstruction(owner, newMetaPubkey);
|
|
1122
|
-
const transaction = new import_web35.Transaction().add(instruction);
|
|
1123
|
-
transaction.recentBlockhash = (await this.connection.getLatestBlockhash()).blockhash;
|
|
1124
|
-
transaction.feePayer = owner;
|
|
1125
|
-
return transaction;
|
|
1126
|
-
}
|
|
1127
|
-
/**
|
|
1128
|
-
* Creates an update transaction (unsigned) - Versioned format (v0)
|
|
1129
|
-
*/
|
|
1130
|
-
async createUpdateTransactionV0(owner, newMetaPubkey) {
|
|
1131
|
-
const instruction = this.createUpdateInstruction(owner, newMetaPubkey);
|
|
1132
|
-
const { blockhash } = await this.connection.getLatestBlockhash();
|
|
1133
|
-
const messageV0 = new import_web35.TransactionMessage({
|
|
1134
|
-
payerKey: owner,
|
|
570
|
+
if (version === "legacy") {
|
|
571
|
+
const tx = new import_web34.Transaction().add(...instructions);
|
|
572
|
+
tx.recentBlockhash = blockhash;
|
|
573
|
+
tx.feePayer = payer;
|
|
574
|
+
return tx;
|
|
575
|
+
}
|
|
576
|
+
const message = new import_web34.TransactionMessage({
|
|
577
|
+
payerKey: payer,
|
|
1135
578
|
recentBlockhash: blockhash,
|
|
1136
|
-
instructions
|
|
579
|
+
instructions
|
|
1137
580
|
}).compileToV0Message();
|
|
1138
|
-
return new
|
|
581
|
+
return new import_web34.VersionedTransaction(message);
|
|
1139
582
|
}
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
async createCloseTransaction(owner) {
|
|
1144
|
-
const instruction = this.createCloseInstruction(owner);
|
|
1145
|
-
const transaction = new import_web35.Transaction().add(instruction);
|
|
1146
|
-
transaction.recentBlockhash = (await this.connection.getLatestBlockhash()).blockhash;
|
|
1147
|
-
transaction.feePayer = owner;
|
|
1148
|
-
return transaction;
|
|
583
|
+
async createRegisterTransaction(owner, metaPubkey) {
|
|
584
|
+
const ix = this.createRegisterInstruction(owner, metaPubkey);
|
|
585
|
+
return this.buildTransaction(owner, [ix], "legacy");
|
|
1149
586
|
}
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
async createCloseTransactionV0(owner) {
|
|
1154
|
-
const instruction = this.createCloseInstruction(owner);
|
|
1155
|
-
const { blockhash } = await this.connection.getLatestBlockhash();
|
|
1156
|
-
const messageV0 = new import_web35.TransactionMessage({
|
|
1157
|
-
payerKey: owner,
|
|
1158
|
-
recentBlockhash: blockhash,
|
|
1159
|
-
instructions: [instruction]
|
|
1160
|
-
}).compileToV0Message();
|
|
1161
|
-
return new import_web35.VersionedTransaction(messageV0);
|
|
587
|
+
async createRegisterTransactionV0(owner, metaPubkey) {
|
|
588
|
+
const ix = this.createRegisterInstruction(owner, metaPubkey);
|
|
589
|
+
return this.buildTransaction(owner, [ix], "v0");
|
|
1162
590
|
}
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
const signature = await this.connection.sendRawTransaction(
|
|
1168
|
-
signedTransaction.serialize()
|
|
1169
|
-
);
|
|
1170
|
-
await this.connection.confirmTransaction(signature, "confirmed");
|
|
1171
|
-
return signature;
|
|
591
|
+
async sendAndConfirm(signedTx) {
|
|
592
|
+
const sig = await this.connection.sendRawTransaction(signedTx.serialize());
|
|
593
|
+
await this.connection.confirmTransaction(sig, "confirmed");
|
|
594
|
+
return sig;
|
|
1172
595
|
}
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
const signature = await this.connection.sendRawTransaction(
|
|
1178
|
-
signedTransaction.serialize()
|
|
1179
|
-
);
|
|
1180
|
-
await this.connection.confirmTransaction(signature, "confirmed");
|
|
1181
|
-
return signature;
|
|
596
|
+
async sendAndConfirmV0(signedTx) {
|
|
597
|
+
const sig = await this.connection.sendRawTransaction(signedTx.serialize());
|
|
598
|
+
await this.connection.confirmTransaction(sig, "confirmed");
|
|
599
|
+
return sig;
|
|
1182
600
|
}
|
|
1183
601
|
};
|
|
1184
602
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1185
603
|
0 && (module.exports = {
|
|
604
|
+
ADELOS_CONFIG,
|
|
1186
605
|
AdelosIndexer,
|
|
1187
606
|
AdelosSDK,
|
|
1188
607
|
IDL,
|
|
1189
|
-
LIGHT_PROGRAM_IDS,
|
|
1190
|
-
LightClient,
|
|
1191
608
|
MEMO_PREFIX,
|
|
1192
609
|
MEMO_PROGRAM_ID,
|
|
1193
610
|
PROGRAM_ID,
|
|
1194
|
-
PROGRAM_IDS,
|
|
1195
|
-
REGISTRY_ACCOUNT_SIZE,
|
|
1196
611
|
REGISTRY_SEED,
|
|
1197
|
-
|
|
612
|
+
RPC_URL,
|
|
1198
613
|
STEALTH_DOMAIN,
|
|
1199
614
|
bytesToHex,
|
|
1200
615
|
computeSharedSecret,
|
|
1201
616
|
computeSharedSecretAsRecipient,
|
|
1202
617
|
createIndexer,
|
|
1203
|
-
createLightClient,
|
|
1204
618
|
deriveRegistryPda,
|
|
1205
619
|
deriveStealthPubkey,
|
|
1206
620
|
generateEphemeralKeypair,
|
|
@@ -1208,7 +622,6 @@ var AdelosSDK = class {
|
|
|
1208
622
|
generateStealthMemo,
|
|
1209
623
|
getDiscriminator,
|
|
1210
624
|
hexToBytes,
|
|
1211
|
-
isStealthTransactionForMe,
|
|
1212
625
|
isValidMetaPubkey,
|
|
1213
626
|
parseStealthMemo,
|
|
1214
627
|
recoverStealthSecretKey
|