@cloak.dev/sdk 0.2.2-staging.33f11a2 → 0.2.2-staging.5dffa29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -8
- package/dist/index.cjs +846 -14
- package/dist/index.d.cts +678 -1
- package/dist/index.d.ts +678 -1
- package/dist/index.js +831 -13
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -542,8 +542,10 @@ var init_utxo = __esm({
|
|
|
542
542
|
// src/index.ts
|
|
543
543
|
var index_exports = {};
|
|
544
544
|
__export(index_exports, {
|
|
545
|
+
BRIDGE_ESCROW_LABEL: () => BRIDGE_ESCROW_LABEL,
|
|
545
546
|
BUILD_ALLOWS_LOCAL_ENDPOINTS: () => BUILD_ALLOWS_LOCAL_ENDPOINTS,
|
|
546
547
|
CHAIN_NOTE_SALT_BITS: () => CHAIN_NOTE_SALT_BITS,
|
|
548
|
+
CLEANUP_FEE_BUDGET: () => CLEANUP_FEE_BUDGET,
|
|
547
549
|
CLOAK_PRODUCTION_RELAY_URL: () => CLOAK_PRODUCTION_RELAY_URL,
|
|
548
550
|
CLOAK_PROGRAM_ID: () => CLOAK_PROGRAM_ID,
|
|
549
551
|
CloakError: () => CloakError,
|
|
@@ -551,16 +553,25 @@ __export(index_exports, {
|
|
|
551
553
|
DEFAULT_TRANSACTION_CIRCUITS_URL: () => DEFAULT_TRANSACTION_CIRCUITS_URL,
|
|
552
554
|
DELIVERY_MEMO_TAG: () => DELIVERY_MEMO_TAG,
|
|
553
555
|
DELIVERY_REGISTRY_SEED: () => DELIVERY_REGISTRY_SEED,
|
|
556
|
+
DepositError: () => DepositError,
|
|
557
|
+
DoNotRetry: () => DoNotRetry,
|
|
558
|
+
ECONOMIC_MINIMUM: () => ECONOMIC_MINIMUM,
|
|
554
559
|
EXPECTED_CIRCUIT_HASHES: () => EXPECTED_CIRCUIT_HASHES,
|
|
560
|
+
FEE_BUDGET: () => FEE_BUDGET,
|
|
555
561
|
FIXED_FEE_LAMPORTS: () => FIXED_FEE_LAMPORTS,
|
|
556
562
|
InsecureRandomnessError: () => InsecureRandomnessError,
|
|
557
563
|
LAMPORTS_PER_SOL: () => LAMPORTS_PER_SOL,
|
|
558
564
|
LocalStorageAdapter: () => LocalStorageAdapter,
|
|
565
|
+
MAINNET_RENT_0: () => MAINNET_RENT_0,
|
|
566
|
+
MAINNET_RENT_1: () => MAINNET_RENT_1,
|
|
567
|
+
MAX_RECEIVER_INDEX: () => MAX_RECEIVER_INDEX,
|
|
559
568
|
MERKLE_TREE_HEIGHT: () => MERKLE_TREE_HEIGHT2,
|
|
560
569
|
MIN_DEPOSIT_LAMPORTS: () => MIN_DEPOSIT_LAMPORTS,
|
|
570
|
+
MIN_DEPOSIT_SPL_BASE_UNITS: () => MIN_DEPOSIT_SPL_BASE_UNITS,
|
|
561
571
|
MemoryStorageAdapter: () => MemoryStorageAdapter,
|
|
562
572
|
MerkleTree: () => MerkleTree,
|
|
563
573
|
NATIVE_SOL_MINT: () => NATIVE_SOL_MINT,
|
|
574
|
+
ONECLICK_PUBKEY_B58: () => ONECLICK_PUBKEY_B58,
|
|
564
575
|
RECIPIENT_DELIVERY_CIPHERTEXT_LEN: () => RECIPIENT_DELIVERY_CIPHERTEXT_LEN,
|
|
565
576
|
RECIPIENT_DELIVERY_EPHEMERAL_PK_LEN: () => RECIPIENT_DELIVERY_EPHEMERAL_PK_LEN,
|
|
566
577
|
RECIPIENT_DELIVERY_NONCE_LEN: () => RECIPIENT_DELIVERY_NONCE_LEN,
|
|
@@ -579,6 +590,7 @@ __export(index_exports, {
|
|
|
579
590
|
SettlementVerificationError: () => SettlementVerificationError,
|
|
580
591
|
ShieldPoolErrors: () => ShieldPoolErrors,
|
|
581
592
|
SimpleWallet: () => SimpleWallet,
|
|
593
|
+
TERMINAL_FAILURE: () => TERMINAL_FAILURE,
|
|
582
594
|
TRANSACTION_CIRCUITS_VERSION: () => TRANSACTION_CIRCUITS_VERSION,
|
|
583
595
|
TRANSACT_AUTH_FIELDS: () => TRANSACT_AUTH_FIELDS,
|
|
584
596
|
TRANSACT_SWAP_AUTH_FIELDS: () => TRANSACT_SWAP_AUTH_FIELDS,
|
|
@@ -588,8 +600,11 @@ __export(index_exports, {
|
|
|
588
600
|
VARIABLE_FEE_NUMERATOR: () => VARIABLE_FEE_NUMERATOR,
|
|
589
601
|
VARIABLE_FEE_RATE: () => VARIABLE_FEE_RATE,
|
|
590
602
|
VERSION: () => VERSION,
|
|
603
|
+
WITHDRAW_FEE_BPS: () => WITHDRAW_FEE_BPS,
|
|
604
|
+
WITHDRAW_FIXED_FEE: () => WITHDRAW_FIXED_FEE,
|
|
591
605
|
assertDirectSubmissionLanded: () => assertDirectSubmissionLanded,
|
|
592
606
|
assertTransactionCircuitIntegrity: () => assertTransactionCircuitIntegrity,
|
|
607
|
+
assessBridgeQuote: () => assessBridgeQuote,
|
|
593
608
|
bigintToBytes32: () => bigintToBytes32,
|
|
594
609
|
bigintToHex: () => bigintToHex,
|
|
595
610
|
buildMerkleTree: () => buildMerkleTree,
|
|
@@ -604,12 +619,16 @@ __export(index_exports, {
|
|
|
604
619
|
calculateRelayFee: () => calculateRelayFee,
|
|
605
620
|
canRebuildMerkleTreeFromChain: () => canRebuildMerkleTreeFromChain,
|
|
606
621
|
canonicalJson: () => canonicalJson,
|
|
622
|
+
canonicalPayloadString: () => canonicalPayloadString,
|
|
607
623
|
chainNoteFromBase64: () => chainNoteFromBase64,
|
|
608
624
|
chainNoteToBase64: () => chainNoteToBase64,
|
|
625
|
+
classifyPostFailure: () => classifyPostFailure,
|
|
609
626
|
classifyRelayError: () => classifyRelayError,
|
|
627
|
+
cleanupReceivingAddress: () => cleanupReceivingAddress,
|
|
610
628
|
cleanupStalePendingOperations: () => cleanupStalePendingOperations,
|
|
611
629
|
clearPendingDeposits: () => clearPendingDeposits,
|
|
612
630
|
clearPendingWithdrawals: () => clearPendingWithdrawals,
|
|
631
|
+
cloakBridgeRail: () => cloakBridgeRail,
|
|
613
632
|
computeChainNoteHash: () => computeChainNoteHash,
|
|
614
633
|
computeExtDataHash: () => computeExtDataHash,
|
|
615
634
|
computeMerkleRoot: () => computeMerkleRoot,
|
|
@@ -631,10 +650,13 @@ __export(index_exports, {
|
|
|
631
650
|
decryptCompactChainNote: () => decryptCompactChainNote,
|
|
632
651
|
decryptComplianceMetadataWithMasterKey: () => decryptComplianceMetadataWithMasterKey,
|
|
633
652
|
decryptTransactionMetadata: () => decryptTransactionMetadata,
|
|
653
|
+
depositFromDerivedKey: () => depositFromDerivedKey,
|
|
654
|
+
deriveBridgeReceiver: () => deriveBridgeReceiver,
|
|
634
655
|
deriveChangeNoteBlinding: () => deriveChangeNoteBlinding,
|
|
635
656
|
deriveDepositNoteSecrets: () => deriveDepositNoteSecrets,
|
|
636
657
|
deriveDiversifiedViewingKey: () => deriveDiversifiedViewingKey,
|
|
637
658
|
deriveDiversifier: () => deriveDiversifier,
|
|
659
|
+
deriveFundingTargets: () => deriveFundingTargets,
|
|
638
660
|
deriveInputNullifierPdas: () => deriveInputNullifierPdas,
|
|
639
661
|
derivePublicKey: () => derivePublicKey,
|
|
640
662
|
deriveSpendKey: () => deriveSpendKey,
|
|
@@ -673,6 +695,7 @@ __export(index_exports, {
|
|
|
673
695
|
formatErrorForLogging: () => formatErrorForLogging,
|
|
674
696
|
formatSol: () => formatSol,
|
|
675
697
|
fullWithdraw: () => fullWithdraw,
|
|
698
|
+
fundReceiverViaPaymaster: () => fundReceiverViaPaymaster,
|
|
676
699
|
generateCloakKeys: () => generateCloakKeys,
|
|
677
700
|
generateCommitmentAsync: () => generateCommitmentAsync,
|
|
678
701
|
generateMasterSeed: () => generateMasterSeed,
|
|
@@ -708,18 +731,21 @@ __export(index_exports, {
|
|
|
708
731
|
isReactNative: () => isReactNative,
|
|
709
732
|
isRootNotFoundError: () => isRootNotFoundError,
|
|
710
733
|
isSubmissionOutcomeUnknownResponse: () => isSubmissionOutcomeUnknownResponse,
|
|
734
|
+
isTerminalFailure: () => isTerminalFailure,
|
|
711
735
|
isValidHex: () => isValidHex,
|
|
712
736
|
isValidRpcUrl: () => isValidRpcUrl,
|
|
713
737
|
isValidSolanaAddress: () => isValidSolanaAddress,
|
|
714
738
|
isWithdrawAmountSufficient: () => isWithdrawAmountSufficient,
|
|
715
739
|
isWithdrawable: () => isWithdrawable,
|
|
716
740
|
keypairToAdapter: () => keypairToAdapter,
|
|
741
|
+
listBridgeDeposits: () => listBridgeDeposits,
|
|
717
742
|
loadPendingDeposits: () => loadPendingDeposits,
|
|
718
743
|
loadPendingWithdrawals: () => loadPendingWithdrawals,
|
|
719
744
|
loadVerifiedCircuitArtifacts: () => loadVerifiedCircuitArtifacts,
|
|
720
745
|
matchChangeNote: () => matchChangeNote,
|
|
721
746
|
matchDepositNote: () => matchDepositNote,
|
|
722
747
|
matchSwapRefundLeaf: () => matchSwapRefundLeaf,
|
|
748
|
+
mayRetry: () => mayRetry,
|
|
723
749
|
openRecipientDeliveryNote: () => openRecipientDeliveryNote,
|
|
724
750
|
parseAmount: () => parseAmount,
|
|
725
751
|
parseDeliveryCarrierMemo: () => parseDeliveryCarrierMemo,
|
|
@@ -742,11 +768,14 @@ __export(index_exports, {
|
|
|
742
768
|
randomDepositNoteSalt: () => randomDepositNoteSalt,
|
|
743
769
|
randomFieldElement: () => randomFieldElement,
|
|
744
770
|
readMerkleTreeState: () => readMerkleTreeState,
|
|
771
|
+
readRent: () => readRent,
|
|
745
772
|
recipientDeliveryNoteToBase64: () => recipientDeliveryNoteToBase64,
|
|
746
773
|
registerViewingKey: () => registerViewingKey,
|
|
747
774
|
removePendingDeposit: () => removePendingDeposit,
|
|
748
775
|
removePendingWithdrawal: () => removePendingWithdrawal,
|
|
776
|
+
renderAssessment: () => renderAssessment,
|
|
749
777
|
resolveCircuitsBase: () => resolveCircuitsBase,
|
|
778
|
+
retryDelayMs: () => retryDelayMs,
|
|
750
779
|
savePendingDeposit: () => savePendingDeposit,
|
|
751
780
|
savePendingWithdrawal: () => savePendingWithdrawal,
|
|
752
781
|
scanNotesForWallet: () => scanNotesForWallet,
|
|
@@ -779,15 +808,19 @@ __export(index_exports, {
|
|
|
779
808
|
validateDepositParams: () => validateDepositParams,
|
|
780
809
|
validateNote: () => validateNote,
|
|
781
810
|
validateOutputsSum: () => validateOutputsSum,
|
|
811
|
+
validatePaymasterTopUpTransaction: () => validatePaymasterTopUpTransaction,
|
|
782
812
|
validateRoot: () => validateRoot,
|
|
783
813
|
validateTransfers: () => validateTransfers,
|
|
784
814
|
validateWalletConnected: () => validateWalletConnected,
|
|
785
815
|
validateWithdrawableNote: () => validateWithdrawableNote,
|
|
786
816
|
verifyAllCircuits: () => verifyAllCircuits,
|
|
787
817
|
verifyCircuitIntegrity: () => verifyCircuitIntegrity,
|
|
818
|
+
verifyQuoteSignature: () => verifyQuoteSignature,
|
|
788
819
|
verifyUtxos: () => verifyUtxos,
|
|
789
820
|
waitForRoot: () => waitForRoot,
|
|
790
|
-
|
|
821
|
+
withShieldRetries: () => withShieldRetries,
|
|
822
|
+
withTiming: () => withTiming,
|
|
823
|
+
withdrawFeeFor: () => withdrawFeeFor
|
|
791
824
|
});
|
|
792
825
|
module.exports = __toCommonJS(index_exports);
|
|
793
826
|
|
|
@@ -2929,8 +2962,8 @@ async function verifyUtxos(utxos, connection, programId, commitment = "confirmed
|
|
|
2929
2962
|
const nullifierHex = nullifierBig.toString(16).padStart(64, "0");
|
|
2930
2963
|
const nullifierBytes = Buffer.from(nullifierHex, "hex");
|
|
2931
2964
|
const { pool } = getShieldPoolPDAs(programId, utxo.mintAddress);
|
|
2932
|
-
const [
|
|
2933
|
-
checkable.push({ utxo, pda });
|
|
2965
|
+
const [pda2] = getNullifierPDA(pool, nullifierBytes, programId);
|
|
2966
|
+
checkable.push({ utxo, pda: pda2 });
|
|
2934
2967
|
} catch {
|
|
2935
2968
|
skipped.push(utxo);
|
|
2936
2969
|
}
|
|
@@ -3000,8 +3033,8 @@ function deriveInputNullifierPdas(programId, mint, inputNullifiers) {
|
|
|
3000
3033
|
const pdas = [];
|
|
3001
3034
|
for (const nullifier of inputNullifiers) {
|
|
3002
3035
|
if (nullifier === BigInt(0)) continue;
|
|
3003
|
-
const [
|
|
3004
|
-
pdas.push(
|
|
3036
|
+
const [pda2] = getNullifierPDA(pool, bigintToBytes324(nullifier), programId);
|
|
3037
|
+
pdas.push(pda2);
|
|
3005
3038
|
}
|
|
3006
3039
|
return pdas;
|
|
3007
3040
|
}
|
|
@@ -4320,7 +4353,7 @@ async function fetchWithRetry(url, options = {}) {
|
|
|
4320
4353
|
const {
|
|
4321
4354
|
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
4322
4355
|
maxRetries = DEFAULT_MAX_RETRIES,
|
|
4323
|
-
retryDelayMs = 1e3
|
|
4356
|
+
retryDelayMs: retryDelayMs2 = 1e3
|
|
4324
4357
|
} = options;
|
|
4325
4358
|
assertAllowedRelayOrigin(url);
|
|
4326
4359
|
let lastError = null;
|
|
@@ -4344,7 +4377,7 @@ async function fetchWithRetry(url, options = {}) {
|
|
|
4344
4377
|
`Relay request failed after ${attempt + 1} attempts: ${lastError.message}`
|
|
4345
4378
|
);
|
|
4346
4379
|
}
|
|
4347
|
-
const delay =
|
|
4380
|
+
const delay = retryDelayMs2 * Math.pow(2, attempt) + Math.random() * 500;
|
|
4348
4381
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
4349
4382
|
}
|
|
4350
4383
|
}
|
|
@@ -7831,7 +7864,7 @@ async function transact(params, options) {
|
|
|
7831
7864
|
// names is refused.
|
|
7832
7865
|
maxRootRetries = 40,
|
|
7833
7866
|
// Increased to handle prolonged relay sync recovery under high concurrency
|
|
7834
|
-
retryDelayMs = 500,
|
|
7867
|
+
retryDelayMs: retryDelayMs2 = 500,
|
|
7835
7868
|
// Start with short delay, will exponentially back off
|
|
7836
7869
|
riskOracleQueue,
|
|
7837
7870
|
riskQuoteUrl: riskQuoteUrlOption,
|
|
@@ -8252,7 +8285,7 @@ async function transact(params, options) {
|
|
|
8252
8285
|
while (submissionAttempts <= maxRootRetries) {
|
|
8253
8286
|
const isRetry = submissionAttempts > 0;
|
|
8254
8287
|
if (isRetry) {
|
|
8255
|
-
const exponentialDelay = Math.min(
|
|
8288
|
+
const exponentialDelay = Math.min(retryDelayMs2 * Math.pow(1.5, submissionAttempts - 1), 5e3);
|
|
8256
8289
|
const jitter = Math.random() * 500;
|
|
8257
8290
|
const totalDelay = Math.floor(exponentialDelay + jitter);
|
|
8258
8291
|
await sleep2(totalDelay);
|
|
@@ -8415,7 +8448,7 @@ async function transact(params, options) {
|
|
|
8415
8448
|
}
|
|
8416
8449
|
treeState = null;
|
|
8417
8450
|
useSiblingInfo = false;
|
|
8418
|
-
const waitMs = Math.min(
|
|
8451
|
+
const waitMs = Math.min(retryDelayMs2 * Math.pow(2, Math.min(submissionAttempts, 4)), 5e3);
|
|
8419
8452
|
if (waitMs > 0) {
|
|
8420
8453
|
onProgress?.(`Waiting ${waitMs}ms for relay sync before retry...`);
|
|
8421
8454
|
await new Promise((r) => setTimeout(r, waitMs));
|
|
@@ -9109,7 +9142,7 @@ async function swapUtxo(params, options) {
|
|
|
9109
9142
|
riskQuoteUrl: riskQuoteUrlOption,
|
|
9110
9143
|
maxRootRetries = 40,
|
|
9111
9144
|
// Increased to handle prolonged relay sync recovery under high concurrency
|
|
9112
|
-
retryDelayMs = 500,
|
|
9145
|
+
retryDelayMs: retryDelayMs2 = 500,
|
|
9113
9146
|
// Start with short delay, will exponentially back off
|
|
9114
9147
|
useUniqueNullifiers,
|
|
9115
9148
|
useChainRootForProof = true
|
|
@@ -9514,7 +9547,7 @@ async function swapUtxo(params, options) {
|
|
|
9514
9547
|
let walletApprovals = 0;
|
|
9515
9548
|
for (let attempt = 0; attempt <= maxRootRetries; attempt++) {
|
|
9516
9549
|
if (attempt > 0) {
|
|
9517
|
-
const exponentialDelay = Math.min(
|
|
9550
|
+
const exponentialDelay = Math.min(retryDelayMs2 * Math.pow(1.5, attempt - 1), 5e3);
|
|
9518
9551
|
const jitter = Math.random() * 500;
|
|
9519
9552
|
const totalDelay = Math.floor(exponentialDelay + jitter);
|
|
9520
9553
|
await sleep2(totalDelay);
|
|
@@ -9652,7 +9685,7 @@ async function swapUtxo(params, options) {
|
|
|
9652
9685
|
}
|
|
9653
9686
|
merkleState = null;
|
|
9654
9687
|
useSiblingInfo = false;
|
|
9655
|
-
const waitMs = Math.min(
|
|
9688
|
+
const waitMs = Math.min(retryDelayMs2 * Math.pow(2, Math.min(attempt, 4)), 5e3);
|
|
9656
9689
|
if (waitMs > 0) {
|
|
9657
9690
|
onProgress?.(`Waiting ${waitMs}ms for relay sync before retry...`);
|
|
9658
9691
|
await new Promise((r) => setTimeout(r, waitMs));
|
|
@@ -11632,13 +11665,781 @@ var SimpleWallet = class {
|
|
|
11632
11665
|
}
|
|
11633
11666
|
};
|
|
11634
11667
|
|
|
11668
|
+
// src/bridge/rail-verify.ts
|
|
11669
|
+
var import_tweetnacl7 = __toESM(require("tweetnacl"), 1);
|
|
11670
|
+
var import_sha256 = require("@noble/hashes/sha256");
|
|
11671
|
+
var ONECLICK_PUBKEY_B58 = "reYaWhvwu8Jzo3WUM3zhn6VrhuMEF4eADL17qtRVifc";
|
|
11672
|
+
var b58 = /* @__PURE__ */ (() => {
|
|
11673
|
+
const A = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
11674
|
+
return {
|
|
11675
|
+
decode(s) {
|
|
11676
|
+
let n = 0n;
|
|
11677
|
+
for (const c of s) {
|
|
11678
|
+
const i = A.indexOf(c);
|
|
11679
|
+
if (i < 0) throw new Error("bad base58");
|
|
11680
|
+
n = n * 58n + BigInt(i);
|
|
11681
|
+
}
|
|
11682
|
+
const bytes = [];
|
|
11683
|
+
while (n > 0n) {
|
|
11684
|
+
bytes.unshift(Number(n & 255n));
|
|
11685
|
+
n >>= 8n;
|
|
11686
|
+
}
|
|
11687
|
+
for (const c of s) {
|
|
11688
|
+
if (c === "1") bytes.unshift(0);
|
|
11689
|
+
else break;
|
|
11690
|
+
}
|
|
11691
|
+
return Uint8Array.from(bytes);
|
|
11692
|
+
},
|
|
11693
|
+
encode(b) {
|
|
11694
|
+
let n = 0n;
|
|
11695
|
+
for (const x of b) n = n * 256n + BigInt(x);
|
|
11696
|
+
let s = "";
|
|
11697
|
+
while (n > 0n) {
|
|
11698
|
+
s = A[Number(n % 58n)] + s;
|
|
11699
|
+
n /= 58n;
|
|
11700
|
+
}
|
|
11701
|
+
for (const x of b) {
|
|
11702
|
+
if (x === 0) s = "1" + s;
|
|
11703
|
+
else break;
|
|
11704
|
+
}
|
|
11705
|
+
return s;
|
|
11706
|
+
}
|
|
11707
|
+
};
|
|
11708
|
+
})();
|
|
11709
|
+
function stable(v) {
|
|
11710
|
+
if (v === null || typeof v !== "object") return JSON.stringify(v) ?? "null";
|
|
11711
|
+
if (Array.isArray(v)) return `[${v.map(stable).join(",")}]`;
|
|
11712
|
+
const o = v;
|
|
11713
|
+
const parts = Object.keys(o).sort().filter((k) => o[k] !== void 0).map((k) => `${JSON.stringify(k)}:${stable(o[k])}`);
|
|
11714
|
+
return `{${parts.join(",")}}`;
|
|
11715
|
+
}
|
|
11716
|
+
function signedRequest(r) {
|
|
11717
|
+
const q = r.quoteRequest ?? {};
|
|
11718
|
+
return {
|
|
11719
|
+
dry: q.dry,
|
|
11720
|
+
swapType: q.swapType,
|
|
11721
|
+
slippageTolerance: q.slippageTolerance,
|
|
11722
|
+
originAsset: q.originAsset,
|
|
11723
|
+
depositType: q.depositType,
|
|
11724
|
+
destinationAsset: q.destinationAsset,
|
|
11725
|
+
amount: q.amount,
|
|
11726
|
+
refundTo: q.refundTo,
|
|
11727
|
+
refundType: q.refundType,
|
|
11728
|
+
recipient: q.recipient,
|
|
11729
|
+
recipientType: q.recipientType,
|
|
11730
|
+
deadline: q.deadline,
|
|
11731
|
+
quoteWaitingTimeMs: q.quoteWaitingTimeMs || void 0,
|
|
11732
|
+
referral: q.referral || void 0,
|
|
11733
|
+
virtualChainRecipient: q.virtualChainRecipient || void 0,
|
|
11734
|
+
virtualChainRefundRecipient: q.virtualChainRefundRecipient || void 0,
|
|
11735
|
+
customRecipientMsg: q.customRecipientMsg || void 0
|
|
11736
|
+
// Deliberately unsigned by the rail: sessionId, connectedWallets, correlationId, appFees,
|
|
11737
|
+
// partnerId, userAccountId, depositMode. APP FEES ARE NOT AUTHENTICATED — never display a fee
|
|
11738
|
+
// caption as if the signature vouched for it.
|
|
11739
|
+
};
|
|
11740
|
+
}
|
|
11741
|
+
function signedQuote(r) {
|
|
11742
|
+
const q = r.quote ?? {};
|
|
11743
|
+
const base = {
|
|
11744
|
+
amountIn: q.amountIn,
|
|
11745
|
+
amountInFormatted: q.amountInFormatted,
|
|
11746
|
+
amountInUsd: q.amountInUsd,
|
|
11747
|
+
minAmountIn: q.minAmountIn,
|
|
11748
|
+
amountOut: q.amountOut,
|
|
11749
|
+
amountOutFormatted: q.amountOutFormatted,
|
|
11750
|
+
amountOutUsd: q.amountOutUsd,
|
|
11751
|
+
minAmountOut: q.minAmountOut
|
|
11752
|
+
};
|
|
11753
|
+
if (r.quoteRequest?.dry) return base;
|
|
11754
|
+
return {
|
|
11755
|
+
...base,
|
|
11756
|
+
depositAddress: q.depositAddress || void 0,
|
|
11757
|
+
// <- the field that makes substitution detectable
|
|
11758
|
+
depositMemo: q.depositMemo || void 0,
|
|
11759
|
+
deadline: q.deadline || void 0,
|
|
11760
|
+
// <- a real, SIGNED expiry
|
|
11761
|
+
timeWhenInactive: q.timeWhenInactive || void 0,
|
|
11762
|
+
timeEstimate: q.timeEstimate || void 0,
|
|
11763
|
+
virtualChainRecipient: q.virtualChainRecipient || void 0,
|
|
11764
|
+
virtualChainRefundRecipient: q.virtualChainRefundRecipient || void 0,
|
|
11765
|
+
customRecipientMsg: q.customRecipientMsg || void 0,
|
|
11766
|
+
refundFee: q.refundFee || void 0,
|
|
11767
|
+
withdrawFee: q.withdrawFee || void 0
|
|
11768
|
+
};
|
|
11769
|
+
}
|
|
11770
|
+
function canonicalPayloadString(resp) {
|
|
11771
|
+
return stable({ ...signedRequest(resp), ...signedQuote(resp), timestamp: resp.timestamp });
|
|
11772
|
+
}
|
|
11773
|
+
function verifyQuoteSignature(resp) {
|
|
11774
|
+
if (!resp?.signature) return { valid: false, reason: "no signature on the response" };
|
|
11775
|
+
const payload = { ...signedRequest(resp), ...signedQuote(resp), timestamp: resp.timestamp };
|
|
11776
|
+
const digest = (0, import_sha256.sha256)(new TextEncoder().encode(stable(payload)));
|
|
11777
|
+
const message = new TextEncoder().encode(b58.encode(new Uint8Array(digest)));
|
|
11778
|
+
const sig = resp.signature.replace(/^ed25519:/, "");
|
|
11779
|
+
try {
|
|
11780
|
+
return { valid: import_tweetnacl7.default.sign.detached.verify(message, b58.decode(sig), b58.decode(ONECLICK_PUBKEY_B58)) };
|
|
11781
|
+
} catch (e) {
|
|
11782
|
+
return { valid: false, reason: e instanceof Error ? e.message : String(e) };
|
|
11783
|
+
}
|
|
11784
|
+
}
|
|
11785
|
+
|
|
11786
|
+
// src/bridge/rails.ts
|
|
11787
|
+
async function parseBridgeResponse(res, what) {
|
|
11788
|
+
let body;
|
|
11789
|
+
try {
|
|
11790
|
+
body = await res.json();
|
|
11791
|
+
} catch {
|
|
11792
|
+
throw new Error(`${what} failed: ${res.status} ${res.statusText} (response body was not JSON)`);
|
|
11793
|
+
}
|
|
11794
|
+
if (!res.ok) {
|
|
11795
|
+
const b = body ?? {};
|
|
11796
|
+
throw new Error(
|
|
11797
|
+
`${what} failed: ${b.message ?? res.statusText} (${b.code ?? res.status}${b.retryable ? ", retryable" : ""})`
|
|
11798
|
+
);
|
|
11799
|
+
}
|
|
11800
|
+
return body;
|
|
11801
|
+
}
|
|
11802
|
+
function toAttestation(raw) {
|
|
11803
|
+
if (raw.kind === "ed25519") {
|
|
11804
|
+
return { kind: "ed25519", verified: raw.verified ?? false, signer: raw.signer ?? "" };
|
|
11805
|
+
}
|
|
11806
|
+
return { kind: "none", checks: raw.checks ?? [], note: raw.note ?? "" };
|
|
11807
|
+
}
|
|
11808
|
+
async function fetchBridgeQuote(relayUrl, req) {
|
|
11809
|
+
const body = {
|
|
11810
|
+
recipient: req.recipient,
|
|
11811
|
+
origin_chain: req.originChain,
|
|
11812
|
+
amount_base_units: req.amountBaseUnits.toString(),
|
|
11813
|
+
allocate: req.allocate ?? false
|
|
11814
|
+
};
|
|
11815
|
+
if (req.refundTo !== void 0) body.refund_to = req.refundTo;
|
|
11816
|
+
if (req.rails !== void 0) body.rails = req.rails;
|
|
11817
|
+
const res = await relayFetch(`${relayUrl}/bridge/quote`, {
|
|
11818
|
+
method: "POST",
|
|
11819
|
+
headers: { "Content-Type": "application/json" },
|
|
11820
|
+
body: JSON.stringify(body)
|
|
11821
|
+
});
|
|
11822
|
+
const raw = await parseBridgeResponse(res, "bridge quote");
|
|
11823
|
+
const options = [];
|
|
11824
|
+
const unavailable = (raw.unavailable ?? []).map((p) => ({
|
|
11825
|
+
rail: p.rail,
|
|
11826
|
+
reason: p.reason
|
|
11827
|
+
}));
|
|
11828
|
+
for (const opt of raw.options) {
|
|
11829
|
+
const attestation = toAttestation(opt.attestation);
|
|
11830
|
+
if (attestation.kind === "ed25519") {
|
|
11831
|
+
const verdict = opt.rail_response ? verifyQuoteSignature(opt.rail_response) : { valid: false, reason: "no rail_response to verify against" };
|
|
11832
|
+
if (!verdict.valid) {
|
|
11833
|
+
unavailable.push({
|
|
11834
|
+
rail: opt.rail,
|
|
11835
|
+
reason: `deposit address failed independent signature verification, refusing to display it (${verdict.reason ?? "signature did not verify"})`
|
|
11836
|
+
});
|
|
11837
|
+
continue;
|
|
11838
|
+
}
|
|
11839
|
+
}
|
|
11840
|
+
options.push({
|
|
11841
|
+
rail: opt.rail,
|
|
11842
|
+
refunds: opt.refunds,
|
|
11843
|
+
addressLifetime: opt.address_lifetime,
|
|
11844
|
+
amountOut: BigInt(opt.amount_out),
|
|
11845
|
+
minAmountOut: BigInt(opt.min_amount_out),
|
|
11846
|
+
timeEstimateSeconds: opt.time_estimate_s,
|
|
11847
|
+
expiresAt: opt.expires_at,
|
|
11848
|
+
depositAddress: opt.deposit_address,
|
|
11849
|
+
attestation
|
|
11850
|
+
});
|
|
11851
|
+
}
|
|
11852
|
+
return { options, unavailable };
|
|
11853
|
+
}
|
|
11854
|
+
var STATUS_STATES = [
|
|
11855
|
+
"pending",
|
|
11856
|
+
"delivered",
|
|
11857
|
+
"refunded",
|
|
11858
|
+
"expired",
|
|
11859
|
+
"unknown"
|
|
11860
|
+
];
|
|
11861
|
+
async function fetchBridgeStatus(relayUrl, depositAddress, rail) {
|
|
11862
|
+
const qs = new URLSearchParams({ deposit_address: depositAddress, rail });
|
|
11863
|
+
const res = await relayFetch(`${relayUrl}/bridge/status?${qs.toString()}`);
|
|
11864
|
+
const raw = await parseBridgeResponse(res, "bridge status");
|
|
11865
|
+
const state = STATUS_STATES.includes(raw.state ?? "") ? raw.state : "unknown";
|
|
11866
|
+
return { rail: raw.rail ?? rail, state, detail: raw.detail ?? "" };
|
|
11867
|
+
}
|
|
11868
|
+
function cloakBridgeRail(relayUrl) {
|
|
11869
|
+
assertAllowedRelayOrigin(relayUrl);
|
|
11870
|
+
return {
|
|
11871
|
+
id: "cloak-bridge",
|
|
11872
|
+
quote: (req) => fetchBridgeQuote(relayUrl, req),
|
|
11873
|
+
status: (depositAddress, rail) => fetchBridgeStatus(relayUrl, depositAddress, rail)
|
|
11874
|
+
};
|
|
11875
|
+
}
|
|
11876
|
+
|
|
11877
|
+
// src/bridge/paymaster-client.ts
|
|
11878
|
+
var import_web312 = require("@solana/web3.js");
|
|
11879
|
+
var import_spl_token3 = require("@solana/spl-token");
|
|
11880
|
+
function validatePaymasterTopUpTransaction(tx, expect) {
|
|
11881
|
+
const ixs = tx.instructions;
|
|
11882
|
+
if (ixs.length !== 1 && ixs.length !== 2) {
|
|
11883
|
+
throw new Error(
|
|
11884
|
+
`paymaster top-up must be exactly 1 or 2 instructions, got ${ixs.length} \u2014 refusing to sign a transaction whose shape does not match the documented top-up contract`
|
|
11885
|
+
);
|
|
11886
|
+
}
|
|
11887
|
+
const ix0 = ixs[0];
|
|
11888
|
+
if (!ix0.programId.equals(import_web312.SystemProgram.programId)) {
|
|
11889
|
+
throw new Error(
|
|
11890
|
+
`paymaster top-up instruction 0 is owned by ${ix0.programId.toBase58()}, not the System Program \u2014 refusing to sign an unrecognised first instruction`
|
|
11891
|
+
);
|
|
11892
|
+
}
|
|
11893
|
+
const transfer2 = import_web312.SystemInstruction.decodeTransfer(ix0);
|
|
11894
|
+
if (!transfer2.toPubkey.equals(expect.recipient)) {
|
|
11895
|
+
throw new Error(
|
|
11896
|
+
`paymaster top-up sends SOL to ${transfer2.toPubkey.toBase58()}, which is not our recipient ${expect.recipient.toBase58()} \u2014 refusing to sign a transaction that funds a key we do not control`
|
|
11897
|
+
);
|
|
11898
|
+
}
|
|
11899
|
+
if (BigInt(transfer2.lamports) > expect.maxGrantLamports) {
|
|
11900
|
+
throw new Error(
|
|
11901
|
+
`paymaster top-up grants ${transfer2.lamports} lamports, more than the ${expect.maxGrantLamports} we asked for \u2014 refusing a transaction that funds beyond our own request`
|
|
11902
|
+
);
|
|
11903
|
+
}
|
|
11904
|
+
if (ixs.length === 1) return;
|
|
11905
|
+
const ix1 = ixs[1];
|
|
11906
|
+
if (!ix1.programId.equals(import_spl_token3.TOKEN_PROGRAM_ID)) {
|
|
11907
|
+
throw new Error(
|
|
11908
|
+
`paymaster top-up instruction 1 is owned by ${ix1.programId.toBase58()}, not the SPL Token program \u2014 refusing to sign an unrecognised second instruction`
|
|
11909
|
+
);
|
|
11910
|
+
}
|
|
11911
|
+
const spl = (0, import_spl_token3.decodeTransferInstruction)(ix1, import_spl_token3.TOKEN_PROGRAM_ID);
|
|
11912
|
+
const authority = spl.keys.owner.pubkey;
|
|
11913
|
+
if (!authority.equals(expect.recipient)) {
|
|
11914
|
+
throw new Error(
|
|
11915
|
+
`paymaster top-up's fee transfer is authorised by ${authority.toBase58()}, not our recipient ${expect.recipient.toBase58()} \u2014 refusing to sign away tokens from an account we do not control`
|
|
11916
|
+
);
|
|
11917
|
+
}
|
|
11918
|
+
const expectedDestination = (0, import_spl_token3.getAssociatedTokenAddressSync)(
|
|
11919
|
+
expect.feeMint,
|
|
11920
|
+
expect.paymentAddress,
|
|
11921
|
+
false
|
|
11922
|
+
);
|
|
11923
|
+
const destination = spl.keys.destination.pubkey;
|
|
11924
|
+
if (!destination.equals(expectedDestination)) {
|
|
11925
|
+
throw new Error(
|
|
11926
|
+
`paymaster top-up's fee transfer is addressed to ${destination.toBase58()}, not the paymaster's own payment ATA ${expectedDestination.toBase58()} \u2014 refusing to sign a payment to an unverified destination`
|
|
11927
|
+
);
|
|
11928
|
+
}
|
|
11929
|
+
const paidAmount = BigInt(spl.data.amount);
|
|
11930
|
+
if (paidAmount !== expect.feeTokenAmount) {
|
|
11931
|
+
throw new Error(
|
|
11932
|
+
`paymaster top-up's fee amount is ${paidAmount}, not the ${expect.feeTokenAmount} Kora quoted at prepare time \u2014 refusing to sign a payment that does not match the quote`
|
|
11933
|
+
);
|
|
11934
|
+
}
|
|
11935
|
+
}
|
|
11936
|
+
async function parseBridgeResponse2(res, what) {
|
|
11937
|
+
let body;
|
|
11938
|
+
try {
|
|
11939
|
+
body = await res.json();
|
|
11940
|
+
} catch {
|
|
11941
|
+
throw new Error(`${what} failed: ${res.status} ${res.statusText} (response body was not JSON)`);
|
|
11942
|
+
}
|
|
11943
|
+
if (!res.ok) {
|
|
11944
|
+
const b = body ?? {};
|
|
11945
|
+
throw new Error(
|
|
11946
|
+
`${what} failed: ${b.message ?? res.statusText} (${b.code ?? res.status}${b.retryable ? ", retryable" : ""})`
|
|
11947
|
+
);
|
|
11948
|
+
}
|
|
11949
|
+
return body;
|
|
11950
|
+
}
|
|
11951
|
+
async function fundReceiverViaPaymaster(relayUrl, receiver, grantLamports) {
|
|
11952
|
+
assertAllowedRelayOrigin(relayUrl);
|
|
11953
|
+
if (grantLamports <= 0n || grantLamports > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
11954
|
+
throw new Error(
|
|
11955
|
+
`grantLamports must be a positive value representable as a JS number, got ${grantLamports}`
|
|
11956
|
+
);
|
|
11957
|
+
}
|
|
11958
|
+
const prepareRes = await relayFetch(`${relayUrl}/bridge/paymaster/prepare`, {
|
|
11959
|
+
method: "POST",
|
|
11960
|
+
headers: { "Content-Type": "application/json" },
|
|
11961
|
+
body: JSON.stringify({
|
|
11962
|
+
recipient: receiver.publicKey.toBase58(),
|
|
11963
|
+
grant_lamports: Number(grantLamports)
|
|
11964
|
+
})
|
|
11965
|
+
});
|
|
11966
|
+
const prepared = await parseBridgeResponse2(prepareRes, "paymaster prepare");
|
|
11967
|
+
if (Math.floor(Date.now() / 1e3) >= prepared.expires_at_unix) {
|
|
11968
|
+
throw new Error(
|
|
11969
|
+
"paymaster prepare returned a voucher that is already expired \u2014 refusing to sign a stale top-up rather than fail confusingly at cosign"
|
|
11970
|
+
);
|
|
11971
|
+
}
|
|
11972
|
+
const feeMint = new import_web312.PublicKey(prepared.fee_mint);
|
|
11973
|
+
const paymentAddress = new import_web312.PublicKey(prepared.payment_address);
|
|
11974
|
+
const feeTokenAmount = BigInt(prepared.fee_token_amount);
|
|
11975
|
+
const tx = import_web312.Transaction.from(Buffer.from(prepared.transaction, "base64"));
|
|
11976
|
+
validatePaymasterTopUpTransaction(tx, {
|
|
11977
|
+
recipient: receiver.publicKey,
|
|
11978
|
+
maxGrantLamports: grantLamports,
|
|
11979
|
+
feeMint,
|
|
11980
|
+
feeTokenAmount,
|
|
11981
|
+
paymentAddress
|
|
11982
|
+
});
|
|
11983
|
+
tx.partialSign(receiver);
|
|
11984
|
+
const cosignRes = await relayFetch(`${relayUrl}/bridge/paymaster/cosign`, {
|
|
11985
|
+
method: "POST",
|
|
11986
|
+
headers: { "Content-Type": "application/json" },
|
|
11987
|
+
body: JSON.stringify({
|
|
11988
|
+
transaction: tx.serialize({ requireAllSignatures: false, verifySignatures: false }).toString("base64"),
|
|
11989
|
+
voucher: prepared.voucher
|
|
11990
|
+
})
|
|
11991
|
+
});
|
|
11992
|
+
const cosigned = await parseBridgeResponse2(cosignRes, "paymaster cosign");
|
|
11993
|
+
return {
|
|
11994
|
+
transaction: import_web312.Transaction.from(Buffer.from(cosigned.transaction, "base64")),
|
|
11995
|
+
feeTokenAmount,
|
|
11996
|
+
feeMint: prepared.fee_mint,
|
|
11997
|
+
paymentAddress: prepared.payment_address
|
|
11998
|
+
};
|
|
11999
|
+
}
|
|
12000
|
+
|
|
12001
|
+
// src/bridge/derive.ts
|
|
12002
|
+
var import_web313 = require("@solana/web3.js");
|
|
12003
|
+
var import_hmac = require("@noble/hashes/hmac");
|
|
12004
|
+
var import_sha512 = require("@noble/hashes/sha512");
|
|
12005
|
+
var BRIDGE_ESCROW_LABEL = "cloak_bridge_escrow";
|
|
12006
|
+
var MAX_RECEIVER_INDEX = 1e4;
|
|
12007
|
+
function deriveBridgeReceiver(nk, index) {
|
|
12008
|
+
if (!Number.isInteger(index) || index < 0) {
|
|
12009
|
+
throw new Error(`index must be a non-negative integer, got ${index}`);
|
|
12010
|
+
}
|
|
12011
|
+
if (index > MAX_RECEIVER_INDEX) {
|
|
12012
|
+
throw new Error(
|
|
12013
|
+
`index ${index} exceeds MAX_RECEIVER_INDEX (${MAX_RECEIVER_INDEX}). Indices must be a small sequential counter \u2014 discovery derives 0\u2026N and reads each on chain, so a timestamp index is unreachable by any scan and the deposit would be invisible to every device but this one.`
|
|
12014
|
+
);
|
|
12015
|
+
}
|
|
12016
|
+
const h = (0, import_hmac.hmac)(import_sha512.sha512, new Uint8Array(nk), new TextEncoder().encode(`${BRIDGE_ESCROW_LABEL}:${index}`));
|
|
12017
|
+
return import_web313.Keypair.fromSeed(h.slice(0, 32));
|
|
12018
|
+
}
|
|
12019
|
+
|
|
12020
|
+
// src/bridge/discover.ts
|
|
12021
|
+
var import_web314 = require("@solana/web3.js");
|
|
12022
|
+
var import_spl_token4 = require("@solana/spl-token");
|
|
12023
|
+
function describeError(err) {
|
|
12024
|
+
return err instanceof Error ? err.message : String(err);
|
|
12025
|
+
}
|
|
12026
|
+
async function listBridgeDeposits(conn, nk, opts) {
|
|
12027
|
+
const scanDepth = Math.min(opts.scanDepth ?? 20, MAX_RECEIVER_INDEX + 1);
|
|
12028
|
+
const stopAfterUnused = opts.stopAfterUnused ?? 5;
|
|
12029
|
+
const out = [];
|
|
12030
|
+
let consecutiveUnused = 0;
|
|
12031
|
+
for (let index = 0; index < scanDepth; index++) {
|
|
12032
|
+
const kp = deriveBridgeReceiver(nk, index);
|
|
12033
|
+
const receiver = kp.publicKey;
|
|
12034
|
+
const tokenAccount = (0, import_spl_token4.getAssociatedTokenAddressSync)(opts.mint, receiver, false);
|
|
12035
|
+
try {
|
|
12036
|
+
const [recvInfo, ataInfo] = await conn.getMultipleAccountsInfo([receiver, tokenAccount]);
|
|
12037
|
+
const lamports = recvInfo?.lamports ?? 0;
|
|
12038
|
+
let tokenBalance = 0n;
|
|
12039
|
+
if (ataInfo) {
|
|
12040
|
+
try {
|
|
12041
|
+
tokenBalance = BigInt((await conn.getTokenAccountBalance(tokenAccount)).value.amount);
|
|
12042
|
+
} catch (err) {
|
|
12043
|
+
if (!(err instanceof import_web314.SolanaJSONRPCError && /could not find account/i.test(err.message))) {
|
|
12044
|
+
throw err;
|
|
12045
|
+
}
|
|
12046
|
+
}
|
|
12047
|
+
}
|
|
12048
|
+
if (lamports === 0 && !ataInfo) {
|
|
12049
|
+
consecutiveUnused++;
|
|
12050
|
+
if (consecutiveUnused >= stopAfterUnused) break;
|
|
12051
|
+
continue;
|
|
12052
|
+
}
|
|
12053
|
+
consecutiveUnused = 0;
|
|
12054
|
+
const shieldSignatures = [];
|
|
12055
|
+
const sigs = await conn.getSignaturesForAddress(receiver, { limit: 20 });
|
|
12056
|
+
for (const s of sigs) {
|
|
12057
|
+
if (s.err) continue;
|
|
12058
|
+
const tx = await conn.getTransaction(s.signature, { maxSupportedTransactionVersion: 0 });
|
|
12059
|
+
const keys = tx?.transaction.message.getAccountKeys({
|
|
12060
|
+
accountKeysFromLookups: tx.meta?.loadedAddresses
|
|
12061
|
+
});
|
|
12062
|
+
if (keys && [...Array(keys.length).keys()].some((i) => keys.get(i)?.equals(opts.programId))) {
|
|
12063
|
+
shieldSignatures.push(s.signature);
|
|
12064
|
+
}
|
|
12065
|
+
}
|
|
12066
|
+
const shieldSignature = shieldSignatures[0];
|
|
12067
|
+
const indexReused = shieldSignatures.length > 1;
|
|
12068
|
+
let state;
|
|
12069
|
+
if (tokenBalance > 0n) state = shieldSignature ? "needs-cleanup" : "arrived";
|
|
12070
|
+
else if (shieldSignature) state = ataInfo ? "needs-cleanup" : "complete";
|
|
12071
|
+
else state = "awaiting";
|
|
12072
|
+
out.push({
|
|
12073
|
+
index,
|
|
12074
|
+
receiver,
|
|
12075
|
+
tokenAccount,
|
|
12076
|
+
state,
|
|
12077
|
+
tokenBalance,
|
|
12078
|
+
lamports,
|
|
12079
|
+
shieldSignature,
|
|
12080
|
+
...indexReused ? { indexReused, shieldSignatures } : {}
|
|
12081
|
+
});
|
|
12082
|
+
} catch (err) {
|
|
12083
|
+
out.push({
|
|
12084
|
+
index,
|
|
12085
|
+
receiver,
|
|
12086
|
+
tokenAccount,
|
|
12087
|
+
state: "unknown",
|
|
12088
|
+
tokenBalance: 0n,
|
|
12089
|
+
lamports: 0,
|
|
12090
|
+
error: describeError(err)
|
|
12091
|
+
});
|
|
12092
|
+
}
|
|
12093
|
+
}
|
|
12094
|
+
return out;
|
|
12095
|
+
}
|
|
12096
|
+
|
|
12097
|
+
// src/bridge/deposit-core.ts
|
|
12098
|
+
var import_web316 = require("@solana/web3.js");
|
|
12099
|
+
var import_tweetnacl8 = __toESM(require("tweetnacl"), 1);
|
|
12100
|
+
init_utxo();
|
|
12101
|
+
|
|
12102
|
+
// src/bridge/funder.ts
|
|
12103
|
+
var import_web315 = require("@solana/web3.js");
|
|
12104
|
+
var import_spl_token5 = require("@solana/spl-token");
|
|
12105
|
+
var MAINNET_RENT_0 = 890880;
|
|
12106
|
+
var MAINNET_RENT_1 = 897840;
|
|
12107
|
+
var FEE_BUDGET = 13e4;
|
|
12108
|
+
var CLEANUP_FEE_BUDGET = 5e3;
|
|
12109
|
+
var pda = (seeds, programId) => import_web315.PublicKey.findProgramAddressSync(seeds.map((s) => Buffer.from(s)), programId)[0];
|
|
12110
|
+
function deriveFundingTargets(d) {
|
|
12111
|
+
const pool = pda([Buffer.from("pool"), d.mint.toBuffer()], d.programId);
|
|
12112
|
+
return {
|
|
12113
|
+
pool,
|
|
12114
|
+
// program: NullifierAccount::derive_pda_with_pool -> [b"nullifier", pool, nullifier]
|
|
12115
|
+
nullifier0: pda([Buffer.from("nullifier"), pool.toBuffer(), d.nullifiers[0]], d.programId),
|
|
12116
|
+
nullifier1: pda([Buffer.from("nullifier"), pool.toBuffer(), d.nullifiers[1]], d.programId),
|
|
12117
|
+
// relay: derive_risk_nonce_pda -> [b"risk_nonce", bind0]
|
|
12118
|
+
riskNonce: pda([Buffer.from("risk_nonce"), d.bind0], d.programId),
|
|
12119
|
+
depositorAta: (0, import_spl_token5.getAssociatedTokenAddressSync)(d.mint, d.depositor, false)
|
|
12120
|
+
};
|
|
12121
|
+
}
|
|
12122
|
+
async function readRent(conn) {
|
|
12123
|
+
const [zero, one] = await Promise.all([
|
|
12124
|
+
conn.getMinimumBalanceForRentExemption(0),
|
|
12125
|
+
conn.getMinimumBalanceForRentExemption(1)
|
|
12126
|
+
]);
|
|
12127
|
+
return { zero, one };
|
|
12128
|
+
}
|
|
12129
|
+
|
|
12130
|
+
// src/bridge/deposit-core.ts
|
|
12131
|
+
var DepositError = class extends Error {
|
|
12132
|
+
constructor(message, fundedAccounts, measuredTxSize) {
|
|
12133
|
+
super(message);
|
|
12134
|
+
this.fundedAccounts = fundedAccounts;
|
|
12135
|
+
this.measuredTxSize = measuredTxSize;
|
|
12136
|
+
this.name = "DepositError";
|
|
12137
|
+
}
|
|
12138
|
+
};
|
|
12139
|
+
async function depositFromDerivedKey(conn, R, funder, amount, log = console.log, grantOverride, opts) {
|
|
12140
|
+
if (!opts.noteSpendKey || opts.noteSpendKey.length !== 32) {
|
|
12141
|
+
throw new Error(
|
|
12142
|
+
"opts.noteSpendKey (32 bytes) is required. It derives the note's spending key, and a note whose key is not derived from something you can reproduce is unspendable forever. Pass the same Cloak seed you derived the receiving address from."
|
|
12143
|
+
);
|
|
12144
|
+
}
|
|
12145
|
+
if (!opts.relayUrl) {
|
|
12146
|
+
throw new Error(
|
|
12147
|
+
"opts.relayUrl is required. There is no default: a missing relay used to resolve silently to the local stack, which is how a live run built a deposit against infrastructure that only existed on someone's laptop. Say which relay, every call."
|
|
12148
|
+
);
|
|
12149
|
+
}
|
|
12150
|
+
if (!opts.programId) {
|
|
12151
|
+
throw new Error(
|
|
12152
|
+
"opts.programId is required. There is no default: this is the exact field a live mainnet run once inherited from this module's local-stack constant, built a deposit against a program that does not exist on mainnet, and failed hunting a merkle tree that was never there."
|
|
12153
|
+
);
|
|
12154
|
+
}
|
|
12155
|
+
if (!opts.mint) {
|
|
12156
|
+
throw new Error(
|
|
12157
|
+
"opts.mint is required. There is no default: a deposit built for the wrong mint produces a note for an asset that never arrived at R, and there is nothing to silently fall back to."
|
|
12158
|
+
);
|
|
12159
|
+
}
|
|
12160
|
+
assertAllowedRpcConnection(conn);
|
|
12161
|
+
const relayUrl = opts.relayUrl;
|
|
12162
|
+
const programId = opts.programId;
|
|
12163
|
+
const mint = opts.mint;
|
|
12164
|
+
setCircuitsPath(resolveCircuitsBase());
|
|
12165
|
+
const grantR = grantOverride ?? MAINNET_RENT_0 + FEE_BUDGET + CLEANUP_FEE_BUDGET;
|
|
12166
|
+
const heldByR = await conn.getBalance(R.publicKey);
|
|
12167
|
+
if (heldByR >= grantR) {
|
|
12168
|
+
log(` R already holds ${heldByR} (>= ${grantR}) \u2014 no top-up needed`);
|
|
12169
|
+
} else {
|
|
12170
|
+
await (0, import_web316.sendAndConfirmTransaction)(conn, new import_web316.Transaction().add(
|
|
12171
|
+
import_web316.SystemProgram.transfer({ fromPubkey: funder.publicKey, toPubkey: R.publicKey, lamports: grantR - heldByR })
|
|
12172
|
+
), [funder]);
|
|
12173
|
+
log(` funder topped R up by ${grantR - heldByR} to ${grantR}${grantOverride !== void 0 ? " (OVERRIDDEN for a deliberate test)" : " \u2014 floor + deposit fee + cleanup fee, no rent"}`);
|
|
12174
|
+
}
|
|
12175
|
+
let measuredSize = -1;
|
|
12176
|
+
let fundedAccounts = [];
|
|
12177
|
+
const signTransaction2 = async (tx) => {
|
|
12178
|
+
if (tx instanceof import_web316.VersionedTransaction) {
|
|
12179
|
+
measuredSize = tx.serialize().length;
|
|
12180
|
+
const alts = await Promise.all(
|
|
12181
|
+
tx.message.addressTableLookups.map(async (l) => (await conn.getAddressLookupTable(l.accountKey)).value)
|
|
12182
|
+
);
|
|
12183
|
+
const keys = tx.message.getAccountKeys({ addressLookupTableAccounts: alts });
|
|
12184
|
+
const ix = tx.message.compiledInstructions.find((i) => keys.get(i.programIdIndex).equals(programId));
|
|
12185
|
+
const at = (n) => keys.get(ix.accountKeyIndexes[n]);
|
|
12186
|
+
const targets = [
|
|
12187
|
+
{ a: at(12), need: MAINNET_RENT_0, name: "risk_nonce" },
|
|
12188
|
+
{ a: at(4), need: MAINNET_RENT_1, name: "nullifier_0" },
|
|
12189
|
+
{ a: at(5), need: MAINNET_RENT_1, name: "nullifier_1" }
|
|
12190
|
+
];
|
|
12191
|
+
const infos = await conn.getMultipleAccountsInfo(targets.map((t) => t.a));
|
|
12192
|
+
fundedAccounts = targets.map((t, i) => ({
|
|
12193
|
+
name: t.name,
|
|
12194
|
+
address: t.a.toBase58(),
|
|
12195
|
+
lamportsSent: Math.max(0, t.need - (infos[i]?.lamports ?? 0))
|
|
12196
|
+
}));
|
|
12197
|
+
const ixs = targets.flatMap((t, i) => (infos[i]?.lamports ?? 0) >= t.need ? [] : [import_web316.SystemProgram.transfer({
|
|
12198
|
+
fromPubkey: funder.publicKey,
|
|
12199
|
+
toPubkey: t.a,
|
|
12200
|
+
lamports: t.need - (infos[i]?.lamports ?? 0)
|
|
12201
|
+
})]);
|
|
12202
|
+
if (ixs.length) {
|
|
12203
|
+
const sig = await (0, import_web316.sendAndConfirmTransaction)(conn, new import_web316.Transaction().add(...ixs), [funder]);
|
|
12204
|
+
log(` seam: funded ${ixs.length} program accounts read off the built tx \u2014 ${sig.slice(0, 16)}\u2026`);
|
|
12205
|
+
}
|
|
12206
|
+
tx.sign([R]);
|
|
12207
|
+
return tx;
|
|
12208
|
+
}
|
|
12209
|
+
tx.partialSign(R);
|
|
12210
|
+
return tx;
|
|
12211
|
+
};
|
|
12212
|
+
const signMessage = async (m) => import_tweetnacl8.default.sign.detached(m, R.secretKey);
|
|
12213
|
+
const utxoKeypair = await deriveUtxoKeypairFromSpendKey(opts.noteSpendKey);
|
|
12214
|
+
const nk = getNkFromUtxoPrivateKey(utxoKeypair.privateKey);
|
|
12215
|
+
const { utxo, noteSalt } = await createRecoverableDepositUtxo(amount, nk, mint);
|
|
12216
|
+
const zeroInput = await createZeroUtxo(mint);
|
|
12217
|
+
const rBefore = await conn.getBalance(R.publicKey);
|
|
12218
|
+
let result;
|
|
12219
|
+
try {
|
|
12220
|
+
result = await transact(
|
|
12221
|
+
{ inputUtxos: [zeroInput], outputUtxos: [utxo], externalAmount: amount, depositor: R.publicKey },
|
|
12222
|
+
{
|
|
12223
|
+
connection: conn,
|
|
12224
|
+
programId,
|
|
12225
|
+
relayUrl,
|
|
12226
|
+
// NO depositorKeypair: the SDK branches `if (keypair) … else if (signTransaction)`
|
|
12227
|
+
// (transact.ts:2786, :2936), so passing one silently skips the funding seam.
|
|
12228
|
+
depositorPublicKey: R.publicKey,
|
|
12229
|
+
walletPublicKey: R.publicKey,
|
|
12230
|
+
signTransaction: signTransaction2,
|
|
12231
|
+
signMessage,
|
|
12232
|
+
chainNoteViewingKeyNk: nk,
|
|
12233
|
+
chainNoteSalt: noteSalt,
|
|
12234
|
+
relaySupplementalAlt: true,
|
|
12235
|
+
onProgress: (s) => log(` \xB7 ${s}`)
|
|
12236
|
+
}
|
|
12237
|
+
);
|
|
12238
|
+
} catch (e) {
|
|
12239
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
12240
|
+
throw new DepositError(msg, fundedAccounts, measuredSize);
|
|
12241
|
+
}
|
|
12242
|
+
const rAfter = await conn.getBalance(R.publicKey);
|
|
12243
|
+
const noteIndex = result.outputUtxos[0].index;
|
|
12244
|
+
if (noteIndex === void 0) throw new Error("deposit landed but the note has no index \u2014 it cannot be discovered later");
|
|
12245
|
+
return {
|
|
12246
|
+
signature: result.signature,
|
|
12247
|
+
noteIndex,
|
|
12248
|
+
amount: result.outputUtxos[0].amount,
|
|
12249
|
+
txSize: measuredSize,
|
|
12250
|
+
rBefore,
|
|
12251
|
+
rAfter,
|
|
12252
|
+
rentExempt: rAfter >= MAINNET_RENT_0,
|
|
12253
|
+
inputNullifiers: result.inputNullifiers,
|
|
12254
|
+
fundedAccounts
|
|
12255
|
+
};
|
|
12256
|
+
}
|
|
12257
|
+
|
|
12258
|
+
// src/bridge/cleanup.ts
|
|
12259
|
+
var import_web317 = require("@solana/web3.js");
|
|
12260
|
+
var import_spl_token6 = require("@solana/spl-token");
|
|
12261
|
+
var DEFAULT_MINT = new import_web317.PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
|
|
12262
|
+
async function cleanupReceivingAddress(conn, R, dustDestination, mint = DEFAULT_MINT) {
|
|
12263
|
+
assertAllowedRpcConnection(conn);
|
|
12264
|
+
const rAta = (0, import_spl_token6.getAssociatedTokenAddressSync)(mint, R.publicKey);
|
|
12265
|
+
const info = await conn.getAccountInfo(rAta);
|
|
12266
|
+
if (!info) {
|
|
12267
|
+
return {
|
|
12268
|
+
closed: false,
|
|
12269
|
+
dustSwept: 0n,
|
|
12270
|
+
rentReturned: 0,
|
|
12271
|
+
destination: null,
|
|
12272
|
+
signature: null,
|
|
12273
|
+
note: "no token account \u2014 nothing to recover"
|
|
12274
|
+
};
|
|
12275
|
+
}
|
|
12276
|
+
const bal = BigInt((await conn.getTokenAccountBalance(rAta)).value.amount);
|
|
12277
|
+
const rentHeld = info.lamports;
|
|
12278
|
+
const before = await conn.getBalance(R.publicKey);
|
|
12279
|
+
const ixs = [];
|
|
12280
|
+
let destination = null;
|
|
12281
|
+
if (bal > 0n && !dustDestination) {
|
|
12282
|
+
return {
|
|
12283
|
+
closed: false,
|
|
12284
|
+
dustSwept: 0n,
|
|
12285
|
+
rentReturned: 0,
|
|
12286
|
+
destination: null,
|
|
12287
|
+
signature: null,
|
|
12288
|
+
note: `dusted with ${bal} base units after the deposit; leaving the account open and ${rentHeld.toLocaleString()} lamports of rent unrecovered, because sweeping it would publish a link from this deposit to whoever receives it`
|
|
12289
|
+
};
|
|
12290
|
+
}
|
|
12291
|
+
if (bal > 0n && dustDestination) {
|
|
12292
|
+
const destAta = (0, import_spl_token6.getAssociatedTokenAddressSync)(mint, dustDestination);
|
|
12293
|
+
const destInfo = await conn.getAccountInfo(destAta);
|
|
12294
|
+
if (!destInfo) {
|
|
12295
|
+
const ataRent = await (0, import_spl_token6.getMinimumBalanceForRentExemptAccount)(conn);
|
|
12296
|
+
if (before < ataRent + CLEANUP_FEE_BUDGET) {
|
|
12297
|
+
throw new Error(
|
|
12298
|
+
`dustDestination ${dustDestination.toBase58()} has no token account for mint ${mint.toBase58()}, and creating one costs ${ataRent} lamports of rent that R does not have: R holds ${before}, which deposit-core.ts reserved only for this transaction's own fee (CLEANUP_FEE_BUDGET = ${CLEANUP_FEE_BUDGET} in funder.ts), not for a fresh account's rent. Fund R with at least ${ataRent + CLEANUP_FEE_BUDGET - before} more lamports first, or choose a destination that already has a token account for this mint.`
|
|
12299
|
+
);
|
|
12300
|
+
}
|
|
12301
|
+
ixs.push((0, import_spl_token6.createAssociatedTokenAccountIdempotentInstruction)(R.publicKey, destAta, dustDestination, mint));
|
|
12302
|
+
}
|
|
12303
|
+
ixs.push((0, import_spl_token6.createTransferInstruction)(rAta, destAta, R.publicKey, bal));
|
|
12304
|
+
destination = destAta.toBase58();
|
|
12305
|
+
}
|
|
12306
|
+
ixs.push((0, import_spl_token6.createCloseAccountInstruction)(rAta, R.publicKey, R.publicKey));
|
|
12307
|
+
const signature = await (0, import_web317.sendAndConfirmTransaction)(conn, new import_web317.Transaction().add(...ixs), [R], {
|
|
12308
|
+
commitment: "confirmed"
|
|
12309
|
+
});
|
|
12310
|
+
const after = await conn.getBalance(R.publicKey);
|
|
12311
|
+
const gone = await conn.getAccountInfo(rAta) === null;
|
|
12312
|
+
return {
|
|
12313
|
+
closed: gone,
|
|
12314
|
+
dustSwept: bal,
|
|
12315
|
+
rentReturned: after - before,
|
|
12316
|
+
destination,
|
|
12317
|
+
signature,
|
|
12318
|
+
note: bal > 0n ? `swept ${bal} base units of dust to the caller-chosen destination and closed, in one transaction \u2014 note this publishes a link from the deposit to that destination` : `closed cleanly, nothing to sweep`
|
|
12319
|
+
};
|
|
12320
|
+
}
|
|
12321
|
+
|
|
12322
|
+
// src/bridge/quote.ts
|
|
12323
|
+
var MIN_DEPOSIT_SPL_BASE_UNITS = 1000000n;
|
|
12324
|
+
var WITHDRAW_FIXED_FEE = 450000n;
|
|
12325
|
+
var WITHDRAW_FEE_BPS = 30n;
|
|
12326
|
+
function withdrawFeeAt(amount, fixedFee, feeBps) {
|
|
12327
|
+
return fixedFee + amount * feeBps / 10000n;
|
|
12328
|
+
}
|
|
12329
|
+
var MAX_FEE_FRACTION = 0.063;
|
|
12330
|
+
var FIXED_ROUND_TRIP = 903000n;
|
|
12331
|
+
var ECONOMIC_MINIMUM = FIXED_ROUND_TRIP * 1000000n / BigInt(Math.round((MAX_FEE_FRACTION - 3e-3) * 1e6));
|
|
12332
|
+
function withdrawFeeFor(amount) {
|
|
12333
|
+
return withdrawFeeAt(amount, WITHDRAW_FIXED_FEE, WITHDRAW_FEE_BPS);
|
|
12334
|
+
}
|
|
12335
|
+
function assessBridgeQuote(q) {
|
|
12336
|
+
if (q.sent < 0n) {
|
|
12337
|
+
throw new Error(`assessBridgeQuote: sent must not be negative (got ${q.sent}).`);
|
|
12338
|
+
}
|
|
12339
|
+
if (q.arrivesMin > q.sent) {
|
|
12340
|
+
throw new Error(
|
|
12341
|
+
`assessBridgeQuote: arrivesMin (${q.arrivesMin}) exceeds sent (${q.sent}) \u2014 no rail returns more than it was given, so this input did not come from a real quote.`
|
|
12342
|
+
);
|
|
12343
|
+
}
|
|
12344
|
+
const shieldedMinRaw = q.arrivesMin - q.paymasterFee;
|
|
12345
|
+
const shieldedTargetRaw = q.arrivesTarget - q.paymasterFee;
|
|
12346
|
+
const shieldedMin = shieldedMinRaw > 0n ? shieldedMinRaw : 0n;
|
|
12347
|
+
const shieldedTarget = shieldedTargetRaw > 0n ? shieldedTargetRaw : 0n;
|
|
12348
|
+
const viable = shieldedMinRaw >= MIN_DEPOSIT_SPL_BASE_UNITS;
|
|
12349
|
+
const economic = q.sent >= ECONOMIC_MINIMUM;
|
|
12350
|
+
const withdrawFee = shieldedMin > 0n ? withdrawFeeAt(shieldedMin, q.liveWithdrawFixedFee ?? WITHDRAW_FIXED_FEE, q.liveWithdrawFeeBps ?? WITHDRAW_FEE_BPS) : 0n;
|
|
12351
|
+
const roundTripCost = q.sent - (shieldedMin > withdrawFee ? shieldedMin - withdrawFee : 0n);
|
|
12352
|
+
const roundTripFraction = q.sent > 0n ? Number(roundTripCost) / Number(q.sent) : 0;
|
|
12353
|
+
const reasons = [];
|
|
12354
|
+
if (!viable) {
|
|
12355
|
+
const short = MIN_DEPOSIT_SPL_BASE_UNITS - shieldedMinRaw;
|
|
12356
|
+
reasons.push(
|
|
12357
|
+
(shieldedMinRaw <= 0n ? `The ${fmt(q.paymasterFee)} paymaster fee alone is ${shieldedMinRaw < 0n ? `${fmt(-shieldedMinRaw)} more than` : "all of"} the ${fmt(q.arrivesMin)} the rail guarantees, so nothing would be left to shield.` : `Only ${fmt(shieldedMinRaw)} would be left to shield after the ${fmt(q.paymasterFee)} paymaster fee.`) + ` The program's minimum deposit is ${fmt(MIN_DEPOSIT_SPL_BASE_UNITS)}. Send at least ${fmt(q.sent + short)} to clear it.`
|
|
12358
|
+
);
|
|
12359
|
+
}
|
|
12360
|
+
if (viable && !economic) {
|
|
12361
|
+
reasons.push(
|
|
12362
|
+
`This works, but ${fmt(roundTripCost)} of ${fmt(q.sent)} goes to fees (${(roundTripFraction * 100).toFixed(0)}%). The costs are almost all fixed, so bridging ${fmt(ECONOMIC_MINIMUM)} or more spreads them much further.`
|
|
12363
|
+
);
|
|
12364
|
+
}
|
|
12365
|
+
return {
|
|
12366
|
+
...q,
|
|
12367
|
+
shieldedMin,
|
|
12368
|
+
shieldedTarget,
|
|
12369
|
+
viable,
|
|
12370
|
+
economic,
|
|
12371
|
+
withdrawFee,
|
|
12372
|
+
roundTripCost,
|
|
12373
|
+
roundTripFraction,
|
|
12374
|
+
reasons
|
|
12375
|
+
};
|
|
12376
|
+
}
|
|
12377
|
+
var fmt = (v) => `${(Number(v) / 1e6).toFixed(6)} USDC`;
|
|
12378
|
+
function renderAssessment(a) {
|
|
12379
|
+
const L = [];
|
|
12380
|
+
L.push(` you send ${fmt(a.sent)}`);
|
|
12381
|
+
L.push(` arrives at least ${fmt(a.arrivesMin)} (target ${fmt(a.arrivesTarget)}, not a promise)`);
|
|
12382
|
+
L.push(` paymaster fee ${fmt(a.paymasterFee)} buys the receiver its SOL, so your wallet stays off chain`);
|
|
12383
|
+
L.push(` SHIELDED ${fmt(a.shieldedMin)} at least \u2014 this is what you end up with`);
|
|
12384
|
+
L.push(` to withdraw later ${fmt(a.withdrawFee)} the program's fee, whenever you take it out`);
|
|
12385
|
+
for (const r of a.reasons) L.push(`
|
|
12386
|
+
${a.viable ? "NOTE" : "REFUSED"}: ${r}`);
|
|
12387
|
+
return L.join("\n");
|
|
12388
|
+
}
|
|
12389
|
+
|
|
12390
|
+
// src/bridge/retry.ts
|
|
12391
|
+
var TERMINAL_FAILURE = /DepositTooSmall|minimum is 1\.000000|insufficient|holds only|below the program|kora wants|over the .* ceiling/i;
|
|
12392
|
+
function isTerminalFailure(message) {
|
|
12393
|
+
return TERMINAL_FAILURE.test(message);
|
|
12394
|
+
}
|
|
12395
|
+
function classifyPostFailure(attempted, after) {
|
|
12396
|
+
if (after === null) return "unknown";
|
|
12397
|
+
if (after === 0n) return "landed";
|
|
12398
|
+
if (after >= attempted) return "did-not-land";
|
|
12399
|
+
return "unknown";
|
|
12400
|
+
}
|
|
12401
|
+
function mayRetry(verdict, message) {
|
|
12402
|
+
return verdict === "did-not-land" && !isTerminalFailure(message);
|
|
12403
|
+
}
|
|
12404
|
+
function retryDelayMs(attempt) {
|
|
12405
|
+
return 15e3 * Math.max(0, attempt - 1);
|
|
12406
|
+
}
|
|
12407
|
+
var DoNotRetry = class extends Error {
|
|
12408
|
+
constructor(message) {
|
|
12409
|
+
super(message);
|
|
12410
|
+
this.name = "DoNotRetry";
|
|
12411
|
+
}
|
|
12412
|
+
};
|
|
12413
|
+
async function withShieldRetries(attempt, hooks = {}) {
|
|
12414
|
+
const attempts = hooks.attempts ?? 3;
|
|
12415
|
+
const sleep4 = hooks.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
12416
|
+
let last = "";
|
|
12417
|
+
for (let n = 1; n <= attempts; n++) {
|
|
12418
|
+
if (n > 1) {
|
|
12419
|
+
const delay = retryDelayMs(n);
|
|
12420
|
+
hooks.onRetry?.(n, delay, last);
|
|
12421
|
+
await sleep4(delay);
|
|
12422
|
+
}
|
|
12423
|
+
try {
|
|
12424
|
+
return await attempt(n);
|
|
12425
|
+
} catch (e) {
|
|
12426
|
+
if (e instanceof DoNotRetry) throw e;
|
|
12427
|
+
last = e instanceof Error ? e.message : String(e);
|
|
12428
|
+
if (isTerminalFailure(last) || n === attempts) throw e;
|
|
12429
|
+
}
|
|
12430
|
+
}
|
|
12431
|
+
throw new Error("unreachable");
|
|
12432
|
+
}
|
|
12433
|
+
|
|
11635
12434
|
// src/index.ts
|
|
11636
12435
|
var VERSION = "0.2.1";
|
|
11637
12436
|
var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
11638
12437
|
// Annotate the CommonJS export names for ESM import in node:
|
|
11639
12438
|
0 && (module.exports = {
|
|
12439
|
+
BRIDGE_ESCROW_LABEL,
|
|
11640
12440
|
BUILD_ALLOWS_LOCAL_ENDPOINTS,
|
|
11641
12441
|
CHAIN_NOTE_SALT_BITS,
|
|
12442
|
+
CLEANUP_FEE_BUDGET,
|
|
11642
12443
|
CLOAK_PRODUCTION_RELAY_URL,
|
|
11643
12444
|
CLOAK_PROGRAM_ID,
|
|
11644
12445
|
CloakError,
|
|
@@ -11646,16 +12447,25 @@ var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
|
11646
12447
|
DEFAULT_TRANSACTION_CIRCUITS_URL,
|
|
11647
12448
|
DELIVERY_MEMO_TAG,
|
|
11648
12449
|
DELIVERY_REGISTRY_SEED,
|
|
12450
|
+
DepositError,
|
|
12451
|
+
DoNotRetry,
|
|
12452
|
+
ECONOMIC_MINIMUM,
|
|
11649
12453
|
EXPECTED_CIRCUIT_HASHES,
|
|
12454
|
+
FEE_BUDGET,
|
|
11650
12455
|
FIXED_FEE_LAMPORTS,
|
|
11651
12456
|
InsecureRandomnessError,
|
|
11652
12457
|
LAMPORTS_PER_SOL,
|
|
11653
12458
|
LocalStorageAdapter,
|
|
12459
|
+
MAINNET_RENT_0,
|
|
12460
|
+
MAINNET_RENT_1,
|
|
12461
|
+
MAX_RECEIVER_INDEX,
|
|
11654
12462
|
MERKLE_TREE_HEIGHT,
|
|
11655
12463
|
MIN_DEPOSIT_LAMPORTS,
|
|
12464
|
+
MIN_DEPOSIT_SPL_BASE_UNITS,
|
|
11656
12465
|
MemoryStorageAdapter,
|
|
11657
12466
|
MerkleTree,
|
|
11658
12467
|
NATIVE_SOL_MINT,
|
|
12468
|
+
ONECLICK_PUBKEY_B58,
|
|
11659
12469
|
RECIPIENT_DELIVERY_CIPHERTEXT_LEN,
|
|
11660
12470
|
RECIPIENT_DELIVERY_EPHEMERAL_PK_LEN,
|
|
11661
12471
|
RECIPIENT_DELIVERY_NONCE_LEN,
|
|
@@ -11674,6 +12484,7 @@ var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
|
11674
12484
|
SettlementVerificationError,
|
|
11675
12485
|
ShieldPoolErrors,
|
|
11676
12486
|
SimpleWallet,
|
|
12487
|
+
TERMINAL_FAILURE,
|
|
11677
12488
|
TRANSACTION_CIRCUITS_VERSION,
|
|
11678
12489
|
TRANSACT_AUTH_FIELDS,
|
|
11679
12490
|
TRANSACT_SWAP_AUTH_FIELDS,
|
|
@@ -11683,8 +12494,11 @@ var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
|
11683
12494
|
VARIABLE_FEE_NUMERATOR,
|
|
11684
12495
|
VARIABLE_FEE_RATE,
|
|
11685
12496
|
VERSION,
|
|
12497
|
+
WITHDRAW_FEE_BPS,
|
|
12498
|
+
WITHDRAW_FIXED_FEE,
|
|
11686
12499
|
assertDirectSubmissionLanded,
|
|
11687
12500
|
assertTransactionCircuitIntegrity,
|
|
12501
|
+
assessBridgeQuote,
|
|
11688
12502
|
bigintToBytes32,
|
|
11689
12503
|
bigintToHex,
|
|
11690
12504
|
buildMerkleTree,
|
|
@@ -11699,12 +12513,16 @@ var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
|
11699
12513
|
calculateRelayFee,
|
|
11700
12514
|
canRebuildMerkleTreeFromChain,
|
|
11701
12515
|
canonicalJson,
|
|
12516
|
+
canonicalPayloadString,
|
|
11702
12517
|
chainNoteFromBase64,
|
|
11703
12518
|
chainNoteToBase64,
|
|
12519
|
+
classifyPostFailure,
|
|
11704
12520
|
classifyRelayError,
|
|
12521
|
+
cleanupReceivingAddress,
|
|
11705
12522
|
cleanupStalePendingOperations,
|
|
11706
12523
|
clearPendingDeposits,
|
|
11707
12524
|
clearPendingWithdrawals,
|
|
12525
|
+
cloakBridgeRail,
|
|
11708
12526
|
computeChainNoteHash,
|
|
11709
12527
|
computeExtDataHash,
|
|
11710
12528
|
computeMerkleRoot,
|
|
@@ -11726,10 +12544,13 @@ var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
|
11726
12544
|
decryptCompactChainNote,
|
|
11727
12545
|
decryptComplianceMetadataWithMasterKey,
|
|
11728
12546
|
decryptTransactionMetadata,
|
|
12547
|
+
depositFromDerivedKey,
|
|
12548
|
+
deriveBridgeReceiver,
|
|
11729
12549
|
deriveChangeNoteBlinding,
|
|
11730
12550
|
deriveDepositNoteSecrets,
|
|
11731
12551
|
deriveDiversifiedViewingKey,
|
|
11732
12552
|
deriveDiversifier,
|
|
12553
|
+
deriveFundingTargets,
|
|
11733
12554
|
deriveInputNullifierPdas,
|
|
11734
12555
|
derivePublicKey,
|
|
11735
12556
|
deriveSpendKey,
|
|
@@ -11768,6 +12589,7 @@ var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
|
11768
12589
|
formatErrorForLogging,
|
|
11769
12590
|
formatSol,
|
|
11770
12591
|
fullWithdraw,
|
|
12592
|
+
fundReceiverViaPaymaster,
|
|
11771
12593
|
generateCloakKeys,
|
|
11772
12594
|
generateCommitmentAsync,
|
|
11773
12595
|
generateMasterSeed,
|
|
@@ -11803,18 +12625,21 @@ var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
|
11803
12625
|
isReactNative,
|
|
11804
12626
|
isRootNotFoundError,
|
|
11805
12627
|
isSubmissionOutcomeUnknownResponse,
|
|
12628
|
+
isTerminalFailure,
|
|
11806
12629
|
isValidHex,
|
|
11807
12630
|
isValidRpcUrl,
|
|
11808
12631
|
isValidSolanaAddress,
|
|
11809
12632
|
isWithdrawAmountSufficient,
|
|
11810
12633
|
isWithdrawable,
|
|
11811
12634
|
keypairToAdapter,
|
|
12635
|
+
listBridgeDeposits,
|
|
11812
12636
|
loadPendingDeposits,
|
|
11813
12637
|
loadPendingWithdrawals,
|
|
11814
12638
|
loadVerifiedCircuitArtifacts,
|
|
11815
12639
|
matchChangeNote,
|
|
11816
12640
|
matchDepositNote,
|
|
11817
12641
|
matchSwapRefundLeaf,
|
|
12642
|
+
mayRetry,
|
|
11818
12643
|
openRecipientDeliveryNote,
|
|
11819
12644
|
parseAmount,
|
|
11820
12645
|
parseDeliveryCarrierMemo,
|
|
@@ -11837,11 +12662,14 @@ var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
|
11837
12662
|
randomDepositNoteSalt,
|
|
11838
12663
|
randomFieldElement,
|
|
11839
12664
|
readMerkleTreeState,
|
|
12665
|
+
readRent,
|
|
11840
12666
|
recipientDeliveryNoteToBase64,
|
|
11841
12667
|
registerViewingKey,
|
|
11842
12668
|
removePendingDeposit,
|
|
11843
12669
|
removePendingWithdrawal,
|
|
12670
|
+
renderAssessment,
|
|
11844
12671
|
resolveCircuitsBase,
|
|
12672
|
+
retryDelayMs,
|
|
11845
12673
|
savePendingDeposit,
|
|
11846
12674
|
savePendingWithdrawal,
|
|
11847
12675
|
scanNotesForWallet,
|
|
@@ -11874,13 +12702,17 @@ var SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
|
11874
12702
|
validateDepositParams,
|
|
11875
12703
|
validateNote,
|
|
11876
12704
|
validateOutputsSum,
|
|
12705
|
+
validatePaymasterTopUpTransaction,
|
|
11877
12706
|
validateRoot,
|
|
11878
12707
|
validateTransfers,
|
|
11879
12708
|
validateWalletConnected,
|
|
11880
12709
|
validateWithdrawableNote,
|
|
11881
12710
|
verifyAllCircuits,
|
|
11882
12711
|
verifyCircuitIntegrity,
|
|
12712
|
+
verifyQuoteSignature,
|
|
11883
12713
|
verifyUtxos,
|
|
11884
12714
|
waitForRoot,
|
|
11885
|
-
|
|
12715
|
+
withShieldRetries,
|
|
12716
|
+
withTiming,
|
|
12717
|
+
withdrawFeeFor
|
|
11886
12718
|
});
|