@sip-protocol/sdk 0.11.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{TransportWebUSB-2KITI5HD.mjs → TransportWebUSB-TXDZJBGS.mjs} +12 -12
- package/dist/browser.d.mts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +864 -545
- package/dist/browser.mjs +13 -3
- package/dist/{chunk-L4RKPNIJ.mjs → chunk-4EHEBTKP.mjs} +132 -87
- package/dist/{chunk-7IUKXWDN.mjs → chunk-MKTCJPFH.mjs} +331 -94
- package/dist/{chunk-IBZVA5Y7.mjs → chunk-NMC5RNMV.mjs} +2 -2
- package/dist/{chunk-XGB3TDIC.mjs → chunk-S3F4CPQ5.mjs} +5 -1
- package/dist/{constants-DCJYTIU3.mjs → constants-NCGOQF7S.mjs} +1 -1
- package/dist/{dist-PYEXZNFD.mjs → dist-4KSUM2PU.mjs} +2 -2
- package/dist/{dist-IFHPYLDX.mjs → dist-4O5YILSN.mjs} +2 -2
- package/dist/{fulfillment_proof-ANHVPKTB.mjs → fulfillment_proof-WCEE5GGO.mjs} +1 -1
- package/dist/{funding_proof-ICFZ5LHY.mjs → funding_proof-X5IP4SG5.mjs} +1 -1
- package/dist/{index-DH5XRHYV.d.mts → index-B_fGN4Fk.d.mts} +796 -597
- package/dist/{index-mw7KGX5M.d.ts → index-rqQpCeVM.d.ts} +796 -597
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +864 -545
- package/dist/index.mjs +13 -3
- package/dist/proofs/halo2.mjs +1 -1
- package/dist/proofs/kimchi.mjs +1 -1
- package/dist/proofs/noir.mjs +1 -1
- package/dist/{solana-7QOA3HBZ.mjs → solana-VKZI66MK.mjs} +12 -2
- package/dist/{validity_proof-3POXLPNY.mjs → validity_proof-2GVV6GA6.mjs} +1 -1
- package/package.json +6 -5
- package/src/chains/solana/gasless-cashout.ts +331 -0
- package/src/chains/solana/index.ts +16 -0
- package/src/chains/solana/privacy-adapter.ts +1 -0
- package/src/chains/solana/providers/webhook.ts +1 -0
- package/src/chains/solana/relayer-fee.ts +39 -0
- package/src/chains/solana/scan.ts +11 -70
- package/src/chains/solana/stealth-scanner.ts +8 -0
- package/src/chains/solana/stealth-signer.ts +145 -0
- package/src/chains/solana/types.ts +2 -0
- package/src/index.ts +14 -0
- package/src/proofs/parallel/concurrency.ts +2 -2
- package/src/solana/jito-relayer.ts +40 -8
- package/src/wallet/solana/privacy-adapter.ts +29 -66
|
@@ -2395,9 +2395,8 @@ function detectCluster3(endpoint) {
|
|
|
2395
2395
|
|
|
2396
2396
|
// src/chains/solana/scan.ts
|
|
2397
2397
|
import {
|
|
2398
|
-
PublicKey as
|
|
2399
|
-
Transaction as
|
|
2400
|
-
Keypair
|
|
2398
|
+
PublicKey as PublicKey5,
|
|
2399
|
+
Transaction as Transaction5
|
|
2401
2400
|
} from "@solana/web3.js";
|
|
2402
2401
|
import {
|
|
2403
2402
|
getAssociatedTokenAddress as getAssociatedTokenAddress3,
|
|
@@ -2434,9 +2433,70 @@ function parseTokenTransferFromBalances(preBalances, postBalances) {
|
|
|
2434
2433
|
return null;
|
|
2435
2434
|
}
|
|
2436
2435
|
|
|
2437
|
-
// src/chains/solana/
|
|
2438
|
-
import {
|
|
2436
|
+
// src/chains/solana/stealth-signer.ts
|
|
2437
|
+
import { PublicKey as PublicKey4 } from "@solana/web3.js";
|
|
2439
2438
|
import { ed25519 as ed255192 } from "@noble/curves/ed25519";
|
|
2439
|
+
import { sha512 as sha5122 } from "@noble/hashes/sha512";
|
|
2440
|
+
import { hexToBytes as hexToBytes2 } from "@noble/hashes/utils";
|
|
2441
|
+
function modL(value) {
|
|
2442
|
+
const reduced = value % ED25519_ORDER;
|
|
2443
|
+
return reduced >= 0n ? reduced : reduced + ED25519_ORDER;
|
|
2444
|
+
}
|
|
2445
|
+
function signEd25519WithScalar(message, scalar) {
|
|
2446
|
+
const a = modL(bytesToBigIntLE(scalar));
|
|
2447
|
+
if (a === 0n) {
|
|
2448
|
+
throw new Error("Invalid stealth scalar: reduces to zero");
|
|
2449
|
+
}
|
|
2450
|
+
const A = ed255192.ExtendedPoint.BASE.multiply(a).toRawBytes();
|
|
2451
|
+
const prefix = sha5122(scalar).slice(32, 64);
|
|
2452
|
+
const r = modL(bytesToBigIntLE(sha5122(new Uint8Array([...prefix, ...message]))));
|
|
2453
|
+
if (r === 0n) {
|
|
2454
|
+
throw new Error("Invalid nonce: reduces to zero");
|
|
2455
|
+
}
|
|
2456
|
+
const R = ed255192.ExtendedPoint.BASE.multiply(r).toRawBytes();
|
|
2457
|
+
const k = modL(bytesToBigIntLE(sha5122(new Uint8Array([...R, ...A, ...message]))));
|
|
2458
|
+
const S = modL(r + k * a);
|
|
2459
|
+
return new Uint8Array([...R, ...bigIntToBytesLE(S, 32)]);
|
|
2460
|
+
}
|
|
2461
|
+
function deriveStealthSigner(params) {
|
|
2462
|
+
const {
|
|
2463
|
+
stealthAddress,
|
|
2464
|
+
ephemeralPublicKey,
|
|
2465
|
+
viewingPrivateKey,
|
|
2466
|
+
spendingPrivateKey,
|
|
2467
|
+
version = "2"
|
|
2468
|
+
} = params;
|
|
2469
|
+
const stealthAddressHex = solanaAddressToEd25519PublicKey(stealthAddress);
|
|
2470
|
+
const ephemeralPubKeyHex = solanaAddressToEd25519PublicKey(ephemeralPublicKey);
|
|
2471
|
+
const stealthAddressObj = {
|
|
2472
|
+
address: stealthAddressHex,
|
|
2473
|
+
ephemeralPublicKey: ephemeralPubKeyHex,
|
|
2474
|
+
viewTag: 0
|
|
2475
|
+
};
|
|
2476
|
+
const recovery = version === "1" ? deriveEd25519StealthPrivateKeyV1(stealthAddressObj, spendingPrivateKey, viewingPrivateKey) : deriveEd25519StealthPrivateKey(stealthAddressObj, spendingPrivateKey, viewingPrivateKey);
|
|
2477
|
+
const scalar = hexToBytes2(recovery.privateKey.slice(2));
|
|
2478
|
+
const publicKey = new PublicKey4(stealthAddress);
|
|
2479
|
+
const expectedPubKeyBytes = publicKey.toBytes();
|
|
2480
|
+
const derivedPubKeyBytes = ed255192.ExtendedPoint.BASE.multiply(modL(bytesToBigIntLE(scalar))).toRawBytes();
|
|
2481
|
+
if (!derivedPubKeyBytes.every((b, i) => b === expectedPubKeyBytes[i])) {
|
|
2482
|
+
throw new Error(
|
|
2483
|
+
"Stealth key derivation failed: derived scalar does not produce expected public key. This may indicate incorrect spending/viewing keys or corrupted announcement data."
|
|
2484
|
+
);
|
|
2485
|
+
}
|
|
2486
|
+
return {
|
|
2487
|
+
publicKey,
|
|
2488
|
+
signMessage(message) {
|
|
2489
|
+
return signEd25519WithScalar(message, scalar);
|
|
2490
|
+
},
|
|
2491
|
+
signTransaction(transaction) {
|
|
2492
|
+
const message = transaction.serializeMessage();
|
|
2493
|
+
const signature = signEd25519WithScalar(message, scalar);
|
|
2494
|
+
transaction.addSignature(publicKey, Buffer.from(signature));
|
|
2495
|
+
}
|
|
2496
|
+
};
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
// src/chains/solana/scan.ts
|
|
2440
2500
|
async function scanForPayments(params) {
|
|
2441
2501
|
const {
|
|
2442
2502
|
connection,
|
|
@@ -2448,7 +2508,7 @@ async function scanForPayments(params) {
|
|
|
2448
2508
|
provider
|
|
2449
2509
|
} = params;
|
|
2450
2510
|
const results = [];
|
|
2451
|
-
const memoProgram = new
|
|
2511
|
+
const memoProgram = new PublicKey5(MEMO_PROGRAM_ID);
|
|
2452
2512
|
try {
|
|
2453
2513
|
const signatures = await connection.getSignaturesForAddress(
|
|
2454
2514
|
memoProgram,
|
|
@@ -2527,6 +2587,7 @@ async function scanForPayments(params) {
|
|
|
2527
2587
|
results.push({
|
|
2528
2588
|
stealthAddress: announcement.stealthAddress || "",
|
|
2529
2589
|
ephemeralPublicKey: announcement.ephemeralPublicKey,
|
|
2590
|
+
version: announcement.version,
|
|
2530
2591
|
amount,
|
|
2531
2592
|
mint: transferInfo.mint,
|
|
2532
2593
|
tokenSymbol,
|
|
@@ -2558,51 +2619,34 @@ async function claimStealthPayment(params) {
|
|
|
2558
2619
|
mint,
|
|
2559
2620
|
version = "2"
|
|
2560
2621
|
} = params;
|
|
2561
|
-
const stealthPubkeyForBalance = new
|
|
2622
|
+
const stealthPubkeyForBalance = new PublicKey5(stealthAddress);
|
|
2562
2623
|
const solBalance = await connection.getBalance(stealthPubkeyForBalance);
|
|
2563
2624
|
if (BigInt(solBalance) < MIN_SOL_FOR_FEES) {
|
|
2564
2625
|
throw new Error(
|
|
2565
2626
|
`Insufficient SOL for transaction fees. Stealth address has ${solBalance} lamports, needs at least ${MIN_SOL_FOR_FEES} lamports (~0.000005 SOL). Fund the stealth address with SOL before claiming.`
|
|
2566
2627
|
);
|
|
2567
2628
|
}
|
|
2568
|
-
const
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
const recovery = version === "1" ? deriveEd25519StealthPrivateKeyV1(stealthAddressObj, spendingPrivateKey, viewingPrivateKey) : deriveEd25519StealthPrivateKey(stealthAddressObj, spendingPrivateKey, viewingPrivateKey);
|
|
2577
|
-
const stealthPrivKeyBytes = hexToBytes2(recovery.privateKey.slice(2));
|
|
2578
|
-
const stealthPubkey = new PublicKey4(stealthAddress);
|
|
2579
|
-
const expectedPubKeyBytes = stealthPubkey.toBytes();
|
|
2580
|
-
const scalarBigInt = bytesToBigIntLE2(stealthPrivKeyBytes);
|
|
2581
|
-
const ED25519_ORDER3 = 2n ** 252n + 27742317777372353535851937790883648493n;
|
|
2582
|
-
let validScalar = scalarBigInt % ED25519_ORDER3;
|
|
2583
|
-
if (validScalar === 0n) validScalar = 1n;
|
|
2584
|
-
const derivedPubKeyBytes = ed255192.ExtendedPoint.BASE.multiply(validScalar).toRawBytes();
|
|
2585
|
-
if (!derivedPubKeyBytes.every((b, i) => b === expectedPubKeyBytes[i])) {
|
|
2586
|
-
throw new Error(
|
|
2587
|
-
"Stealth key derivation failed: derived private key does not produce expected public key. This may indicate incorrect spending/viewing keys or corrupted announcement data."
|
|
2588
|
-
);
|
|
2589
|
-
}
|
|
2590
|
-
const stealthKeypair = Keypair.fromSecretKey(
|
|
2591
|
-
new Uint8Array([...stealthPrivKeyBytes, ...expectedPubKeyBytes])
|
|
2592
|
-
);
|
|
2629
|
+
const stealthSigner = deriveStealthSigner({
|
|
2630
|
+
stealthAddress,
|
|
2631
|
+
ephemeralPublicKey,
|
|
2632
|
+
viewingPrivateKey,
|
|
2633
|
+
spendingPrivateKey,
|
|
2634
|
+
version
|
|
2635
|
+
});
|
|
2636
|
+
const stealthPubkey = new PublicKey5(stealthAddress);
|
|
2593
2637
|
const stealthATA = await getAssociatedTokenAddress3(
|
|
2594
2638
|
mint,
|
|
2595
2639
|
stealthPubkey,
|
|
2596
2640
|
true
|
|
2597
2641
|
);
|
|
2598
|
-
const destinationPubkey = new
|
|
2642
|
+
const destinationPubkey = new PublicKey5(destinationAddress);
|
|
2599
2643
|
const destinationATA = await getAssociatedTokenAddress3(
|
|
2600
2644
|
mint,
|
|
2601
2645
|
destinationPubkey
|
|
2602
2646
|
);
|
|
2603
2647
|
const stealthAccount = await getAccount3(connection, stealthATA);
|
|
2604
2648
|
const amount = stealthAccount.amount;
|
|
2605
|
-
const transaction = new
|
|
2649
|
+
const transaction = new Transaction5();
|
|
2606
2650
|
transaction.add(
|
|
2607
2651
|
createTransferInstruction3(
|
|
2608
2652
|
stealthATA,
|
|
@@ -2615,7 +2659,7 @@ async function claimStealthPayment(params) {
|
|
|
2615
2659
|
transaction.recentBlockhash = blockhash;
|
|
2616
2660
|
transaction.lastValidBlockHeight = lastValidBlockHeight;
|
|
2617
2661
|
transaction.feePayer = stealthPubkey;
|
|
2618
|
-
|
|
2662
|
+
stealthSigner.signTransaction(transaction);
|
|
2619
2663
|
const txSignature = await connection.sendRawTransaction(
|
|
2620
2664
|
transaction.serialize(),
|
|
2621
2665
|
{
|
|
@@ -2647,7 +2691,7 @@ async function getStealthBalance(connection, stealthAddress, mint, provider) {
|
|
|
2647
2691
|
}
|
|
2648
2692
|
}
|
|
2649
2693
|
try {
|
|
2650
|
-
const stealthPubkey = new
|
|
2694
|
+
const stealthPubkey = new PublicKey5(stealthAddress);
|
|
2651
2695
|
const ata = await getAssociatedTokenAddress3(mint, stealthPubkey, true);
|
|
2652
2696
|
const account = await getAccount3(connection, ata);
|
|
2653
2697
|
return account.amount;
|
|
@@ -2667,16 +2711,9 @@ function detectCluster4(endpoint) {
|
|
|
2667
2711
|
}
|
|
2668
2712
|
return "mainnet-beta";
|
|
2669
2713
|
}
|
|
2670
|
-
function bytesToBigIntLE2(bytes) {
|
|
2671
|
-
let result = 0n;
|
|
2672
|
-
for (let i = bytes.length - 1; i >= 0; i--) {
|
|
2673
|
-
result = result << 8n | BigInt(bytes[i]);
|
|
2674
|
-
}
|
|
2675
|
-
return result;
|
|
2676
|
-
}
|
|
2677
2714
|
|
|
2678
2715
|
// src/chains/solana/stealth-scanner.ts
|
|
2679
|
-
import { PublicKey as
|
|
2716
|
+
import { PublicKey as PublicKey6 } from "@solana/web3.js";
|
|
2680
2717
|
var StealthScanner = class {
|
|
2681
2718
|
connection;
|
|
2682
2719
|
provider;
|
|
@@ -2743,7 +2780,7 @@ var StealthScanner = class {
|
|
|
2743
2780
|
let scannedCount = 0;
|
|
2744
2781
|
let lastSignature;
|
|
2745
2782
|
let lastSlot;
|
|
2746
|
-
const memoProgram = new
|
|
2783
|
+
const memoProgram = new PublicKey6(MEMO_PROGRAM_ID);
|
|
2747
2784
|
try {
|
|
2748
2785
|
const signatures = await this.connection.getSignaturesForAddress(
|
|
2749
2786
|
memoProgram,
|
|
@@ -2811,7 +2848,7 @@ var StealthScanner = class {
|
|
|
2811
2848
|
}
|
|
2812
2849
|
this.paymentCallback = onPayment;
|
|
2813
2850
|
this.errorCallback = onError ?? null;
|
|
2814
|
-
const memoProgram = new
|
|
2851
|
+
const memoProgram = new PublicKey6(MEMO_PROGRAM_ID);
|
|
2815
2852
|
this.subscriptionId = this.connection.onLogs(
|
|
2816
2853
|
memoProgram,
|
|
2817
2854
|
async (logs) => {
|
|
@@ -2913,6 +2950,7 @@ var StealthScanner = class {
|
|
|
2913
2950
|
return {
|
|
2914
2951
|
stealthAddress: announcement.stealthAddress || "",
|
|
2915
2952
|
ephemeralPublicKey: announcement.ephemeralPublicKey,
|
|
2953
|
+
version: announcement.version,
|
|
2916
2954
|
viewTag: viewTagNumber,
|
|
2917
2955
|
amount,
|
|
2918
2956
|
mint: transferInfo.mint,
|
|
@@ -3072,7 +3110,7 @@ function wipeEphemeralPrivateKey(privateKeyHex) {
|
|
|
3072
3110
|
}
|
|
3073
3111
|
|
|
3074
3112
|
// src/chains/solana/privacy-adapter.ts
|
|
3075
|
-
import { PublicKey as
|
|
3113
|
+
import { PublicKey as PublicKey10 } from "@solana/web3.js";
|
|
3076
3114
|
|
|
3077
3115
|
// src/chains/solana/providers/helius.ts
|
|
3078
3116
|
var DEFAULT_FETCH_TIMEOUT_MS = 3e4;
|
|
@@ -3282,7 +3320,7 @@ var HeliusProvider = class {
|
|
|
3282
3320
|
// src/chains/solana/providers/generic.ts
|
|
3283
3321
|
import {
|
|
3284
3322
|
Connection as Connection3,
|
|
3285
|
-
PublicKey as
|
|
3323
|
+
PublicKey as PublicKey7
|
|
3286
3324
|
} from "@solana/web3.js";
|
|
3287
3325
|
import {
|
|
3288
3326
|
TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID3,
|
|
@@ -3298,7 +3336,7 @@ var CLUSTER_ENDPOINTS = {
|
|
|
3298
3336
|
};
|
|
3299
3337
|
function validateSolanaAddress(address, paramName) {
|
|
3300
3338
|
try {
|
|
3301
|
-
return new
|
|
3339
|
+
return new PublicKey7(address);
|
|
3302
3340
|
} catch {
|
|
3303
3341
|
throw new ValidationError("invalid Solana address format", paramName, void 0, "SIP_2007" /* INVALID_ADDRESS */);
|
|
3304
3342
|
}
|
|
@@ -3405,7 +3443,7 @@ var GenericProvider = class {
|
|
|
3405
3443
|
// src/chains/solana/providers/quicknode.ts
|
|
3406
3444
|
import {
|
|
3407
3445
|
Connection as Connection4,
|
|
3408
|
-
PublicKey as
|
|
3446
|
+
PublicKey as PublicKey8
|
|
3409
3447
|
} from "@solana/web3.js";
|
|
3410
3448
|
import {
|
|
3411
3449
|
TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID4,
|
|
@@ -3419,7 +3457,7 @@ import Client, {
|
|
|
3419
3457
|
import { base58 } from "@scure/base";
|
|
3420
3458
|
function validateSolanaAddress2(address, paramName) {
|
|
3421
3459
|
try {
|
|
3422
|
-
return new
|
|
3460
|
+
return new PublicKey8(address);
|
|
3423
3461
|
} catch {
|
|
3424
3462
|
throw new ValidationError("invalid Solana address format", paramName, void 0, "SIP_2007" /* INVALID_ADDRESS */);
|
|
3425
3463
|
}
|
|
@@ -3534,7 +3572,7 @@ var QuickNodeProvider = class {
|
|
|
3534
3572
|
return cached;
|
|
3535
3573
|
}
|
|
3536
3574
|
try {
|
|
3537
|
-
const mintPubkey = new
|
|
3575
|
+
const mintPubkey = new PublicKey8(mint);
|
|
3538
3576
|
const mintInfo = await getMint2(this.connection, mintPubkey);
|
|
3539
3577
|
const decimals = mintInfo.decimals;
|
|
3540
3578
|
this.mintDecimalsCache.set(mint, decimals);
|
|
@@ -3582,7 +3620,7 @@ var QuickNodeProvider = class {
|
|
|
3582
3620
|
try {
|
|
3583
3621
|
const data = accountData.data;
|
|
3584
3622
|
if (data && data.length >= 72) {
|
|
3585
|
-
const mint = new
|
|
3623
|
+
const mint = new PublicKey8(data.slice(0, 32)).toBase58();
|
|
3586
3624
|
const amount = BigInt(
|
|
3587
3625
|
"0x" + Buffer.from(data.slice(64, 72)).reverse().toString("hex")
|
|
3588
3626
|
);
|
|
@@ -3682,7 +3720,7 @@ var QuickNodeProvider = class {
|
|
|
3682
3720
|
// src/chains/solana/providers/triton.ts
|
|
3683
3721
|
import {
|
|
3684
3722
|
Connection as Connection5,
|
|
3685
|
-
PublicKey as
|
|
3723
|
+
PublicKey as PublicKey9
|
|
3686
3724
|
} from "@solana/web3.js";
|
|
3687
3725
|
import {
|
|
3688
3726
|
TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID5,
|
|
@@ -3704,7 +3742,7 @@ var TRITON_GRPC_ENDPOINTS = {
|
|
|
3704
3742
|
};
|
|
3705
3743
|
function validateSolanaAddress3(address, paramName) {
|
|
3706
3744
|
try {
|
|
3707
|
-
return new
|
|
3745
|
+
return new PublicKey9(address);
|
|
3708
3746
|
} catch {
|
|
3709
3747
|
throw new ValidationError("invalid Solana address format", paramName, void 0, "SIP_2007" /* INVALID_ADDRESS */);
|
|
3710
3748
|
}
|
|
@@ -3810,7 +3848,7 @@ var TritonProvider = class {
|
|
|
3810
3848
|
return cached;
|
|
3811
3849
|
}
|
|
3812
3850
|
try {
|
|
3813
|
-
const mintPubkey = new
|
|
3851
|
+
const mintPubkey = new PublicKey9(mint);
|
|
3814
3852
|
const mintInfo = await getMint3(this.connection, mintPubkey);
|
|
3815
3853
|
const decimals = mintInfo.decimals;
|
|
3816
3854
|
this.mintDecimalsCache.set(mint, decimals);
|
|
@@ -3861,7 +3899,7 @@ var TritonProvider = class {
|
|
|
3861
3899
|
try {
|
|
3862
3900
|
const data = accountData.data;
|
|
3863
3901
|
if (data && data.length >= 72) {
|
|
3864
|
-
const mint = new
|
|
3902
|
+
const mint = new PublicKey9(data.slice(0, 32)).toBase58();
|
|
3865
3903
|
const amount = BigInt(
|
|
3866
3904
|
"0x" + Buffer.from(data.slice(64, 72)).reverse().toString("hex")
|
|
3867
3905
|
);
|
|
@@ -4188,6 +4226,7 @@ async function processRawTransaction(tx, viewingPrivateKey, spendingPublicKey, o
|
|
|
4188
4226
|
const payment = {
|
|
4189
4227
|
stealthAddress: announcement.stealthAddress || "",
|
|
4190
4228
|
ephemeralPublicKey: announcement.ephemeralPublicKey,
|
|
4229
|
+
version: announcement.version,
|
|
4191
4230
|
amount: transferInfo?.amount ?? 0n,
|
|
4192
4231
|
mint: transferInfo?.mint ?? "",
|
|
4193
4232
|
tokenSymbol: transferInfo?.mint ? getTokenSymbol(transferInfo.mint) : void 0,
|
|
@@ -4855,7 +4894,8 @@ var SolanaPrivacyAdapter = class {
|
|
|
4855
4894
|
viewingPrivateKey: params.viewingPrivateKey,
|
|
4856
4895
|
spendingPrivateKey: params.spendingPrivateKey,
|
|
4857
4896
|
destinationAddress: params.destinationAddress,
|
|
4858
|
-
mint: new
|
|
4897
|
+
mint: new PublicKey10(params.payment.mint),
|
|
4898
|
+
version: params.payment.version
|
|
4859
4899
|
});
|
|
4860
4900
|
}
|
|
4861
4901
|
/**
|
|
@@ -4920,7 +4960,7 @@ import {
|
|
|
4920
4960
|
} from "@scure/bip39";
|
|
4921
4961
|
import { wordlist as english } from "@scure/bip39/wordlists/english.js";
|
|
4922
4962
|
import { ed25519 as ed255194 } from "@noble/curves/ed25519";
|
|
4923
|
-
import { sha256 as sha2564, sha512 as
|
|
4963
|
+
import { sha256 as sha2564, sha512 as sha5123 } from "@noble/hashes/sha2";
|
|
4924
4964
|
import { hmac as hmac2 } from "@noble/hashes/hmac";
|
|
4925
4965
|
var SOLANA_DEFAULT_PATH = "m/44'/501'/0'/0'";
|
|
4926
4966
|
var VIEWING_KEY_CONTEXT = "SIP-viewing-key-v1";
|
|
@@ -4962,7 +5002,7 @@ function validateDerivationPath(path) {
|
|
|
4962
5002
|
return true;
|
|
4963
5003
|
}
|
|
4964
5004
|
function slip0010DeriveEd25519(seed, path) {
|
|
4965
|
-
const I = hmac2(
|
|
5005
|
+
const I = hmac2(sha5123, "ed25519 seed", seed);
|
|
4966
5006
|
let key = new Uint8Array(I.slice(0, 32));
|
|
4967
5007
|
let chainCode = new Uint8Array(I.slice(32, 64));
|
|
4968
5008
|
const components = path.split("/").slice(1);
|
|
@@ -4981,7 +5021,7 @@ function slip0010DeriveEd25519(seed, path) {
|
|
|
4981
5021
|
data[0] = 0;
|
|
4982
5022
|
data.set(key, 1);
|
|
4983
5023
|
new DataView(data.buffer).setUint32(33, hardenedIndex, false);
|
|
4984
|
-
const derivedI = hmac2(
|
|
5024
|
+
const derivedI = hmac2(sha5123, chainCode, data);
|
|
4985
5025
|
key = new Uint8Array(derivedI.slice(0, 32));
|
|
4986
5026
|
chainCode = new Uint8Array(derivedI.slice(32, 64));
|
|
4987
5027
|
}
|
|
@@ -5607,7 +5647,7 @@ import {
|
|
|
5607
5647
|
} from "@solana/kit";
|
|
5608
5648
|
import {
|
|
5609
5649
|
Connection as Connection8,
|
|
5610
|
-
Transaction as
|
|
5650
|
+
Transaction as Transaction6,
|
|
5611
5651
|
ComputeBudgetProgram
|
|
5612
5652
|
} from "@solana/web3.js";
|
|
5613
5653
|
|
|
@@ -5625,7 +5665,7 @@ import {
|
|
|
5625
5665
|
} from "@solana/compat";
|
|
5626
5666
|
import {
|
|
5627
5667
|
Connection as Connection7,
|
|
5628
|
-
PublicKey as
|
|
5668
|
+
PublicKey as PublicKey11
|
|
5629
5669
|
} from "@solana/web3.js";
|
|
5630
5670
|
function toAddress(pubkey) {
|
|
5631
5671
|
if (typeof pubkey === "string") {
|
|
@@ -5634,7 +5674,7 @@ function toAddress(pubkey) {
|
|
|
5634
5674
|
return fromLegacyPublicKey(pubkey);
|
|
5635
5675
|
}
|
|
5636
5676
|
function toPublicKey(addr) {
|
|
5637
|
-
return new
|
|
5677
|
+
return new PublicKey11(addr);
|
|
5638
5678
|
}
|
|
5639
5679
|
function createAddress(base583) {
|
|
5640
5680
|
return kitAddress(base583);
|
|
@@ -5692,18 +5732,18 @@ function isAddress(value) {
|
|
|
5692
5732
|
return typeof value === "string" && value.length >= 32 && value.length <= 44;
|
|
5693
5733
|
}
|
|
5694
5734
|
function isPublicKey(value) {
|
|
5695
|
-
return value instanceof
|
|
5735
|
+
return value instanceof PublicKey11;
|
|
5696
5736
|
}
|
|
5697
5737
|
function normalizeAddress(input) {
|
|
5698
5738
|
let base583;
|
|
5699
|
-
if (input instanceof
|
|
5739
|
+
if (input instanceof PublicKey11) {
|
|
5700
5740
|
base583 = input.toBase58();
|
|
5701
5741
|
} else {
|
|
5702
5742
|
base583 = input;
|
|
5703
5743
|
}
|
|
5704
5744
|
return {
|
|
5705
5745
|
address: kitAddress(base583),
|
|
5706
|
-
publicKey: new
|
|
5746
|
+
publicKey: new PublicKey11(base583),
|
|
5707
5747
|
base58: base583
|
|
5708
5748
|
};
|
|
5709
5749
|
}
|
|
@@ -5883,11 +5923,11 @@ async function createProxyAgent(config, options = {}) {
|
|
|
5883
5923
|
const parsed = parseProxyConfig(config === "tor" ? `socks5://${TOR_HOST}:${TOR_PORTS[0]}` : config);
|
|
5884
5924
|
try {
|
|
5885
5925
|
if (parsed.type === "socks5" || parsed.type === "socks4" || config === "tor") {
|
|
5886
|
-
const { SocksProxyAgent } = await import("./dist-
|
|
5926
|
+
const { SocksProxyAgent } = await import("./dist-4KSUM2PU.mjs");
|
|
5887
5927
|
return new SocksProxyAgent(proxyUrl, { timeout });
|
|
5888
5928
|
}
|
|
5889
5929
|
if (parsed.type === "http" || parsed.type === "https") {
|
|
5890
|
-
const { HttpsProxyAgent } = await import("./dist-
|
|
5930
|
+
const { HttpsProxyAgent } = await import("./dist-4O5YILSN.mjs");
|
|
5891
5931
|
return new HttpsProxyAgent(proxyUrl, { timeout });
|
|
5892
5932
|
}
|
|
5893
5933
|
} catch (error) {
|
|
@@ -6176,7 +6216,7 @@ var SolanaRPCClient = class _SolanaRPCClient {
|
|
|
6176
6216
|
...sendOptions
|
|
6177
6217
|
} = options;
|
|
6178
6218
|
let txToSend = transaction;
|
|
6179
|
-
if (this.usePriorityFees && !skipPriorityFee && transaction instanceof
|
|
6219
|
+
if (this.usePriorityFees && !skipPriorityFee && transaction instanceof Transaction6) {
|
|
6180
6220
|
txToSend = await this.addPriorityFee(
|
|
6181
6221
|
transaction,
|
|
6182
6222
|
priorityFeeMicroLamports,
|
|
@@ -6319,7 +6359,7 @@ var SolanaRPCClient = class _SolanaRPCClient {
|
|
|
6319
6359
|
const estimate = await this.estimatePriorityFee(transaction);
|
|
6320
6360
|
feeToUse = estimate.microLamportsPerComputeUnit;
|
|
6321
6361
|
}
|
|
6322
|
-
const modifiedTx = new
|
|
6362
|
+
const modifiedTx = new Transaction6();
|
|
6323
6363
|
modifiedTx.add(
|
|
6324
6364
|
ComputeBudgetProgram.setComputeUnitLimit({
|
|
6325
6365
|
units: computeUnitLimit ?? 2e5
|
|
@@ -6616,8 +6656,8 @@ function createClusterClient(cluster, options = {}) {
|
|
|
6616
6656
|
|
|
6617
6657
|
// src/chains/solana/transaction-builder.ts
|
|
6618
6658
|
import {
|
|
6619
|
-
PublicKey as
|
|
6620
|
-
Transaction as
|
|
6659
|
+
PublicKey as PublicKey13,
|
|
6660
|
+
Transaction as Transaction7,
|
|
6621
6661
|
TransactionInstruction as TransactionInstruction4,
|
|
6622
6662
|
TransactionMessage,
|
|
6623
6663
|
VersionedTransaction as VersionedTransaction2,
|
|
@@ -6681,7 +6721,7 @@ var ShieldedTransactionBuilder = class {
|
|
|
6681
6721
|
}
|
|
6682
6722
|
const { stealthAddress } = generateEd25519StealthAddress(recipientMetaAddress);
|
|
6683
6723
|
const stealthAddressBase58 = ed25519PublicKeyToSolanaAddress(stealthAddress.address);
|
|
6684
|
-
const stealthPubkey = new
|
|
6724
|
+
const stealthPubkey = new PublicKey13(stealthAddressBase58);
|
|
6685
6725
|
const ephemeralPubkeyBase58 = ed25519PublicKeyToSolanaAddress(stealthAddress.ephemeralPublicKey);
|
|
6686
6726
|
const stealthATA = await getAssociatedTokenAddress7(mint, stealthPubkey, true);
|
|
6687
6727
|
const instructions = [];
|
|
@@ -6722,7 +6762,7 @@ var ShieldedTransactionBuilder = class {
|
|
|
6722
6762
|
instructions.push(
|
|
6723
6763
|
new TransactionInstruction4({
|
|
6724
6764
|
keys: [],
|
|
6725
|
-
programId: new
|
|
6765
|
+
programId: new PublicKey13(MEMO_PROGRAM_ID),
|
|
6726
6766
|
data: Buffer.from(memoContent, "utf-8")
|
|
6727
6767
|
})
|
|
6728
6768
|
);
|
|
@@ -6754,7 +6794,7 @@ var ShieldedTransactionBuilder = class {
|
|
|
6754
6794
|
}
|
|
6755
6795
|
const { stealthAddress } = generateEd25519StealthAddress(recipientMetaAddress);
|
|
6756
6796
|
const stealthAddressBase58 = ed25519PublicKeyToSolanaAddress(stealthAddress.address);
|
|
6757
|
-
const stealthPubkey = new
|
|
6797
|
+
const stealthPubkey = new PublicKey13(stealthAddressBase58);
|
|
6758
6798
|
const ephemeralPubkeyBase58 = ed25519PublicKeyToSolanaAddress(stealthAddress.ephemeralPublicKey);
|
|
6759
6799
|
const instructions = [];
|
|
6760
6800
|
if (this.priorityFee > 0) {
|
|
@@ -6779,7 +6819,7 @@ var ShieldedTransactionBuilder = class {
|
|
|
6779
6819
|
instructions.push(
|
|
6780
6820
|
new TransactionInstruction4({
|
|
6781
6821
|
keys: [],
|
|
6782
|
-
programId: new
|
|
6822
|
+
programId: new PublicKey13(MEMO_PROGRAM_ID),
|
|
6783
6823
|
data: Buffer.from(memoContent, "utf-8")
|
|
6784
6824
|
})
|
|
6785
6825
|
);
|
|
@@ -6822,7 +6862,7 @@ var ShieldedTransactionBuilder = class {
|
|
|
6822
6862
|
}
|
|
6823
6863
|
const { stealthAddress } = generateEd25519StealthAddress(transfer.recipientMetaAddress);
|
|
6824
6864
|
const stealthAddressBase58 = ed25519PublicKeyToSolanaAddress(stealthAddress.address);
|
|
6825
|
-
const stealthPubkey = new
|
|
6865
|
+
const stealthPubkey = new PublicKey13(stealthAddressBase58);
|
|
6826
6866
|
const ephemeralPubkeyBase58 = ed25519PublicKeyToSolanaAddress(stealthAddress.ephemeralPublicKey);
|
|
6827
6867
|
const stealthATA = await getAssociatedTokenAddress7(mint, stealthPubkey, true);
|
|
6828
6868
|
try {
|
|
@@ -6863,7 +6903,7 @@ var ShieldedTransactionBuilder = class {
|
|
|
6863
6903
|
instructions.push(
|
|
6864
6904
|
new TransactionInstruction4({
|
|
6865
6905
|
keys: [],
|
|
6866
|
-
programId: new
|
|
6906
|
+
programId: new PublicKey13(MEMO_PROGRAM_ID),
|
|
6867
6907
|
data: Buffer.from(memoContent, "utf-8")
|
|
6868
6908
|
})
|
|
6869
6909
|
);
|
|
@@ -6911,7 +6951,7 @@ var ShieldedTransactionBuilder = class {
|
|
|
6911
6951
|
estimatedFee
|
|
6912
6952
|
};
|
|
6913
6953
|
} else {
|
|
6914
|
-
const transaction = new
|
|
6954
|
+
const transaction = new Transaction7();
|
|
6915
6955
|
transaction.recentBlockhash = blockhash;
|
|
6916
6956
|
transaction.lastValidBlockHeight = lastValidBlockHeight;
|
|
6917
6957
|
transaction.feePayer = this.feePayer;
|
|
@@ -6958,7 +6998,7 @@ var ShieldedTransactionBuilder = class {
|
|
|
6958
6998
|
if (isVersioned) {
|
|
6959
6999
|
return VersionedTransaction2.deserialize(buffer);
|
|
6960
7000
|
} else {
|
|
6961
|
-
return
|
|
7001
|
+
return Transaction7.from(buffer);
|
|
6962
7002
|
}
|
|
6963
7003
|
}
|
|
6964
7004
|
// ─── Configuration ────────────────────────────────────────────────────────────
|
|
@@ -7040,8 +7080,8 @@ function calculatePriorityFee(priority) {
|
|
|
7040
7080
|
|
|
7041
7081
|
// src/chains/solana/anchor-transfer.ts
|
|
7042
7082
|
import {
|
|
7043
|
-
PublicKey as
|
|
7044
|
-
Transaction as
|
|
7083
|
+
PublicKey as PublicKey14,
|
|
7084
|
+
Transaction as Transaction8,
|
|
7045
7085
|
TransactionInstruction as TransactionInstruction5,
|
|
7046
7086
|
SystemProgram as SystemProgram3
|
|
7047
7087
|
} from "@solana/web3.js";
|
|
@@ -7249,13 +7289,13 @@ function bigIntToBytes3(value, length) {
|
|
|
7249
7289
|
}
|
|
7250
7290
|
|
|
7251
7291
|
// src/chains/solana/anchor-transfer.ts
|
|
7252
|
-
var SIP_PRIVACY_PROGRAM_ID = new
|
|
7292
|
+
var SIP_PRIVACY_PROGRAM_ID = new PublicKey14(
|
|
7253
7293
|
"S1PMFspo4W6BYKHWkHNF7kZ3fnqibEXg3LQjxepS9at"
|
|
7254
7294
|
);
|
|
7255
|
-
var CONFIG_PDA = new
|
|
7295
|
+
var CONFIG_PDA = new PublicKey14(
|
|
7256
7296
|
"BVawZkppFewygA5nxdrLma4ThKx8Th7bW4KTCkcWTZwZ"
|
|
7257
7297
|
);
|
|
7258
|
-
var FEE_COLLECTOR = new
|
|
7298
|
+
var FEE_COLLECTOR = new PublicKey14(
|
|
7259
7299
|
"S1P6j1yeTm6zkewQVeihrTZvmfoHABRkHDhabWTuWMd"
|
|
7260
7300
|
);
|
|
7261
7301
|
var TRANSFER_RECORD_SEED = Buffer.from("transfer_record");
|
|
@@ -7293,7 +7333,7 @@ async function shieldedTransfer(params) {
|
|
|
7293
7333
|
const stealthResult = generateEd25519StealthAddress(recipientMeta);
|
|
7294
7334
|
const stealthAddr = stealthResult.stealthAddress;
|
|
7295
7335
|
const stealthPubkey = ed25519PublicKeyToSolanaAddress(stealthAddr.address);
|
|
7296
|
-
const stealthAccountPubkey = new
|
|
7336
|
+
const stealthAccountPubkey = new PublicKey14(stealthPubkey);
|
|
7297
7337
|
const { commitment, blinding } = commit(amount);
|
|
7298
7338
|
const commitmentBytes = hexToBytes7(commitment.slice(2));
|
|
7299
7339
|
if (commitmentBytes.length !== 33) {
|
|
@@ -7317,7 +7357,7 @@ async function shieldedTransfer(params) {
|
|
|
7317
7357
|
throw new ValidationError("SIP Privacy program not initialized", "config");
|
|
7318
7358
|
}
|
|
7319
7359
|
const totalTransfers = configAccount.data.readBigUInt64LE(43);
|
|
7320
|
-
const [transferRecordPda] =
|
|
7360
|
+
const [transferRecordPda] = PublicKey14.findProgramAddressSync(
|
|
7321
7361
|
[
|
|
7322
7362
|
TRANSFER_RECORD_SEED,
|
|
7323
7363
|
sender.toBuffer(),
|
|
@@ -7346,7 +7386,7 @@ async function shieldedTransfer(params) {
|
|
|
7346
7386
|
programId: SIP_PRIVACY_PROGRAM_ID,
|
|
7347
7387
|
data: instructionData
|
|
7348
7388
|
});
|
|
7349
|
-
const transaction = new
|
|
7389
|
+
const transaction = new Transaction8();
|
|
7350
7390
|
transaction.add(instruction);
|
|
7351
7391
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
|
|
7352
7392
|
transaction.recentBlockhash = blockhash;
|
|
@@ -7452,8 +7492,8 @@ function encryptAmount(amount, viewingKey) {
|
|
|
7452
7492
|
|
|
7453
7493
|
// src/chains/solana/sunspot-verifier.ts
|
|
7454
7494
|
import {
|
|
7455
|
-
PublicKey as
|
|
7456
|
-
Transaction as
|
|
7495
|
+
PublicKey as PublicKey15,
|
|
7496
|
+
Transaction as Transaction9,
|
|
7457
7497
|
TransactionInstruction as TransactionInstruction6,
|
|
7458
7498
|
ComputeBudgetProgram as ComputeBudgetProgram3
|
|
7459
7499
|
} from "@solana/web3.js";
|
|
@@ -7572,7 +7612,7 @@ var SunspotVerifier = class {
|
|
|
7572
7612
|
proofBytes,
|
|
7573
7613
|
...publicInputBytes.map((b) => Buffer.from(b))
|
|
7574
7614
|
]);
|
|
7575
|
-
const transaction = new
|
|
7615
|
+
const transaction = new Transaction9();
|
|
7576
7616
|
transaction.add(
|
|
7577
7617
|
ComputeBudgetProgram3.setComputeUnitLimit({
|
|
7578
7618
|
units: this.config.computeUnits
|
|
@@ -7692,7 +7732,7 @@ function formatOwnershipInputs(params) {
|
|
|
7692
7732
|
];
|
|
7693
7733
|
}
|
|
7694
7734
|
function toPublicKey2(input) {
|
|
7695
|
-
return typeof input === "string" ? new
|
|
7735
|
+
return typeof input === "string" ? new PublicKey15(input) : input;
|
|
7696
7736
|
}
|
|
7697
7737
|
function toBytes(input) {
|
|
7698
7738
|
if (typeof input === "string") {
|
|
@@ -7710,6 +7750,198 @@ function bigintToBytes32(value) {
|
|
|
7710
7750
|
return bytes;
|
|
7711
7751
|
}
|
|
7712
7752
|
|
|
7753
|
+
// src/chains/solana/gasless-cashout.ts
|
|
7754
|
+
import {
|
|
7755
|
+
PublicKey as PublicKey16,
|
|
7756
|
+
Transaction as Transaction10
|
|
7757
|
+
} from "@solana/web3.js";
|
|
7758
|
+
import {
|
|
7759
|
+
getAssociatedTokenAddress as getAssociatedTokenAddress8,
|
|
7760
|
+
createTransferInstruction as createTransferInstruction5,
|
|
7761
|
+
createAssociatedTokenAccountIdempotentInstruction,
|
|
7762
|
+
getAccount as getAccount7
|
|
7763
|
+
} from "@solana/spl-token";
|
|
7764
|
+
|
|
7765
|
+
// src/chains/solana/relayer-fee.ts
|
|
7766
|
+
function computeRelayerFee(amount, config) {
|
|
7767
|
+
if (!Number.isInteger(config.bps) || config.bps < 0) {
|
|
7768
|
+
throw new Error("bps must be a non-negative integer");
|
|
7769
|
+
}
|
|
7770
|
+
if (amount < 0n) {
|
|
7771
|
+
throw new Error("amount must be a non-negative bigint");
|
|
7772
|
+
}
|
|
7773
|
+
if (typeof config.flatFloor !== "bigint" || config.flatFloor < 0n) {
|
|
7774
|
+
throw new Error("flatFloor must be a non-negative bigint");
|
|
7775
|
+
}
|
|
7776
|
+
const bpsFee = amount * BigInt(config.bps) / 10000n;
|
|
7777
|
+
return bpsFee > config.flatFloor ? bpsFee : config.flatFloor;
|
|
7778
|
+
}
|
|
7779
|
+
|
|
7780
|
+
// src/chains/solana/gasless-cashout.ts
|
|
7781
|
+
async function buildGaslessCashout(params) {
|
|
7782
|
+
const {
|
|
7783
|
+
connection,
|
|
7784
|
+
stealthAddress,
|
|
7785
|
+
ephemeralPublicKey,
|
|
7786
|
+
viewingPrivateKey,
|
|
7787
|
+
spendingPrivateKey,
|
|
7788
|
+
destinationAddress,
|
|
7789
|
+
mint,
|
|
7790
|
+
relayerPublicKey,
|
|
7791
|
+
relayerFeeAccount,
|
|
7792
|
+
feeConfig,
|
|
7793
|
+
version = "2"
|
|
7794
|
+
} = params;
|
|
7795
|
+
const stealthSigner = deriveStealthSigner({
|
|
7796
|
+
stealthAddress,
|
|
7797
|
+
ephemeralPublicKey,
|
|
7798
|
+
viewingPrivateKey,
|
|
7799
|
+
spendingPrivateKey,
|
|
7800
|
+
version
|
|
7801
|
+
});
|
|
7802
|
+
const stealthPubkey = stealthSigner.publicKey;
|
|
7803
|
+
const stealthATA = await getAssociatedTokenAddress8(mint, stealthPubkey, true);
|
|
7804
|
+
const destinationPubkey = new PublicKey16(destinationAddress);
|
|
7805
|
+
const destinationATA = await getAssociatedTokenAddress8(mint, destinationPubkey);
|
|
7806
|
+
if (destinationATA.equals(stealthATA)) {
|
|
7807
|
+
throw new Error(
|
|
7808
|
+
"destinationAddress resolves to the stealth token account; choose a different destination"
|
|
7809
|
+
);
|
|
7810
|
+
}
|
|
7811
|
+
let feeAccount;
|
|
7812
|
+
try {
|
|
7813
|
+
feeAccount = await getAccount7(connection, relayerFeeAccount);
|
|
7814
|
+
} catch {
|
|
7815
|
+
throw new Error("relayerFeeAccount does not exist or is not a token account");
|
|
7816
|
+
}
|
|
7817
|
+
if (!feeAccount.mint.equals(mint)) {
|
|
7818
|
+
throw new Error("relayerFeeAccount is not an associated token account for the given mint");
|
|
7819
|
+
}
|
|
7820
|
+
let balanceResp;
|
|
7821
|
+
try {
|
|
7822
|
+
balanceResp = await connection.getTokenAccountBalance(stealthATA);
|
|
7823
|
+
} catch {
|
|
7824
|
+
throw new Error(
|
|
7825
|
+
`Stealth token account ${stealthATA.toBase58()} for mint ${mint.toBase58()} does not exist or holds no balance; nothing to cash out`
|
|
7826
|
+
);
|
|
7827
|
+
}
|
|
7828
|
+
const grossAmount = BigInt(balanceResp.value.amount);
|
|
7829
|
+
const relayerFee = computeRelayerFee(grossAmount, feeConfig);
|
|
7830
|
+
if (relayerFee >= grossAmount) {
|
|
7831
|
+
throw new Error(
|
|
7832
|
+
`Relayer fee (${relayerFee}) equals or exceeds the claim amount (${grossAmount}); nothing left to forward`
|
|
7833
|
+
);
|
|
7834
|
+
}
|
|
7835
|
+
const netAmount = grossAmount - relayerFee;
|
|
7836
|
+
const transaction = new Transaction10();
|
|
7837
|
+
transaction.add(
|
|
7838
|
+
createAssociatedTokenAccountIdempotentInstruction(
|
|
7839
|
+
relayerPublicKey,
|
|
7840
|
+
// payer (relayer pays rent)
|
|
7841
|
+
destinationATA,
|
|
7842
|
+
destinationPubkey,
|
|
7843
|
+
mint
|
|
7844
|
+
)
|
|
7845
|
+
);
|
|
7846
|
+
transaction.add(
|
|
7847
|
+
createTransferInstruction5(stealthATA, relayerFeeAccount, stealthPubkey, relayerFee)
|
|
7848
|
+
);
|
|
7849
|
+
transaction.add(
|
|
7850
|
+
createTransferInstruction5(stealthATA, destinationATA, stealthPubkey, netAmount)
|
|
7851
|
+
);
|
|
7852
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
|
|
7853
|
+
transaction.recentBlockhash = blockhash;
|
|
7854
|
+
transaction.lastValidBlockHeight = lastValidBlockHeight;
|
|
7855
|
+
transaction.feePayer = relayerPublicKey;
|
|
7856
|
+
stealthSigner.signTransaction(transaction);
|
|
7857
|
+
return {
|
|
7858
|
+
transaction,
|
|
7859
|
+
stealthAddress,
|
|
7860
|
+
destinationAddress,
|
|
7861
|
+
grossAmount,
|
|
7862
|
+
relayerFee,
|
|
7863
|
+
netAmount,
|
|
7864
|
+
blockhash,
|
|
7865
|
+
lastValidBlockHeight
|
|
7866
|
+
};
|
|
7867
|
+
}
|
|
7868
|
+
function detectCluster5(endpoint) {
|
|
7869
|
+
if (endpoint.includes("devnet")) {
|
|
7870
|
+
return "devnet";
|
|
7871
|
+
}
|
|
7872
|
+
if (endpoint.includes("testnet")) {
|
|
7873
|
+
return "testnet";
|
|
7874
|
+
}
|
|
7875
|
+
if (endpoint.includes("localhost") || endpoint.includes("127.0.0.1")) {
|
|
7876
|
+
return "localnet";
|
|
7877
|
+
}
|
|
7878
|
+
return "mainnet-beta";
|
|
7879
|
+
}
|
|
7880
|
+
async function submitGaslessCashout(params) {
|
|
7881
|
+
const { connection, build, relayerKeypair, jitoRelayer, tipLamports } = params;
|
|
7882
|
+
const { transaction, netAmount, relayerFee, destinationAddress } = build;
|
|
7883
|
+
if (!transaction.feePayer || !transaction.feePayer.equals(relayerKeypair.publicKey)) {
|
|
7884
|
+
throw new Error("relayerKeypair does not match the transaction fee-payer");
|
|
7885
|
+
}
|
|
7886
|
+
const relayerAlreadySigned = transaction.signatures.some(
|
|
7887
|
+
(s) => s.publicKey.equals(relayerKeypair.publicKey) && s.signature !== null
|
|
7888
|
+
);
|
|
7889
|
+
if (!relayerAlreadySigned) {
|
|
7890
|
+
transaction.partialSign(relayerKeypair);
|
|
7891
|
+
}
|
|
7892
|
+
const cluster = detectCluster5(connection.rpcEndpoint);
|
|
7893
|
+
if (jitoRelayer) {
|
|
7894
|
+
const relayed = await jitoRelayer.relayTransaction({
|
|
7895
|
+
transaction,
|
|
7896
|
+
tipLamports,
|
|
7897
|
+
tipPayer: relayerKeypair,
|
|
7898
|
+
waitForConfirmation: true
|
|
7899
|
+
});
|
|
7900
|
+
if (relayed.status !== "confirmed") {
|
|
7901
|
+
throw new Error(
|
|
7902
|
+
`Gasless cash-out via Jito did not confirm (status: ${relayed.status})` + (relayed.error ? `: ${relayed.error}` : "")
|
|
7903
|
+
);
|
|
7904
|
+
}
|
|
7905
|
+
if (!relayed.signature) {
|
|
7906
|
+
throw new Error("Gasless cash-out via Jito returned an empty transaction signature");
|
|
7907
|
+
}
|
|
7908
|
+
return {
|
|
7909
|
+
txSignature: relayed.signature,
|
|
7910
|
+
destinationAddress,
|
|
7911
|
+
amount: netAmount,
|
|
7912
|
+
relayerFee,
|
|
7913
|
+
explorerUrl: getExplorerUrl(relayed.signature, cluster),
|
|
7914
|
+
// Report the TRUE path: the relayer may have fallen back to direct submission.
|
|
7915
|
+
viaJito: relayed.relayed
|
|
7916
|
+
};
|
|
7917
|
+
}
|
|
7918
|
+
const txSignature = await connection.sendRawTransaction(transaction.serialize(), {
|
|
7919
|
+
skipPreflight: false,
|
|
7920
|
+
preflightCommitment: "confirmed"
|
|
7921
|
+
});
|
|
7922
|
+
const confirmation = await connection.confirmTransaction(
|
|
7923
|
+
{
|
|
7924
|
+
signature: txSignature,
|
|
7925
|
+
blockhash: build.blockhash,
|
|
7926
|
+
lastValidBlockHeight: build.lastValidBlockHeight
|
|
7927
|
+
},
|
|
7928
|
+
"confirmed"
|
|
7929
|
+
);
|
|
7930
|
+
if (confirmation.value.err) {
|
|
7931
|
+
throw new Error(
|
|
7932
|
+
`Gasless cash-out landed but failed on-chain: ${JSON.stringify(confirmation.value.err)}`
|
|
7933
|
+
);
|
|
7934
|
+
}
|
|
7935
|
+
return {
|
|
7936
|
+
txSignature,
|
|
7937
|
+
destinationAddress,
|
|
7938
|
+
amount: netAmount,
|
|
7939
|
+
relayerFee,
|
|
7940
|
+
explorerUrl: getExplorerUrl(txSignature, cluster),
|
|
7941
|
+
viaJito: false
|
|
7942
|
+
};
|
|
7943
|
+
}
|
|
7944
|
+
|
|
7713
7945
|
export {
|
|
7714
7946
|
isValidChainId,
|
|
7715
7947
|
isValidPrivacyLevel,
|
|
@@ -7797,6 +8029,8 @@ export {
|
|
|
7797
8029
|
formatLamports,
|
|
7798
8030
|
parseSOLToLamports,
|
|
7799
8031
|
getSOLBalance,
|
|
8032
|
+
signEd25519WithScalar,
|
|
8033
|
+
deriveStealthSigner,
|
|
7800
8034
|
scanForPayments,
|
|
7801
8035
|
claimStealthPayment,
|
|
7802
8036
|
getStealthBalance,
|
|
@@ -7911,5 +8145,8 @@ export {
|
|
|
7911
8145
|
SunspotVerifier,
|
|
7912
8146
|
createVerifyInstructionData,
|
|
7913
8147
|
formatFundingInputs,
|
|
7914
|
-
formatOwnershipInputs
|
|
8148
|
+
formatOwnershipInputs,
|
|
8149
|
+
computeRelayerFee,
|
|
8150
|
+
buildGaslessCashout,
|
|
8151
|
+
submitGaslessCashout
|
|
7915
8152
|
};
|