@dfx.swiss/wallet 0.0.0-stage → 0.1.1-beta.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.
Files changed (142) hide show
  1. package/README.md +39 -2
  2. package/dist/config/environment.d.ts +40 -0
  3. package/dist/config/environment.d.ts.map +1 -0
  4. package/dist/config/environment.js +37 -0
  5. package/dist/config/environment.js.map +1 -0
  6. package/dist/derivation/bitcoin-keys.d.ts +20 -0
  7. package/dist/derivation/bitcoin-keys.d.ts.map +1 -0
  8. package/dist/derivation/bitcoin-keys.js +50 -0
  9. package/dist/derivation/bitcoin-keys.js.map +1 -0
  10. package/dist/derivation/evm-keys.d.ts +8 -0
  11. package/dist/derivation/evm-keys.d.ts.map +1 -0
  12. package/dist/derivation/evm-keys.js +32 -0
  13. package/dist/derivation/evm-keys.js.map +1 -0
  14. package/dist/derivation/keyring.d.ts +68 -0
  15. package/dist/derivation/keyring.d.ts.map +1 -0
  16. package/dist/derivation/keyring.js +150 -0
  17. package/dist/derivation/keyring.js.map +1 -0
  18. package/dist/derivation/public-data.d.ts +26 -0
  19. package/dist/derivation/public-data.d.ts.map +1 -0
  20. package/dist/derivation/public-data.js +19 -0
  21. package/dist/derivation/public-data.js.map +1 -0
  22. package/dist/derivation/seed-check.d.ts +6 -0
  23. package/dist/derivation/seed-check.d.ts.map +1 -0
  24. package/dist/derivation/seed-check.js +13 -0
  25. package/dist/derivation/seed-check.js.map +1 -0
  26. package/dist/derivation/spark-keys.d.ts +14 -0
  27. package/dist/derivation/spark-keys.d.ts.map +1 -0
  28. package/dist/derivation/spark-keys.js +64 -0
  29. package/dist/derivation/spark-keys.js.map +1 -0
  30. package/dist/derivation/v1.d.ts +32 -0
  31. package/dist/derivation/v1.d.ts.map +1 -0
  32. package/dist/derivation/v1.js +64 -0
  33. package/dist/derivation/v1.js.map +1 -0
  34. package/dist/index.d.ts +46 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +36 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/passkey/ceremonies.d.ts +91 -0
  39. package/dist/passkey/ceremonies.d.ts.map +1 -0
  40. package/dist/passkey/ceremonies.js +250 -0
  41. package/dist/passkey/ceremonies.js.map +1 -0
  42. package/dist/passkey/ceremony-gate.d.ts +25 -0
  43. package/dist/passkey/ceremony-gate.d.ts.map +1 -0
  44. package/dist/passkey/ceremony-gate.js +45 -0
  45. package/dist/passkey/ceremony-gate.js.map +1 -0
  46. package/dist/passkey/credential-cache.d.ts +38 -0
  47. package/dist/passkey/credential-cache.d.ts.map +1 -0
  48. package/dist/passkey/credential-cache.js +91 -0
  49. package/dist/passkey/credential-cache.js.map +1 -0
  50. package/dist/passkey/diagnostics.d.ts +22 -0
  51. package/dist/passkey/diagnostics.d.ts.map +1 -0
  52. package/dist/passkey/diagnostics.js +59 -0
  53. package/dist/passkey/diagnostics.js.map +1 -0
  54. package/dist/passkey/errors.d.ts +49 -0
  55. package/dist/passkey/errors.d.ts.map +1 -0
  56. package/dist/passkey/errors.js +87 -0
  57. package/dist/passkey/errors.js.map +1 -0
  58. package/dist/passkey/platform.d.ts +77 -0
  59. package/dist/passkey/platform.d.ts.map +1 -0
  60. package/dist/passkey/platform.js +163 -0
  61. package/dist/passkey/platform.js.map +1 -0
  62. package/dist/passkey/webauthn-json.d.ts +35 -0
  63. package/dist/passkey/webauthn-json.d.ts.map +1 -0
  64. package/dist/passkey/webauthn-json.js +79 -0
  65. package/dist/passkey/webauthn-json.js.map +1 -0
  66. package/dist/providers/blocklist.d.ts +22 -0
  67. package/dist/providers/blocklist.d.ts.map +1 -0
  68. package/dist/providers/blocklist.js +51 -0
  69. package/dist/providers/blocklist.js.map +1 -0
  70. package/dist/providers/chain-registry.d.ts +26 -0
  71. package/dist/providers/chain-registry.d.ts.map +1 -0
  72. package/dist/providers/chain-registry.js +59 -0
  73. package/dist/providers/chain-registry.js.map +1 -0
  74. package/dist/providers/dfx-data.d.ts +25 -0
  75. package/dist/providers/dfx-data.d.ts.map +1 -0
  76. package/dist/providers/dfx-data.js +44 -0
  77. package/dist/providers/dfx-data.js.map +1 -0
  78. package/dist/providers/price.d.ts +34 -0
  79. package/dist/providers/price.d.ts.map +1 -0
  80. package/dist/providers/price.js +46 -0
  81. package/dist/providers/price.js.map +1 -0
  82. package/dist/providers/snapshot.d.ts +28 -0
  83. package/dist/providers/snapshot.d.ts.map +1 -0
  84. package/dist/providers/snapshot.js +2 -0
  85. package/dist/providers/snapshot.js.map +1 -0
  86. package/dist/session/idle-lock.d.ts +31 -0
  87. package/dist/session/idle-lock.d.ts.map +1 -0
  88. package/dist/session/idle-lock.js +73 -0
  89. package/dist/session/idle-lock.js.map +1 -0
  90. package/dist/session/passkey-auth.d.ts +95 -0
  91. package/dist/session/passkey-auth.d.ts.map +1 -0
  92. package/dist/session/passkey-auth.js +356 -0
  93. package/dist/session/passkey-auth.js.map +1 -0
  94. package/dist/session/tab-lock.d.ts +30 -0
  95. package/dist/session/tab-lock.d.ts.map +1 -0
  96. package/dist/session/tab-lock.js +79 -0
  97. package/dist/session/tab-lock.js.map +1 -0
  98. package/dist/signing/auto-signer.d.ts +26 -0
  99. package/dist/signing/auto-signer.d.ts.map +1 -0
  100. package/dist/signing/auto-signer.js +76 -0
  101. package/dist/signing/auto-signer.js.map +1 -0
  102. package/dist/signing/bitcoin-message.d.ts +11 -0
  103. package/dist/signing/bitcoin-message.d.ts.map +1 -0
  104. package/dist/signing/bitcoin-message.js +62 -0
  105. package/dist/signing/bitcoin-message.js.map +1 -0
  106. package/dist/signing/login-messages.d.ts +15 -0
  107. package/dist/signing/login-messages.d.ts.map +1 -0
  108. package/dist/signing/login-messages.js +16 -0
  109. package/dist/signing/login-messages.js.map +1 -0
  110. package/dist/signing/login-text-guard.d.ts +3 -0
  111. package/dist/signing/login-text-guard.d.ts.map +1 -0
  112. package/dist/signing/login-text-guard.js +13 -0
  113. package/dist/signing/login-text-guard.js.map +1 -0
  114. package/dist/signing/spark-login.d.ts +17 -0
  115. package/dist/signing/spark-login.d.ts.map +1 -0
  116. package/dist/signing/spark-login.js +51 -0
  117. package/dist/signing/spark-login.js.map +1 -0
  118. package/dist/util/bytes.d.ts +11 -0
  119. package/dist/util/bytes.d.ts.map +1 -0
  120. package/dist/util/bytes.js +26 -0
  121. package/dist/util/bytes.js.map +1 -0
  122. package/dist/util/emitter.d.ts +17 -0
  123. package/dist/util/emitter.d.ts.map +1 -0
  124. package/dist/util/emitter.js +53 -0
  125. package/dist/util/emitter.js.map +1 -0
  126. package/dist/util/errors.d.ts +12 -0
  127. package/dist/util/errors.d.ts.map +1 -0
  128. package/dist/util/errors.js +15 -0
  129. package/dist/util/errors.js.map +1 -0
  130. package/dist/util/jwt.d.ts +6 -0
  131. package/dist/util/jwt.d.ts.map +1 -0
  132. package/dist/util/jwt.js +23 -0
  133. package/dist/util/jwt.js.map +1 -0
  134. package/dist/util/kv-store.d.ts +51 -0
  135. package/dist/util/kv-store.d.ts.map +1 -0
  136. package/dist/util/kv-store.js +133 -0
  137. package/dist/util/kv-store.js.map +1 -0
  138. package/dist/util/random.d.ts +3 -0
  139. package/dist/util/random.d.ts.map +1 -0
  140. package/dist/util/random.js +18 -0
  141. package/dist/util/random.js.map +1 -0
  142. package/package.json +42 -4
