@cloak.dev/sdk 0.2.3-staging.f2d7f2a → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +15 -847
- package/dist/index.d.cts +1 -678
- package/dist/index.d.ts +1 -678
- package/dist/index.js +14 -832
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -4714,683 +4714,6 @@ declare class SimpleWallet {
|
|
|
4714
4714
|
sync(): Promise<void>;
|
|
4715
4715
|
}
|
|
4716
4716
|
|
|
4717
|
-
/**
|
|
4718
|
-
* What a quote option attests, which is NOT the same question as whether the rail worked.
|
|
4719
|
-
*
|
|
4720
|
-
* Mirrors the service's `rails::Attestation` enum field-for-field (`services/api/bridge/src/rails/
|
|
4721
|
-
* mod.rs`) rather than collapsing it into a boolean: 1Click signs the deposit address AND the
|
|
4722
|
-
* recipient, so a substituted address is detectable by the client even if the service substituted
|
|
4723
|
-
* it. Jupiter signs nothing, so on that rail the user is trusting Cloak — and a UI reading this
|
|
4724
|
-
* union is forced to say so, where a UI reading a boolean could quietly treat both the same.
|
|
4725
|
-
*/
|
|
4726
|
-
type BridgeRailAttestation = {
|
|
4727
|
-
kind: "ed25519";
|
|
4728
|
-
verified: boolean;
|
|
4729
|
-
signer: string;
|
|
4730
|
-
} | {
|
|
4731
|
-
kind: "none";
|
|
4732
|
-
checks: string[];
|
|
4733
|
-
note: string;
|
|
4734
|
-
};
|
|
4735
|
-
interface BridgeRailQuoteOption {
|
|
4736
|
-
/** `"oneclick" | "jupiter"` today; typed as `string` so a new rail the service adds is not a
|
|
4737
|
-
* compile error here — the attestation union is what a caller must actually branch on. */
|
|
4738
|
-
rail: string;
|
|
4739
|
-
/** False means a mis-sent or under-filled transfer has NO automated recovery on this rail. */
|
|
4740
|
-
refunds: boolean;
|
|
4741
|
-
/** Whether `depositAddress` is reusable, or fresh per order and expiring. */
|
|
4742
|
-
addressLifetime: string;
|
|
4743
|
-
/** What the rail expects to deliver. NOT a promise — never display this alone. */
|
|
4744
|
-
amountOut: bigint;
|
|
4745
|
-
/** The floor the rail commits to. This is the number a UI should lead with. */
|
|
4746
|
-
minAmountOut: bigint;
|
|
4747
|
-
timeEstimateSeconds?: number;
|
|
4748
|
-
/** The rail's own expiry, when it returns one. Do not invent a value it attests to. */
|
|
4749
|
-
expiresAt?: string;
|
|
4750
|
-
/** Where the user sends funds on the origin chain. Absent on a dry quote (`allocate: false`),
|
|
4751
|
-
* where nothing has been reserved and there is nothing to send to yet. */
|
|
4752
|
-
depositAddress?: string;
|
|
4753
|
-
attestation: BridgeRailAttestation;
|
|
4754
|
-
}
|
|
4755
|
-
interface BridgeRailProblem {
|
|
4756
|
-
rail: string;
|
|
4757
|
-
reason: string;
|
|
4758
|
-
}
|
|
4759
|
-
interface BridgeRailQuoteRequest {
|
|
4760
|
-
/** The derived receiving address R. Base58, on Solana. */
|
|
4761
|
-
recipient: string;
|
|
4762
|
-
originChain: string;
|
|
4763
|
-
/** Base units on the origin chain, as a bigint — a JS `number` loses precision above 2^53 and
|
|
4764
|
-
* this can be an arbitrary token amount. */
|
|
4765
|
-
amountBaseUnits: bigint;
|
|
4766
|
-
/** Origin-chain address an unfillable 1Click order refunds to. Required for that rail. */
|
|
4767
|
-
refundTo?: string;
|
|
4768
|
-
rails?: string[];
|
|
4769
|
-
/** False (the default) sends `dry: true` to 1Click and skips GUM's allocation probes: nothing is
|
|
4770
|
-
* reserved and no `depositAddress` comes back. Requesting an allocation for a deposit the quote
|
|
4771
|
-
* gate might still refuse is the wrong order of operations — leave this false until the caller
|
|
4772
|
-
* has already decided to proceed. */
|
|
4773
|
-
allocate?: boolean;
|
|
4774
|
-
}
|
|
4775
|
-
interface BridgeRailQuoteResponse {
|
|
4776
|
-
options: BridgeRailQuoteOption[];
|
|
4777
|
-
/** Errors from rails that failed, so one rail being down does not hide the other's answer. */
|
|
4778
|
-
unavailable: BridgeRailProblem[];
|
|
4779
|
-
}
|
|
4780
|
-
/**
|
|
4781
|
-
* Mirrors the service's `api::status::DeliveryState` (`services/api/bridge/src/api/status.rs`),
|
|
4782
|
-
* `snake_case` on the wire and identical here. `"unknown"` is a real answer, not a parse failure:
|
|
4783
|
-
* Jupiter/GUM hands out permanent deposit addresses and has no per-transfer status API, so on
|
|
4784
|
-
* that rail the service ALWAYS answers `"unknown"` and says so in `detail` — poll the recipient's
|
|
4785
|
-
* on-chain balance instead. `"expired"` is derived by the service from the order deadline, not a
|
|
4786
|
-
* value 1Click returns.
|
|
4787
|
-
*/
|
|
4788
|
-
type BridgeDeliveryState = "pending" | "delivered" | "refunded" | "expired" | "unknown";
|
|
4789
|
-
interface BridgeRailStatusResult {
|
|
4790
|
-
/** The rail that answered, echoed from the service. */
|
|
4791
|
-
rail: string;
|
|
4792
|
-
state: BridgeDeliveryState;
|
|
4793
|
-
/** The service's own explanation of `state`, e.g. why a `"jupiter"` query is `"unknown"`. */
|
|
4794
|
-
detail: string;
|
|
4795
|
-
}
|
|
4796
|
-
interface BridgeRail {
|
|
4797
|
-
readonly id: string;
|
|
4798
|
-
quote(req: BridgeRailQuoteRequest): Promise<BridgeRailQuoteResponse>;
|
|
4799
|
-
/**
|
|
4800
|
-
* `rail` is the `rail` of the quote option whose `depositAddress` this is: the service keys its
|
|
4801
|
-
* status lookup on (address, rail) because the two rails have unrelated status surfaces.
|
|
4802
|
-
*/
|
|
4803
|
-
status(depositAddress: string, rail: string): Promise<BridgeRailStatusResult>;
|
|
4804
|
-
}
|
|
4805
|
-
/**
|
|
4806
|
-
* The one constructor this package exposes for talking to the bridge rails — always through
|
|
4807
|
-
* Cloak's own service, never through a rail's API or Kora.
|
|
4808
|
-
*
|
|
4809
|
-
* `relayUrl` is checked HERE, at construction, in addition to the check `relayFetch` repeats on
|
|
4810
|
-
* every call: a caller who mistypes a rail's own base URL (or Kora's) finds out immediately rather
|
|
4811
|
-
* than on first use, and `assertAllowedRelayOrigin` in this function's own body is what lets
|
|
4812
|
-
* `relay-origin-lock.test.ts` enumerate this door the same way it enumerates `RelayService`'s
|
|
4813
|
-
* constructor.
|
|
4814
|
-
*/
|
|
4815
|
-
declare function cloakBridgeRail(relayUrl: string): BridgeRail;
|
|
4816
|
-
|
|
4817
|
-
/**
|
|
4818
|
-
* The paymaster client — the SOL top-up that lets a bridge receiver R (which arrives holding only
|
|
4819
|
-
* bridged tokens, no SOL) shield without the user's own wallet ever appearing on chain.
|
|
4820
|
-
*
|
|
4821
|
-
* Talks ONLY to Cloak's own bridge service (`api.cloak.ag/bridge/paymaster/*`), never to Kora
|
|
4822
|
-
* directly: under fixed pricing (docs/00-DECISION-STATE.md, PAYMASTER ECONOMICS) the Kora API key is
|
|
4823
|
-
* worth real money to whoever holds it, and a browser bundle is not a place that can keep a secret.
|
|
4824
|
-
*
|
|
4825
|
-
* ── The two-round-trip shape, and why it is not one call ─────────────────────────────────────
|
|
4826
|
-
* `prepare` returns an UNSIGNED transaction the service built and priced, plus a voucher that MACs
|
|
4827
|
-
* the exact message bytes. The client's receiving key R signs it — R never leaves the client, and
|
|
4828
|
-
* this is the only place it signs anything for the paymaster flow — and hands the bytes back
|
|
4829
|
-
* unchanged to `cosign`, which recognises them via the voucher and only THEN asks Kora to co-sign as
|
|
4830
|
-
* fee payer. The paymaster's key never leaves the server; R's key never leaves the client; neither
|
|
4831
|
-
* round trip needs the other's secret. See `services/api/bridge/src/api/paymaster.rs` for the
|
|
4832
|
-
* server half of this contract.
|
|
4833
|
-
*
|
|
4834
|
-
* ── Why the shape check below is not optional ────────────────────────────────────────────────
|
|
4835
|
-
* `cosign` answers exactly one question — "is this the message I built?" — and answers it by MAC,
|
|
4836
|
-
* not by re-deriving policy from an arbitrary transaction. That makes `prepare`'s response the ONLY
|
|
4837
|
-
* point where an unexpected instruction could sneak in (a compromised service, a MITM'd response, a
|
|
4838
|
-
* bug that built the wrong thing), because nothing downstream re-checks it. `validate
|
|
4839
|
-
* PaymasterTopUpTransaction` is that one check, and it runs BEFORE R signs anything: signing is the
|
|
4840
|
-
* one irreversible step in this flow from the client's point of view, so the check that matters has
|
|
4841
|
-
* to sit in front of it, not after.
|
|
4842
|
-
*/
|
|
4843
|
-
|
|
4844
|
-
/** What `prepare`'s response is checked against before R ever signs it. */
|
|
4845
|
-
interface PaymasterTopUpExpectation {
|
|
4846
|
-
/** R — the only account this transaction may fund or spend from. */
|
|
4847
|
-
recipient: PublicKey;
|
|
4848
|
-
/** The lamports we asked for. `ix0.lamports` may come in at or under this, never over. */
|
|
4849
|
-
maxGrantLamports: bigint;
|
|
4850
|
-
feeMint: PublicKey;
|
|
4851
|
-
/** The fee Kora actually quoted at `prepare` time. `ix1.amount`, if `ix1` exists, must equal this
|
|
4852
|
-
* exactly — not "at most", because the fee is a quote the service already committed to, not a
|
|
4853
|
-
* ceiling. */
|
|
4854
|
-
feeTokenAmount: bigint;
|
|
4855
|
-
/** The paymaster's own token account owner, from `prepare`'s `payment_address`. `ix1`'s
|
|
4856
|
-
* destination must be exactly THIS address's ATA for `feeMint` — nothing else, and never an ATA
|
|
4857
|
-
* derived from `recipient` or from an address the caller does not already trust. */
|
|
4858
|
-
paymentAddress: PublicKey;
|
|
4859
|
-
}
|
|
4860
|
-
/**
|
|
4861
|
-
* The one check standing between `prepare`'s response and R's signature.
|
|
4862
|
-
*
|
|
4863
|
-
* Two instructions, and the shape IS the security story (`paymaster/topup.rs`'s own words, mirrored
|
|
4864
|
-
* here on the verifying side):
|
|
4865
|
-
*
|
|
4866
|
-
* ix0 System transfer, paymaster -> recipient, <= the lamports we asked for
|
|
4867
|
-
* ix1 (optional) SPL transfer, recipient's fee-mint ATA -> paymaster's fee-mint ATA, authority
|
|
4868
|
-
* = recipient, amount == the quoted fee
|
|
4869
|
-
*
|
|
4870
|
-
* Anything else — a third instruction, a different destination, a different authority, an amount
|
|
4871
|
-
* that does not match the quote — is refused. This function throws rather than returning a verdict:
|
|
4872
|
-
* there is no partial-trust path here, and a caller that wants to keep going after a refusal is a
|
|
4873
|
-
* caller papering over a corrupted or hostile response.
|
|
4874
|
-
*/
|
|
4875
|
-
declare function validatePaymasterTopUpTransaction(tx: Transaction, expect: PaymasterTopUpExpectation): void;
|
|
4876
|
-
interface PaymasterTopUpResult {
|
|
4877
|
-
/** Fully signed by both R and the paymaster. The caller submits it — Kora's own
|
|
4878
|
-
* `signAndSendTransaction` is disabled service-side, and the broadcast should not carry the
|
|
4879
|
-
* service's IP any more than the deposit itself should carry R's. */
|
|
4880
|
-
transaction: Transaction;
|
|
4881
|
-
feeTokenAmount: bigint;
|
|
4882
|
-
feeMint: string;
|
|
4883
|
-
paymentAddress: string;
|
|
4884
|
-
}
|
|
4885
|
-
/**
|
|
4886
|
-
* The whole paymaster flow: prepare, verify the shape, sign as R, cosign, return the fully-signed
|
|
4887
|
-
* transaction for the caller to submit.
|
|
4888
|
-
*
|
|
4889
|
-
* `receiver` is the derived bridge receiving key (`deriveBridgeReceiver`). It signs here and only
|
|
4890
|
-
* here in this file's flow, and its secret never leaves this function — nothing above needs it, and
|
|
4891
|
-
* nothing here sends it anywhere.
|
|
4892
|
-
*/
|
|
4893
|
-
declare function fundReceiverViaPaymaster(relayUrl: string, receiver: Keypair, grantLamports: bigint): Promise<PaymasterTopUpResult>;
|
|
4894
|
-
|
|
4895
|
-
/**
|
|
4896
|
-
* Deriving a bridge receiving address.
|
|
4897
|
-
*
|
|
4898
|
-
* One single-use address per deposit, from the wallet's own key material. Deterministic, offline,
|
|
4899
|
-
* and stateless — which is what lets every other function here work on a device that has never
|
|
4900
|
-
* seen this deposit before.
|
|
4901
|
-
*/
|
|
4902
|
-
|
|
4903
|
-
declare const BRIDGE_ESCROW_LABEL = "cloak_bridge_escrow";
|
|
4904
|
-
/**
|
|
4905
|
-
* The index MUST be a small sequential counter (0, 1, 2, …), never a timestamp.
|
|
4906
|
-
*
|
|
4907
|
-
* This is not a style preference: discovery works by deriving indices 0…N and reading each on
|
|
4908
|
-
* chain. A timestamp index is unreachable by any scan, so a deposit made under one is invisible to
|
|
4909
|
-
* every device except the one that made it — which is precisely the failure that made a resume
|
|
4910
|
-
* link look necessary. The prototype harness used `Date.now()` for test hermeticity and those
|
|
4911
|
-
* deposits are, correctly, undiscoverable.
|
|
4912
|
-
*/
|
|
4913
|
-
/**
|
|
4914
|
-
* The largest index discovery could plausibly reach. A scan is one round of on-chain reads per
|
|
4915
|
-
* index, so anything past a few thousand is not recoverable in practice — and a timestamp (~1.8e12)
|
|
4916
|
-
* is not recoverable even in principle. Rejecting it here is the difference between the constraint
|
|
4917
|
-
* being documented and it being enforced.
|
|
4918
|
-
*/
|
|
4919
|
-
declare const MAX_RECEIVER_INDEX = 10000;
|
|
4920
|
-
declare function deriveBridgeReceiver(nk: Uint8Array | Buffer, index: number): Keypair;
|
|
4921
|
-
|
|
4922
|
-
/**
|
|
4923
|
-
* Finding a user's bridge deposits from their key material alone.
|
|
4924
|
-
*
|
|
4925
|
-
* THIS IS THE FUNCTION THAT MAKES THE BRIDGE AN SDK CAPABILITY RATHER THAN A WEB FEATURE.
|
|
4926
|
-
*
|
|
4927
|
-
* Derive receivers for index 0…N and read each on chain. No stored state, no link to carry, no
|
|
4928
|
-
* localStorage. It works on a device that has never seen the app, in a CLI, on mobile, after a
|
|
4929
|
-
* browser wipe. An earlier design proposed a shareable URL to carry the deposit index to a second
|
|
4930
|
-
* device; the index does not need carrying, it needs scanning, and the link it replaced was a
|
|
4931
|
-
* packaged correlation between an origin payment and a Solana address about to enter the pool.
|
|
4932
|
-
*/
|
|
4933
|
-
|
|
4934
|
-
type BridgeDepositState =
|
|
4935
|
-
/** Nothing ever happened at this index. */
|
|
4936
|
-
"unused"
|
|
4937
|
-
/** Funded for a deposit, but no tokens have arrived. */
|
|
4938
|
-
| "awaiting"
|
|
4939
|
-
/** Tokens are sitting at the receiver, in the open, not yet shielded. */
|
|
4940
|
-
| "arrived"
|
|
4941
|
-
/** Shielded, and the receiver's token account has been closed. */
|
|
4942
|
-
| "complete"
|
|
4943
|
-
/** Shielded, but the token account is still open and holding its rent. */
|
|
4944
|
-
| "needs-cleanup"
|
|
4945
|
-
/**
|
|
4946
|
-
* An RPC read failed while checking this index. This is NOT evidence of absence — it is the
|
|
4947
|
-
* opposite of "unused" in every way that matters to a caller: a rate-limited or dropped read
|
|
4948
|
-
* used to fall back to a zero/empty default, which reported a real deposit's index as nothing-
|
|
4949
|
-
* here, indistinguishable from the index truly never having been touched. A user reading that
|
|
4950
|
-
* concludes their money is gone. `error` on the deposit explains what failed; the fix is to
|
|
4951
|
-
* retry, not to trust this entry's tokenBalance/lamports, which are placeholders.
|
|
4952
|
-
*/
|
|
4953
|
-
| "unknown";
|
|
4954
|
-
interface BridgeDeposit {
|
|
4955
|
-
index: number;
|
|
4956
|
-
receiver: PublicKey;
|
|
4957
|
-
tokenAccount: PublicKey;
|
|
4958
|
-
state: BridgeDepositState;
|
|
4959
|
-
/** Placeholder 0n when state is "unknown" — the read that would have set this failed. */
|
|
4960
|
-
tokenBalance: bigint;
|
|
4961
|
-
/** Placeholder 0 when state is "unknown" — the read that would have set this failed. */
|
|
4962
|
-
lamports: number;
|
|
4963
|
-
/** Signature of the shield-pool transaction, when one was found. Most recent, if more than one — see indexReused. */
|
|
4964
|
-
shieldSignature?: string;
|
|
4965
|
-
/**
|
|
4966
|
-
* True when this receiver's own history holds more than one shield-pool transaction: this index
|
|
4967
|
-
* was used for more than one deposit. Two deposits at the same index share one on-chain address,
|
|
4968
|
-
* which links them to each other, and `shieldSignature` alone would silently pick one and hide
|
|
4969
|
-
* that a second one exists. A caller MUST warn the user instead of treating this as a single
|
|
4970
|
-
* ordinary deposit.
|
|
4971
|
-
*/
|
|
4972
|
-
indexReused?: boolean;
|
|
4973
|
-
/** Every shield-pool signature found at this receiver, most recent first. Present only when indexReused. */
|
|
4974
|
-
shieldSignatures?: string[];
|
|
4975
|
-
/** Set only when state is "unknown": the failure that made this index's status unconfirmable. */
|
|
4976
|
-
error?: string;
|
|
4977
|
-
}
|
|
4978
|
-
interface DiscoverOptions {
|
|
4979
|
-
/**
|
|
4980
|
-
* How many indices to derive, starting at 0. Discovery is one to a few on-chain reads per index,
|
|
4981
|
-
* so this bounds the cost of a scan — it is NOT a claim about where deposits can live. An index
|
|
4982
|
-
* can be as large as MAX_RECEIVER_INDEX (10,000, see ./derive), and the default of 20 only covers
|
|
4983
|
-
* indices allocated sequentially with the stopAfterUnused gap tolerance below. A caller with
|
|
4984
|
-
* reason to believe a deposit landed further out (a CLI --index flag, a resumed session that
|
|
4985
|
-
* knows its own counter) MUST pass a larger scanDepth explicitly — anything past the configured
|
|
4986
|
-
* depth is simply never read, and reports as neither found nor absent, because it was not looked
|
|
4987
|
-
* at. Clamped to MAX_RECEIVER_INDEX + 1 (the count of valid indices, 0 through MAX_RECEIVER_INDEX
|
|
4988
|
-
* inclusive): deriveBridgeReceiver throws past that ceiling, and without the clamp a caller who
|
|
4989
|
-
* over-estimates scanDepth turns that into a mid-scan crash that discards every deposit already
|
|
4990
|
-
* found in the same call.
|
|
4991
|
-
*/
|
|
4992
|
-
scanDepth?: number;
|
|
4993
|
-
/** Stop after this many consecutive unused indices. An "unknown" index (RPC failure) neither
|
|
4994
|
-
* counts toward nor resets this run — it carries no information about presence or absence, so
|
|
4995
|
-
* letting it break a real run of unused indices early would reintroduce the same false-absence
|
|
4996
|
-
* failure this file exists to prevent. */
|
|
4997
|
-
stopAfterUnused?: number;
|
|
4998
|
-
programId: PublicKey;
|
|
4999
|
-
mint: PublicKey;
|
|
5000
|
-
}
|
|
5001
|
-
/**
|
|
5002
|
-
* A terminal state needs TWO conjuncts, never one.
|
|
5003
|
-
*
|
|
5004
|
-
* After the rent cleanup runs, "the receiver's token balance is zero" is indistinguishable from
|
|
5005
|
-
* "nothing ever happened at this address". Deriving completion from balance alone overwrites a
|
|
5006
|
-
* real completion record with an empty one — observed live, and it crashed the view that read it.
|
|
5007
|
-
* Completion therefore requires the shield-pool transaction to be present in the receiver's own
|
|
5008
|
-
* history as well.
|
|
5009
|
-
*/
|
|
5010
|
-
declare function listBridgeDeposits(conn: Connection, nk: Uint8Array | Buffer, opts: DiscoverOptions): Promise<BridgeDeposit[]>;
|
|
5011
|
-
|
|
5012
|
-
/**
|
|
5013
|
-
* The client half of a bridge deposit, from "tokens have arrived at R" onwards.
|
|
5014
|
-
*
|
|
5015
|
-
* This module is deliberately RAIL-AGNOSTIC. It is imported unchanged by:
|
|
5016
|
-
* - phase1-deposit.ts, where a seeded account plays the rail with a direct SPL transfer
|
|
5017
|
-
* - phase2-e2e.ts, where the rail stand-in delivers over HTTP
|
|
5018
|
-
* - phase3-e2e.ts, where a real Polygon fork drives the whole thing
|
|
5019
|
-
*
|
|
5020
|
-
* That import graph IS the proof of 11-E2E-PLAN.md Phase 2's pass criterion — "the client code
|
|
5021
|
-
* from Phase 1 runs unchanged against the stand-in" — enforced structurally rather than by
|
|
5022
|
-
* eyeballing two copies.
|
|
5023
|
-
*
|
|
5024
|
-
* It was NOT true when first written: phase1-deposit.ts kept its own inline copy, and so never
|
|
5025
|
-
* received the CLEANUP_FEE_BUDGET fix that landed here and in funder.ts. A reviewer caught both
|
|
5026
|
-
* the stale copy and the false claim. Keep every phase importing this file; do not fork it.
|
|
5027
|
-
*/
|
|
5028
|
-
|
|
5029
|
-
interface DepositOutcome {
|
|
5030
|
-
signature: string;
|
|
5031
|
-
noteIndex: number;
|
|
5032
|
-
amount: bigint;
|
|
5033
|
-
txSize: number;
|
|
5034
|
-
rBefore: number;
|
|
5035
|
-
rAfter: number;
|
|
5036
|
-
rentExempt: boolean;
|
|
5037
|
-
/** The proof's two input nullifiers (zero-value padding for a pure deposit, but each one is a
|
|
5038
|
-
* genuine Poseidon hash over a random salt — NOT the literal zero sentinel the program treats
|
|
5039
|
-
* as "no PDA needed". See phase4-adversarial.ts case (c). */
|
|
5040
|
-
inputNullifiers: bigint[];
|
|
5041
|
-
/** The three program accounts the funding seam read off the built tx, and what it sent each —
|
|
5042
|
-
* 0 if the account already held enough. Exposed so a caller can independently verify their
|
|
5043
|
-
* on-chain state afterward, including after a thrown error (see `DepositError` below). */
|
|
5044
|
-
fundedAccounts: {
|
|
5045
|
-
name: string;
|
|
5046
|
-
address: string;
|
|
5047
|
-
lamportsSent: number;
|
|
5048
|
-
}[];
|
|
5049
|
-
}
|
|
5050
|
-
/** Thrown by `depositFromDerivedKey` in place of a bare `Error` whenever the funding seam ran
|
|
5051
|
-
* before the failure, so a caller can see exactly what already landed on chain despite the
|
|
5052
|
-
* overall deposit failing. `fundedAccounts` / `measuredSize` are `undefined` only if the seam
|
|
5053
|
-
* never ran at all (failure before signTransaction was called). */
|
|
5054
|
-
declare class DepositError extends Error {
|
|
5055
|
-
readonly fundedAccounts: DepositOutcome["fundedAccounts"];
|
|
5056
|
-
readonly measuredTxSize: number;
|
|
5057
|
-
constructor(message: string, fundedAccounts: DepositOutcome["fundedAccounts"], measuredTxSize: number);
|
|
5058
|
-
}
|
|
5059
|
-
/**
|
|
5060
|
-
* Fund R minimally, then deposit with R as the only signer.
|
|
5061
|
-
*
|
|
5062
|
-
* The funding seam is the SDK's `signTransaction`: by the time it is called the proof and the
|
|
5063
|
-
* relay's risk quote both exist, so the three program accounts are READ OFF the built
|
|
5064
|
-
* transaction rather than re-derived, and cannot drift from what the program will touch.
|
|
5065
|
-
*
|
|
5066
|
-
* `grantOverride` replaces the computed grant (rent floor + deposit fee + cleanup fee) with an
|
|
5067
|
-
* arbitrary lamport amount. Only phase4-adversarial.ts case (a) passes it, to reproduce the
|
|
5068
|
-
* "funded R with just its fee, not its floor" mistake deliberately; every other caller omits it
|
|
5069
|
-
* and gets the same grant this function has always sent.
|
|
5070
|
-
*/
|
|
5071
|
-
declare function depositFromDerivedKey(conn: Connection, R: Keypair, funder: Keypair, amount: bigint, log: ((s: string) => void) | undefined, grantOverride: number | undefined,
|
|
5072
|
-
/**
|
|
5073
|
-
* relayUrl, programId and mint are all REQUIRED — no default, for any of the three, on any
|
|
5074
|
-
* environment. They used to fall back to the module-level RELAY/PROGRAM/MINT constants above,
|
|
5075
|
-
* each evaluated once at import time, and that is exactly how a live mainnet deposit got built
|
|
5076
|
-
* against the local program id while the banner said api.cloak.ag: the default filled the hole
|
|
5077
|
-
* silently instead of the caller having to say so. There is nothing left to fall into.
|
|
5078
|
-
*/
|
|
5079
|
-
opts: {
|
|
5080
|
-
relayUrl: string;
|
|
5081
|
-
programId: PublicKey;
|
|
5082
|
-
mint: PublicKey;
|
|
5083
|
-
noteSpendKey: Uint8Array;
|
|
5084
|
-
}): Promise<DepositOutcome>;
|
|
5085
|
-
|
|
5086
|
-
/**
|
|
5087
|
-
* Recover the receiving address's token-account rent, even when someone has dusted it.
|
|
5088
|
-
*
|
|
5089
|
-
* THE PROBLEM (found by testing, docs/11-E2E-PLAN.md Phase 4): the rail creates R's token account
|
|
5090
|
-
* and pays its 2,039,280 rent. After the deposit that account is empty and closing it returns the
|
|
5091
|
-
* rent TO THE USER. But SPL Token refuses to close a non-empty account, and dust below the
|
|
5092
|
-
* program's 1,000,000-base-unit deposit minimum cannot be swept by re-depositing it — the program
|
|
5093
|
-
* correctly rejects it with DepositTooSmall. So one base unit from anyone permanently strands
|
|
5094
|
-
* about forty cents of somebody else's money, for free.
|
|
5095
|
-
*
|
|
5096
|
-
* THE FIX, in two parts. Dust that arrives BEFORE the deposit is not a problem at all: the deposit
|
|
5097
|
-
* shields R's whole balance, so it goes into the pool with everything else. The griefing only bites
|
|
5098
|
-
* when dust lands AFTER the deposit, and then the honest answer is to leave it.
|
|
5099
|
-
*
|
|
5100
|
-
* WHY LEAVE IT — this reverses an earlier decision, deliberately. Sweeping the dust to the user's
|
|
5101
|
-
* own wallet publishes `R -> user` on a public ledger, and R has just deposited into the shielded
|
|
5102
|
-
* pool. Anyone can join those two facts and learn that this user made that deposit. That is the
|
|
5103
|
-
* precise inference the pool exists to prevent, and it is the same leak that funding R from the
|
|
5104
|
-
* user's wallet used to cause at the other end of the flow — moved to the end, not removed. It is
|
|
5105
|
-
* not worth about twenty-two cents of rent. Sweeping to Cloak instead is not an option either:
|
|
5106
|
-
* capturing user funds off-chain is an off-chain fee, which the team rule forbids.
|
|
5107
|
-
*
|
|
5108
|
-
* So the default is privacy-first: close when empty, and when dusted, leave the account open and
|
|
5109
|
-
* say so. `dustDestination` lets a caller sweep anyway, with the linkage stated in its doc comment.
|
|
5110
|
-
* Burning stays out: dust can be up to 999,999 base units, and destroying a dollar to recover
|
|
5111
|
-
* twenty-two cents is a worse outcome than the griefing it answers.
|
|
5112
|
-
*/
|
|
5113
|
-
|
|
5114
|
-
interface CleanupResult {
|
|
5115
|
-
closed: boolean;
|
|
5116
|
-
dustSwept: bigint;
|
|
5117
|
-
rentReturned: number;
|
|
5118
|
-
destination: string | null;
|
|
5119
|
-
signature: string | null;
|
|
5120
|
-
note: string;
|
|
5121
|
-
}
|
|
5122
|
-
/**
|
|
5123
|
-
* @param dustDestination where post-deposit dust goes, if the caller wants it swept at all.
|
|
5124
|
-
* LEAVE IT UNDEFINED unless the user has been told the cost: any destination they control
|
|
5125
|
-
* publishes `R -> them` and deanonymises the deposit R just made. It is never Cloak's, because
|
|
5126
|
-
* capturing user funds off-chain would be an off-chain fee, which the team rule forbids.
|
|
5127
|
-
* Undefined means "close if empty, otherwise leave it alone and report it".
|
|
5128
|
-
* @param mint the shielded asset R was funded for. Defaults to mainnet USDC so a caller written
|
|
5129
|
-
* before this parameter existed keeps compiling and keeps recovering the same account it always
|
|
5130
|
-
* has; a bridge for any other asset MUST pass its own mint, since R's token account and the
|
|
5131
|
-
* dust sitting in it both belong to whatever mint the rail actually delivered, not to this
|
|
5132
|
-
* default.
|
|
5133
|
-
*/
|
|
5134
|
-
declare function cleanupReceivingAddress(conn: Connection, R: Keypair, dustDestination?: PublicKey, mint?: PublicKey): Promise<CleanupResult>;
|
|
5135
|
-
|
|
5136
|
-
/**
|
|
5137
|
-
* Local deposit funder for the bridge testbed.
|
|
5138
|
-
*
|
|
5139
|
-
* The bridge pays a derived address R that arrives with zero SOL, and the deposit takes its
|
|
5140
|
-
* account rent from R (`transact_spl/mod.rs:92` passes `payer_info` into `create_nullifier_pdas`).
|
|
5141
|
-
* But `create_pda_account_safe` (`utils/pda.rs:30-61`) ADOPTS an already-funded, System-owned,
|
|
5142
|
-
* zero-data account and transfers only the shortfall — so the rent can be paid straight to the
|
|
5143
|
-
* three PDAs in an earlier transaction, and R never touches it.
|
|
5144
|
-
*
|
|
5145
|
-
* That split is the whole point. Lamports parked at the nullifier and risk-nonce PDAs are
|
|
5146
|
-
* unrecoverable by ANYONE (no instruction in the program closes them), so flooding this funder
|
|
5147
|
-
* burns Cloak's SOL and earns an attacker nothing. Sending the same total to R instead would put
|
|
5148
|
-
* all of it in an account the requester can sweep in one instruction.
|
|
5149
|
-
*
|
|
5150
|
-
* WHAT SURVIVED THE PORT: the rent constants, the funding-target derivation, and the live rent
|
|
5151
|
-
* read. Everything that SUBMITTED a transaction stayed behind in the prototype — see the note at
|
|
5152
|
-
* the bottom of this file. The production funder is the paymaster, and it runs on a server.
|
|
5153
|
-
*/
|
|
5154
|
-
|
|
5155
|
-
/** Rent for a 0-byte System account. `utils/pda.rs:99` -> `minimum_balance(0)`. */
|
|
5156
|
-
declare const MAINNET_RENT_0 = 890880;
|
|
5157
|
-
/** Rent for a 1-byte account. `state/nullifier.rs:18` says `SIZE = 1`. */
|
|
5158
|
-
declare const MAINNET_RENT_1 = 897840;
|
|
5159
|
-
/**
|
|
5160
|
-
* R must be able to pay its own transaction fee. The SDK hard-codes
|
|
5161
|
-
* setComputeUnitPrice(100_000) over setComputeUnitLimit(1_200_000) with no caller lever
|
|
5162
|
-
* (`sdk/src/flows/transact.ts:2598-2599`), so a deposit that fits costs 5,000 + 120,000.
|
|
5163
|
-
* Funding R with the 20,000 an earlier draft assumed leaves it 105,000 short and every
|
|
5164
|
-
* deposit fails under load.
|
|
5165
|
-
*/
|
|
5166
|
-
declare const FEE_BUDGET = 130000;
|
|
5167
|
-
/**
|
|
5168
|
-
* A SECOND fee, for the cleanup transaction in which R closes its own token account and the
|
|
5169
|
-
* rail-paid 2,039,280 goes back to the user.
|
|
5170
|
-
*
|
|
5171
|
-
* MEASURED 2026-09-05: without it the close is impossible. Solana checks the fee payer's
|
|
5172
|
-
* rent-exemption after deducting the fee and BEFORE executing, so an R funded to exactly the
|
|
5173
|
-
* floor fails with "insufficient funds for rent" — even though the very transaction being
|
|
5174
|
-
* rejected would have credited it 2,039,280. Budgeting only the deposit's fee strands the
|
|
5175
|
-
* largest recoverable line in the whole flow.
|
|
5176
|
-
*/
|
|
5177
|
-
declare const CLEANUP_FEE_BUDGET = 5000;
|
|
5178
|
-
interface DepositRef {
|
|
5179
|
-
programId: PublicKey;
|
|
5180
|
-
mint: PublicKey;
|
|
5181
|
-
/** The two input nullifiers from the proof's public inputs. */
|
|
5182
|
-
nullifiers: [Uint8Array, Uint8Array];
|
|
5183
|
-
/** bind0 from the relay's signed risk quote; the risk-nonce PDA is derived from it. */
|
|
5184
|
-
bind0: Uint8Array;
|
|
5185
|
-
/** R — the derived receiving address that will sign the deposit. */
|
|
5186
|
-
depositor: PublicKey;
|
|
5187
|
-
}
|
|
5188
|
-
/** Mirrors relay `derive_addresses` (supplemental_alt.rs) and the program's own derivations. */
|
|
5189
|
-
declare function deriveFundingTargets(d: DepositRef): {
|
|
5190
|
-
pool: PublicKey;
|
|
5191
|
-
nullifier0: PublicKey;
|
|
5192
|
-
nullifier1: PublicKey;
|
|
5193
|
-
riskNonce: PublicKey;
|
|
5194
|
-
depositorAta: PublicKey;
|
|
5195
|
-
};
|
|
5196
|
-
interface RentRates {
|
|
5197
|
-
zero: number;
|
|
5198
|
-
one: number;
|
|
5199
|
-
}
|
|
5200
|
-
/** Read rent live. Never hard-code it: a local validator's rent sysvar is not authoritative. */
|
|
5201
|
-
declare function readRent(conn: Connection): Promise<RentRates>;
|
|
5202
|
-
interface FundingPlan {
|
|
5203
|
-
transfers: {
|
|
5204
|
-
to: PublicKey;
|
|
5205
|
-
lamports: number;
|
|
5206
|
-
why: string;
|
|
5207
|
-
}[];
|
|
5208
|
-
total: number;
|
|
5209
|
-
alreadyFunded: string[];
|
|
5210
|
-
rent: RentRates;
|
|
5211
|
-
warnings: string[];
|
|
5212
|
-
}
|
|
5213
|
-
|
|
5214
|
-
declare const ONECLICK_PUBKEY_B58 = "reYaWhvwu8Jzo3WUM3zhn6VrhuMEF4eADL17qtRVifc";
|
|
5215
|
-
/**
|
|
5216
|
-
* The exact string this rail signs over, exported so a second implementation can be checked against
|
|
5217
|
-
* it rather than reasoned about.
|
|
5218
|
-
*
|
|
5219
|
-
* A Rust twin of `stable()` has to reproduce JavaScript's key ordering and number formatting byte
|
|
5220
|
-
* for byte, and the two languages do not agree by default: `Object.keys().sort()` orders by UTF-16
|
|
5221
|
-
* code unit while Rust's `sort()` orders by UTF-8 byte. They coincide for ASCII and diverge above
|
|
5222
|
-
* it. This is the same class of bug as `canonicalJson` versus Rust's `keys.sort_unstable()` in the
|
|
5223
|
-
* relay-auth payload, and it fails in the worst direction: a verifier that rejects HONEST quotes
|
|
5224
|
-
* looks like a rail outage, and teaches whoever is on call to ignore it.
|
|
5225
|
-
*
|
|
5226
|
-
* So the cross-language test compares THIS string, not just the boolean verdict. Two verifiers can
|
|
5227
|
-
* agree on a signature by both being wrong in the same place; they cannot agree on the bytes by
|
|
5228
|
-
* accident.
|
|
5229
|
-
*/
|
|
5230
|
-
declare function canonicalPayloadString(resp: any): string;
|
|
5231
|
-
declare function verifyQuoteSignature(resp: any): {
|
|
5232
|
-
valid: boolean;
|
|
5233
|
-
reason?: string;
|
|
5234
|
-
};
|
|
5235
|
-
|
|
5236
|
-
/**
|
|
5237
|
-
* Deciding whether a bridge deposit can be honoured — BEFORE the user sends anything.
|
|
5238
|
-
*
|
|
5239
|
-
* WHY THIS EXISTS. Shielding on arrival is mandatory, not a choice: a user who bridges and then
|
|
5240
|
-
* sweeps unshielded has manufactured exactly the `receiver -> them` link the whole design removes.
|
|
5241
|
-
* But "mandatory" moves every failure from the user's account to ours. If someone sends 3 USDC and
|
|
5242
|
-
* the paymaster fee leaves less than the program's 1,000,000-base-unit floor, the shield CANNOT
|
|
5243
|
-
* happen — and under a mandatory model that is the product breaking its own promise, with the money
|
|
5244
|
-
* stranded unshielded at an address the user has never heard of.
|
|
5245
|
-
*
|
|
5246
|
-
* So the check belongs at quote time. The rule is the one the rail-signature check already
|
|
5247
|
-
* established: NEVER SHOW AN ADDRESS YOU CANNOT HONOUR. An unviable deposit is refused before the
|
|
5248
|
-
* deposit address is displayed, not diagnosed after the money has landed.
|
|
5249
|
-
*
|
|
5250
|
-
* All figures are worst-case, taken from the rail's guaranteed floor (`minAmountOut`), never its
|
|
5251
|
-
* target. A quote that only works at the target is a quote that fails on a bad day.
|
|
5252
|
-
*/
|
|
5253
|
-
/** programs/shield-pool/src/constants.rs:126 — enforced at transact_spl/deposit.rs:69. */
|
|
5254
|
-
declare const MIN_DEPOSIT_SPL_BASE_UNITS = 1000000n;
|
|
5255
|
-
/**
|
|
5256
|
-
* Live mainnet USDC PoolConfig at deploy time: a flat fee plus a proportional part, charged on
|
|
5257
|
-
* WITHDRAWAL. These are the program's DEFAULTS, not a live read — quote.ts has no RPC client, so it
|
|
5258
|
-
* cannot see a PoolConfig an admin has since changed. Treat this pair as a fallback only: it is
|
|
5259
|
-
* shown to a user as what it will cost to get their money out, and if the live config has moved,
|
|
5260
|
-
* this UNDERSTATES that cost. A caller that has already fetched PoolConfig should pass the real
|
|
5261
|
-
* figures through `BridgeQuoteInput.liveWithdrawFixedFee` / `liveWithdrawFeeBps` instead.
|
|
5262
|
-
*/
|
|
5263
|
-
declare const WITHDRAW_FIXED_FEE = 450000n;
|
|
5264
|
-
declare const WITHDRAW_FEE_BPS = 30n;
|
|
5265
|
-
/**
|
|
5266
|
-
* Below this, the fixed costs dominate: a deposit works, but most of it goes to fees.
|
|
5267
|
-
*
|
|
5268
|
-
* It is ADVISORY. `viable` is the hard gate; this only warns and asks for a second confirmation,
|
|
5269
|
-
* because it is the user's money and their call.
|
|
5270
|
-
*
|
|
5271
|
-
* WAS 20 USDC, derived from a 1.21 round trip when the paymaster charged $0.458 for something that
|
|
5272
|
-
* cost it $0.104. Fixed pricing took that to $0.150 on 2026-09-07 (docs/17-PAYMASTER-ECONOMICS.md),
|
|
5273
|
-
* the round trip fell to ~0.90, and leaving the constant alone would have warned people off
|
|
5274
|
-
* deposits that had become perfectly reasonable. If the paymaster fee moves again, recompute
|
|
5275
|
-
* FIXED_ROUND_TRIP rather than editing this number.
|
|
5276
|
-
*
|
|
5277
|
-
* 0.903 / a + 0.003 = 0.063 -> a = 15.05
|
|
5278
|
-
*/
|
|
5279
|
-
declare const ECONOMIC_MINIMUM: bigint;
|
|
5280
|
-
interface BridgeQuoteInput {
|
|
5281
|
-
/** What the user sends on the origin chain, in the destination asset's base units. */
|
|
5282
|
-
sent: bigint;
|
|
5283
|
-
/** The rail's GUARANTEED floor. Assess against this, never `amountOut`. */
|
|
5284
|
-
arrivesMin: bigint;
|
|
5285
|
-
/** The rail's target, for display only. */
|
|
5286
|
-
arrivesTarget: bigint;
|
|
5287
|
-
/** What the paymaster will charge to fund the receiver, buffered, in the same units. */
|
|
5288
|
-
paymasterFee: bigint;
|
|
5289
|
-
/**
|
|
5290
|
-
* Live PoolConfig withdraw-fee figures, when the caller has already fetched them on-chain.
|
|
5291
|
-
* Optional: omitting either falls back to the compile-time WITHDRAW_FIXED_FEE / WITHDRAW_FEE_BPS
|
|
5292
|
-
* constants above, which can be stale. quote.ts never fetches these itself — no RPC call belongs
|
|
5293
|
-
* in a pure quote assessment — so the live figures can only arrive this way.
|
|
5294
|
-
*/
|
|
5295
|
-
liveWithdrawFixedFee?: bigint;
|
|
5296
|
-
liveWithdrawFeeBps?: bigint;
|
|
5297
|
-
}
|
|
5298
|
-
interface BridgeQuoteAssessment extends BridgeQuoteInput {
|
|
5299
|
-
/** What actually lands shielded, worst case. This is the number to show the user. */
|
|
5300
|
-
shieldedMin: bigint;
|
|
5301
|
-
shieldedTarget: bigint;
|
|
5302
|
-
/** False means REFUSE: the shield is impossible, so the deposit must not be offered. */
|
|
5303
|
-
viable: boolean;
|
|
5304
|
-
/** False means warn: it will work, but the fixed costs dominate. */
|
|
5305
|
-
economic: boolean;
|
|
5306
|
-
/** What it would cost to take it out again, so "shielded" is not mistaken for "free to exit". */
|
|
5307
|
-
withdrawFee: bigint;
|
|
5308
|
-
/** Origin-to-recipient loss if they shielded and immediately withdrew, worst case. */
|
|
5309
|
-
roundTripCost: bigint;
|
|
5310
|
-
roundTripFraction: number;
|
|
5311
|
-
/** Human-readable, ordered most important first. Empty when everything is fine. */
|
|
5312
|
-
reasons: string[];
|
|
5313
|
-
}
|
|
5314
|
-
declare function withdrawFeeFor(amount: bigint): bigint;
|
|
5315
|
-
declare function assessBridgeQuote(q: BridgeQuoteInput): BridgeQuoteAssessment;
|
|
5316
|
-
/** The quote screen, as the user must see it BEFORE any address is shown. */
|
|
5317
|
-
declare function renderAssessment(a: BridgeQuoteAssessment): string;
|
|
5318
|
-
|
|
5319
|
-
/**
|
|
5320
|
-
* Deciding whether a failed shield attempt may be retried.
|
|
5321
|
-
*
|
|
5322
|
-
* This is the most dangerous decision in the flow and the least observable, because it only runs
|
|
5323
|
-
* when something has already gone wrong. Getting it wrong in either direction costs money:
|
|
5324
|
-
*
|
|
5325
|
-
* retry when the deposit actually landed -> a second proof and a second deposit fee, for a
|
|
5326
|
-
* deposit that already happened
|
|
5327
|
-
* refuse when it did not land -> the user is told their funds are unshielded and has
|
|
5328
|
-
* to re-run, which costs a re-run and nothing else
|
|
5329
|
-
*
|
|
5330
|
-
* The asymmetry is the whole design: an unnecessary stop is cheap, a wrongful retry is not. So
|
|
5331
|
-
* anything the evidence cannot explain resolves to "do not retry".
|
|
5332
|
-
*
|
|
5333
|
-
* It lives in the SDK rather than in a CLI script because the shield service will need exactly this
|
|
5334
|
-
* decision, and a second implementation of it would be a second way to lose track of the same money.
|
|
5335
|
-
* It is pure — no chain, no clock — so it can be tested exhaustively, which the CLI version never was.
|
|
5336
|
-
*/
|
|
5337
|
-
/**
|
|
5338
|
-
* Failures where retrying only burns another proof: the deposit cannot succeed as constructed, so
|
|
5339
|
-
* a second attempt fails identically and costs another fee to find out.
|
|
5340
|
-
*/
|
|
5341
|
-
declare const TERMINAL_FAILURE: RegExp;
|
|
5342
|
-
declare function isTerminalFailure(message: string): boolean;
|
|
5343
|
-
type PostFailureVerdict =
|
|
5344
|
-
/** The receiver's tokens are gone: the deposit transaction landed despite the error. */
|
|
5345
|
-
"landed"
|
|
5346
|
-
/** The balance is untouched: the deposit demonstrably did not consume it. Safe to retry. */
|
|
5347
|
-
| "did-not-land"
|
|
5348
|
-
/** The balance moved by an amount nothing here explains, or could not be read at all. */
|
|
5349
|
-
| "unknown";
|
|
5350
|
-
/**
|
|
5351
|
-
* What the receiver's token balance says about a deposit attempt that threw.
|
|
5352
|
-
*
|
|
5353
|
-
* The deposit transaction moves the receiver's ENTIRE `attempted` balance atomically with the rest
|
|
5354
|
-
* of its instructions, so the balance is a reliable witness: drained to zero means it landed,
|
|
5355
|
-
* unchanged means it did not. Anything else — a partial move, a fresh delivery mid-flight, an
|
|
5356
|
-
* unreadable account — is not something this can interpret, and guessing is exactly the mistake
|
|
5357
|
-
* this function exists to prevent.
|
|
5358
|
-
*
|
|
5359
|
-
* @param attempted what the receiver held when the attempt started
|
|
5360
|
-
* @param after what it holds now, or null if the balance could not be read
|
|
5361
|
-
*/
|
|
5362
|
-
declare function classifyPostFailure(attempted: bigint, after: bigint | null): PostFailureVerdict;
|
|
5363
|
-
/** Whether the loop may go again, given what the evidence says. */
|
|
5364
|
-
declare function mayRetry(verdict: PostFailureVerdict, message: string): boolean;
|
|
5365
|
-
/** Linear backoff. Deliberately not exponential: the failures seen here are relay and blockhash
|
|
5366
|
-
* timing, which clear in seconds, and a long tail just strands the user watching a terminal. */
|
|
5367
|
-
declare function retryDelayMs(attempt: number): number;
|
|
5368
|
-
/** Raised in place of the underlying error when the evidence says the deposit landed, or says
|
|
5369
|
-
* nothing this can interpret. The loop stops on it without claiming the funds are unshielded. */
|
|
5370
|
-
declare class DoNotRetry extends Error {
|
|
5371
|
-
constructor(message: string);
|
|
5372
|
-
}
|
|
5373
|
-
interface RetryHooks {
|
|
5374
|
-
/** Called before each wait, so a CLI can say what it is doing and a service can log it. */
|
|
5375
|
-
onRetry?: (attempt: number, delayMs: number, lastError: string) => void;
|
|
5376
|
-
/** Injectable so tests do not actually wait, and a service can use its own scheduler. */
|
|
5377
|
-
sleep?: (ms: number) => Promise<void>;
|
|
5378
|
-
attempts?: number;
|
|
5379
|
-
}
|
|
5380
|
-
/**
|
|
5381
|
-
* Run `attempt` until it succeeds or the evidence says stop.
|
|
5382
|
-
*
|
|
5383
|
-
* The loop is separated from what it runs so it can be tested against injected failures. Its
|
|
5384
|
-
* previous form lived inside a CLI script wired to mainnet constants, which meant the only way to
|
|
5385
|
-
* exercise it was to cause a real failure during a real deposit — so it never was exercised, across
|
|
5386
|
-
* two rounds of changes to it.
|
|
5387
|
-
*
|
|
5388
|
-
* `attempt` is expected to throw `DoNotRetry` when it has already checked chain state and found the
|
|
5389
|
-
* deposit landed, or found something it cannot explain. Everything else is judged by
|
|
5390
|
-
* `isTerminalFailure`.
|
|
5391
|
-
*/
|
|
5392
|
-
declare function withShieldRetries<T>(attempt: (attemptNo: number) => Promise<T>, hooks?: RetryHooks): Promise<T>;
|
|
5393
|
-
|
|
5394
4717
|
/**
|
|
5395
4718
|
* Cloak SDK - TypeScript SDK for Private Transactions on Solana
|
|
5396
4719
|
*
|
|
@@ -5401,4 +4724,4 @@ declare const VERSION = "0.2.3";
|
|
|
5401
4724
|
/** True when scanner supports TransactSwap (tag 1). Check this to verify the correct SDK bundle is loaded. */
|
|
5402
4725
|
declare const SCANNER_SUPPORTS_TRANSACT_SWAP = true;
|
|
5403
4726
|
|
|
5404
|
-
export {
|
|
4727
|
+
export { BUILD_ALLOWS_LOCAL_ENDPOINTS, type BuildRecipientDeliveryNotesParams, CHAIN_NOTE_SALT_BITS, CLOAK_PRODUCTION_RELAY_URL, CLOAK_PROGRAM_ID, type ChainNoteTxType, type CircuitVerificationResult, type CloakConfig, CloakError, type CloakKeyPair, type CloakNote, type CommitmentEntry, type CommitmentsResponse, type CompactChainNote, type ComplianceReport, type ComplianceTxType, type ConfirmSettlementParams, DEFAULT_CIRCUITS_URL, DEFAULT_TRANSACTION_CIRCUITS_URL, DELIVERY_MEMO_TAG, DELIVERY_REGISTRY_SEED, type DeliveredNote, type DepositInstructionParams, type DepositNoteSecrets, type DepositOptions, type DepositResult, type DepositStatus, type DiscoverSwapRefundsOptions, type DiscoveredSwapRefund, EXPECTED_CIRCUIT_HASHES, type EncryptedMetadataBundle, type EncryptedNote$1 as EncryptedNote, type ErrorCategory, type ExpandedSpendKey, type ExternalFeePayerAdapter, FIXED_FEE_LAMPORTS, type Groth16Proof, InsecureRandomnessError, LAMPORTS_PER_SOL, LocalStorageAdapter, type LogLevel, type Logger, MERKLE_TREE_HEIGHT, MIN_DEPOSIT_LAMPORTS, type MasterKey, type MatchChangeNoteParams, type MatchDepositNoteParams, type MatchSwapRefundLeafParams, type MaxLengthArray, MemoryStorageAdapter, type MerkleProof, type MerkleRootResponse, MerkleTree, NATIVE_SOL_MINT, type Network, type NoteData, type OnchainMerkleProof, type ParsedDeliveryCarrier, type PendingDeposit, type PendingWithdrawal, RECIPIENT_DELIVERY_CIPHERTEXT_LEN, RECIPIENT_DELIVERY_EPHEMERAL_PK_LEN, RECIPIENT_DELIVERY_NONCE_LEN, RECIPIENT_DELIVERY_NOTE_BYTES, RECIPIENT_DELIVERY_PLAINTEXT_LEN, RECIPIENT_DELIVERY_TAG_LEN, RELAY_ORIGIN_ALLOWLIST, REQUEST_AUTH_MAX_AGE_SECONDS, REQUEST_AUTH_MAX_FUTURE_SKEW_SECONDS, type RecipientDeliveryNote, type RecoveredChangeNote, type RecoveredChangeNoteRecord, type RecoveredDepositNote, type RecoveredDepositNoteRecord, type RecoveredSwapRefund, type RelayAuthPreimage, type RelayAuthSigner, RelayInternalError, RelayService, type RelaySubmissionResult, type RiskQuoteInstructionResponse, RootNotFoundError, SCANNER_SUPPORTS_TRANSACT_SWAP, SIGN_IN_MESSAGE, SanctionsQuoteError, type ScanOptions, type ScanRecipientDeliveryOptions, type ScanResult, type ScanSummary, type ScannedTransaction, type SettlementConnection, type SettlementContext, type SettlementStatus, type SettlementVerdict, SettlementVerificationError, ShieldPoolErrors, type ShieldPoolPDAs, SimpleWallet, type SpendKey, type StorageAdapter, type SubmitTransactToRelayArgs, type SwapOptions, type SwapParams, type SwapRefundAuthorization, type SwapResult, TRANSACTION_CIRCUITS_VERSION, TRANSACT_AUTH_FIELDS, TRANSACT_SWAP_AUTH_FIELDS, type TransactOptions, type TransactParams, type TransactRequestBodyParams, type TransactResult, type TransactionMetadata, type Transfer, type TransferOptions, type TransferResult, type TxStatus, type UserFriendlyError, type Utxo, UtxoAlreadySpentError, type EncryptedNote as UtxoEncryptedNote, type UtxoKeypair, type UtxoSwapParams, type UtxoSwapResult, UtxoWallet, VARIABLE_FEE_DENOMINATOR, VARIABLE_FEE_NUMERATOR, VARIABLE_FEE_RATE, VERSION, type VerifyUtxosResult, type ViewKey, type ViewingKeyPair, type WalletAdapter, type WalletUtxo, type WithdrawOptions, type WithdrawSubmissionResult, assertDirectSubmissionLanded, assertInputMints, assertTransactionCircuitIntegrity, bigintToBytes32$1 as bigintToBytes32, bigintToHex, buildMerkleTree, buildMerkleTreeFromChain, buildMerkleTreeFromRelay, buildRecipientDeliveryNotes, buildRelayAuthPreimage, buildTransactRequestBody, bytesToHex, calculateFee, calculateFeeBigint, calculateRelayFee, canRebuildMerkleTreeFromChain, canonicalJson, chainNoteFromBase64, chainNoteToBase64, classifyRelayError, cleanupStalePendingOperations, clearPendingDeposits, clearPendingWithdrawals, computeChainNoteHash, computeExtDataHash, computeMerkleRoot, computeProofForLatestDeposit, computeProofFromChain, computeSignature, computeSwapRefundCommitment, computeCommitment as computeUtxoCommitment, computeNullifier as computeUtxoNullifier, confirmTransactSettlement, copyNoteToClipboard, createCloakError, createDepositInstruction, createLogger, createRecoverableChangeUtxo, createRecoverableDepositUtxo, createUtxo, createZeroUtxo, decryptCompactChainNote, decryptComplianceMetadataWithMasterKey, decryptTransactionMetadata, deriveChangeNoteBlinding, deriveDepositNoteSecrets, deriveDiversifiedViewingKey, deriveDiversifier, deriveInputNullifierPdas, derivePublicKey, deriveSpendKey, deriveSwapRefundAuthorization, deriveUserCompliancePublicKey, deriveUserComplianceScalar, deriveUtxoKeypairFromSpendKey, deriveViewKey, deriveViewingKeyFromNk, deriveViewingKeyFromSpendKey, deriveViewingKeyFromUtxoPrivateKey, deserializeUtxo, detectNetworkFromRpcUrl, discoverSwapRefunds, downloadNote, encodeDeliveryCarrierMemo, encodeNoteSimple, encodeRecipientDeliveryNote, encryptCompactChainNote, encryptNoteForRecipient, encryptTransactionMetadata, encryptTransactionMetadataBundle, expandSpendKey, explainRelayAuthRejection, exportKeys, exportNote, exportWalletKeys, fetchCommitments, fetchRiskQuoteInstruction, fetchRiskQuoteIx, filterNotesByNetwork, filterWithdrawableNotes, findNoteByCommitment, formatAmount, formatComplianceCsv, formatErrorForLogging, formatSol, fullWithdraw, generateCloakKeys, generateCommitmentAsync, generateMasterSeed, generateNoteFromWallet, generateUtxoKeypair, generateViewingKeyPair, getAddressExplorerUrl, getChainNoteRegistryPDA, getCircuitsPath, getDeliveryRegistryPDA, getDistributableAmount, getExplorerUrl, getNkFromUtxoPrivateKey, getNullifierPDA, getPendingOperationsSummary, getPoolAuthorityConfigPDA, getPublicKey, getPublicViewKey, getRecipientAmount, getRpcUrlForNetwork, getShieldPoolPDAs, getSwapStatePDA, getViewKey, hasPendingOperations, hexToBigint$1 as hexToBigint, hexToBytes, importKeys, importWalletKeys, isBrowser, isBrowserLike, isDebugEnabled, isPlausibleSignature, isReactNative, isRootNotFoundError, isSubmissionOutcomeUnknownResponse, isValidHex, isValidRpcUrl, isValidSolanaAddress, isWithdrawAmountSufficient, isWithdrawable, keypairToAdapter, loadPendingDeposits, loadPendingWithdrawals, loadVerifiedCircuitArtifacts, matchChangeNote, matchDepositNote, matchSwapRefundLeaf, openRecipientDeliveryNote, parseAmount, parseDeliveryCarrierMemo, parseError, parseNote, parseRelayErrorResponse, parseRelayErrorSignature, parseTransactionError, partialWithdraw, poseidonHash, preflightCheck, preflightNullifiers, prepareEncryptedOutput, prepareEncryptedOutputForRecipient, proofToBytes, pubkeyToFieldElement, pubkeyToLimbs, randomBytes, randomChangeNoteSalt, randomDepositNoteSalt, randomFieldElement, readMerkleTreeState, recipientDeliveryNoteToBase64, registerViewingKey, removePendingDeposit, removePendingWithdrawal, resolveCircuitsBase, savePendingDeposit, savePendingWithdrawal, scanNotesForWallet, scanRecipientDeliveryNotes, scanTransactions, sdkLogger, selectUtxos, sendTransaction, serializeNote, serializeUtxo, setCircuitsPath, setDebugMode, signTransaction, splitTo2Limbs, submitTransactToRelay, sumUtxoAmounts, swapUtxo, swapWithChange, toComplianceReport, transact, transfer, truncate, tryDecryptNote, updateNoteWithDeposit, updatePendingDeposit, updatePendingWithdrawal, bigintToBytes32 as utxoBigintToBytes32, utxoEquals, hexToBigint as utxoHexToBigint, validateDepositParams, validateNote, validateOutputsSum, validateRoot, validateTransfers, validateWalletConnected, validateWithdrawableNote, verifyAllCircuits, verifyCircuitIntegrity, verifyUtxos, waitForRoot, withTiming };
|