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