@@ -0,0 +1,163 @@
1
+ import { RP_IDS } from '../config/environment';
2
+ /** Case-insensitive UA tokens of embedded in-app browsers that cannot run WebAuthn. */
3
+ const IN_APP_UA = /Telegram|Instagram|FBAN|FBAV|FB_IAB|FBIOS|FB4A|Messenger|Orca-Android|WhatsApp|BytedanceWebview|musical_ly|TikTok|TwitterAndroid|\bTwitter\b|LinkedInApp|Snapchat|Pinterest|Reddit|MicroMessenger|\bLine\/|KAKAOTALK|Weibo|NAVER|baiduboxapp|\bGSA\b|Barcelona/i;
4
+ const IOS_UA = /iPhone|iPad|iPod/i;
5
+ const ANDROID_UA = /\bAndroid (\d+)(?:\.(\d+))?(?:\.(\d+))?/;
6
+ function host(win) {
7
+ if (win !== undefined)
8
+ return win;
9
+ return typeof globalThis.window === 'undefined' ? undefined : globalThis.window;
10
+ }
11
+ function isTelegramHost(h) {
12
+ return (h.TelegramWebviewProxy !== undefined ||
13
+ h.TelegramWebview !== undefined ||
14
+ h.Telegram?.WebApp !== undefined ||
15
+ /Telegram/i.test(h.navigator.userAgent));
16
+ }
17
+ /** True inside an embedded in-app browser (Telegram, Instagram, …). */
18
+ export function isInAppBrowser(win) {
19
+ const h = host(win);
20
+ if (!h)
21
+ return false;
22
+ return isTelegramHost(h) || IN_APP_UA.test(h.navigator.userAgent);
23
+ }
24
+ /** Installed iOS version from the UA, or null on other platforms / missing token. */
25
+ export function iosInstalledVersion(userAgent) {
26
+ if (!IOS_UA.test(userAgent))
27
+ return null;
28
+ const match = /\bOS (\d+)[_.](\d+)(?:[_.](\d+))?/.exec(userAgent);
29
+ if (!match)
30
+ return null;
31
+ return match[3] === undefined ? `${match[1]}.${match[2]}` : `${match[1]}.${match[2]}.${match[3]}`;
32
+ }
33
+ /** iPadOS desktop mode reports a Macintosh UA. Touch points tell it apart from desktop Safari. */
34
+ export function isIpadDesktopMode(nav) {
35
+ return nav.platform === 'MacIntel' && (nav.maxTouchPoints ?? 0) > 1;
36
+ }
37
+ /**
38
+ * Installed iPadOS version in desktop mode. That UA drops the iPad token and puts the OS major in
39
+ * Safari's `Version/`. A real Mac has no touch points, so its Safari version is not an iPadOS release.
40
+ * Null when this is not iPad desktop mode or the token is missing — the floor must not guess.
41
+ */
42
+ export function ipadDesktopInstalledVersion(nav) {
43
+ if (!isIpadDesktopMode(nav))
44
+ return null;
45
+ const match = /\bVersion\/(\d+)(?:\.(\d+))?(?:\.(\d+))?/.exec(nav.userAgent);
46
+ if (!match)
47
+ return null;
48
+ if (match[2] === undefined)
49
+ return match[1];
50
+ return match[3] === undefined ? `${match[1]}.${match[2]}` : `${match[1]}.${match[2]}.${match[3]}`;
51
+ }
52
+ function parseAndroid(ua) {
53
+ const match = ANDROID_UA.exec(ua);
54
+ if (!match)
55
+ return null;
56
+ return {
57
+ major: Number(match[1]),
58
+ installed: match[2] === undefined
59
+ ? match[1]
60
+ : match[3] === undefined
61
+ ? `${match[1]}.${match[2]}`
62
+ : `${match[1]}.${match[2]}.${match[3]}`,
63
+ };
64
+ }
65
+ /** Installed Android version, preferring `userAgentData` (Chrome freezes the UA at Android 10). */
66
+ export async function androidInstalledVersion(win) {
67
+ const h = host(win);
68
+ if (!h)
69
+ return null;
70
+ const read = h.navigator.userAgentData?.getHighEntropyValues;
71
+ if (typeof read === 'function') {
72
+ try {
73
+ const values = await read.call(h.navigator.userAgentData, ['platform', 'platformVersion']);
74
+ const platform = typeof values['platform'] === 'string' ? values['platform'] : '';
75
+ const platformVersion = typeof values['platformVersion'] === 'string' ? values['platformVersion'].trim() : '';
76
+ const platformIsAndroid = /android/i.test(platform);
77
+ // Linux reports an empty platformVersion; macOS and Windows report their own. Neither is an Android release.
78
+ const platformIsOther = platform !== '' && !platformIsAndroid;
79
+ const uaIsAndroid = ANDROID_UA.test(h.navigator.userAgent);
80
+ if (!platformIsOther && platformVersion !== '' && (platformIsAndroid || uaIsAndroid)) {
81
+ return platformVersion.split('.')[0] || platformVersion;
82
+ }
83
+ }
84
+ catch {
85
+ // fall through to the UA token
86
+ }
87
+ }
88
+ return parseAndroid(h.navigator.userAgent)?.installed ?? null;
89
+ }
90
+ /**
91
+ * Checks whether the wallet's passkey ceremonies can run here at all: real top-level page on the
92
+ * environment's RP host, WebAuthn present, OS new enough, not inside an in-app browser. The PRF soft gate
93
+ * only hides the tile (`available: false`, `prf: 'no'`); PRF absence in an old browser is `unknown`.
94
+ */
95
+ export async function checkPasskeyPlatform(env, win) {
96
+ const h = host(win);
97
+ const webauthn = !!h &&
98
+ typeof h.PublicKeyCredential === 'function' &&
99
+ typeof h.navigator.credentials?.create === 'function' &&
100
+ typeof h.navigator.credentials?.get === 'function';
101
+ if (!h || !webauthn)
102
+ return { available: false, reason: 'no-webauthn', prf: 'unknown' };
103
+ if (isInAppBrowser(h))
104
+ return { available: false, reason: 'in-app-browser', prf: 'unknown' };
105
+ if (h.location.hostname !== RP_IDS[env])
106
+ return { available: false, reason: 'wrong-origin', prf: 'unknown' };
107
+ const topKnown = h.top !== undefined || h.self !== undefined || typeof globalThis.window !== 'undefined';
108
+ try {
109
+ const top = h.top ??
110
+ (typeof globalThis.window !== 'undefined' ? globalThis.window.top : undefined);
111
+ const self = h.self ??
112
+ (typeof globalThis.window !== 'undefined'
113
+ ? globalThis.window.self
114
+ : undefined);
115
+ if (topKnown && top !== self)
116
+ return { available: false, reason: 'embedded', prf: 'unknown' };
117
+ }
118
+ catch {
119
+ return { available: false, reason: 'embedded', prf: 'unknown' };
120
+ }
121
+ const ua = h.navigator.userAgent;
122
+ const ios = iosInstalledVersion(ua) ?? ipadDesktopInstalledVersion(h.navigator);
123
+ if (ios !== null && Number(ios.split('.')[0]) < 18)
124
+ return { available: false, reason: 'os-too-old', prf: 'unknown', os: ios };
125
+ const android = await androidInstalledVersion(h);
126
+ if (android !== null && !IOS_UA.test(ua) && Number(android.split('.')[0]) < 9) {
127
+ return { available: false, reason: 'os-too-old', prf: 'unknown', os: android };
128
+ }
129
+ const Credential = h.PublicKeyCredential;
130
+ try {
131
+ const capabilities = await Credential?.getClientCapabilities?.();
132
+ const prf = capabilities?.['extension:prf'];
133
+ if (prf === false)
134
+ return { available: false, reason: 'no-prf', prf: 'no', os: ios ?? android ?? undefined };
135
+ return { available: true, prf: prf === true ? 'yes' : 'unknown', os: ios ?? android ?? undefined };
136
+ }
137
+ catch {
138
+ return { available: true, prf: 'unknown', os: ios ?? android ?? undefined };
139
+ }
140
+ }
141
+ /** Best-effort handoff of the login URL to the system browser when stuck in an in-app browser. */
142
+ export function openInSystemBrowser(url, win) {
143
+ const h = host(win);
144
+ if (!h)
145
+ return;
146
+ const ua = h.navigator.userAgent;
147
+ if (/Android/i.test(ua)) {
148
+ const hostAndPath = url.replace(/^https:\/\//u, '');
149
+ h.location.href = `intent://${hostAndPath}#Intent;scheme=https;package=com.android.chrome;S.browser_fallback_url=${encodeURIComponent(url)};end`;
150
+ return;
151
+ }
152
+ const openLink = h.Telegram?.WebApp?.openLink;
153
+ if (typeof openLink === 'function') {
154
+ openLink(url);
155
+ return;
156
+ }
157
+ if (IOS_UA.test(ua) && isTelegramHost(h) && url.startsWith('https://')) {
158
+ h.location.href = `x-safari-${url}`;
159
+ return;
160
+ }
161
+ h.open?.(url, '_blank', 'noopener,noreferrer');
162
+ }
163
+ //# sourceMappingURL=platform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/passkey/platform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /** Minimal host surface the JSON helpers need (a browser, or a fake in tests). */
2
+ export interface WebAuthnJsonHost {
3
+ PublicKeyCredential?: unknown;
4
+ atob?: (data: string) => string;
5
+ btoa?: (data: string) => string;
6
+ }
7
+ /** PRF client inputs as sent to `create()`/`get()` (not in every lib.dom). */
8
+ export type PrfClientInputs = AuthenticationExtensionsClientInputs & {
9
+ prf?: {
10
+ eval?: {
11
+ first?: Uint8Array;
12
+ };
13
+ };
14
+ };
15
+ /** PRF results as returned by `getClientExtensionResults()`. */
16
+ export interface PrfClientResults {
17
+ prf?: {
18
+ results?: {
19
+ first?: BufferSource;
20
+ };
21
+ };
22
+ }
23
+ /** Decodes base64url (no padding required) with `atob` semantics. */
24
+ export declare function base64UrlToBytes(value: string): Uint8Array;
25
+ /** Encodes bytes as base64url without padding. */
26
+ export declare function bytesToBase64Url(bytes: Uint8Array): string;
27
+ /** A credential or assertion serialized for the DFX API, PRF results stripped. */
28
+ export type WebAuthnJson = Record<string, unknown>;
29
+ /**
30
+ * Serializes a `PublicKeyCredential` for the API: WebAuthn Level 3 `toJSON()` when present, otherwise by
31
+ * hand. Never carries `clientExtensionResults.prf` (the PRF bytes never leave the tab), but adds
32
+ * `authenticatorAttachment` and attestation `transports`.
33
+ */
34
+ export declare function credentialToJSON(credential: PublicKeyCredential): WebAuthnJson;
35
+ //# sourceMappingURL=webauthn-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webauthn-json.d.ts","sourceRoot":"","sources":["../../src/passkey/webauthn-json.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAChC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACjC;AAED,8EAA8E;AAC9E,MAAM,MAAM,eAAe,GAAG,oCAAoC,GAAG;IACnE,GAAG,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,UAAU,CAAA;SAAE,CAAA;KAAE,CAAC;CACzC,CAAC;AAEF,gEAAgE;AAChE,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,YAAY,CAAA;SAAE,CAAA;KAAE,CAAC;CAC9C;AAMD,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAU1D;AAED,kDAAkD;AAClD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAO1D;AAED,kFAAkF;AAClF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAUnD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,mBAAmB,GAAG,YAAY,CA6C9E"}
@@ -0,0 +1,79 @@
1
+ function host() {
2
+ return globalThis;
3
+ }
4
+ /** Decodes base64url (no padding required) with `atob` semantics. */
5
+ export function base64UrlToBytes(value) {
6
+ const api = host();
7
+ const atob = typeof api.atob === 'function' ? api.atob.bind(api) : undefined;
8
+ if (!atob)
9
+ throw new TypeError('base64url decoding needs atob');
10
+ const padded = value.replace(/-/g, '+').replace(/_/g, '/');
11
+ const pad = padded.length % 4 === 0 ? '' : '='.repeat(4 - (padded.length % 4));
12
+ const binary = atob(`${padded}${pad}`);
13
+ const bytes = new Uint8Array(binary.length);
14
+ for (let i = 0; i < binary.length; i++)
15
+ bytes[i] = binary.charCodeAt(i);
16
+ return bytes;
17
+ }
18
+ /** Encodes bytes as base64url without padding. */
19
+ export function bytesToBase64Url(bytes) {
20
+ const api = host();
21
+ const btoa = typeof api.btoa === 'function' ? api.btoa.bind(api) : undefined;
22
+ if (!btoa)
23
+ throw new TypeError('base64url encoding needs btoa');
24
+ let binary = '';
25
+ for (const byte of bytes)
26
+ binary += String.fromCharCode(byte);
27
+ return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/u, '');
28
+ }
29
+ function withoutPrfResults(json) {
30
+ const ext = json['clientExtensionResults'];
31
+ if (ext === null || typeof ext !== 'object' || Array.isArray(ext))
32
+ return json;
33
+ const next = { ...ext };
34
+ delete next['prf'];
35
+ return { ...json, clientExtensionResults: next };
36
+ }
37
+ /**
38
+ * Serializes a `PublicKeyCredential` for the API: WebAuthn Level 3 `toJSON()` when present, otherwise by
39
+ * hand. Never carries `clientExtensionResults.prf` (the PRF bytes never leave the tab), but adds
40
+ * `authenticatorAttachment` and attestation `transports`.
41
+ */
42
+ export function credentialToJSON(credential) {
43
+ const native = credential;
44
+ let json;
45
+ if (typeof native.toJSON === 'function') {
46
+ json = native.toJSON();
47
+ }
48
+ else {
49
+ const response = credential.response;
50
+ const base = {
51
+ id: credential.id,
52
+ rawId: bytesToBase64Url(new Uint8Array(credential.rawId)),
53
+ type: credential.type,
54
+ clientExtensionResults: credential.getClientExtensionResults(),
55
+ authenticatorAttachment: native.authenticatorAttachment ?? null,
56
+ };
57
+ if (response.attestationObject !== undefined) {
58
+ base['response'] = {
59
+ clientDataJSON: bytesToBase64Url(new Uint8Array(response.clientDataJSON)),
60
+ attestationObject: bytesToBase64Url(new Uint8Array(response.attestationObject)),
61
+ transports: typeof response.getTransports === 'function' ? response.getTransports() : [],
62
+ };
63
+ }
64
+ else {
65
+ base['response'] = {
66
+ clientDataJSON: bytesToBase64Url(new Uint8Array(response.clientDataJSON)),
67
+ authenticatorData: bytesToBase64Url(new Uint8Array(response.authenticatorData ?? new ArrayBuffer(0))),
68
+ signature: bytesToBase64Url(new Uint8Array(response.signature ?? new ArrayBuffer(0))),
69
+ userHandle: response.userHandle === null || response.userHandle === undefined
70
+ ? null
71
+ : bytesToBase64Url(new Uint8Array(response.userHandle)),
72
+ };
73
+ }
74
+ json = base;
75
+ }
76
+ json['authenticatorAttachment'] = native.authenticatorAttachment ?? null;
77
+ return withoutPrfResults(json);
78
+ }
79
+ //# sourceMappingURL=webauthn-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webauthn-json.js","sourceRoot":"","sources":["../../src/passkey/webauthn-json.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { WalletDataApi } from '@dfx.swiss/core';
2
+ import type { SnapshotBlocklists } from './snapshot';
3
+ /**
4
+ * Local blocklist matching over the bundled snapshot, refreshed through the DFX list capability (§9.2).
5
+ * Matching is local and synchronous; a failed refresh keeps the last state.
6
+ */
7
+ export declare class Blocklists {
8
+ private phishingDomains;
9
+ private scamAddresses;
10
+ refreshedAt?: Date;
11
+ constructor(snapshot: SnapshotBlocklists);
12
+ /** Listed host, or a subdomain of one. A trailing DNS dot does not bypass the list. */
13
+ isPhishingDomain(hostname: string): boolean;
14
+ isScamAddress(address: string): boolean;
15
+ get sizes(): {
16
+ phishingDomains: number;
17
+ scamAddresses: number;
18
+ };
19
+ /** Best-effort refresh through the DFX API; never throws. */
20
+ refresh(walletData: WalletDataApi, now?: Date): Promise<void>;
21
+ }
22
+ //# sourceMappingURL=blocklist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocklist.d.ts","sourceRoot":"","sources":["../../src/providers/blocklist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,eAAe,CAAc;IACrC,OAAO,CAAC,aAAa,CAAc;IACnC,WAAW,CAAC,EAAE,IAAI,CAAC;gBAEP,QAAQ,EAAE,kBAAkB;IAKxC,uFAAuF;IACvF,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAS3C,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIvC,IAAI,KAAK,IAAI;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAE9D;IAED,6DAA6D;IACvD,OAAO,CAAC,UAAU,EAAE,aAAa,EAAE,GAAG,OAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CAa1E"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Local blocklist matching over the bundled snapshot, refreshed through the DFX list capability (§9.2).
3
+ * Matching is local and synchronous; a failed refresh keeps the last state.
4
+ */
5
+ export class Blocklists {
6
+ constructor(snapshot) {
7
+ this.phishingDomains = new Set(snapshot.phishingDomains.map(canonicalHost));
8
+ this.scamAddresses = new Set(snapshot.scamAddresses.map((a) => a.toLowerCase()));
9
+ }
10
+ /** Listed host, or a subdomain of one. A trailing DNS dot does not bypass the list. */
11
+ isPhishingDomain(hostname) {
12
+ let host = canonicalHost(hostname);
13
+ while (host.includes('.')) {
14
+ if (this.phishingDomains.has(host))
15
+ return true;
16
+ host = host.slice(host.indexOf('.') + 1);
17
+ }
18
+ return false;
19
+ }
20
+ isScamAddress(address) {
21
+ return this.scamAddresses.has(address.toLowerCase());
22
+ }
23
+ get sizes() {
24
+ return { phishingDomains: this.phishingDomains.size, scamAddresses: this.scamAddresses.size };
25
+ }
26
+ /** Best-effort refresh through the DFX API; never throws. */
27
+ async refresh(walletData, now = new Date()) {
28
+ try {
29
+ const [domains, addresses] = await Promise.all([
30
+ walletData.list('PhishingDomains'),
31
+ walletData.list('ScamAddresses'),
32
+ ]);
33
+ if (isStringArray(domains))
34
+ this.phishingDomains = new Set(domains.map(canonicalHost));
35
+ if (isStringArray(addresses))
36
+ this.scamAddresses = new Set(addresses.map((a) => a.toLowerCase()));
37
+ this.refreshedAt = now;
38
+ }
39
+ catch {
40
+ // keep the bundled state; the next refresh retries
41
+ }
42
+ }
43
+ }
44
+ function isStringArray(value) {
45
+ return Array.isArray(value) && value.every((entry) => typeof entry === 'string');
46
+ }
47
+ /** Lower case, trailing dots removed. The matcher never consults a single label such as `com`. */
48
+ function canonicalHost(value) {
49
+ return value.trim().toLowerCase().replace(/\.+$/, '');
50
+ }
51
+ //# sourceMappingURL=blocklist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocklist.js","sourceRoot":"","sources":["../../src/providers/blocklist.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,OAAO,UAAU;IAKrB,YAAY,QAA4B;QACtC,IAAI,CAAC,eAAe,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;QAC5E,IAAI,CAAC,aAAa,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACnF,CAAC;IAED,uFAAuF;IACvF,gBAAgB,CAAC,QAAgB;QAC/B,IAAI,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;YAChD,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,aAAa,CAAC,OAAe;QAC3B,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,KAAK;QACP,OAAO,EAAE,eAAe,EAAE,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;IAChG,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,OAAO,CAAC,UAAyB,EAAE,GAAG,GAAG,IAAI,IAAI,EAAE;QACvD,IAAI,CAAC;YACH,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBAC7C,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC;gBAClC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC;aACjC,CAAC,CAAC;YACH,IAAI,aAAa,CAAC,OAAO,CAAC;gBAAE,IAAI,CAAC,eAAe,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;YACvF,IAAI,aAAa,CAAC,SAAS,CAAC;gBAAE,IAAI,CAAC,aAAa,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;YAClG,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;QACrD,CAAC;IACH,CAAC;CACF;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;AACnF,CAAC;AAED,kGAAkG;AAClG,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ChainInfo } from '@dfx.swiss/core';
2
+ import type { WalletEnv } from '../config/environment';
3
+ import type { WalletSnapshot } from './snapshot';
4
+ /**
5
+ * The chains the wallet may use, from the DFX chain classification (D23) with a release-pinned snapshot as
6
+ * the offline fallback. `walletSupported` already encodes the environment rule server-side (PRD: mainnets;
7
+ * DEV/LOC: testnets + Spark); the registry additionally ties Bitcoin to the compiled network of the
8
+ * environment and only ever exposes EVM chains with a numeric chain id.
9
+ */
10
+ export declare class ChainRegistry {
11
+ private readonly chains;
12
+ private readonly source;
13
+ private constructor();
14
+ static fromApi(chains: ChainInfo[]): ChainRegistry;
15
+ static fromSnapshot(snapshot: WalletSnapshot): ChainRegistry;
16
+ get isLive(): boolean;
17
+ all(): ChainInfo[];
18
+ /** Bitcoin of this environment (PRD mainnet, DEV/LOC testnet4), `walletSupported` checked. */
19
+ bitcoin(env: WalletEnv): ChainInfo;
20
+ /** Every wallet-supported EVM chain of the environment kind; Haqq (no chain id) is never included. */
21
+ evmChains(env: WalletEnv): ChainInfo[];
22
+ evmChain(chainId: number): ChainInfo;
23
+ /** Spark runs on mainnet in every environment (D28). */
24
+ spark(): ChainInfo;
25
+ }
26
+ //# sourceMappingURL=chain-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain-registry.d.ts","sourceRoot":"","sources":["../../src/providers/chain-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAkB,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAOjD;;;;;GAKG;AACH,qBAAa,aAAa;IAEtB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFzB,OAAO;IAKP,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,aAAa;IAIlD,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,cAAc,GAAG,aAAa;IAI5D,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,GAAG,IAAI,SAAS,EAAE;IAIlB,8FAA8F;IAC9F,OAAO,CAAC,GAAG,EAAE,SAAS,GAAG,SAAS;IAOlC,sGAAsG;IACtG,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,SAAS,EAAE;IAWtC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS;IAMpC,wDAAwD;IACxD,KAAK,IAAI,SAAS;CAKnB"}
@@ -0,0 +1,59 @@
1
+ import { WALLET_NETWORKS } from '../config/environment';
2
+ import { WalletError } from '../util/errors';
3
+ function bitcoinBlockchain(network) {
4
+ return network === 'mainnet' ? 'Bitcoin' : 'BitcoinTestnet4';
5
+ }
6
+ /**
7
+ * The chains the wallet may use, from the DFX chain classification (D23) with a release-pinned snapshot as
8
+ * the offline fallback. `walletSupported` already encodes the environment rule server-side (PRD: mainnets;
9
+ * DEV/LOC: testnets + Spark); the registry additionally ties Bitcoin to the compiled network of the
10
+ * environment and only ever exposes EVM chains with a numeric chain id.
11
+ */
12
+ export class ChainRegistry {
13
+ constructor(chains, source) {
14
+ this.chains = chains;
15
+ this.source = source;
16
+ }
17
+ static fromApi(chains) {
18
+ return new ChainRegistry(chains, 'api');
19
+ }
20
+ static fromSnapshot(snapshot) {
21
+ return new ChainRegistry(snapshot.chains, 'snapshot');
22
+ }
23
+ get isLive() {
24
+ return this.source === 'api';
25
+ }
26
+ all() {
27
+ return this.chains;
28
+ }
29
+ /** Bitcoin of this environment (PRD mainnet, DEV/LOC testnet4), `walletSupported` checked. */
30
+ bitcoin(env) {
31
+ const network = WALLET_NETWORKS[env].bitcoin;
32
+ const chain = this.chains.find((c) => c.blockchain === bitcoinBlockchain(network) && c.walletSupported);
33
+ if (!chain)
34
+ throw new WalletError('chain-unavailable', `Bitcoin (${network}) is not available in this environment`);
35
+ return chain;
36
+ }
37
+ /** Every wallet-supported EVM chain of the environment kind; Haqq (no chain id) is never included. */
38
+ evmChains(env) {
39
+ const kind = WALLET_NETWORKS[env].evm;
40
+ return this.chains.filter((chain) => chain.family === 'Evm' &&
41
+ chain.chainId !== undefined &&
42
+ chain.walletSupported &&
43
+ (kind === 'mainnet' ? !chain.isTestnet : chain.isTestnet));
44
+ }
45
+ evmChain(chainId) {
46
+ const chain = this.chains.find((c) => c.family === 'Evm' && c.chainId === chainId && c.walletSupported);
47
+ if (!chain)
48
+ throw new WalletError('chain-unavailable', `Chain ${chainId} is not wallet-supported`);
49
+ return chain;
50
+ }
51
+ /** Spark runs on mainnet in every environment (D28). */
52
+ spark() {
53
+ const chain = this.chains.find((c) => c.family === 'Spark' && c.walletSupported);
54
+ if (!chain)
55
+ throw new WalletError('chain-unavailable', 'Spark is not available in this environment');
56
+ return chain;
57
+ }
58
+ }
59
+ //# sourceMappingURL=chain-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain-registry.js","sourceRoot":"","sources":["../../src/providers/chain-registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,SAAS,iBAAiB,CAAC,OAAuB;IAChD,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAE,SAAwB,CAAC,CAAC,CAAE,iBAAgC,CAAC;AAC/F,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,aAAa;IACxB,YACmB,MAAmB,EACnB,MAA0B;QAD1B,WAAM,GAAN,MAAM,CAAa;QACnB,WAAM,GAAN,MAAM,CAAoB;IAC1C,CAAC;IAEJ,MAAM,CAAC,OAAO,CAAC,MAAmB;QAChC,OAAO,IAAI,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,CAAC,YAAY,CAAC,QAAwB;QAC1C,OAAO,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC;IAC/B,CAAC;IAED,GAAG;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,8FAA8F;IAC9F,OAAO,CAAC,GAAc;QACpB,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;QAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC,CAAC;QACxG,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,WAAW,CAAC,mBAAmB,EAAE,YAAY,OAAO,wCAAwC,CAAC,CAAC;QACpH,OAAO,KAAK,CAAC;IACf,CAAC;IAED,sGAAsG;IACtG,SAAS,CAAC,GAAc;QACtB,MAAM,IAAI,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;QACtC,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CACvB,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,MAAM,KAAK,KAAK;YACtB,KAAK,CAAC,OAAO,KAAK,SAAS;YAC3B,KAAK,CAAC,eAAe;YACrB,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAC5D,CAAC;IACJ,CAAC;IAED,QAAQ,CAAC,OAAe;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,eAAe,CAAC,CAAC;QACxG,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,WAAW,CAAC,mBAAmB,EAAE,SAAS,OAAO,0BAA0B,CAAC,CAAC;QACnG,OAAO,KAAK,CAAC;IACf,CAAC;IAED,wDAAwD;IACxD,KAAK;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,IAAI,CAAC,CAAC,eAAe,CAAC,CAAC;QACjF,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,WAAW,CAAC,mBAAmB,EAAE,4CAA4C,CAAC,CAAC;QACrG,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
@@ -0,0 +1,25 @@
1
+ import type { ChainApi, WalletDataApi } from '@dfx.swiss/core';
2
+ import { WalletError } from '../util/errors';
3
+ /** The DFX data capability is unreachable (rate-limited out, network, or paused server-side). */
4
+ export declare class ProviderUnavailableError extends WalletError {
5
+ constructor(cause?: unknown);
6
+ }
7
+ export interface DfxDataOptions {
8
+ /** Retries on 429/5xx with linear backoff (default 2). */
9
+ retries?: number;
10
+ backoffMs?: (attempt: number) => number;
11
+ }
12
+ /**
13
+ * Every wallet data call goes through the DFX API (D8): two retries with backoff on 429/5xx, everything
14
+ * else fails fast; after the last attempt the wallet shows "unavailable" instead of guessing.
15
+ */
16
+ export declare class DfxData {
17
+ private readonly walletData;
18
+ private readonly chain;
19
+ private readonly options;
20
+ constructor(walletData: WalletDataApi, chain: ChainApi, options?: DfxDataOptions);
21
+ chains<T>(run: (chain: ChainApi) => Promise<T>): Promise<T>;
22
+ query<T>(run: (walletData: WalletDataApi) => Promise<T>): Promise<T>;
23
+ private run;
24
+ }
25
+ //# sourceMappingURL=dfx-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dfx-data.d.ts","sourceRoot":"","sources":["../../src/providers/dfx-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,iGAAiG;AACjG,qBAAa,wBAAyB,SAAQ,WAAW;gBAC3C,KAAK,CAAC,EAAE,OAAO;CAG5B;AAED,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CACzC;AAED;;;GAGG;AACH,qBAAa,OAAO;IAEhB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAFP,UAAU,EAAE,aAAa,EACzB,KAAK,EAAE,QAAQ,EACf,OAAO,GAAE,cAAmB;IAGzC,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAI3D,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;YAI5D,GAAG;CAiBlB"}
@@ -0,0 +1,44 @@
1
+ import { ApiException } from '@dfx.swiss/core';
2
+ import { WalletError } from '../util/errors';
3
+ /** The DFX data capability is unreachable (rate-limited out, network, or paused server-side). */
4
+ export class ProviderUnavailableError extends WalletError {
5
+ constructor(cause) {
6
+ super('provider-unavailable', 'The DFX wallet data capability is currently unavailable', { cause });
7
+ }
8
+ }
9
+ /**
10
+ * Every wallet data call goes through the DFX API (D8): two retries with backoff on 429/5xx, everything
11
+ * else fails fast; after the last attempt the wallet shows "unavailable" instead of guessing.
12
+ */
13
+ export class DfxData {
14
+ constructor(walletData, chain, options = {}) {
15
+ this.walletData = walletData;
16
+ this.chain = chain;
17
+ this.options = options;
18
+ }
19
+ async chains(run) {
20
+ return this.run(() => run(this.chain));
21
+ }
22
+ async query(run) {
23
+ return this.run(() => run(this.walletData));
24
+ }
25
+ async run(call) {
26
+ const retries = this.options.retries ?? 2;
27
+ const backoff = this.options.backoffMs ?? ((attempt) => 250 * (attempt + 1));
28
+ for (let attempt = 0;; attempt++) {
29
+ try {
30
+ return await call();
31
+ }
32
+ catch (error) {
33
+ const retryable = error instanceof ApiException && (error.statusCode === 429 || error.statusCode >= 500);
34
+ if (!retryable || attempt >= retries) {
35
+ if (error instanceof WalletError)
36
+ throw error;
37
+ throw new ProviderUnavailableError(error);
38
+ }
39
+ await new Promise((resolve) => setTimeout(resolve, backoff(attempt)));
40
+ }
41
+ }
42
+ }
43
+ }
44
+ //# sourceMappingURL=dfx-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dfx-data.js","sourceRoot":"","sources":["../../src/providers/dfx-data.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,iGAAiG;AACjG,MAAM,OAAO,wBAAyB,SAAQ,WAAW;IACvD,YAAY,KAAe;QACzB,KAAK,CAAC,sBAAsB,EAAE,yDAAyD,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACtG,CAAC;CACF;AAQD;;;GAGG;AACH,MAAM,OAAO,OAAO;IAClB,YACmB,UAAyB,EACzB,KAAe,EACf,UAA0B,EAAE;QAF5B,eAAU,GAAV,UAAU,CAAe;QACzB,UAAK,GAAL,KAAK,CAAU;QACf,YAAO,GAAP,OAAO,CAAqB;IAC5C,CAAC;IAEJ,KAAK,CAAC,MAAM,CAAI,GAAoC;QAClD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,KAAK,CAAI,GAA8C;QAC3D,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IAC9C,CAAC;IAEO,KAAK,CAAC,GAAG,CAAI,IAAsB;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,OAAe,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;QAErF,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,EAAE,EAAE,CAAC;YAClC,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,EAAE,CAAC;YACtB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,SAAS,GAAG,KAAK,YAAY,YAAY,IAAI,CAAC,KAAK,CAAC,UAAU,KAAK,GAAG,IAAI,KAAK,CAAC,UAAU,IAAI,GAAG,CAAC,CAAC;gBACzG,IAAI,CAAC,SAAS,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;oBACrC,IAAI,KAAK,YAAY,WAAW;wBAAE,MAAM,KAAK,CAAC;oBAC9C,MAAM,IAAI,wBAAwB,CAAC,KAAK,CAAC,CAAC;gBAC5C,CAAC;gBACD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,34 @@
1
+ import type { WalletDataApi } from '@dfx.swiss/core';
2
+ /** A price older than this is stale; a stale price must not enter a fiat amount (§9.6). */
3
+ export declare const PRICE_STALE_MS: number;
4
+ export type PricedAsset = {
5
+ assetId: number;
6
+ price?: number;
7
+ stale?: boolean;
8
+ };
9
+ export interface PricePolicyOptions {
10
+ now?: () => number;
11
+ }
12
+ /**
13
+ * Fiat prices of public assets, always by asset id — never by symbol (D32). A missing asset is simply
14
+ * unpriced ("–"); a stale price is returned as stale so callers can refuse fiat entry (§9.6). Prices never
15
+ * feed fee caps.
16
+ */
17
+ export declare class PricePolicy {
18
+ private readonly walletData;
19
+ private readonly options;
20
+ constructor(walletData: WalletDataApi, options?: PricePolicyOptions);
21
+ prices(assetIds: number[], currency: string, now?: () => number): Promise<Map<number, {
22
+ price: number;
23
+ stale: boolean;
24
+ }>>;
25
+ /** Convenience: price with staleness, or `undefined` when the asset has none. */
26
+ priceOf(prices: Map<number, {
27
+ price: number;
28
+ stale: boolean;
29
+ }>, assetId: number): {
30
+ price: number;
31
+ stale: boolean;
32
+ } | undefined;
33
+ }
34
+ //# sourceMappingURL=price.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"price.d.ts","sourceRoot":"","sources":["../../src/providers/price.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,iBAAiB,CAAC;AAIlE,2FAA2F;AAC3F,eAAO,MAAM,cAAc,QAAgB,CAAC;AAE5C,MAAM,MAAM,WAAW,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE/E,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,UAAU,EAAE,aAAa,EACzB,OAAO,GAAE,kBAAuB;IAG7C,MAAM,CACV,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,EAAE,MAAM,EAChB,GAAG,SAjBO,MAiBwB,GACjC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAwB1D,iFAAiF;IACjF,OAAO,CACL,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,EACtD,OAAO,EAAE,MAAM,GACd;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS;CAGjD"}