@adelos/sdk 0.1.2 → 0.1.3
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 +137 -725
- package/dist/index.mjs +137 -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,51 @@ 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 metaPoint = ed.ExtendedPoint.fromHex(
|
|
391
|
-
const stealthPoint = metaPoint.add(
|
|
372
|
+
function computeSharedSecretAsRecipient(metaSk, ephemeralPk) {
|
|
373
|
+
const point = ed.ExtendedPoint.fromHex(bytesToHex(ephemeralPk));
|
|
374
|
+
const scalar = ed.etc.mod(BigInt("0x" + bytesToHex(metaSk)), ed.CURVE.n);
|
|
375
|
+
return (0, import_sha256.sha256)(point.multiply(scalar).toRawBytes());
|
|
376
|
+
}
|
|
377
|
+
function deriveStealthPubkey(metaPk, sharedSecret) {
|
|
378
|
+
const domain = encoder.encode(ADELOS_CONFIG.STEALTH_DOMAIN);
|
|
379
|
+
const scalarBytes = (0, import_sha256.sha256)(new Uint8Array([...sharedSecret, ...domain]));
|
|
380
|
+
const scalar = ed.etc.mod(BigInt("0x" + bytesToHex(scalarBytes)), ed.CURVE.n);
|
|
381
|
+
const metaPoint = ed.ExtendedPoint.fromHex(bytesToHex(metaPk));
|
|
382
|
+
const stealthPoint = metaPoint.add(ed.ExtendedPoint.BASE.multiply(scalar));
|
|
392
383
|
return stealthPoint.toRawBytes();
|
|
393
384
|
}
|
|
394
385
|
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
|
-
);
|
|
386
|
+
const domain = encoder.encode(ADELOS_CONFIG.STEALTH_DOMAIN);
|
|
387
|
+
const scalarBytes = (0, import_sha256.sha256)(new Uint8Array([...sharedSecret, ...domain]));
|
|
388
|
+
const scalar = ed.etc.mod(BigInt("0x" + bytesToHex(scalarBytes)), ed.CURVE.n);
|
|
389
|
+
const metaScalar = ed.etc.mod(BigInt("0x" + bytesToHex(metaSk)), ed.CURVE.n);
|
|
406
390
|
const stealthScalar = ed.etc.mod(metaScalar + scalar, ed.CURVE.n);
|
|
407
391
|
const hex = stealthScalar.toString(16).padStart(64, "0");
|
|
408
392
|
return hexToBytes(hex);
|
|
409
393
|
}
|
|
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
394
|
function generateStealthMemo(ephemeralPubkey) {
|
|
418
|
-
|
|
419
|
-
return `${MEMO_PREFIX}${pubkeyHex}`;
|
|
395
|
+
return `${ADELOS_CONFIG.MEMO_PREFIX}${bytesToHex(ephemeralPubkey)}`;
|
|
420
396
|
}
|
|
421
397
|
function parseStealthMemo(memo) {
|
|
422
|
-
if (!memo.startsWith(MEMO_PREFIX)) return null;
|
|
423
|
-
const pubkeyHex = memo.slice(MEMO_PREFIX.length);
|
|
398
|
+
if (!memo.startsWith(ADELOS_CONFIG.MEMO_PREFIX)) return null;
|
|
399
|
+
const pubkeyHex = memo.slice(ADELOS_CONFIG.MEMO_PREFIX.length);
|
|
424
400
|
if (pubkeyHex.length !== 64) return null;
|
|
425
401
|
try {
|
|
426
402
|
return hexToBytes(pubkeyHex);
|
|
@@ -428,613 +404,115 @@ function parseStealthMemo(memo) {
|
|
|
428
404
|
return null;
|
|
429
405
|
}
|
|
430
406
|
}
|
|
431
|
-
|
|
407
|
+
function generateStealthAddress(recipientMetaPk) {
|
|
432
408
|
const ephemeralKeypair = generateEphemeralKeypair();
|
|
433
|
-
const sharedSecret =
|
|
434
|
-
|
|
435
|
-
recipientMetaPubkey
|
|
436
|
-
);
|
|
437
|
-
const stealthPubkey = deriveStealthPubkey(recipientMetaPubkey, sharedSecret);
|
|
409
|
+
const sharedSecret = computeSharedSecret(ephemeralKeypair.secretKey, recipientMetaPk);
|
|
410
|
+
const stealthPubkey = deriveStealthPubkey(recipientMetaPk, sharedSecret);
|
|
438
411
|
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);
|
|
412
|
+
return { stealthPubkey, ephemeralKeypair, sharedSecret, memo };
|
|
665
413
|
}
|
|
666
414
|
|
|
667
415
|
// src/indexer.ts
|
|
668
|
-
var
|
|
416
|
+
var import_web33 = require("@solana/web3.js");
|
|
669
417
|
var AdelosIndexer = class _AdelosIndexer {
|
|
670
418
|
constructor(config) {
|
|
671
|
-
this.
|
|
672
|
-
this.
|
|
673
|
-
this.config = config;
|
|
674
|
-
this.connection = new import_web34.Connection(config.rpcUrl, "confirmed");
|
|
419
|
+
this.connection = new import_web33.Connection(config.rpcUrl, "confirmed");
|
|
420
|
+
this.heliusApiKey = config.heliusApiKey;
|
|
675
421
|
}
|
|
676
|
-
/**
|
|
677
|
-
* Creates an indexer instance
|
|
678
|
-
*/
|
|
679
422
|
static create(config) {
|
|
680
423
|
return new _AdelosIndexer(config);
|
|
681
424
|
}
|
|
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) {
|
|
425
|
+
/** Scan for stealth transfers to this recipient */
|
|
426
|
+
async scanForStealthTransfers(metaSk, metaPk, limit = 100) {
|
|
427
|
+
const sigs = await this.connection.getSignaturesForAddress(
|
|
428
|
+
ADELOS_CONFIG.MEMO_PROGRAM_ID,
|
|
429
|
+
{ limit }
|
|
430
|
+
);
|
|
733
431
|
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
|
-
}
|
|
432
|
+
for (const s of sigs) {
|
|
433
|
+
const tx = await this.connection.getParsedTransaction(s.signature, {
|
|
434
|
+
maxSupportedTransactionVersion: 0
|
|
435
|
+
});
|
|
436
|
+
if (!tx) continue;
|
|
437
|
+
const memo = this.extractMemo(tx);
|
|
438
|
+
if (!memo?.startsWith(ADELOS_CONFIG.MEMO_PREFIX)) continue;
|
|
439
|
+
const detected = this.attemptDecryption(tx, metaSk, metaPk);
|
|
440
|
+
if (detected) {
|
|
441
|
+
results.push({
|
|
442
|
+
signature: s.signature,
|
|
443
|
+
blockTime: tx.blockTime ?? null,
|
|
444
|
+
stealthAddress: detected.stealthAddress,
|
|
445
|
+
amount: detected.amount
|
|
446
|
+
});
|
|
756
447
|
}
|
|
757
|
-
} catch (error) {
|
|
758
|
-
console.error("Error scanning by memo:", error);
|
|
759
448
|
}
|
|
760
449
|
return results;
|
|
761
450
|
}
|
|
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) {
|
|
451
|
+
/** Trial Decryption: Check if transaction is for this recipient */
|
|
452
|
+
attemptDecryption(tx, metaSk, metaPk) {
|
|
793
453
|
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
|
-
}
|
|
454
|
+
const ephemeralPk = parseStealthMemo(memo || "");
|
|
455
|
+
if (!ephemeralPk) return null;
|
|
456
|
+
const secret = computeSharedSecretAsRecipient(metaSk, ephemeralPk);
|
|
457
|
+
const expectedStealthHex = bytesToHex(deriveStealthPubkey(metaPk, secret));
|
|
809
458
|
const accounts = tx.transaction.message.accountKeys;
|
|
459
|
+
const idx = accounts.findIndex(
|
|
460
|
+
(a) => bytesToHex(a.pubkey.toBytes()) === expectedStealthHex
|
|
461
|
+
);
|
|
462
|
+
if (idx === -1) return null;
|
|
810
463
|
const preBalances = tx.meta?.preBalances || [];
|
|
811
464
|
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
|
-
}
|
|
832
|
-
return {
|
|
833
|
-
signature,
|
|
834
|
-
blockTime: tx.blockTime ?? null,
|
|
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
|
|
842
|
-
};
|
|
843
|
-
}
|
|
844
|
-
/**
|
|
845
|
-
* Starts continuous scanning for stealth transfers
|
|
846
|
-
*
|
|
847
|
-
* @param metaSk - Recipient's meta secret key
|
|
848
|
-
* @param metaPubkey - Recipient's meta public key
|
|
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;
|
|
465
|
+
const change = (postBalances[idx] || 0) - (preBalances[idx] || 0);
|
|
927
466
|
return {
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
slot: payload.slot,
|
|
931
|
-
sender: null,
|
|
932
|
-
stealthAddress,
|
|
933
|
-
amount,
|
|
934
|
-
ephemeralPubkey,
|
|
935
|
-
isForMe: true
|
|
467
|
+
stealthAddress: accounts[idx].pubkey,
|
|
468
|
+
amount: BigInt(Math.max(change, 0))
|
|
936
469
|
};
|
|
937
470
|
}
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
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
|
-
}
|
|
471
|
+
extractMemo(tx) {
|
|
472
|
+
const ix = tx.transaction.message.instructions.find(
|
|
473
|
+
(i) => i.programId.equals(ADELOS_CONFIG.MEMO_PROGRAM_ID)
|
|
474
|
+
);
|
|
475
|
+
return ix?.parsed || null;
|
|
971
476
|
}
|
|
972
477
|
};
|
|
973
478
|
function createIndexer(config) {
|
|
974
|
-
return AdelosIndexer
|
|
479
|
+
return new AdelosIndexer(config);
|
|
975
480
|
}
|
|
976
481
|
|
|
977
482
|
// src/index.ts
|
|
978
483
|
var AdelosSDK = class {
|
|
979
484
|
constructor(options = {}) {
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
this.
|
|
983
|
-
this.programId = PROGRAM_IDS[this.cluster];
|
|
984
|
-
this.heliusApiKey = options.heliusApiKey;
|
|
485
|
+
const rpcUrl = options.rpcUrl ?? ADELOS_CONFIG.RPC_URL;
|
|
486
|
+
this.connection = new import_web34.Connection(rpcUrl, "confirmed");
|
|
487
|
+
this.programId = ADELOS_CONFIG.PROGRAM_ID;
|
|
985
488
|
}
|
|
986
|
-
|
|
987
|
-
* Derives the registry PDA for an owner
|
|
988
|
-
*/
|
|
489
|
+
// --- Registry Operations ---
|
|
989
490
|
deriveRegistryAddress(owner) {
|
|
990
491
|
return deriveRegistryPda(owner, this.programId);
|
|
991
492
|
}
|
|
992
|
-
/**
|
|
993
|
-
* Fetches a registry account by owner
|
|
994
|
-
*/
|
|
995
493
|
async getRegistry(owner) {
|
|
996
494
|
const [address] = this.deriveRegistryAddress(owner);
|
|
997
495
|
const accountInfo = await this.connection.getAccountInfo(address);
|
|
998
496
|
if (!accountInfo) {
|
|
999
|
-
return {
|
|
1000
|
-
address,
|
|
1001
|
-
exists: false,
|
|
1002
|
-
account: null
|
|
1003
|
-
};
|
|
497
|
+
return { address, exists: false, account: null };
|
|
1004
498
|
}
|
|
1005
499
|
const data = accountInfo.data.slice(8);
|
|
1006
500
|
const account = {
|
|
1007
|
-
owner: new
|
|
501
|
+
owner: new import_web34.PublicKey(data.slice(0, 32)),
|
|
1008
502
|
metaPubkey: new Uint8Array(data.slice(32, 64)),
|
|
1009
503
|
bump: data[64]
|
|
1010
504
|
};
|
|
1011
505
|
return { address, exists: true, account };
|
|
1012
506
|
}
|
|
1013
|
-
/**
|
|
1014
|
-
* Gets the meta pubkey for an owner
|
|
1015
|
-
* @returns The meta pubkey as Uint8Array, or null if not registered
|
|
1016
|
-
*/
|
|
1017
507
|
async getMetaPubkey(owner) {
|
|
1018
508
|
const registry = await this.getRegistry(owner);
|
|
1019
509
|
return registry.exists ? registry.account.metaPubkey : null;
|
|
1020
510
|
}
|
|
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
511
|
async isRegistered(owner) {
|
|
1032
512
|
const registry = await this.getRegistry(owner);
|
|
1033
513
|
return registry.exists;
|
|
1034
514
|
}
|
|
1035
|
-
|
|
1036
|
-
* Creates a register identity instruction
|
|
1037
|
-
*/
|
|
515
|
+
// --- Instruction Builders ---
|
|
1038
516
|
createRegisterInstruction(owner, metaPubkey) {
|
|
1039
517
|
if (!isValidMetaPubkey(metaPubkey)) {
|
|
1040
518
|
throw new Error("Invalid meta pubkey: must be 32 bytes and not all zeros");
|
|
@@ -1044,19 +522,16 @@ var AdelosSDK = class {
|
|
|
1044
522
|
Buffer.from(getDiscriminator("register_identity")),
|
|
1045
523
|
Buffer.from(metaPubkey)
|
|
1046
524
|
]);
|
|
1047
|
-
return new
|
|
525
|
+
return new import_web34.TransactionInstruction({
|
|
1048
526
|
keys: [
|
|
1049
527
|
{ pubkey: owner, isSigner: true, isWritable: true },
|
|
1050
528
|
{ pubkey: registryPda, isSigner: false, isWritable: true },
|
|
1051
|
-
{ pubkey:
|
|
529
|
+
{ pubkey: import_web34.SystemProgram.programId, isSigner: false, isWritable: false }
|
|
1052
530
|
],
|
|
1053
531
|
programId: this.programId,
|
|
1054
532
|
data
|
|
1055
533
|
});
|
|
1056
534
|
}
|
|
1057
|
-
/**
|
|
1058
|
-
* Creates an update identity instruction
|
|
1059
|
-
*/
|
|
1060
535
|
createUpdateInstruction(owner, newMetaPubkey) {
|
|
1061
536
|
if (!isValidMetaPubkey(newMetaPubkey)) {
|
|
1062
537
|
throw new Error("Invalid meta pubkey: must be 32 bytes and not all zeros");
|
|
@@ -1066,22 +541,20 @@ var AdelosSDK = class {
|
|
|
1066
541
|
Buffer.from(getDiscriminator("update_identity")),
|
|
1067
542
|
Buffer.from(newMetaPubkey)
|
|
1068
543
|
]);
|
|
1069
|
-
return new
|
|
544
|
+
return new import_web34.TransactionInstruction({
|
|
1070
545
|
keys: [
|
|
1071
|
-
{ pubkey: owner, isSigner: true, isWritable:
|
|
1072
|
-
{ pubkey: registryPda, isSigner: false, isWritable: true }
|
|
546
|
+
{ pubkey: owner, isSigner: true, isWritable: true },
|
|
547
|
+
{ pubkey: registryPda, isSigner: false, isWritable: true },
|
|
548
|
+
{ pubkey: import_web34.SystemProgram.programId, isSigner: false, isWritable: false }
|
|
1073
549
|
],
|
|
1074
550
|
programId: this.programId,
|
|
1075
551
|
data
|
|
1076
552
|
});
|
|
1077
553
|
}
|
|
1078
|
-
/**
|
|
1079
|
-
* Creates a close registry instruction
|
|
1080
|
-
*/
|
|
1081
554
|
createCloseInstruction(owner) {
|
|
1082
555
|
const [registryPda] = this.deriveRegistryAddress(owner);
|
|
1083
556
|
const data = Buffer.from(getDiscriminator("close_registry"));
|
|
1084
|
-
return new
|
|
557
|
+
return new import_web34.TransactionInstruction({
|
|
1085
558
|
keys: [
|
|
1086
559
|
{ pubkey: owner, isSigner: true, isWritable: true },
|
|
1087
560
|
{ pubkey: registryPda, isSigner: false, isWritable: true }
|
|
@@ -1090,117 +563,57 @@ var AdelosSDK = class {
|
|
|
1090
563
|
data
|
|
1091
564
|
});
|
|
1092
565
|
}
|
|
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);
|
|
1109
|
-
const { blockhash } = await this.connection.getLatestBlockhash();
|
|
1110
|
-
const messageV0 = new import_web35.TransactionMessage({
|
|
1111
|
-
payerKey: owner,
|
|
1112
|
-
recentBlockhash: blockhash,
|
|
1113
|
-
instructions: [instruction]
|
|
1114
|
-
}).compileToV0Message();
|
|
1115
|
-
return new import_web35.VersionedTransaction(messageV0);
|
|
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);
|
|
566
|
+
// --- Transaction Builders ---
|
|
567
|
+
async buildTransaction(payer, instructions, version = "v0") {
|
|
1132
568
|
const { blockhash } = await this.connection.getLatestBlockhash();
|
|
1133
|
-
|
|
1134
|
-
|
|
569
|
+
if (version === "legacy") {
|
|
570
|
+
const tx = new import_web34.Transaction().add(...instructions);
|
|
571
|
+
tx.recentBlockhash = blockhash;
|
|
572
|
+
tx.feePayer = payer;
|
|
573
|
+
return tx;
|
|
574
|
+
}
|
|
575
|
+
const message = new import_web34.TransactionMessage({
|
|
576
|
+
payerKey: payer,
|
|
1135
577
|
recentBlockhash: blockhash,
|
|
1136
|
-
instructions
|
|
578
|
+
instructions
|
|
1137
579
|
}).compileToV0Message();
|
|
1138
|
-
return new
|
|
580
|
+
return new import_web34.VersionedTransaction(message);
|
|
1139
581
|
}
|
|
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;
|
|
582
|
+
async createRegisterTransaction(owner, metaPubkey) {
|
|
583
|
+
const ix = this.createRegisterInstruction(owner, metaPubkey);
|
|
584
|
+
return this.buildTransaction(owner, [ix], "legacy");
|
|
1149
585
|
}
|
|
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);
|
|
586
|
+
async createRegisterTransactionV0(owner, metaPubkey) {
|
|
587
|
+
const ix = this.createRegisterInstruction(owner, metaPubkey);
|
|
588
|
+
return this.buildTransaction(owner, [ix], "v0");
|
|
1162
589
|
}
|
|
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;
|
|
590
|
+
async sendAndConfirm(signedTx) {
|
|
591
|
+
const sig = await this.connection.sendRawTransaction(signedTx.serialize());
|
|
592
|
+
await this.connection.confirmTransaction(sig, "confirmed");
|
|
593
|
+
return sig;
|
|
1172
594
|
}
|
|
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;
|
|
595
|
+
async sendAndConfirmV0(signedTx) {
|
|
596
|
+
const sig = await this.connection.sendRawTransaction(signedTx.serialize());
|
|
597
|
+
await this.connection.confirmTransaction(sig, "confirmed");
|
|
598
|
+
return sig;
|
|
1182
599
|
}
|
|
1183
600
|
};
|
|
1184
601
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1185
602
|
0 && (module.exports = {
|
|
603
|
+
ADELOS_CONFIG,
|
|
1186
604
|
AdelosIndexer,
|
|
1187
605
|
AdelosSDK,
|
|
1188
606
|
IDL,
|
|
1189
|
-
LIGHT_PROGRAM_IDS,
|
|
1190
|
-
LightClient,
|
|
1191
607
|
MEMO_PREFIX,
|
|
1192
608
|
MEMO_PROGRAM_ID,
|
|
1193
609
|
PROGRAM_ID,
|
|
1194
|
-
PROGRAM_IDS,
|
|
1195
|
-
REGISTRY_ACCOUNT_SIZE,
|
|
1196
610
|
REGISTRY_SEED,
|
|
1197
|
-
|
|
611
|
+
RPC_URL,
|
|
1198
612
|
STEALTH_DOMAIN,
|
|
1199
613
|
bytesToHex,
|
|
1200
614
|
computeSharedSecret,
|
|
1201
615
|
computeSharedSecretAsRecipient,
|
|
1202
616
|
createIndexer,
|
|
1203
|
-
createLightClient,
|
|
1204
617
|
deriveRegistryPda,
|
|
1205
618
|
deriveStealthPubkey,
|
|
1206
619
|
generateEphemeralKeypair,
|
|
@@ -1208,7 +621,6 @@ var AdelosSDK = class {
|
|
|
1208
621
|
generateStealthMemo,
|
|
1209
622
|
getDiscriminator,
|
|
1210
623
|
hexToBytes,
|
|
1211
|
-
isStealthTransactionForMe,
|
|
1212
624
|
isValidMetaPubkey,
|
|
1213
625
|
parseStealthMemo,
|
|
1214
626
|
recoverStealthSecretKey
|