@anywalletkit/extension-kit 0.3.6 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -7
- package/dist/index.cjs +814 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +467 -18
- package/dist/index.d.ts +467 -18
- package/dist/index.js +815 -55
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KeyringStorage, SecretStorage } from '@anywalletkit/keyring';
|
|
2
|
-
import { Quote, Swap2ExecutionPlan, CrossChainProvider,
|
|
2
|
+
import { Quote, QuoteParams, Swap2ExecutionPlan, CrossChainProvider, IntentStatus } from '@anywalletkit/protocol-swap2-core';
|
|
3
3
|
import { TonSignDataPayload } from '@anywalletkit/wallet-ton/tonconnect';
|
|
4
4
|
export { TONCONNECT_ERRORS, TONCONNECT_MAX_MESSAGES, TONCONNECT_NETWORKS, TONCONNECT_SIGN_DATA_MAX, TonConnectError, TonConnectMessage, TonConnectParseOptions, TonConnectRequest, TonConnectSendOptions, TonConnectSendTransaction, TonSignDataPayload, parseConnectRequest, parseSendTransaction, parseSignData, sameTonConnectAddress, tonConnectFriendlyAddress, tonConnectRawAddress } from '@anywalletkit/wallet-ton/tonconnect';
|
|
5
5
|
|
|
@@ -178,6 +178,14 @@ declare class Vault {
|
|
|
178
178
|
*/
|
|
179
179
|
unlock(password: string): Promise<Uint8Array>;
|
|
180
180
|
private _unlock;
|
|
181
|
+
/**
|
|
182
|
+
* A DEK unwrapped from a dek / passkey box must be the key this vault's secrets are sealed under
|
|
183
|
+
* (audit 2026-11-09 E21): a box spliced in from another vault, under another password or passkey,
|
|
184
|
+
* opens with that password but holds a foreign key. Proven with the DEK check, or — in an envelope
|
|
185
|
+
* written before it — the first secret; an old empty envelope has nothing to prove it with. Returns
|
|
186
|
+
* `dek`; on a mismatch zeroizes it and fails as `wrong-password` (the same failure as tampering).
|
|
187
|
+
*/
|
|
188
|
+
private _proveOwn;
|
|
181
189
|
/**
|
|
182
190
|
* Re-wrap the DEK under a new password (fresh salt, current KDF). Secrets and passkeys are untouched —
|
|
183
191
|
* and so is the DEK: after a suspected compromise (a copied profile, a leaked session, a lost passkey)
|
|
@@ -194,8 +202,11 @@ declare class Vault {
|
|
|
194
202
|
*
|
|
195
203
|
* Passkeys are dropped — their boxes hold the old DEK and cannot be re-wrapped without their PRF
|
|
196
204
|
* output — and must be registered again ({@link Vault.addPasskey} with the new DEK).
|
|
205
|
+
*
|
|
206
|
+
* With `newPassword` this is also the password change: the new DEK is wrapped under `newPassword`
|
|
207
|
+
* (at least {@link VAULT_MIN_PASSWORD_LENGTH} characters), and `password` must be the current one.
|
|
197
208
|
*/
|
|
198
|
-
rotateVaultKey(password: string): Promise<Uint8Array>;
|
|
209
|
+
rotateVaultKey(password: string, newPassword?: string): Promise<Uint8Array>;
|
|
199
210
|
/** Public view of the registered passkeys (ids, labels; whether each can verify assertions). */
|
|
200
211
|
listPasskeys(): Promise<Array<{
|
|
201
212
|
id: string;
|
|
@@ -321,10 +332,20 @@ declare class Session {
|
|
|
321
332
|
* a missed alarm cannot keep the key alive.
|
|
322
333
|
*/
|
|
323
334
|
getKey(): Promise<Uint8Array>;
|
|
324
|
-
/**
|
|
335
|
+
/**
|
|
336
|
+
* User activity: push the auto-lock out again. No-op when locked. Call it for explicit user
|
|
337
|
+
* gestures only (unlock, send, approve / decline, an action in the wallet's own UI) — not for
|
|
338
|
+
* passive polls, page requests or worker restarts, or the timer never runs out.
|
|
339
|
+
*/
|
|
325
340
|
touch(): Promise<void>;
|
|
326
341
|
get autoLockMs(): number;
|
|
327
|
-
/**
|
|
342
|
+
/**
|
|
343
|
+
* Set the timer period (0 disables). Never pushes the deadline out — call this at every worker
|
|
344
|
+
* start with the stored setting: it re-arms the alarm at the stored deadline (a restart must not
|
|
345
|
+
* count as activity, audit 2026-11-09 E11), and only brings the deadline forward when the new
|
|
346
|
+
* period ends sooner. A longer period (or 0) applies from the next {@link Session.touch} /
|
|
347
|
+
* {@link Session.unlock}; call `touch()` right after when the user changed it explicitly.
|
|
348
|
+
*/
|
|
328
349
|
setAutoLockMs(ms: number): Promise<void>;
|
|
329
350
|
onLock(callback: () => void): () => void;
|
|
330
351
|
private _serial;
|
|
@@ -587,6 +608,11 @@ declare class NetworksTable {
|
|
|
587
608
|
/** Cache first (readers see it at once), rolled back when storage refuses. */
|
|
588
609
|
private write;
|
|
589
610
|
private custom;
|
|
611
|
+
/**
|
|
612
|
+
* Forget the cached table: the next read asks storage again. For a storage whose answer changes under
|
|
613
|
+
* the table — e.g. one that only hands out the user's networks once the wallet is unlocked.
|
|
614
|
+
*/
|
|
615
|
+
reload(): Promise<void>;
|
|
590
616
|
}
|
|
591
617
|
/**
|
|
592
618
|
* EIP-3085 `wallet_addEthereumChain` parameter → {@link EvmNetwork}, or the error
|
|
@@ -664,12 +690,23 @@ declare class PermissionStore {
|
|
|
664
690
|
get(origin: string): Promise<OriginPermission | null>;
|
|
665
691
|
list(): Promise<OriginPermission[]>;
|
|
666
692
|
connect(origin: string, accounts: string[], chain: string): Promise<OriginPermission>;
|
|
693
|
+
/**
|
|
694
|
+
* Add EVM accounts to an origin's grant (per-site grants): the new ones first, the ones it already
|
|
695
|
+
* holds stay. The chain stays the origin's own when it has one. Used by the router's connect; `connect`
|
|
696
|
+
* replaces the list instead.
|
|
697
|
+
*/
|
|
698
|
+
grant(origin: string, accounts: string[], chain: string): Promise<OriginPermission>;
|
|
667
699
|
/** Connect another chain's accounts to the same origin (one "connected sites" list). */
|
|
668
700
|
connectChain(origin: string, key: ChainAccountsKey, accounts: string[], defaultChain: string): Promise<OriginPermission>;
|
|
669
701
|
/** Drop one chain's accounts; the origin stays connected while any chain remains. A no-op (no write) when there is nothing to drop. */
|
|
670
702
|
disconnectChain(origin: string, key: 'accounts' | ChainAccountsKey): Promise<void>;
|
|
671
703
|
setChain(origin: string, chain: string): Promise<OriginPermission | null>;
|
|
672
704
|
/**
|
|
705
|
+
* @deprecated Rewrites every origin's grant to the active account, which shows that account to sites
|
|
706
|
+
* the user never connected it to (and links accounts across sites). Grants are per site now: the
|
|
707
|
+
* router shows an origin its granted accounts that are also active, and connecting another account
|
|
708
|
+
* adds it to that one origin ({@link grant}). Kept for compatibility; nothing in this package calls it.
|
|
709
|
+
*
|
|
673
710
|
* The active EVM account changed: every origin holding an EVM grant now sees `accounts` (MetaMask behaviour).
|
|
674
711
|
* An origin connected only on another chain (`accounts: []` — Solana/TON/Tron/BTC/NEAR providers, a WalletConnect
|
|
675
712
|
* session without eip155) is skipped: it never passed an EVM connect and must not learn the EVM address (scan F6/F8).
|
|
@@ -708,6 +745,21 @@ declare class OriginRefused extends Error {
|
|
|
708
745
|
constructor(message: string);
|
|
709
746
|
}
|
|
710
747
|
declare const APPROVALS_MAX_PENDING_PER_ORIGIN = 3;
|
|
748
|
+
/** Requests one site (registrable domain: every subdomain counts) may have waiting. */
|
|
749
|
+
declare const APPROVALS_MAX_PENDING_PER_SITE = 5;
|
|
750
|
+
/** Requests the whole queue holds (exempt origins not counted). */
|
|
751
|
+
declare const APPROVALS_MAX_PENDING_TOTAL = 20;
|
|
752
|
+
/** How fast one site may open sheets: a token bucket per site; running dry refuses for a cooldown that doubles on every repeat. */
|
|
753
|
+
interface ApprovalRateOptions {
|
|
754
|
+
/** Sheets a site may open at once. Default 10. */
|
|
755
|
+
burst?: number;
|
|
756
|
+
/** Sheets per second a site earns back. Default 1/6 (10 a minute). */
|
|
757
|
+
refillPerSecond?: number;
|
|
758
|
+
/** First cooldown after the bucket ran dry. Default 30 s. */
|
|
759
|
+
backoffMs?: number;
|
|
760
|
+
/** Longest cooldown; also how long a site must stay quiet for its strikes to reset. Default 10 min. */
|
|
761
|
+
maxBackoffMs?: number;
|
|
762
|
+
}
|
|
711
763
|
interface ApprovalRequest<P = unknown> {
|
|
712
764
|
id: string;
|
|
713
765
|
origin: string;
|
|
@@ -732,6 +784,28 @@ interface ApprovalQueueOptions {
|
|
|
732
784
|
refuse?: (origin: string) => string | null | undefined;
|
|
733
785
|
/** Requests one origin may have waiting (current + queued). Default {@link APPROVALS_MAX_PENDING_PER_ORIGIN}. */
|
|
734
786
|
maxPendingPerOrigin?: number;
|
|
787
|
+
/** Requests one site may have waiting. Default {@link APPROVALS_MAX_PENDING_PER_SITE}. */
|
|
788
|
+
maxPendingPerSite?: number;
|
|
789
|
+
/** Requests the queue holds in all. Default {@link APPROVALS_MAX_PENDING_TOTAL}. */
|
|
790
|
+
maxPendingTotal?: number;
|
|
791
|
+
/** Origin → site for the per-site limits. Default {@link defaultSiteOf siteOf} (conservative eTLD+1; pass a Public Suffix List based one if you ship it). */
|
|
792
|
+
siteOf?: (origin: string) => string;
|
|
793
|
+
/** Origins that skip every limit (the wallet's own pages: Send, swaps). They still queue behind other requests. */
|
|
794
|
+
exempt?: (origin: string) => boolean;
|
|
795
|
+
/** Sheet-opening rate per site; `false` turns it off. */
|
|
796
|
+
openRate?: ApprovalRateOptions | false;
|
|
797
|
+
/** Clock (ms), injectable for tests. */
|
|
798
|
+
now?: () => number;
|
|
799
|
+
}
|
|
800
|
+
/** Options of one {@link ApprovalQueue.request}. */
|
|
801
|
+
interface ApprovalRequestOptions {
|
|
802
|
+
/**
|
|
803
|
+
* Another sheet for a request the user has just approved (the fee changed before signing). It skips
|
|
804
|
+
* the queue and rate limits and is shown ahead of the requests already waiting — once per approval
|
|
805
|
+
* of the same origin, kind and chain; with no such approval behind it, it is an ordinary request.
|
|
806
|
+
* `refuse` still applies.
|
|
807
|
+
*/
|
|
808
|
+
followUp?: boolean;
|
|
735
809
|
}
|
|
736
810
|
/** The window side: open for one request, close when it is answered. `memoryApprovalWindow()` for tests. */
|
|
737
811
|
interface ApprovalWindow {
|
|
@@ -748,15 +822,39 @@ declare class ApprovalQueue {
|
|
|
748
822
|
private readonly _waiting;
|
|
749
823
|
private readonly _listeners;
|
|
750
824
|
private readonly _via;
|
|
825
|
+
private readonly _rate;
|
|
826
|
+
/** Per site: cooldown end and strikes (how many times the bucket ran dry recently). */
|
|
827
|
+
private readonly _cooldown;
|
|
828
|
+
/** Per origin + kind + chain: approvals that have not been followed up (see {@link ApprovalRequestOptions.followUp}). */
|
|
829
|
+
private readonly _approved;
|
|
751
830
|
constructor(window: ApprovalWindow, newId?: () => string, options?: ApprovalQueueOptions);
|
|
831
|
+
private site;
|
|
832
|
+
private get all();
|
|
833
|
+
/** The per-site rate: a reason to refuse, or null (and one token spent). */
|
|
834
|
+
private rateRefusal;
|
|
835
|
+
private static followUpKey;
|
|
836
|
+
/** The user approved `r`: it may be followed up once. */
|
|
837
|
+
private approved;
|
|
838
|
+
/** Spends one approval of the same origin, kind and chain; false when there is none. */
|
|
839
|
+
private spendApproval;
|
|
752
840
|
/** Enqueue and wait for the user's answer. Refuses (never queues) past the per-origin limits. */
|
|
753
|
-
request<T = unknown>(input: Omit<ApprovalRequest, 'id' | 'createdAt' | 'originWarnings' | 'via'
|
|
841
|
+
request<T = unknown>(input: Omit<ApprovalRequest, 'id' | 'createdAt' | 'originWarnings' | 'via'>, opts?: ApprovalRequestOptions): Promise<T>;
|
|
754
842
|
/** Attach (or clear) the transport note every later request from `origin` carries. */
|
|
755
843
|
setVia(origin: string, via: OriginVia | null): void;
|
|
756
844
|
/** The transport note later requests from `origin` carry (WalletConnect Verify's verdict for `wc:<topic>`), if any. */
|
|
757
845
|
viaFor(origin: string): OriginVia | undefined;
|
|
846
|
+
private isExempt;
|
|
758
847
|
/** Requests waiting for `origin` (current + queued). */
|
|
759
848
|
pendingFor(origin: string): number;
|
|
849
|
+
/** Requests waiting for any origin of `site` (current + queued). */
|
|
850
|
+
pendingForSite(site: string): number;
|
|
851
|
+
/** The site (registrable domain) the queue's limits put `origin` under. */
|
|
852
|
+
siteFor(origin: string): string;
|
|
853
|
+
/** Decline everything waiting for `origin` (its last page closed). Returns how many requests were declined. */
|
|
854
|
+
declineOrigin(origin: string, error?: Error): number;
|
|
855
|
+
/** "Decline all from this site": everything waiting for any origin of `site` (see {@link siteFor}). */
|
|
856
|
+
declineSite(site: string, error?: Error): number;
|
|
857
|
+
private declineWhere;
|
|
760
858
|
/** The request currently shown (the window asks for it by id on load). */
|
|
761
859
|
get current(): ApprovalRequest | null;
|
|
762
860
|
get queued(): number;
|
|
@@ -797,6 +895,14 @@ interface RelayErrorOptions {
|
|
|
797
895
|
declare function toRelayError(e: unknown, options?: RelayErrorOptions): RelayError;
|
|
798
896
|
/** Read-only methods answered from our RPC without asking the user. */
|
|
799
897
|
declare const READ_METHODS: ReadonlySet<string>;
|
|
898
|
+
/**
|
|
899
|
+
* Blocks an `eth_getLogs` from an origin without an EVM grant may span. A page that is not connected
|
|
900
|
+
* reads recent events (a token's latest transfers, a pool's last swaps), not history: 1000 blocks is
|
|
901
|
+
* ~3.3 h on Ethereum and ~30 min on 2 s chains, and stays inside every public RPC's own range cap,
|
|
902
|
+
* so one call cannot make the wallet's RPC scan millions of blocks for a page nobody connected.
|
|
903
|
+
* Connected origins are not bounded here (the node's own limits apply).
|
|
904
|
+
*/
|
|
905
|
+
declare const GETLOGS_MAX_SPAN_UNCONNECTED = 1000;
|
|
800
906
|
/** Methods that produce a signature — the review flow's business (step 4), never answered here. */
|
|
801
907
|
declare const SIGNING_METHODS: ReadonlySet<string>;
|
|
802
908
|
interface ConnectApproval {
|
|
@@ -843,9 +949,12 @@ declare class RequestRouter {
|
|
|
843
949
|
handle(origin: string, chain: RelayChain, method: string, rawParams: unknown): Promise<unknown>;
|
|
844
950
|
/** What a connected origin sees right now: its permitted accounts that the wallet can expose (none while locked). */
|
|
845
951
|
private visibleAccounts;
|
|
952
|
+
/** An unconnected origin's `eth_getLogs`: a block hash, or a range of at most {@link GETLOGS_MAX_SPAN_UNCONNECTED} blocks. */
|
|
953
|
+
private boundLogs;
|
|
846
954
|
/**
|
|
847
955
|
* Connected and unlocked → the accounts; otherwise the approval window (which
|
|
848
|
-
* unlocks first when needed) picks them
|
|
956
|
+
* unlocks first when needed) picks them, and they are ADDED to this origin's
|
|
957
|
+
* grant (other origins are untouched). Emits `connect` + `accountsChanged`.
|
|
849
958
|
*/
|
|
850
959
|
private connect;
|
|
851
960
|
disconnect(origin: string): Promise<void>;
|
|
@@ -887,7 +996,22 @@ interface SiweInfo {
|
|
|
887
996
|
problems: string[];
|
|
888
997
|
/** The header said "sign-in" but the rest did not parse as EIP-4361 (`message` then holds what could be read). */
|
|
889
998
|
malformed?: boolean;
|
|
999
|
+
/**
|
|
1000
|
+
* Set when the sign-in names another site than the one asking (its host differs from the page's
|
|
1001
|
+
* host, or from a WalletConnect Verify-attested URL): `domain` as written in the message, `origin`
|
|
1002
|
+
* the asking site as `scheme://host`. A sheet should make this its headline, not one warning among many.
|
|
1003
|
+
*/
|
|
1004
|
+
crossSite?: {
|
|
1005
|
+
domain: string;
|
|
1006
|
+
origin: string;
|
|
1007
|
+
};
|
|
890
1008
|
}
|
|
1009
|
+
/**
|
|
1010
|
+
* Characters a sign-in message is refused for: bidi controls (ALM, LRM / RLM, embeddings, overrides,
|
|
1011
|
+
* isolates), zero-width space / joiners, word joiner and invisible operators, BOM — they can make the
|
|
1012
|
+
* domain or the statement read differently from the bytes that are signed.
|
|
1013
|
+
*/
|
|
1014
|
+
declare const SIWE_FORBIDDEN_CHARS: RegExp;
|
|
891
1015
|
interface SiweContext {
|
|
892
1016
|
/** The page that asked, as the browser recorded it (`https://…`), or a transport pseudo-origin (`wc:<topic>`). */
|
|
893
1017
|
origin: string;
|
|
@@ -905,6 +1029,15 @@ declare function parseSiwe(text: string): SiweMessage | null;
|
|
|
905
1029
|
declare function isLocalHost(host: string): boolean;
|
|
906
1030
|
/** The checks; `origin` is the page that asked (as the browser recorded it), `account` the signing address, `chainId` the site's chain. */
|
|
907
1031
|
declare function siweProblems(m: SiweMessage, ctx: SiweContext): string[];
|
|
1032
|
+
/**
|
|
1033
|
+
* The asking site when the sign-in names a different host: the browser-recorded origin, or for a
|
|
1034
|
+
* WalletConnect pseudo-origin the URL Verify attested (VALID, not scam). `null` when the hosts agree
|
|
1035
|
+
* or when no site can be vouched for at all (that case is a separate "cannot verify" problem).
|
|
1036
|
+
*/
|
|
1037
|
+
declare function siweCrossSite(m: SiweMessage, ctx: SiweContext): {
|
|
1038
|
+
domain: string;
|
|
1039
|
+
origin: string;
|
|
1040
|
+
} | null;
|
|
908
1041
|
/** `null` only when the text does not start with an EIP-4361 header; a header with unreadable fields comes back with a "malformed sign-in message" problem. */
|
|
909
1042
|
declare function describeSiwe(text: string, ctx: SiweContext): SiweInfo | null;
|
|
910
1043
|
|
|
@@ -930,7 +1063,10 @@ declare function describeSiwe(text: string, ctx: SiweContext): SiweInfo | null;
|
|
|
930
1063
|
* The fee caps signed are the ones shown, unless the network outgrew them
|
|
931
1064
|
* while the sheet was open (EIP-1559: base fee + tip above the shown cap;
|
|
932
1065
|
* legacy: a higher gas price) — then the user is asked again with the new
|
|
933
|
-
* numbers (`repriced: true`)
|
|
1066
|
+
* numbers (`repriced: true`, `repricedFrom` = the max fee shown before) on a
|
|
1067
|
+
* follow-up sheet the queue limits do not refuse, at most {@link MAX_FEE_REASKS}
|
|
1068
|
+
* times in a row; declining it signs nothing. A new max fee above the wallet's
|
|
1069
|
+
* own ceiling ({@link SignDeps.feeCeiling}) is refused without a sheet.
|
|
934
1070
|
*
|
|
935
1071
|
* The review payload ({@link SignApproval}) carries what the window shows: the
|
|
936
1072
|
* classified request, the prepared fields, the fee, and the preview the wallet
|
|
@@ -943,16 +1079,19 @@ declare function describeSiwe(text: string, ctx: SiweContext): SiweInfo | null;
|
|
|
943
1079
|
type SignRequestInfo = {
|
|
944
1080
|
kind: 'sign-message';
|
|
945
1081
|
method: 'personal_sign';
|
|
946
|
-
account: string; /** Decoded text when printable, else the hex. */
|
|
1082
|
+
account: string; /** Decoded text when printable, else the hex; invisible / direction-changing characters shown as `⟨U+XXXX⟩` ({@link revealHidden}). */
|
|
947
1083
|
text: string; /** What is actually signed (hex or utf-8 string). */
|
|
948
1084
|
raw: string; /** Parsed Sign-In with Ethereum (EIP-4361) with the checks against the asking origin, when the text is one. */
|
|
949
|
-
siwe?: SiweInfo;
|
|
1085
|
+
siwe?: SiweInfo; /** `text` had invisible or direction-changing characters (now escaped): the sheet should warn. */
|
|
1086
|
+
hiddenChars?: true; /** The message is exactly 32 bytes (`0x` + 64 hex): a blind hash signature that CoW Protocol (`ethsign`), Safe (v > 30) and others accept as an order or a transfer. Only with the wallet's opt-in ({@link SignDeps.allowBlindHash}); the sheet must make it a danger screen. */
|
|
1087
|
+
blindHash?: true;
|
|
950
1088
|
} | {
|
|
951
1089
|
kind: 'sign-typed-data';
|
|
952
1090
|
method: string;
|
|
953
|
-
account: string; /** Pretty-printed JSON. */
|
|
1091
|
+
account: string; /** Pretty-printed JSON, invisible / direction-changing characters escaped. */
|
|
954
1092
|
text: string;
|
|
955
|
-
typedData: TypedData;
|
|
1093
|
+
typedData: TypedData; /** `text` had invisible or direction-changing characters (now escaped): the sheet should warn. */
|
|
1094
|
+
hiddenChars?: true;
|
|
956
1095
|
} | {
|
|
957
1096
|
kind: 'send-transaction';
|
|
958
1097
|
method: 'eth_sendTransaction';
|
|
@@ -983,6 +1122,15 @@ interface PreparedTx {
|
|
|
983
1122
|
gasPrice?: string;
|
|
984
1123
|
/** gasLimit × max fee, base units. */
|
|
985
1124
|
maxFee: string;
|
|
1125
|
+
/**
|
|
1126
|
+
* Set when the page chose the gas limit and the wallet's own `eth_estimateGas` answered: the estimate
|
|
1127
|
+
* (0x hex) and whether the page's limit is above max(estimate × 1.5, estimate + 50 000) — then the sheet
|
|
1128
|
+
* should warn with the max fee. The page's limit is still the one signed.
|
|
1129
|
+
*/
|
|
1130
|
+
gasCheck?: {
|
|
1131
|
+
estimate: string;
|
|
1132
|
+
excessive: boolean;
|
|
1133
|
+
};
|
|
986
1134
|
}
|
|
987
1135
|
/** The approval window's payload for the three signing kinds. */
|
|
988
1136
|
interface SignApproval {
|
|
@@ -991,6 +1139,8 @@ interface SignApproval {
|
|
|
991
1139
|
prepared?: PreparedTx;
|
|
992
1140
|
/** A second sheet for the same transaction: the network's fee outgrew the cap the first one showed. */
|
|
993
1141
|
repriced?: true;
|
|
1142
|
+
/** With `repriced`: the max fee (`prepared.maxFee`, base units) the sheet before this one showed. */
|
|
1143
|
+
repricedFrom?: string;
|
|
994
1144
|
/** What the wallet attached (tx-preview-evm `TxPreview`, typed-data description…). */
|
|
995
1145
|
preview: unknown;
|
|
996
1146
|
}
|
|
@@ -1026,8 +1176,33 @@ interface SignDeps {
|
|
|
1026
1176
|
}): Promise<unknown>;
|
|
1027
1177
|
/** Tip floor per chain id in wei (default 0.1 gwei everywhere). */
|
|
1028
1178
|
tipFloor?: (chainId: number) => bigint;
|
|
1179
|
+
/**
|
|
1180
|
+
* Whether a personal_sign of a raw 32-byte hash may reach the sheet (read per request). Default: refused — a
|
|
1181
|
+
* blind hash signature can be a CoW order or a Safe transaction paying someone else (extension audit E55).
|
|
1182
|
+
*/
|
|
1183
|
+
allowBlindHash?: () => boolean | Promise<boolean>;
|
|
1184
|
+
/**
|
|
1185
|
+
* The most one transaction may cost in fee on `network` (base units), when the wallet has such a limit
|
|
1186
|
+
* (the one its signer enforces). A fee that rose above it after the sheet is refused right away, with
|
|
1187
|
+
* no second sheet. The first sheet is not checked here: the signer is the guard for it.
|
|
1188
|
+
*/
|
|
1189
|
+
feeCeiling?: (network: EvmNetwork) => bigint | undefined;
|
|
1029
1190
|
}
|
|
1030
|
-
/**
|
|
1191
|
+
/** How many times in a row one transaction's fee may be asked again ({@link SignApproval.repriced}); the next rise stops the request, nothing signed. */
|
|
1192
|
+
declare const MAX_FEE_REASKS = 3;
|
|
1193
|
+
/**
|
|
1194
|
+
* Text for a review sheet: every invisible or direction-changing character replaced by a visible
|
|
1195
|
+
* `⟨U+XXXX⟩`, so the order on screen is the order of the bytes (a right-to-left override can make
|
|
1196
|
+
* "exe.gnp" read as "png.exe"). `hidden` says whether anything was replaced — the sheet should warn.
|
|
1197
|
+
*/
|
|
1198
|
+
declare function revealHidden(text: string): {
|
|
1199
|
+
text: string;
|
|
1200
|
+
hidden: boolean;
|
|
1201
|
+
};
|
|
1202
|
+
/**
|
|
1203
|
+
* Vaulty's `messageText`: hex that decodes to printable text is shown decoded; binary payloads stay hex.
|
|
1204
|
+
* Invisible and direction-changing characters come back escaped ({@link revealHidden}).
|
|
1205
|
+
*/
|
|
1031
1206
|
declare function messageText(value: unknown): string;
|
|
1032
1207
|
/**
|
|
1033
1208
|
* The message as the signer will sign it: hex decoded when it is valid UTF-8, whatever
|
|
@@ -1035,7 +1210,6 @@ declare function messageText(value: unknown): string;
|
|
|
1035
1210
|
* signed, not the hex fallback `messageText` shows for unprintable text).
|
|
1036
1211
|
*/
|
|
1037
1212
|
declare function decodedMessage(value: unknown): string | null;
|
|
1038
|
-
/** Signing method + params → what the window reviews, or the error to answer with. */
|
|
1039
1213
|
declare function classifySignRequest(input: {
|
|
1040
1214
|
network: EvmNetwork;
|
|
1041
1215
|
method: string;
|
|
@@ -1043,9 +1217,16 @@ declare function classifySignRequest(input: {
|
|
|
1043
1217
|
accounts: string[]; /** The asking page (browser-recorded) — needed for the SIWE domain check. */
|
|
1044
1218
|
origin?: string; /** Transport note for pseudo-origins (WalletConnect Verify), for the SIWE check. */
|
|
1045
1219
|
via?: OriginVia;
|
|
1046
|
-
now?: number;
|
|
1220
|
+
now?: number; /** Let a 32-byte hash personal_sign reach the sheet (marked `blindHash`) instead of refusing it. Default false. */
|
|
1221
|
+
allowBlindHash?: boolean;
|
|
1047
1222
|
}): SignRequestInfo | RelayError;
|
|
1048
|
-
/**
|
|
1223
|
+
/** A page's gas limit above max(estimate × 1.5, estimate + 50 000) is flagged on the sheet (never replaced). */
|
|
1224
|
+
declare function gasLimitExcessive(limit: bigint, estimate: bigint): boolean;
|
|
1225
|
+
/**
|
|
1226
|
+
* Nonce, gas, fees from the wallet's RPC. A gas limit the page set is used as given, but it is checked
|
|
1227
|
+
* against the wallet's own estimate ({@link PreparedTx.gasCheck}); a failed estimate (a call that
|
|
1228
|
+
* reverts now) leaves the check out instead of failing the request.
|
|
1229
|
+
*/
|
|
1049
1230
|
declare function prepareTransaction(deps: Pick<SignDeps, 'rpc' | 'tipFloor'>, network: EvmNetwork, from: string, tx: {
|
|
1050
1231
|
to: string;
|
|
1051
1232
|
value: string;
|
|
@@ -1168,6 +1349,40 @@ interface RouteView {
|
|
|
1168
1349
|
etaSeconds: number;
|
|
1169
1350
|
validUntilMs: number;
|
|
1170
1351
|
tags: ('best' | 'fastest')[];
|
|
1352
|
+
/** Why this route is not a plain pick: a flagged route is never BEST (see {@link rank}). Absent when there is nothing to say. */
|
|
1353
|
+
warnings?: RouteWarning[];
|
|
1354
|
+
}
|
|
1355
|
+
/**
|
|
1356
|
+
* What the wallet cannot vouch for on a route — data for the app's list and sheet, never a refusal:
|
|
1357
|
+
* - `min-below-slippage`: the provider's minimum sits `minGapBps` under its own quote, further than the `slippageBps`
|
|
1358
|
+
* the app asked for (a backend that inflates the output and drops the minimum would otherwise win BEST);
|
|
1359
|
+
* - `deposit-address`: the route pays an address the provider's server assigns (a 1Click deposit address, a THORChain
|
|
1360
|
+
* inbound vault on a non-EVM source chain, a Bitcoin deposit address), so where the funds end up is that server's
|
|
1361
|
+
* word, not calldata the wallet can check.
|
|
1362
|
+
*/
|
|
1363
|
+
type RouteWarning = {
|
|
1364
|
+
kind: 'min-below-slippage';
|
|
1365
|
+
slippageBps: number;
|
|
1366
|
+
minGapBps: number;
|
|
1367
|
+
} | {
|
|
1368
|
+
kind: 'deposit-address';
|
|
1369
|
+
};
|
|
1370
|
+
/** The app's route policy inputs for {@link rank}. */
|
|
1371
|
+
interface RankOptions {
|
|
1372
|
+
/** The slippage the quotes were requested at (bps): a route whose minimum sits further under its output is flagged and never BEST. */
|
|
1373
|
+
slippageBps?: number;
|
|
1374
|
+
/**
|
|
1375
|
+
* Providers whose routes pay an address their server assigns (NEAR Intents 1Click): flagged, and BEST only when no
|
|
1376
|
+
* route from any other provider exists. Which providers these are is the app's call.
|
|
1377
|
+
*/
|
|
1378
|
+
depositAddressProviders?: readonly string[];
|
|
1379
|
+
/**
|
|
1380
|
+
* The same flag per route, for a provider that pays a server-assigned address only on some routes (a THORChain
|
|
1381
|
+
* inbound vault on a non-EVM source chain, a Bitcoin deposit address) and verifiable calldata on the rest. A route is
|
|
1382
|
+
* flagged when its provider is listed above OR this returns true; a throw counts as flagged. BEST goes to a flagged
|
|
1383
|
+
* route only when every route is flagged. Which routes these are is the app's call.
|
|
1384
|
+
*/
|
|
1385
|
+
depositAddressRoute?: (quote: Quote) => boolean;
|
|
1171
1386
|
}
|
|
1172
1387
|
interface RouteListView {
|
|
1173
1388
|
routes: RouteView[];
|
|
@@ -1180,6 +1395,10 @@ interface RouteListView {
|
|
|
1180
1395
|
}
|
|
1181
1396
|
interface QuoteRoutesOptions {
|
|
1182
1397
|
onUpdate?: (view: RouteListView) => void;
|
|
1398
|
+
/** See {@link RankOptions.depositAddressProviders}; the slippage comes from `params.slippageBps`. */
|
|
1399
|
+
depositAddressProviders?: readonly string[];
|
|
1400
|
+
/** {@link RankOptions.depositAddressRoute} with the request next to the quote (a quote does not name its source chain). */
|
|
1401
|
+
depositAddressRoute?: (quote: Quote, params: QuoteParams) => boolean;
|
|
1183
1402
|
/** Per-provider wall clock (default 20 s). */
|
|
1184
1403
|
timeoutMs?: number;
|
|
1185
1404
|
signal?: AbortSignal;
|
|
@@ -1187,8 +1406,15 @@ interface QuoteRoutesOptions {
|
|
|
1187
1406
|
}
|
|
1188
1407
|
/** Dry quotes from every enabled provider that claims the route, progressively. */
|
|
1189
1408
|
declare function quoteRoutes(providers: readonly CrossChainProvider[], params: QuoteParams, options?: QuoteRoutesOptions): Promise<RouteListView>;
|
|
1190
|
-
/**
|
|
1191
|
-
|
|
1409
|
+
/**
|
|
1410
|
+
* Highest output first (same destination token for every quote); FASTEST = lowest ETA among them.
|
|
1411
|
+
*
|
|
1412
|
+
* BEST goes to the highest output among the routes without a {@link RouteWarning} that bars it: never a route whose
|
|
1413
|
+
* minimum is below the requested slippage, and a deposit-address route only when every route is one (no route with
|
|
1414
|
+
* verifiable calldata exists).
|
|
1415
|
+
* The BEST route is listed first; the rest keep the output order. With no route eligible there is no BEST.
|
|
1416
|
+
*/
|
|
1417
|
+
declare function rank(quotes: Quote[], options?: RankOptions): RouteView[];
|
|
1192
1418
|
/** Vaulty's execution floor: 50 bps under the quoted minimum rides normal drift while the user reviews, still refuses a real reprice. */
|
|
1193
1419
|
declare const FLOOR_TOLERANCE_BPS = 50n;
|
|
1194
1420
|
declare function executionFloor(minDestAmount: bigint): bigint;
|
|
@@ -1206,6 +1432,14 @@ interface SwapReviewMeta {
|
|
|
1206
1432
|
toChainName: string;
|
|
1207
1433
|
/** All of the user's addresses — recipient own/foreign. */
|
|
1208
1434
|
own: string[];
|
|
1435
|
+
/** The slippage the swap was quoted at (bps): a plan minimum further under its output is warned on the sheet (never refused). */
|
|
1436
|
+
slippageBps?: number;
|
|
1437
|
+
/**
|
|
1438
|
+
* The route pays an address the provider's server assigned (a NEAR Intents 1Click deposit address, a THORChain
|
|
1439
|
+
* inbound vault on a non-EVM source chain, a Bitcoin deposit address — the app's call per route): the sheet warns,
|
|
1440
|
+
* and the recipient check does not pass on `plan.recipient` alone — the transaction does not carry it.
|
|
1441
|
+
*/
|
|
1442
|
+
depositAddressAssignedByProvider?: boolean;
|
|
1209
1443
|
}
|
|
1210
1444
|
/** What the swap sheet renders. Amounts are base-unit strings. */
|
|
1211
1445
|
interface SwapApproval {
|
|
@@ -1264,6 +1498,14 @@ interface SwapApproval {
|
|
|
1264
1498
|
status: 'ok' | 'warn' | 'unknown';
|
|
1265
1499
|
label: string;
|
|
1266
1500
|
}[];
|
|
1501
|
+
/** With `meta.slippageBps`: how far the minimum sits under the output, and whether that is more than the slippage. */
|
|
1502
|
+
slippage?: {
|
|
1503
|
+
bps: number;
|
|
1504
|
+
minGapBps: number;
|
|
1505
|
+
below: boolean;
|
|
1506
|
+
};
|
|
1507
|
+
/** With `meta.depositAddressAssignedByProvider`: the funds go to an address the provider's server named. */
|
|
1508
|
+
depositAssignedByProvider?: true;
|
|
1267
1509
|
}
|
|
1268
1510
|
declare const encodeApproveCalldata: (spender: string, amount: bigint) => string;
|
|
1269
1511
|
declare function swapApprovalPayload(plan: Swap2ExecutionPlan, meta: SwapReviewMeta): SwapApproval;
|
|
@@ -1606,6 +1848,8 @@ declare class RecipientBook {
|
|
|
1606
1848
|
private state;
|
|
1607
1849
|
list(namespace: string): Promise<string[]>;
|
|
1608
1850
|
remember(namespace: string, address: string): Promise<void>;
|
|
1851
|
+
/** Forget the cached book: the next read asks storage again (e.g. a storage that only answers once the wallet is unlocked). */
|
|
1852
|
+
reload(): void;
|
|
1609
1853
|
/** `known` → the address is one the user paid before; `lookalike` → it imitates one. */
|
|
1610
1854
|
check(namespace: string, address: string): Promise<{
|
|
1611
1855
|
known: boolean;
|
|
@@ -1613,4 +1857,209 @@ declare class RecipientBook {
|
|
|
1613
1857
|
}>;
|
|
1614
1858
|
}
|
|
1615
1859
|
|
|
1616
|
-
|
|
1860
|
+
/** Field of the stored envelope that holds the MAC (base64), or `null` for a value written without a key. */
|
|
1861
|
+
declare const STORAGE_MAC_FIELD = "anywalletkit.mac/1";
|
|
1862
|
+
/** Field of the stored envelope that holds the value's version (a positive integer, inside the MAC) when the store has a {@link storageVersionLedger}. */
|
|
1863
|
+
declare const STORAGE_VERSION_FIELD = "anywalletkit.ver/1";
|
|
1864
|
+
/**
|
|
1865
|
+
* The storage MAC key: HKDF-SHA256(ikm = DEK, salt = none, info = "anywalletkit/storage-mac/1"), 32
|
|
1866
|
+
* bytes. One-way — it reveals nothing about the DEK — so a wallet may keep it in
|
|
1867
|
+
* `chrome.storage.session` while locked. The same DEK always gives the same key; a rotated DEK a new one.
|
|
1868
|
+
*/
|
|
1869
|
+
declare function deriveStorageMacKey(dek: Uint8Array, crypto?: Crypto): Promise<Uint8Array>;
|
|
1870
|
+
/**
|
|
1871
|
+
* What a read found:
|
|
1872
|
+
* - `ok`: a value with a valid MAC;
|
|
1873
|
+
* - `empty`: nothing stored;
|
|
1874
|
+
* - `unsigned`: a value without a MAC (written before the wrapper existed, or while no key was there);
|
|
1875
|
+
* - `invalid`: a MAC that does not match (edited, from another store, or under another key);
|
|
1876
|
+
* - `no-key`: something is stored but there is no key to check it with;
|
|
1877
|
+
* - `stale` (only with a {@link storageVersionLedger}): the MAC is valid — or nothing is stored — but
|
|
1878
|
+
* this is not the latest value the ledger knows: an older signed value put back, a deleted one, or
|
|
1879
|
+
* a ledger that was itself removed, edited or rolled back.
|
|
1880
|
+
*/
|
|
1881
|
+
type MacState = 'ok' | 'empty' | 'unsigned' | 'invalid' | 'no-key' | 'stale';
|
|
1882
|
+
interface MacRead<T> {
|
|
1883
|
+
state: MacState;
|
|
1884
|
+
/** The stored value — verified only when `state` is `ok`. */
|
|
1885
|
+
value: T | null;
|
|
1886
|
+
/** With a ledger, for a value whose MAC is valid: its version (`0` = signed before versions existed). */
|
|
1887
|
+
version?: number;
|
|
1888
|
+
}
|
|
1889
|
+
interface MacJsonStorageOptions {
|
|
1890
|
+
/** Names the store inside the MAC: a value signed for one store does not verify in another. */
|
|
1891
|
+
label: string;
|
|
1892
|
+
/** The MAC key ({@link deriveStorageMacKey}), or `null` when the wallet has none (locked). The wrapper zeroizes the copy it gets. */
|
|
1893
|
+
key: () => Promise<Uint8Array | null>;
|
|
1894
|
+
/** `get()` without a key: the stored value unverified (`'unverified'`, default) or `null`. */
|
|
1895
|
+
readWithoutKey?: 'unverified' | 'null';
|
|
1896
|
+
/** `set()` without a key: store the value with no MAC (`'unsigned'`, default — it fails verification later) or throw `VaultError('locked')`. */
|
|
1897
|
+
writeWithoutKey?: 'unsigned' | 'refuse';
|
|
1898
|
+
/**
|
|
1899
|
+
* Rollback protection: the ledger shared by the wallet's signed stores. Every signed write takes the
|
|
1900
|
+
* store's next version (inside the MAC) and records it; a read whose version the ledger does not
|
|
1901
|
+
* agree with is `stale`. The label must not contain a line break.
|
|
1902
|
+
*/
|
|
1903
|
+
versions?: StorageVersionLedger;
|
|
1904
|
+
}
|
|
1905
|
+
interface MacJsonStorage<T> extends JsonStorage<T> {
|
|
1906
|
+
/** The verified value (`null` when empty, unsigned or invalid); without a key, per `readWithoutKey`. */
|
|
1907
|
+
get(): Promise<T | null>;
|
|
1908
|
+
/** Sign with the current key; without one, per `writeWithoutKey`. */
|
|
1909
|
+
set(value: T): Promise<void>;
|
|
1910
|
+
/** The stored value and what verification found, under `key` (default: the current key). */
|
|
1911
|
+
read(key?: Uint8Array): Promise<MacRead<T>>;
|
|
1912
|
+
/** Store `value` signed under `key` (default: the current key; refused without one). */
|
|
1913
|
+
write(value: T, key?: Uint8Array): Promise<void>;
|
|
1914
|
+
/**
|
|
1915
|
+
* Re-sign the stored value under `newKey` when it verifies under `oldKey`; anything else is left as it is. Returns what `oldKey` found.
|
|
1916
|
+
* With a ledger: rekey the ledger first ({@link StorageVersionLedger.rekey}); the value keeps its version, and is re-signed only when the
|
|
1917
|
+
* re-signed ledger agrees with it (`stale` otherwise).
|
|
1918
|
+
*/
|
|
1919
|
+
rekey(oldKey: Uint8Array, newKey: Uint8Array): Promise<MacState>;
|
|
1920
|
+
}
|
|
1921
|
+
/** Wrap `inner` (e.g. `chromeJsonStorage(chrome.storage.local, key)`) with a MAC; see the module comment. */
|
|
1922
|
+
declare function macJsonStorage<T>(inner: JsonStorage<unknown>, options: MacJsonStorageOptions): MacJsonStorage<T>;
|
|
1923
|
+
/** Deterministic JSON: the same data gives the same text whatever order its keys were stored in. */
|
|
1924
|
+
declare function canonicalJson(value: unknown): string;
|
|
1925
|
+
/** What a {@link StorageVersionLedger} holds, as {@link StorageVersionLedger.read} found it. */
|
|
1926
|
+
interface StorageVersions {
|
|
1927
|
+
/** `ok`; `empty` (no manifest and none expected); `invalid` (unsigned, edited, or another key); `stale` (missing or older than this browser session has seen). */
|
|
1928
|
+
state: 'ok' | 'empty' | 'invalid' | 'stale';
|
|
1929
|
+
/** Goes up by one with every manifest write. `0` when there is no readable manifest. */
|
|
1930
|
+
epoch: number;
|
|
1931
|
+
/** Where this manifest's numbering started: a store's first version is `base + 1`. */
|
|
1932
|
+
base: number;
|
|
1933
|
+
/** After {@link StorageVersionLedger.condemn}: a store the manifest does not list is not trusted, stored or not. */
|
|
1934
|
+
sealed: boolean;
|
|
1935
|
+
/** The latest version of each store, by label. */
|
|
1936
|
+
versions: Record<string, number>;
|
|
1937
|
+
}
|
|
1938
|
+
/** The ledger operations a store runs inside {@link StorageVersionLedger.exclusive}. */
|
|
1939
|
+
interface StorageVersionOps {
|
|
1940
|
+
/**
|
|
1941
|
+
* Is `version` the latest for `label`? `null` = nothing is stored, `0` = a signed value without a
|
|
1942
|
+
* version. A value exactly one ahead of the manifest is accepted and recorded (an interrupted write).
|
|
1943
|
+
*/
|
|
1944
|
+
check(label: string, version: number | null, key: Uint8Array): Promise<'ok' | 'stale'>;
|
|
1945
|
+
/**
|
|
1946
|
+
* One write: `write(version)` stores the value signed with the next version, then the manifest records
|
|
1947
|
+
* it. `seen()` is the version of the value stored now (0 when none this key signed). A missing manifest
|
|
1948
|
+
* is created first; a refused one is replaced by a sealed one ({@link StorageVersionLedger.condemn}).
|
|
1949
|
+
*/
|
|
1950
|
+
advance(label: string, key: Uint8Array, seen: () => Promise<number>, write: (version: number) => Promise<void>): Promise<number>;
|
|
1951
|
+
}
|
|
1952
|
+
interface StorageVersionLedgerOptions {
|
|
1953
|
+
/** Where the manifest lives — the same area as the stores it covers (`chrome.storage.local`). */
|
|
1954
|
+
manifest: JsonStorage<unknown>;
|
|
1955
|
+
/**
|
|
1956
|
+
* The highest manifest epoch seen, kept where a write to the stores' area cannot reach it and where it
|
|
1957
|
+
* dies with the browser session (`chrome.storage.session`). `set(null)` clears it.
|
|
1958
|
+
*/
|
|
1959
|
+
mark: JsonStorage<unknown>;
|
|
1960
|
+
/** Names the manifest inside its MAC. No store may use it. */
|
|
1961
|
+
label?: string;
|
|
1962
|
+
/**
|
|
1963
|
+
* Accept a validly signed value that carries no version (written before the ledger existed) for a
|
|
1964
|
+
* store the manifest has no record of. Off by default: such a value can be replayed for as long as it
|
|
1965
|
+
* is accepted, so switch it on only to migrate, write every store once, and switch it off again.
|
|
1966
|
+
*/
|
|
1967
|
+
acceptUnversioned?: boolean;
|
|
1968
|
+
/** Milliseconds since the epoch — where a new manifest starts numbering. */
|
|
1969
|
+
now?: () => number;
|
|
1970
|
+
}
|
|
1971
|
+
interface StorageVersionLedger {
|
|
1972
|
+
/** Run `fn` with no other ledger operation in between (stores use it for read-and-check and for a write). Do not nest. */
|
|
1973
|
+
exclusive<R>(fn: (ops: StorageVersionOps) => Promise<R>): Promise<R>;
|
|
1974
|
+
/**
|
|
1975
|
+
* Stop trusting everything signed so far: a fresh, sealed manifest numbered above all it replaces.
|
|
1976
|
+
* Every store then reads `stale` — also one with nothing stored — until it is written again.
|
|
1977
|
+
*/
|
|
1978
|
+
condemn(key: Uint8Array): Promise<void>;
|
|
1979
|
+
/** Re-sign the manifest under `newKey` when it is `ok` under `oldKey` (one epoch up); otherwise it is left as it is. Returns what `oldKey` found. Then rekey the stores. */
|
|
1980
|
+
rekey(oldKey: Uint8Array, newKey: Uint8Array): Promise<StorageVersions['state']>;
|
|
1981
|
+
/** The manifest as `key` sees it. */
|
|
1982
|
+
read(key: Uint8Array): Promise<StorageVersions>;
|
|
1983
|
+
/** Forget manifest and mark — only when the stores are wiped with them (a new vault). */
|
|
1984
|
+
reset(): Promise<void>;
|
|
1985
|
+
}
|
|
1986
|
+
/**
|
|
1987
|
+
* Rollback protection for {@link macJsonStorage} stores: one signed manifest that says which version
|
|
1988
|
+
* of each store is the latest.
|
|
1989
|
+
*
|
|
1990
|
+
* - Every signed value carries its version inside the MAC. A write stores the value with the store's
|
|
1991
|
+
* next version, then the manifest (its `epoch` goes up by one), then the session mark. A value the
|
|
1992
|
+
* manifest lists another version for — or lists, when nothing is stored — is `stale`: putting ONE
|
|
1993
|
+
* store back, or deleting it, is caught, across browser restarts too.
|
|
1994
|
+
* - The manifest lives next to the stores, so the whole area can be put back together. `mark` — the
|
|
1995
|
+
* highest epoch seen, in session storage — catches that for as long as the browser session lives: a
|
|
1996
|
+
* manifest older than the mark, or missing while there is a mark, makes every store `stale`.
|
|
1997
|
+
* - A manifest that is unsigned, edited or under another key makes every store `stale`. So does a
|
|
1998
|
+
* signed value with a version when there is no manifest at all.
|
|
1999
|
+
* - A worker killed between the value and the manifest write leaves a value exactly one version ahead.
|
|
2000
|
+
* That is accepted and recorded: only the key holder can sign that version, so it is the wallet's own
|
|
2001
|
+
* last write. Until it is recorded the previous value still verifies — the same as the interrupted
|
|
2002
|
+
* write never having happened.
|
|
2003
|
+
*
|
|
2004
|
+
* What it cannot see: the whole area (manifest and stores together) put back to an earlier state when
|
|
2005
|
+
* there is no mark — after a browser restart, or an extension reload — and likewise everything deleted
|
|
2006
|
+
* together. Nothing an extension can store survives that and is out of the same writer's reach; it is
|
|
2007
|
+
* what restoring a profile backup looks like. Versions start from the clock (`now`) so that a manifest
|
|
2008
|
+
* created after a loss does not hand out numbers already used; a clock set far back defeats that.
|
|
2009
|
+
*
|
|
2010
|
+
* The ledger never repairs on a read (beyond recording an interrupted write): the wallet decides what
|
|
2011
|
+
* a `stale` store falls back to, calls {@link StorageVersionLedger.condemn} when the manifest itself was
|
|
2012
|
+
* refused, and writes the stores again.
|
|
2013
|
+
*/
|
|
2014
|
+
declare function storageVersionLedger(options: StorageVersionLedgerOptions): StorageVersionLedger;
|
|
2015
|
+
|
|
2016
|
+
/**
|
|
2017
|
+
* "Same site" for limits: the registrable domain (eTLD+1) of an origin, and a
|
|
2018
|
+
* token bucket keyed by any string. Both exist so a page cannot multiply its
|
|
2019
|
+
* allowance by spreading requests over subdomains (`a1.evil.tld`, `a2.evil.tld`…).
|
|
2020
|
+
*
|
|
2021
|
+
* There is no Public Suffix List in this package (it is large and changes); the
|
|
2022
|
+
* helper is conservative instead: the last two labels, or three when the last two
|
|
2023
|
+
* are a known multi-label public suffix ({@link MULTI_LABEL_SUFFIXES}: country
|
|
2024
|
+
* second-level domains such as `co.uk`, and hosting domains where anyone gets a
|
|
2025
|
+
* subdomain, such as `github.io` or `vercel.app`). A suffix that is missing from
|
|
2026
|
+
* the list makes unrelated sites under it share one limit (stricter, never looser);
|
|
2027
|
+
* pass your own `siteOf` to the queue when you ship a full list.
|
|
2028
|
+
*/
|
|
2029
|
+
/**
|
|
2030
|
+
* Multi-label public suffixes the helper knows. Two groups: country second-level
|
|
2031
|
+
* registries, and hosting platforms that hand out subdomains to anyone (the
|
|
2032
|
+
* Public Suffix List's private section).
|
|
2033
|
+
*/
|
|
2034
|
+
declare const MULTI_LABEL_SUFFIXES: ReadonlySet<string>;
|
|
2035
|
+
/**
|
|
2036
|
+
* The site an origin belongs to: `https://a.b.example.co.uk:8443` → `example.co.uk`,
|
|
2037
|
+
* `https://x.vercel.app` → `x.vercel.app`. IP addresses and single-label hosts
|
|
2038
|
+
* (`localhost`) are their own site. A pseudo-origin that is not a URL (`wc:<topic>`)
|
|
2039
|
+
* is returned unchanged.
|
|
2040
|
+
*/
|
|
2041
|
+
declare function siteOf(origin: string): string;
|
|
2042
|
+
interface TokenBucketOptions {
|
|
2043
|
+
/** Tokens a key holds when full (the burst). */
|
|
2044
|
+
capacity: number;
|
|
2045
|
+
/** Tokens added per second. */
|
|
2046
|
+
refillPerSecond: number;
|
|
2047
|
+
/** Clock (ms), injectable for tests. */
|
|
2048
|
+
now?: () => number;
|
|
2049
|
+
/** Keys tracked before full buckets are dropped (memory bound). Default 2000. */
|
|
2050
|
+
maxKeys?: number;
|
|
2051
|
+
}
|
|
2052
|
+
/** A token bucket per key: `take(key)` spends one token, `false` when the key is out of tokens. Memory only. */
|
|
2053
|
+
declare class TokenBucket {
|
|
2054
|
+
private readonly options;
|
|
2055
|
+
private readonly buckets;
|
|
2056
|
+
constructor(options: TokenBucketOptions);
|
|
2057
|
+
take(key: string, cost?: number): boolean;
|
|
2058
|
+
/** Tokens `key` holds right now (full for an unknown key). */
|
|
2059
|
+
available(key: string): number;
|
|
2060
|
+
private refill;
|
|
2061
|
+
/** Drop buckets that are full again (they carry no state); the oldest half when every one is in use. */
|
|
2062
|
+
private prune;
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
export { ACTIVE_STATUSES, APPROVALS_MAX_PENDING_PER_ORIGIN, APPROVALS_MAX_PENDING_PER_SITE, APPROVALS_MAX_PENDING_TOTAL, type AddChainApproval, type AlarmsLike, type ApprovalKind, ApprovalQueue, type ApprovalQueueOptions, type ApprovalRateOptions, type ApprovalRequest, type ApprovalRequestOptions, type ApprovalWindow, type AssertionExpectations, type AssertionInput, type AssertionVerdict, BTC_CHAIN, BTC_ESPLORA, CHAIN_ACCOUNT_KEYS, type ChainAccountsKey, type ChainDescriptor, type ConnectApproval, DEFAULT_CHAIN, DEFAULT_NETWORKS, type EarnApproval, type EarnPlan, type EarnReviewMeta, type EarnTx, type EvmNetwork, type EvmSigner, FLOOR_TOLERANCE_BPS, GETLOGS_MAX_SPAN_UNCONNECTED, type GateMatcher, type GatedOp, type HostCheck, type JsonStorage, KEYRING_STORAGE_KEY, LOOKALIKE_PREFIX, LOOKALIKE_SUFFIX, MAX_FEE_REASKS, MULTI_LABEL_SUFFIXES, type MacJsonStorage, type MacJsonStorageOptions, type MacRead, type MacState, NEAR_CHAIN, NEAR_PROVIDERS, NON_EVM_CHAINS, NetworksTable, type OriginPermission, OriginRefused, type OriginVia, PAGE_TARGET, PORT_NAME, type PageEvent, type PageMessageEvent, type PageRequest, type PageResponse, type PageWindow, PermissionStore, type PermissionsState, PhishingDetector, type PhishingList, type PortSender, type PreparedTx, QueueLimitError, type QuoteRoutesOptions, READ_METHODS, RELAY_ERRORS, RELAY_METHOD_MAX, type RankOptions, RecipientBook, type RecipientsState, type RelayChain, type RelayError, type RelayErrorOptions, type RelayEvent, type RelayRequest, type RelayResponse, type RelayToContent, type RelayToWorker, RequestRouter, ReviewDeclined, ReviewGate, type RouteListView, type RouteView, type RouteWarning, type RouterDeps, RouterError, SESSION_DEFAULT_AUTOLOCK_MS, SIGNING_METHODS, SIWE_FORBIDDEN_CHARS, SOLANA_CHAIN, SOLANA_RPCS, STORAGE_MAC_FIELD, STORAGE_VERSION_FIELD, type SealedBox, Session, type SessionAlarms, type SessionOptions, type SessionStorage, type SignApproval, type SignDeps, type SignRequestInfo, type SiweContext, type SiweInfo, type SiweMessage, type StorageAreaLike, type StorageVersionLedger, type StorageVersionLedgerOptions, type StorageVersionOps, type StorageVersions, type SwapApproval, type SwapRecord, type SwapRecordStatus, type SwapReviewMeta, SwapTracker, type SwapTrackerDeps, SwapsStore, type SwitchChainApproval, TON_CHAIN, TON_ENDPOINTS, TRON_CHAIN, TRON_PROVIDERS, TokenBucket, type TokenBucketOptions, type TonAddressParts, type TypedData, VAULT_DEFAULT_ITERATIONS, VAULT_LIMITS, VAULT_MIN_ITERATIONS, VAULT_MIN_PASSWORD_LENGTH, VAULT_MIN_SCRYPT, VAULT_SCRYPT, VAULT_STORAGE_KEY, Vault, type VaultEnvelope, type VaultEnvelopeV1, type VaultEnvelopeV2, VaultError, type VaultErrorCode, type VaultKdfInfo, type VaultOptions, type VaultPasskey, type VaultStorage, ZCASH_BLOCKCHAIR, ZCASH_CHAIN, approvalChallenge, caip2FromChainId, canonicalJson, chainHex, chainTxMatcher, checkSenderOrigin, chromeAlarms, chromeJsonStorage, chromeKeyringStorage, chromeLocalVaultStorage, chromeSessionStorage, classifySignRequest, createSignHandler, decodedMessage, derToRaw, deriveStorageMacKey, describeSiwe, earnApprovalPayload, earnPlanMatchers, encodeApproveCalldata, evmCallMatcher, executionFloor, fromBase64Url, gasLimitExcessive, hostOf, isCatalogChain, isEnvelopeV1, isEnvelopeV2, isLocalHost, isPageEvent, isPageRequest, isPageResponse, isRelayMethod, isRelayRequest, isRelayToContent, levenshtein, lookalikeOf, macJsonStorage, memoryAlarms, memoryApprovalWindow, memoryJsonStorage, memorySessionStorage, memoryVaultStorage, messageText, newRequestId, nonEvmChain, normalizeHost, pageRequestFrom, parseAddChainParams, parseRawAddress, parseSiwe, parseSwapId, planMatchers, prepareTransaction, proofDomain, quoteRoutes, rank, rawToDer, relayError, revealHidden, reviewEarnPlan, reviewSwapPlan, siteOf, siweCrossSite, siweProblems, stampOrigin, storageVersionLedger, swapApprovalPayload, toBase64Url, toRelayError, tonConnectErrorCode, tonProofMessage, tonSignDataMessage, typedDataMatcher, vaultSecretStorage, verifyAssertion };
|