@solana-mobile/wallet-standard-mobile 0.5.2 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,170 +1,62 @@
1
- import { SolanaSignAndSendTransaction, SolanaSignIn, SolanaSignMessage, SolanaSignTransaction } from "@solana/wallet-standard-features";
1
+ import { base58FromUint8Array, base58ToUint8Array, base64FromUint8Array, base64ToUint8Array } from "@solana-mobile/mobile-wallet-adapter-protocol/encoding";
2
+ import { SOLANA_MAINNET_CHAIN } from "@solana/wallet-standard-chains";
3
+ import { registerWallet } from "@wallet-standard/wallet";
2
4
  import { SolanaMobileWalletAdapterError, SolanaMobileWalletAdapterErrorCode, startRemoteScenario, startScenario } from "@solana-mobile/mobile-wallet-adapter-protocol";
5
+ import { SolanaSignAndSendTransaction, SolanaSignIn, SolanaSignMessage, SolanaSignTransaction } from "@solana/wallet-standard-features";
3
6
  import { StandardConnect, StandardDisconnect, StandardEvents } from "@wallet-standard/features";
4
- import base58 from "bs58";
5
7
  import QRCode from "qrcode";
6
- import { registerWallet } from "@wallet-standard/wallet";
7
- import { SOLANA_MAINNET_CHAIN } from "@solana/wallet-standard-chains";
8
- //#region src/base64Utils.ts
9
- function fromUint8Array(byteArray) {
10
- return window.btoa(String.fromCharCode.call(null, ...byteArray));
11
- }
12
- function toUint8Array(base64EncodedByteArray) {
13
- return new Uint8Array(window.atob(base64EncodedByteArray).split("").map((c) => c.charCodeAt(0)));
8
+ //#region src/createDefaultAuthorizationCache.ts
9
+ const CACHE_KEY = "SolanaMobileWalletAdapterDefaultAuthorizationCache";
10
+ function createDefaultAuthorizationCache() {
11
+ let storage;
12
+ try {
13
+ storage = window.localStorage;
14
+ } catch {}
15
+ return {
16
+ async clear() {
17
+ if (!storage) return;
18
+ try {
19
+ storage.removeItem(CACHE_KEY);
20
+ } catch {}
21
+ },
22
+ async get() {
23
+ if (!storage) return;
24
+ try {
25
+ const parsed = JSON.parse(storage.getItem(CACHE_KEY));
26
+ if (parsed && parsed.accounts) {
27
+ const parsedAccounts = parsed.accounts.map((account) => {
28
+ return {
29
+ ...account,
30
+ publicKey: "publicKey" in account ? new Uint8Array(Object.values(account.publicKey)) : base58ToUint8Array(account.address)
31
+ };
32
+ });
33
+ return {
34
+ ...parsed,
35
+ accounts: parsedAccounts
36
+ };
37
+ } else return parsed || void 0;
38
+ } catch {}
39
+ },
40
+ async set(authorization) {
41
+ if (!storage) return;
42
+ try {
43
+ storage.setItem(CACHE_KEY, JSON.stringify(authorization));
44
+ } catch {}
45
+ }
46
+ };
14
47
  }
15
48
  //#endregion
16
- //#region src/embedded-modal/loadingSpinner.ts
17
- const modalHtml$1 = `
18
- <div class="mobile-wallet-adapter-embedded-loading-indicator" role="dialog" aria-modal="true" aria-labelledby="modal-title">
19
- <div data-modal-close style="position: absolute; width: 100%; height: 100%;"></div>
20
- <div class="mobile-wallet-adapter-embedded-loading-container">
21
- <div class="mobile-wallet-adapter-embedded-loading-animation"></div>
22
- </div>
23
- </div>
24
- `;
25
- const css$6 = `
26
- .mobile-wallet-adapter-embedded-loading-indicator {
27
- display: flex; /* Use flexbox to center content */
28
- justify-content: center; /* Center horizontally */
29
- align-items: start; /* Center vertically */
30
- position: fixed; /* Stay in place */
31
- z-index: 1; /* Sit on top */
32
- left: 0;
33
- top: 0;
34
- width: 100%; /* Full width */
35
- height: 100%; /* Full height */
36
- background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
37
- overflow-y: auto; /* enable scrolling */
38
- }
39
-
40
- .mobile-wallet-adapter-embedded-loading-container {
41
- display: flex;
42
- margin: auto;
43
- }
44
-
45
- .mobile-wallet-adapter-embedded-loading-animation {
46
- position: relative;
47
- left: -9999px;
48
- width: 10px;
49
- height: 10px;
50
- border-radius: 5px;
51
- background-color: var(--spinner-color);
52
- color: var(--spinner-color);
53
- box-shadow: 9984px 0 0 0 var(--spinner-color),
54
- 9999px 0 0 0 var(--spinner-color),
55
- 10014px 0 0 0 var(--spinner-color);
56
- animation: dot-typing 1.5s infinite linear;
57
- }
58
-
59
- @keyframes dot-typing {
60
- 0% {
61
- box-shadow: 9984px 0 0 0 var(--spinner-color),
62
- 9999px 0 0 0 var(--spinner-color),
63
- 10014px 0 0 0 var(--spinner-color);
64
- }
65
- 16.667% {
66
- box-shadow: 9984px -10px 0 0 var(--spinner-color),
67
- 9999px 0 0 0 var(--spinner-color),
68
- 10014px 0 0 0 var(--spinner-color);
69
- }
70
- 33.333% {
71
- box-shadow: 9984px 0 0 0 var(--spinner-color),
72
- 9999px 0 0 0 var(--spinner-color),
73
- 10014px 0 0 0 var(--spinner-color);
74
- }
75
- 50% {
76
- box-shadow: 9984px 0 0 0 var(--spinner-color),
77
- 9999px -10px 0 0 var(--spinner-color),
78
- 10014px 0 0 0 var(--spinner-color);
79
- }
80
- 66.667% {
81
- box-shadow: 9984px 0 0 0 var(--spinner-color),
82
- 9999px 0 0 0 var(--spinner-color),
83
- 10014px 0 0 0 var(--spinner-color);
84
- }
85
- 83.333% {
86
- box-shadow: 9984px 0 0 0 var(--spinner-color),
87
- 9999px 0 0 0 var(--spinner-color),
88
- 10014px -10px 0 0 var(--spinner-color);
89
- }
90
- 100% {
91
- box-shadow: 9984px 0 0 0 var(--spinner-color),
92
- 9999px 0 0 0 var(--spinner-color),
93
- 10014px 0 0 0 var(--spinner-color);
94
- }
49
+ //#region src/createDefaultChainSelector.ts
50
+ function createDefaultChainSelector() {
51
+ return { async select(chains) {
52
+ if (chains.length === 1) return chains[0];
53
+ else if (chains.includes(SOLANA_MAINNET_CHAIN)) return SOLANA_MAINNET_CHAIN;
54
+ else return chains[0];
55
+ } };
95
56
  }
96
- `;
97
- var EmbeddedLoadingSpinner = class {
98
- #root = null;
99
- #eventListeners = {};
100
- #listenersAttached = false;
101
- dom = null;
102
- constructor() {
103
- this.init = this.init.bind(this);
104
- this.#root = document.getElementById("mobile-wallet-adapter-embedded-root-ui");
105
- }
106
- async init() {
107
- console.log("Injecting modal");
108
- this.#injectHTML();
109
- }
110
- open = () => {
111
- console.debug("Modal open");
112
- this.#attachEventListeners();
113
- if (this.#root) this.#root.style.display = "flex";
114
- };
115
- close = (event = void 0) => {
116
- console.debug("Modal close");
117
- this.#removeEventListeners();
118
- if (this.#root) this.#root.style.display = "none";
119
- this.#eventListeners["close"]?.forEach((listener) => listener(event));
120
- };
121
- addEventListener(event, listener) {
122
- this.#eventListeners[event]?.push(listener) || (this.#eventListeners[event] = [listener]);
123
- return () => this.removeEventListener(event, listener);
124
- }
125
- removeEventListener(event, listener) {
126
- this.#eventListeners[event] = this.#eventListeners[event]?.filter((existingListener) => listener !== existingListener);
127
- }
128
- #injectHTML() {
129
- if (this.dom) return;
130
- this.#root = document.createElement("div");
131
- this.#root.id = "mobile-wallet-adapter-embedded-root-ui";
132
- this.#root.innerHTML = modalHtml$1;
133
- this.#root.style.display = "none";
134
- const styles = document.createElement("style");
135
- styles.id = "mobile-wallet-adapter-embedded-modal-styles";
136
- styles.textContent = css$6;
137
- const host = document.createElement("div");
138
- this.dom = host.attachShadow({ mode: "closed" });
139
- host.style.setProperty("--spinner-color", "#FFFFFF");
140
- this.dom.appendChild(styles);
141
- this.dom.appendChild(this.#root);
142
- document.body.appendChild(host);
143
- }
144
- #attachEventListeners() {
145
- if (!this.#root || this.#listenersAttached) return;
146
- [...this.#root.querySelectorAll("[data-modal-close]")].forEach((closer) => closer?.addEventListener("click", (event) => {
147
- this.close(event);
148
- }));
149
- window.addEventListener("load", this.close);
150
- document.addEventListener("keydown", this.#handleKeyDown);
151
- this.#listenersAttached = true;
152
- }
153
- #removeEventListeners() {
154
- if (!this.#listenersAttached) return;
155
- window.removeEventListener("load", this.close);
156
- document.removeEventListener("keydown", this.#handleKeyDown);
157
- if (!this.#root) return;
158
- [...this.#root.querySelectorAll("[data-modal-close]")].forEach((closer) => closer?.removeEventListener("click", this.close));
159
- this.#listenersAttached = false;
160
- }
161
- #handleKeyDown = (event) => {
162
- if (event.key === "Escape") this.close(event);
163
- };
164
- };
165
57
  //#endregion
166
58
  //#region src/embedded-modal/modal.ts
167
- const modalHtml = `
59
+ const modalHtml$1 = `
168
60
  <div class="mobile-wallet-adapter-embedded-modal-container" role="dialog" aria-modal="true" aria-labelledby="modal-title">
169
61
  <div data-modal-close style="position: absolute; width: 100%; height: 100%;"></div>
170
62
  <div class="mobile-wallet-adapter-embedded-modal-card">
@@ -179,7 +71,7 @@ const modalHtml = `
179
71
  </div>
180
72
  </div>
181
73
  `;
182
- const css$5 = `
74
+ const css$6 = `
183
75
  .mobile-wallet-adapter-embedded-modal-container {
184
76
  display: flex; /* Use flexbox to center content */
185
77
  justify-content: center; /* Center horizontally */
@@ -279,13 +171,13 @@ var EmbeddedModal = class {
279
171
  }
280
172
  this.#root = document.createElement("div");
281
173
  this.#root.id = "mobile-wallet-adapter-embedded-root-ui";
282
- this.#root.innerHTML = modalHtml;
174
+ this.#root.innerHTML = modalHtml$1;
283
175
  this.#root.style.display = "none";
284
176
  const content = this.#root.querySelector(".mobile-wallet-adapter-embedded-modal-content");
285
177
  if (content) content.innerHTML = this.contentHtml;
286
178
  const styles = document.createElement("style");
287
179
  styles.id = "mobile-wallet-adapter-embedded-modal-styles";
288
- styles.textContent = css$5 + this.contentStyles;
180
+ styles.textContent = css$6 + this.contentStyles;
289
181
  const host = document.createElement("div");
290
182
  host.innerHTML = fonts;
291
183
  this.dom = host.attachShadow({ mode: "closed" });
@@ -313,292 +205,124 @@ var EmbeddedModal = class {
313
205
  };
314
206
  };
315
207
  //#endregion
316
- //#region src/embedded-modal/remoteConnectionModal.ts
317
- var RemoteConnectionModal = class extends EmbeddedModal {
318
- contentStyles = css$4;
319
- contentHtml = QRCodeHtml;
320
- async initWithQR(qrCode) {
208
+ //#region src/embedded-modal/errorModal.ts
209
+ const WALLET_NOT_FOUND_ERROR_MESSAGE = "To use mobile wallet adapter, you must have a compatible mobile wallet application installed on your device.";
210
+ const BROWSER_NOT_SUPPORTED_ERROR_MESSAGE = "This browser appears to be incompatible with mobile wallet adapter. Open this page in a compatible mobile browser app and try again.";
211
+ var ErrorModal = class extends EmbeddedModal {
212
+ contentStyles = css$5;
213
+ contentHtml = ErrorDialogHtml$3;
214
+ initWithError(error) {
321
215
  super.init();
322
- this.populateQRCode(qrCode);
216
+ this.populateError(error);
323
217
  }
324
- async populateQRCode(qrUrl) {
325
- const qrcodeContainer = this.dom?.getElementById("mobile-wallet-adapter-embedded-modal-qr-code-container");
326
- if (qrcodeContainer) {
327
- const qrCodeElement = await QRCode.toCanvas(qrUrl, {
328
- width: 200,
329
- margin: 0
330
- });
331
- if (qrcodeContainer.firstElementChild !== null) qrcodeContainer.replaceChild(qrCodeElement, qrcodeContainer.firstElementChild);
332
- else qrcodeContainer.appendChild(qrCodeElement);
333
- const qrPlaceholder = this.dom?.getElementById("mobile-wallet-adapter-embedded-modal-qr-placeholder");
334
- if (qrPlaceholder) qrPlaceholder.style.display = "none";
335
- } else console.error("QRCode Container not found");
218
+ populateError(error) {
219
+ const errorMessageElement = this.dom?.getElementById("mobile-wallet-adapter-error-message");
220
+ const actionBtn = this.dom?.getElementById("mobile-wallet-adapter-error-action");
221
+ if (errorMessageElement) {
222
+ if (error.name === "SolanaMobileWalletAdapterError") switch (error.code) {
223
+ case "ERROR_WALLET_NOT_FOUND":
224
+ errorMessageElement.innerHTML = WALLET_NOT_FOUND_ERROR_MESSAGE;
225
+ if (actionBtn) actionBtn.addEventListener("click", () => {
226
+ window.location.href = "https://solanamobile.com/wallets";
227
+ });
228
+ return;
229
+ case "ERROR_BROWSER_NOT_SUPPORTED":
230
+ errorMessageElement.innerHTML = BROWSER_NOT_SUPPORTED_ERROR_MESSAGE;
231
+ if (actionBtn) actionBtn.style.display = "none";
232
+ return;
233
+ }
234
+ errorMessageElement.innerHTML = `An unexpected error occurred: ${error.message}`;
235
+ } else console.log("Failed to locate error dialog element");
336
236
  }
337
237
  };
338
- const QRCodeHtml = `
339
- <div class="mobile-wallet-adapter-embedded-modal-qr-content">
340
- <div>
341
- <svg class="mobile-wallet-adapter-embedded-modal-icon" width="100%" height="100%">
342
- <circle r="52" cx="53" cy="53" fill="#99b3be" stroke="#000000" stroke-width="2"/>
343
- <path d="m 53,82.7305 c -3.3116,0 -6.1361,-1.169 -8.4735,-3.507 -2.338,-2.338 -3.507,-5.1625 -3.507,-8.4735 0,-3.3116 1.169,-6.1364 3.507,-8.4744 2.3374,-2.338 5.1619,-3.507 8.4735,-3.507 3.3116,0 6.1361,1.169 8.4735,3.507 2.338,2.338 3.507,5.1628 3.507,8.4744 0,3.311 -1.169,6.1355 -3.507,8.4735 -2.3374,2.338 -5.1619,3.507 -8.4735,3.507 z m 0.007,-5.25 c 1.8532,0 3.437,-0.6598 4.7512,-1.9793 1.3149,-1.3195 1.9723,-2.9058 1.9723,-4.7591 0,-1.8526 -0.6598,-3.4364 -1.9793,-4.7512 -1.3195,-1.3149 -2.9055,-1.9723 -4.7582,-1.9723 -1.8533,0 -3.437,0.6598 -4.7513,1.9793 -1.3148,1.3195 -1.9722,2.9058 -1.9722,4.7591 0,1.8527 0.6597,3.4364 1.9792,4.7512 1.3195,1.3149 2.9056,1.9723 4.7583,1.9723 z m -28,-33.5729 -3.85,-3.6347 c 4.1195,-4.025 8.8792,-7.1984 14.2791,-9.52 5.4005,-2.3223 11.2551,-3.4834 17.5639,-3.4834 6.3087,0 12.1634,1.1611 17.5639,3.4834 5.3999,2.3216 10.1596,5.495 14.2791,9.52 l -3.85,3.6347 C 77.2999,40.358 73.0684,37.5726 68.2985,35.5514 63.5292,33.5301 58.4296,32.5195 53,32.5195 c -5.4297,0 -10.5292,1.0106 -15.2985,3.0319 -4.7699,2.0212 -9.0014,4.8066 -12.6945,8.3562 z m 44.625,10.8771 c -2.2709,-2.1046 -4.7962,-3.7167 -7.5758,-4.8361 -2.7795,-1.12 -5.7983,-1.68 -9.0562,-1.68 -3.2579,0 -6.2621,0.56 -9.0125,1.68 -2.7504,1.1194 -5.2903,2.7315 -7.6195,4.8361 L 32.5189,51.15 c 2.8355,-2.6028 5.9777,-4.6086 9.4263,-6.0174 3.4481,-1.4087 7.133,-2.1131 11.0548,-2.1131 3.9217,0 7.5979,0.7044 11.0285,2.1131 3.43,1.4088 6.5631,3.4146 9.3992,6.0174 z"/>
344
- </svg>
345
- <div class="mobile-wallet-adapter-embedded-modal-title">Remote Mobile Wallet Adapter</div>
346
- </div>
347
- <div>
348
- <div>
349
- <h4 class="mobile-wallet-adapter-embedded-modal-qr-label">
350
- Open your wallet and scan this code
351
- </h4>
352
- </div>
353
- <div id="mobile-wallet-adapter-embedded-modal-qr-code-container" class="mobile-wallet-adapter-embedded-modal-qr-code-container">
354
- <div id="mobile-wallet-adapter-embedded-modal-qr-placeholder" class="mobile-wallet-adapter-embedded-modal-qr-placeholder"></div>
355
- </div>
356
- </div>
357
- </div>
358
- <div class="mobile-wallet-adapter-embedded-modal-divider"><hr></div>
359
- <div class="mobile-wallet-adapter-embedded-modal-footer">
360
- <div class="mobile-wallet-adapter-embedded-modal-subtitle">
361
- Follow the instructions on your device. When you're finished, this screen will update.
362
- </div>
363
- <div class="mobile-wallet-adapter-embedded-modal-progress-badge">
364
- <div>
365
- <div class="spinner">
366
- <div class="leftWrapper">
367
- <div class="left">
368
- <div class="circle"></div>
369
- </div>
370
- </div>
371
- <div class="rightWrapper">
372
- <div class="right">
373
- <div class="circle"></div>
374
- </div>
375
- </div>
376
- </div>
377
- </div>
378
- <div>Waiting for scan</div>
379
- </div>
238
+ const ErrorDialogHtml$3 = `
239
+ <svg class="mobile-wallet-adapter-embedded-modal-error-icon" xmlns="http://www.w3.org/2000/svg" height="50px" viewBox="0 -960 960 960" width="50px" fill="#000000"><path d="M 280,-80 Q 197,-80 138.5,-138.5 80,-197 80,-280 80,-363 138.5,-421.5 197,-480 280,-480 q 83,0 141.5,58.5 58.5,58.5 58.5,141.5 0,83 -58.5,141.5 Q 363,-80 280,-80 Z M 824,-120 568,-376 Q 556,-389 542.5,-402.5 529,-416 516,-428 q 38,-24 61,-64 23,-40 23,-88 0,-75 -52.5,-127.5 Q 495,-760 420,-760 345,-760 292.5,-707.5 240,-655 240,-580 q 0,6 0.5,11.5 0.5,5.5 1.5,11.5 -18,2 -39.5,8 -21.5,6 -38.5,14 -2,-11 -3,-22 -1,-11 -1,-23 0,-109 75.5,-184.5 Q 311,-840 420,-840 q 109,0 184.5,75.5 75.5,75.5 75.5,184.5 0,43 -13.5,81.5 Q 653,-460 629,-428 l 251,252 z m -615,-61 71,-71 70,71 29,-28 -71,-71 71,-71 -28,-28 -71,71 -71,-71 -28,28 71,71 -71,71 z"/></svg>
240
+ <div class="mobile-wallet-adapter-embedded-modal-title">We can't find a wallet.</div>
241
+ <div id="mobile-wallet-adapter-error-message" class="mobile-wallet-adapter-embedded-modal-subtitle"></div>
242
+ <div>
243
+ <button data-error-action id="mobile-wallet-adapter-error-action" class="mobile-wallet-adapter-embedded-modal-error-action">
244
+ Find a wallet
245
+ </button>
380
246
  </div>
381
247
  `;
382
- const css$4 = `
383
- .mobile-wallet-adapter-embedded-modal-qr-content {
384
- display: flex;
385
- margin-top: 10px;
386
- padding: 10px;
387
- }
388
-
389
- .mobile-wallet-adapter-embedded-modal-qr-content > div:first-child {
390
- display: flex;
391
- flex-direction: column;
392
- flex: 2;
393
- margin-top: auto;
394
- margin-right: 30px;
395
- }
396
-
397
- .mobile-wallet-adapter-embedded-modal-qr-content > div:nth-child(2) {
398
- display: flex;
399
- flex-direction: column;
400
- flex: 1;
401
- margin-left: auto;
248
+ const css$5 = `
249
+ .mobile-wallet-adapter-embedded-modal-content {
250
+ text-align: center;
402
251
  }
403
252
 
404
- .mobile-wallet-adapter-embedded-modal-footer {
405
- display: flex;
406
- padding: 10px;
253
+ .mobile-wallet-adapter-embedded-modal-error-icon {
254
+ margin-top: 24px;
407
255
  }
408
256
 
409
- .mobile-wallet-adapter-embedded-modal-icon {}
410
-
411
257
  .mobile-wallet-adapter-embedded-modal-title {
258
+ margin: 18px 100px auto 100px;
412
259
  color: #000000;
413
- font-size: 2.5em;
260
+ font-size: 2.75em;
414
261
  font-weight: 600;
415
262
  }
416
263
 
417
- .mobile-wallet-adapter-embedded-modal-qr-label {
418
- text-align: right;
419
- color: #000000;
420
- }
421
-
422
- .mobile-wallet-adapter-embedded-modal-qr-code-container {
423
- margin-left: auto;
424
- }
425
-
426
- .mobile-wallet-adapter-embedded-modal-qr-placeholder {
427
- margin-left: auto;
428
- min-width: 200px;
429
- min-height: 200px;
430
- background: linear-gradient(-60deg, #F7F8F8 30%, #ECEEEE 50%, #F7F8F8 70%);
431
- background-size: 200%;
432
- animation: placeholderAnimate 2.7s linear infinite;
433
- border-radius: 12px;
434
- }
435
-
436
- .mobile-wallet-adapter-embedded-modal-divider {
437
- margin-top: 20px;
438
- padding-left: 10px;
439
- padding-right: 10px;
440
- }
441
-
442
- .mobile-wallet-adapter-embedded-modal-divider hr {
443
- border-top: 1px solid #D9DEDE;
444
- }
445
-
446
264
  .mobile-wallet-adapter-embedded-modal-subtitle {
447
- margin: auto;
448
- margin-right: 60px;
449
- padding: 20px;
450
- color: #6E8286;
265
+ margin: 30px 60px 40px 60px;
266
+ color: #000000;
267
+ font-size: 1.25em;
268
+ font-weight: 400;
451
269
  }
452
270
 
453
- .mobile-wallet-adapter-embedded-modal-progress-badge {
454
- display: flex;
455
- background: #F7F8F8;
271
+ .mobile-wallet-adapter-embedded-modal-error-action {
272
+ display: block;
273
+ width: 100%;
456
274
  height: 56px;
457
- min-width: 200px;
458
- margin: auto;
459
- padding-left: 20px;
460
- padding-right: 20px;
275
+ /*margin-top: 40px;*/
276
+ font-size: 1.25em;
277
+ /*line-height: 24px;*/
278
+ /*letter-spacing: -1%;*/
279
+ background: #000000;
280
+ color: #FFFFFF;
461
281
  border-radius: 18px;
462
- color: #A8B6B8;
463
- align-items: center;
464
- }
465
-
466
- .mobile-wallet-adapter-embedded-modal-progress-badge > div:first-child {
467
- margin-left: auto;
468
- margin-right: 20px;
469
- }
470
-
471
- .mobile-wallet-adapter-embedded-modal-progress-badge > div:nth-child(2) {
472
- margin-right: auto;
473
282
  }
474
283
 
475
284
  /* Smaller screens */
476
285
  @media all and (max-width: 600px) {
477
- .mobile-wallet-adapter-embedded-modal-card {
478
- text-align: center;
479
- }
480
- .mobile-wallet-adapter-embedded-modal-qr-content {
481
- flex-direction: column;
482
- }
483
- .mobile-wallet-adapter-embedded-modal-qr-content > div:first-child {
484
- margin: auto;
485
- }
486
- .mobile-wallet-adapter-embedded-modal-qr-content > div:nth-child(2) {
487
- margin: auto;
488
- flex: 2 auto;
489
- }
490
- .mobile-wallet-adapter-embedded-modal-footer {
491
- flex-direction: column;
492
- }
493
- .mobile-wallet-adapter-embedded-modal-icon {
494
- display: none;
495
- }
496
286
  .mobile-wallet-adapter-embedded-modal-title {
497
287
  font-size: 1.5em;
288
+ margin-right: 12px;
289
+ margin-left: 12px;
498
290
  }
499
291
  .mobile-wallet-adapter-embedded-modal-subtitle {
500
- margin-right: unset;
501
- }
502
- .mobile-wallet-adapter-embedded-modal-qr-label {
503
- text-align: center;
504
- }
505
- .mobile-wallet-adapter-embedded-modal-qr-code-container {
506
- margin: auto;
507
- }
508
- .mobile-wallet-adapter-embedded-modal-qr-placeholder {
509
- margin: auto;
510
- }
511
- }
512
-
513
- /* QR Placeholder */
514
- @keyframes placeholderAnimate {
515
- 0% { background-position: 200% 0; }
516
- 100% { background-position: -200% 0; }
517
- }
518
-
519
- /* Spinner */
520
- @keyframes spinLeft {
521
- 0% {
522
- transform: rotate(20deg);
523
- }
524
- 50% {
525
- transform: rotate(160deg);
526
- }
527
- 100% {
528
- transform: rotate(20deg);
529
- }
530
- }
531
- @keyframes spinRight {
532
- 0% {
533
- transform: rotate(160deg);
534
- }
535
- 50% {
536
- transform: rotate(20deg);
537
- }
538
- 100% {
539
- transform: rotate(160deg);
540
- }
541
- }
542
- @keyframes spin {
543
- 0% {
544
- transform: rotate(0deg);
545
- }
546
- 100% {
547
- transform: rotate(2520deg);
292
+ margin-right: 12px;
293
+ margin-left: 12px;
548
294
  }
549
295
  }
550
-
551
- .spinner {
552
- position: relative;
553
- width: 1.5em;
554
- height: 1.5em;
555
- margin: auto;
556
- animation: spin 10s linear infinite;
557
- }
558
- .spinner::before {
559
- content: "";
560
- position: absolute;
561
- top: 0;
562
- bottom: 0;
563
- left: 0;
564
- right: 0;
565
- }
566
- .right, .rightWrapper, .left, .leftWrapper {
567
- position: absolute;
568
- top: 0;
569
- overflow: hidden;
570
- width: .75em;
571
- height: 1.5em;
572
- }
573
- .left, .leftWrapper {
574
- left: 0;
575
- }
576
- .right {
577
- left: -12px;
578
- }
579
- .rightWrapper {
580
- right: 0;
581
- }
582
- .circle {
583
- border: .125em solid #A8B6B8;
584
- width: 1.25em; /* 1.5em - 2*0.125em border */
585
- height: 1.25em; /* 1.5em - 2*0.125em border */
586
- border-radius: 0.75em; /* 0.5*1.5em spinner size 8 */
587
- }
588
- .left {
589
- transform-origin: 100% 50%;
590
- animation: spinLeft 2.5s cubic-bezier(.2,0,.8,1) infinite;
591
- }
592
- .right {
593
- transform-origin: 100% 50%;
594
- animation: spinRight 2.5s cubic-bezier(.2,0,.8,1) infinite;
595
- }
596
296
  `;
597
297
  //#endregion
298
+ //#region src/createDefaultWalletNotFoundHandler.ts
299
+ async function defaultErrorModalWalletNotFoundHandler() {
300
+ if (typeof window !== "undefined") {
301
+ const userAgent = window.navigator.userAgent.toLowerCase();
302
+ const errorDialog = new ErrorModal();
303
+ if (userAgent.includes("wv")) errorDialog.initWithError({
304
+ name: "SolanaMobileWalletAdapterError",
305
+ code: "ERROR_BROWSER_NOT_SUPPORTED",
306
+ message: ""
307
+ });
308
+ else errorDialog.initWithError({
309
+ name: "SolanaMobileWalletAdapterError",
310
+ code: "ERROR_WALLET_NOT_FOUND",
311
+ message: ""
312
+ });
313
+ errorDialog.open();
314
+ }
315
+ }
316
+ function createDefaultWalletNotFoundHandler() {
317
+ return async () => {
318
+ defaultErrorModalWalletNotFoundHandler();
319
+ };
320
+ }
321
+ //#endregion
598
322
  //#region src/embedded-modal/localConnectionModal.ts
599
323
  var LocalConnectionModal = class extends EmbeddedModal {
600
- contentStyles = css$3;
601
- contentHtml = ErrorDialogHtml$3;
324
+ contentStyles = css$4;
325
+ contentHtml = ErrorDialogHtml$2;
602
326
  initWithCallback(callback) {
603
327
  super.init();
604
328
  this.#prepareLaunchAction(callback);
@@ -613,7 +337,7 @@ var LocalConnectionModal = class extends EmbeddedModal {
613
337
  launchButton?.addEventListener("click", listener);
614
338
  }
615
339
  };
616
- const ErrorDialogHtml$3 = `
340
+ const ErrorDialogHtml$2 = `
617
341
  <svg class="mobile-wallet-adapter-embedded-modal-launch-icon" width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
618
342
  <path d="M21.6 48C7.2 48 0 40.8 0 26.4V21.6C0 7.2 7.2 0 21.6 0H26.4C40.8 0 48 7.2 48 21.6V26.4C48 40.8 40.8 48 26.4 48H21.6Z" fill="#15994E"/>
619
343
  <mask id="mask0_189_522" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="8" y="8" width="32" height="32">
@@ -635,7 +359,7 @@ const ErrorDialogHtml$3 = `
635
359
  </button>
636
360
  </div>
637
361
  `;
638
- const css$3 = `
362
+ const css$4 = `
639
363
  .mobile-wallet-adapter-embedded-modal-close {
640
364
  display: none;
641
365
  }
@@ -673,10 +397,10 @@ const css$3 = `
673
397
  //#endregion
674
398
  //#region src/embedded-modal/loopbackBlockedModal.ts
675
399
  var LoopbackPermissionBlockedModal = class extends EmbeddedModal {
676
- contentStyles = css$2;
400
+ contentStyles = css$3;
677
401
  get contentHtml() {
678
402
  const instructions = getIsPwaLaunchedAsApp() ? "Long press the app icon on your home screen to open site settings" : "Tap the lock or settings icon in the address bar to open site settings";
679
- return ErrorDialogHtml$2.replace("{{PERMISSION_INSTRUCTION_DETAIL}}", instructions);
403
+ return ErrorDialogHtml$1.replace("{{PERMISSION_INSTRUCTION_DETAIL}}", instructions);
680
404
  }
681
405
  async init() {
682
406
  super.init();
@@ -691,7 +415,7 @@ var LoopbackPermissionBlockedModal = class extends EmbeddedModal {
691
415
  launchButton?.addEventListener("click", listener);
692
416
  }
693
417
  };
694
- const ErrorDialogHtml$2 = `
418
+ const ErrorDialogHtml$1 = `
695
419
  <div class="mobile-wallet-adapter-embedded-modal-header">
696
420
  Local Wallet Connection
697
421
  </div>
@@ -744,7 +468,7 @@ const ErrorDialogHtml$2 = `
744
468
  </button>
745
469
  </div>
746
470
  `;
747
- const css$2 = `
471
+ const css$3 = `
748
472
  .mobile-wallet-adapter-embedded-modal-close {
749
473
  display: none;
750
474
  }
@@ -834,8 +558,8 @@ const css$2 = `
834
558
  //#endregion
835
559
  //#region src/embedded-modal/loopbackPermissionModal.ts
836
560
  var LoopbackPermissionModal = class extends EmbeddedModal {
837
- contentStyles = css$1;
838
- contentHtml = ErrorDialogHtml$1;
561
+ contentStyles = css$2;
562
+ contentHtml = ErrorDialogHtml;
839
563
  async init() {
840
564
  super.init();
841
565
  this.#prepareLaunchAction();
@@ -852,7 +576,7 @@ var LoopbackPermissionModal = class extends EmbeddedModal {
852
576
  launchButton?.addEventListener("click", listener);
853
577
  }
854
578
  };
855
- const ErrorDialogHtml$1 = `
579
+ const ErrorDialogHtml = `
856
580
  <div class="mobile-wallet-adapter-embedded-modal-title">Allow connections to your wallet</div>
857
581
  <div id="mobile-wallet-adapter-local-launch-message" class="mobile-wallet-adapter-embedded-modal-subtitle">
858
582
  Tap "Allow" on the next screen
@@ -878,7 +602,7 @@ const ErrorDialogHtml$1 = `
878
602
  </button>
879
603
  </div>
880
604
  `;
881
- const css$1 = `
605
+ const css$2 = `
882
606
  .mobile-wallet-adapter-embedded-modal-close {
883
607
  display: none;
884
608
  }
@@ -924,72 +648,504 @@ const css$1 = `
924
648
  margin-left: 12px;
925
649
  }
926
650
  }
927
- `;
928
- //#endregion
929
- //#region src/getIsSupported.ts
930
- function getIsLocalAssociationSupported() {
931
- return typeof window !== "undefined" && window.isSecureContext && typeof document !== "undefined" && /android/i.test(navigator.userAgent);
651
+ `;
652
+ //#endregion
653
+ //#region src/getIsSupported.ts
654
+ function getIsLocalAssociationSupported() {
655
+ return typeof window !== "undefined" && window.isSecureContext && typeof document !== "undefined" && /android/i.test(navigator.userAgent);
656
+ }
657
+ function getIsRemoteAssociationSupported() {
658
+ return typeof window !== "undefined" && window.isSecureContext && typeof document !== "undefined" && !/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
659
+ }
660
+ function isWebView(userAgentString) {
661
+ return /(WebView|Version\/.+(Chrome)\/(\d+)\.(\d+)\.(\d+)\.(\d+)|; wv\).+(Chrome)\/(\d+)\.(\d+)\.(\d+)\.(\d+))/i.test(userAgentString);
662
+ }
663
+ function isSolanaMobileWebShell(userAgentString) {
664
+ return userAgentString.includes("Solana Mobile Web Shell");
665
+ }
666
+ function getIsPwaLaunchedAsApp() {
667
+ const isAndroidTwa = typeof document !== "undefined" && document.referrer.startsWith("android-app://");
668
+ if (typeof window == "undefined") return isAndroidTwa;
669
+ const isStandalone = window.matchMedia("(display-mode: standalone)").matches;
670
+ const isFullscreen = window.matchMedia("(display-mode: fullscreen)").matches;
671
+ const isMinimalUI = window.matchMedia("(display-mode: minimal-ui)").matches;
672
+ return isAndroidTwa || isStandalone || isFullscreen || isMinimalUI;
673
+ }
674
+ async function checkLocalNetworkAccessPermission() {
675
+ if (typeof navigator !== "undefined" && isSolanaMobileWebShell(navigator.userAgent)) return;
676
+ try {
677
+ const lnaPermission = await navigator.permissions.query({ name: "loopback-network" });
678
+ if (lnaPermission.state === "granted") return;
679
+ else if (lnaPermission.state === "denied") {
680
+ const modal = new LoopbackPermissionBlockedModal();
681
+ modal.init();
682
+ modal.open();
683
+ throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_LOOPBACK_ACCESS_BLOCKED, "Local Network Access permission denied");
684
+ } else if (lnaPermission.state === "prompt") {
685
+ const modal = new LoopbackPermissionModal();
686
+ if (await new Promise((resolve, reject) => {
687
+ modal.addEventListener("close", (event) => {
688
+ if (event) reject(new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_ASSOCIATION_CANCELLED, "Wallet connection cancelled by user", { event }));
689
+ });
690
+ lnaPermission.onchange = () => {
691
+ lnaPermission.onchange = null;
692
+ resolve(lnaPermission.state);
693
+ };
694
+ modal.init();
695
+ modal.open();
696
+ }) === "granted") {
697
+ const modal = new LocalConnectionModal();
698
+ await new Promise((resolve, reject) => {
699
+ modal.addEventListener("close", (event) => {
700
+ if (event) reject(new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_ASSOCIATION_CANCELLED, "Wallet connection cancelled by user", { event }));
701
+ });
702
+ modal.initWithCallback(async () => {
703
+ resolve(true);
704
+ });
705
+ modal.open();
706
+ });
707
+ return;
708
+ } else return await checkLocalNetworkAccessPermission();
709
+ }
710
+ throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_LOOPBACK_ACCESS_BLOCKED, "Local Network Access permission unknown");
711
+ } catch (e) {
712
+ if (e instanceof TypeError && (e.message.includes("loopback-network") || e.message.includes("local-network-access"))) return;
713
+ if (e instanceof SolanaMobileWalletAdapterError) throw e;
714
+ throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_LOOPBACK_ACCESS_BLOCKED, e instanceof Error ? e.message : "Local Network Access permission unknown");
715
+ }
716
+ }
717
+ //#endregion
718
+ //#region src/embedded-modal/loadingSpinner.ts
719
+ const modalHtml = `
720
+ <div class="mobile-wallet-adapter-embedded-loading-indicator" role="dialog" aria-modal="true" aria-labelledby="modal-title">
721
+ <div data-modal-close style="position: absolute; width: 100%; height: 100%;"></div>
722
+ <div class="mobile-wallet-adapter-embedded-loading-container">
723
+ <div class="mobile-wallet-adapter-embedded-loading-animation"></div>
724
+ </div>
725
+ </div>
726
+ `;
727
+ const css$1 = `
728
+ .mobile-wallet-adapter-embedded-loading-indicator {
729
+ display: flex; /* Use flexbox to center content */
730
+ justify-content: center; /* Center horizontally */
731
+ align-items: start; /* Center vertically */
732
+ position: fixed; /* Stay in place */
733
+ z-index: 1; /* Sit on top */
734
+ left: 0;
735
+ top: 0;
736
+ width: 100%; /* Full width */
737
+ height: 100%; /* Full height */
738
+ background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
739
+ overflow-y: auto; /* enable scrolling */
740
+ }
741
+
742
+ .mobile-wallet-adapter-embedded-loading-container {
743
+ display: flex;
744
+ margin: auto;
745
+ }
746
+
747
+ .mobile-wallet-adapter-embedded-loading-animation {
748
+ position: relative;
749
+ left: -9999px;
750
+ width: 10px;
751
+ height: 10px;
752
+ border-radius: 5px;
753
+ background-color: var(--spinner-color);
754
+ color: var(--spinner-color);
755
+ box-shadow: 9984px 0 0 0 var(--spinner-color),
756
+ 9999px 0 0 0 var(--spinner-color),
757
+ 10014px 0 0 0 var(--spinner-color);
758
+ animation: dot-typing 1.5s infinite linear;
759
+ }
760
+
761
+ @keyframes dot-typing {
762
+ 0% {
763
+ box-shadow: 9984px 0 0 0 var(--spinner-color),
764
+ 9999px 0 0 0 var(--spinner-color),
765
+ 10014px 0 0 0 var(--spinner-color);
766
+ }
767
+ 16.667% {
768
+ box-shadow: 9984px -10px 0 0 var(--spinner-color),
769
+ 9999px 0 0 0 var(--spinner-color),
770
+ 10014px 0 0 0 var(--spinner-color);
771
+ }
772
+ 33.333% {
773
+ box-shadow: 9984px 0 0 0 var(--spinner-color),
774
+ 9999px 0 0 0 var(--spinner-color),
775
+ 10014px 0 0 0 var(--spinner-color);
776
+ }
777
+ 50% {
778
+ box-shadow: 9984px 0 0 0 var(--spinner-color),
779
+ 9999px -10px 0 0 var(--spinner-color),
780
+ 10014px 0 0 0 var(--spinner-color);
781
+ }
782
+ 66.667% {
783
+ box-shadow: 9984px 0 0 0 var(--spinner-color),
784
+ 9999px 0 0 0 var(--spinner-color),
785
+ 10014px 0 0 0 var(--spinner-color);
786
+ }
787
+ 83.333% {
788
+ box-shadow: 9984px 0 0 0 var(--spinner-color),
789
+ 9999px 0 0 0 var(--spinner-color),
790
+ 10014px -10px 0 0 var(--spinner-color);
791
+ }
792
+ 100% {
793
+ box-shadow: 9984px 0 0 0 var(--spinner-color),
794
+ 9999px 0 0 0 var(--spinner-color),
795
+ 10014px 0 0 0 var(--spinner-color);
796
+ }
797
+ }
798
+ `;
799
+ var EmbeddedLoadingSpinner = class {
800
+ #root = null;
801
+ #eventListeners = {};
802
+ #listenersAttached = false;
803
+ dom = null;
804
+ constructor() {
805
+ this.init = this.init.bind(this);
806
+ this.#root = document.getElementById("mobile-wallet-adapter-embedded-root-ui");
807
+ }
808
+ async init() {
809
+ console.log("Injecting modal");
810
+ this.#injectHTML();
811
+ }
812
+ open = () => {
813
+ console.debug("Modal open");
814
+ this.#attachEventListeners();
815
+ if (this.#root) this.#root.style.display = "flex";
816
+ };
817
+ close = (event = void 0) => {
818
+ console.debug("Modal close");
819
+ this.#removeEventListeners();
820
+ if (this.#root) this.#root.style.display = "none";
821
+ this.#eventListeners["close"]?.forEach((listener) => listener(event));
822
+ };
823
+ addEventListener(event, listener) {
824
+ this.#eventListeners[event]?.push(listener) || (this.#eventListeners[event] = [listener]);
825
+ return () => this.removeEventListener(event, listener);
826
+ }
827
+ removeEventListener(event, listener) {
828
+ this.#eventListeners[event] = this.#eventListeners[event]?.filter((existingListener) => listener !== existingListener);
829
+ }
830
+ #injectHTML() {
831
+ if (this.dom) return;
832
+ this.#root = document.createElement("div");
833
+ this.#root.id = "mobile-wallet-adapter-embedded-root-ui";
834
+ this.#root.innerHTML = modalHtml;
835
+ this.#root.style.display = "none";
836
+ const styles = document.createElement("style");
837
+ styles.id = "mobile-wallet-adapter-embedded-modal-styles";
838
+ styles.textContent = css$1;
839
+ const host = document.createElement("div");
840
+ this.dom = host.attachShadow({ mode: "closed" });
841
+ host.style.setProperty("--spinner-color", "#FFFFFF");
842
+ this.dom.appendChild(styles);
843
+ this.dom.appendChild(this.#root);
844
+ document.body.appendChild(host);
845
+ }
846
+ #attachEventListeners() {
847
+ if (!this.#root || this.#listenersAttached) return;
848
+ [...this.#root.querySelectorAll("[data-modal-close]")].forEach((closer) => closer?.addEventListener("click", (event) => {
849
+ this.close(event);
850
+ }));
851
+ window.addEventListener("load", this.close);
852
+ document.addEventListener("keydown", this.#handleKeyDown);
853
+ this.#listenersAttached = true;
854
+ }
855
+ #removeEventListeners() {
856
+ if (!this.#listenersAttached) return;
857
+ window.removeEventListener("load", this.close);
858
+ document.removeEventListener("keydown", this.#handleKeyDown);
859
+ if (!this.#root) return;
860
+ [...this.#root.querySelectorAll("[data-modal-close]")].forEach((closer) => closer?.removeEventListener("click", this.close));
861
+ this.#listenersAttached = false;
862
+ }
863
+ #handleKeyDown = (event) => {
864
+ if (event.key === "Escape") this.close(event);
865
+ };
866
+ };
867
+ //#endregion
868
+ //#region src/embedded-modal/remoteConnectionModal.ts
869
+ var RemoteConnectionModal = class extends EmbeddedModal {
870
+ contentStyles = css;
871
+ contentHtml = QRCodeHtml;
872
+ async initWithQR(qrCode) {
873
+ super.init();
874
+ this.populateQRCode(qrCode);
875
+ }
876
+ async populateQRCode(qrUrl) {
877
+ const qrcodeContainer = this.dom?.getElementById("mobile-wallet-adapter-embedded-modal-qr-code-container");
878
+ if (qrcodeContainer) {
879
+ const qrCodeElement = await QRCode.toCanvas(qrUrl, {
880
+ width: 200,
881
+ margin: 0
882
+ });
883
+ if (qrcodeContainer.firstElementChild !== null) qrcodeContainer.replaceChild(qrCodeElement, qrcodeContainer.firstElementChild);
884
+ else qrcodeContainer.appendChild(qrCodeElement);
885
+ const qrPlaceholder = this.dom?.getElementById("mobile-wallet-adapter-embedded-modal-qr-placeholder");
886
+ if (qrPlaceholder) qrPlaceholder.style.display = "none";
887
+ } else console.error("QRCode Container not found");
888
+ }
889
+ };
890
+ const QRCodeHtml = `
891
+ <div class="mobile-wallet-adapter-embedded-modal-qr-content">
892
+ <div>
893
+ <svg class="mobile-wallet-adapter-embedded-modal-icon" width="100%" height="100%">
894
+ <circle r="52" cx="53" cy="53" fill="#99b3be" stroke="#000000" stroke-width="2"/>
895
+ <path d="m 53,82.7305 c -3.3116,0 -6.1361,-1.169 -8.4735,-3.507 -2.338,-2.338 -3.507,-5.1625 -3.507,-8.4735 0,-3.3116 1.169,-6.1364 3.507,-8.4744 2.3374,-2.338 5.1619,-3.507 8.4735,-3.507 3.3116,0 6.1361,1.169 8.4735,3.507 2.338,2.338 3.507,5.1628 3.507,8.4744 0,3.311 -1.169,6.1355 -3.507,8.4735 -2.3374,2.338 -5.1619,3.507 -8.4735,3.507 z m 0.007,-5.25 c 1.8532,0 3.437,-0.6598 4.7512,-1.9793 1.3149,-1.3195 1.9723,-2.9058 1.9723,-4.7591 0,-1.8526 -0.6598,-3.4364 -1.9793,-4.7512 -1.3195,-1.3149 -2.9055,-1.9723 -4.7582,-1.9723 -1.8533,0 -3.437,0.6598 -4.7513,1.9793 -1.3148,1.3195 -1.9722,2.9058 -1.9722,4.7591 0,1.8527 0.6597,3.4364 1.9792,4.7512 1.3195,1.3149 2.9056,1.9723 4.7583,1.9723 z m -28,-33.5729 -3.85,-3.6347 c 4.1195,-4.025 8.8792,-7.1984 14.2791,-9.52 5.4005,-2.3223 11.2551,-3.4834 17.5639,-3.4834 6.3087,0 12.1634,1.1611 17.5639,3.4834 5.3999,2.3216 10.1596,5.495 14.2791,9.52 l -3.85,3.6347 C 77.2999,40.358 73.0684,37.5726 68.2985,35.5514 63.5292,33.5301 58.4296,32.5195 53,32.5195 c -5.4297,0 -10.5292,1.0106 -15.2985,3.0319 -4.7699,2.0212 -9.0014,4.8066 -12.6945,8.3562 z m 44.625,10.8771 c -2.2709,-2.1046 -4.7962,-3.7167 -7.5758,-4.8361 -2.7795,-1.12 -5.7983,-1.68 -9.0562,-1.68 -3.2579,0 -6.2621,0.56 -9.0125,1.68 -2.7504,1.1194 -5.2903,2.7315 -7.6195,4.8361 L 32.5189,51.15 c 2.8355,-2.6028 5.9777,-4.6086 9.4263,-6.0174 3.4481,-1.4087 7.133,-2.1131 11.0548,-2.1131 3.9217,0 7.5979,0.7044 11.0285,2.1131 3.43,1.4088 6.5631,3.4146 9.3992,6.0174 z"/>
896
+ </svg>
897
+ <div class="mobile-wallet-adapter-embedded-modal-title">Remote Mobile Wallet Adapter</div>
898
+ </div>
899
+ <div>
900
+ <div>
901
+ <h4 class="mobile-wallet-adapter-embedded-modal-qr-label">
902
+ Open your wallet and scan this code
903
+ </h4>
904
+ </div>
905
+ <div id="mobile-wallet-adapter-embedded-modal-qr-code-container" class="mobile-wallet-adapter-embedded-modal-qr-code-container">
906
+ <div id="mobile-wallet-adapter-embedded-modal-qr-placeholder" class="mobile-wallet-adapter-embedded-modal-qr-placeholder"></div>
907
+ </div>
908
+ </div>
909
+ </div>
910
+ <div class="mobile-wallet-adapter-embedded-modal-divider"><hr></div>
911
+ <div class="mobile-wallet-adapter-embedded-modal-footer">
912
+ <div class="mobile-wallet-adapter-embedded-modal-subtitle">
913
+ Follow the instructions on your device. When you're finished, this screen will update.
914
+ </div>
915
+ <div class="mobile-wallet-adapter-embedded-modal-progress-badge">
916
+ <div>
917
+ <div class="spinner">
918
+ <div class="leftWrapper">
919
+ <div class="left">
920
+ <div class="circle"></div>
921
+ </div>
922
+ </div>
923
+ <div class="rightWrapper">
924
+ <div class="right">
925
+ <div class="circle"></div>
926
+ </div>
927
+ </div>
928
+ </div>
929
+ </div>
930
+ <div>Waiting for scan</div>
931
+ </div>
932
+ </div>
933
+ `;
934
+ const css = `
935
+ .mobile-wallet-adapter-embedded-modal-qr-content {
936
+ display: flex;
937
+ margin-top: 10px;
938
+ padding: 10px;
939
+ }
940
+
941
+ .mobile-wallet-adapter-embedded-modal-qr-content > div:first-child {
942
+ display: flex;
943
+ flex-direction: column;
944
+ flex: 2;
945
+ margin-top: auto;
946
+ margin-right: 30px;
947
+ }
948
+
949
+ .mobile-wallet-adapter-embedded-modal-qr-content > div:nth-child(2) {
950
+ display: flex;
951
+ flex-direction: column;
952
+ flex: 1;
953
+ margin-left: auto;
954
+ }
955
+
956
+ .mobile-wallet-adapter-embedded-modal-footer {
957
+ display: flex;
958
+ padding: 10px;
959
+ }
960
+
961
+ .mobile-wallet-adapter-embedded-modal-icon {}
962
+
963
+ .mobile-wallet-adapter-embedded-modal-title {
964
+ color: #000000;
965
+ font-size: 2.5em;
966
+ font-weight: 600;
967
+ }
968
+
969
+ .mobile-wallet-adapter-embedded-modal-qr-label {
970
+ text-align: right;
971
+ color: #000000;
972
+ }
973
+
974
+ .mobile-wallet-adapter-embedded-modal-qr-code-container {
975
+ margin-left: auto;
976
+ }
977
+
978
+ .mobile-wallet-adapter-embedded-modal-qr-placeholder {
979
+ margin-left: auto;
980
+ min-width: 200px;
981
+ min-height: 200px;
982
+ background: linear-gradient(-60deg, #F7F8F8 30%, #ECEEEE 50%, #F7F8F8 70%);
983
+ background-size: 200%;
984
+ animation: placeholderAnimate 2.7s linear infinite;
985
+ border-radius: 12px;
986
+ }
987
+
988
+ .mobile-wallet-adapter-embedded-modal-divider {
989
+ margin-top: 20px;
990
+ padding-left: 10px;
991
+ padding-right: 10px;
992
+ }
993
+
994
+ .mobile-wallet-adapter-embedded-modal-divider hr {
995
+ border-top: 1px solid #D9DEDE;
996
+ }
997
+
998
+ .mobile-wallet-adapter-embedded-modal-subtitle {
999
+ margin: auto;
1000
+ margin-right: 60px;
1001
+ padding: 20px;
1002
+ color: #6E8286;
1003
+ }
1004
+
1005
+ .mobile-wallet-adapter-embedded-modal-progress-badge {
1006
+ display: flex;
1007
+ background: #F7F8F8;
1008
+ height: 56px;
1009
+ min-width: 200px;
1010
+ margin: auto;
1011
+ padding-left: 20px;
1012
+ padding-right: 20px;
1013
+ border-radius: 18px;
1014
+ color: #A8B6B8;
1015
+ align-items: center;
1016
+ }
1017
+
1018
+ .mobile-wallet-adapter-embedded-modal-progress-badge > div:first-child {
1019
+ margin-left: auto;
1020
+ margin-right: 20px;
1021
+ }
1022
+
1023
+ .mobile-wallet-adapter-embedded-modal-progress-badge > div:nth-child(2) {
1024
+ margin-right: auto;
1025
+ }
1026
+
1027
+ /* Smaller screens */
1028
+ @media all and (max-width: 600px) {
1029
+ .mobile-wallet-adapter-embedded-modal-card {
1030
+ text-align: center;
1031
+ }
1032
+ .mobile-wallet-adapter-embedded-modal-qr-content {
1033
+ flex-direction: column;
1034
+ }
1035
+ .mobile-wallet-adapter-embedded-modal-qr-content > div:first-child {
1036
+ margin: auto;
1037
+ }
1038
+ .mobile-wallet-adapter-embedded-modal-qr-content > div:nth-child(2) {
1039
+ margin: auto;
1040
+ flex: 2 auto;
1041
+ }
1042
+ .mobile-wallet-adapter-embedded-modal-footer {
1043
+ flex-direction: column;
1044
+ }
1045
+ .mobile-wallet-adapter-embedded-modal-icon {
1046
+ display: none;
1047
+ }
1048
+ .mobile-wallet-adapter-embedded-modal-title {
1049
+ font-size: 1.5em;
1050
+ }
1051
+ .mobile-wallet-adapter-embedded-modal-subtitle {
1052
+ margin-right: unset;
1053
+ }
1054
+ .mobile-wallet-adapter-embedded-modal-qr-label {
1055
+ text-align: center;
1056
+ }
1057
+ .mobile-wallet-adapter-embedded-modal-qr-code-container {
1058
+ margin: auto;
1059
+ }
1060
+ .mobile-wallet-adapter-embedded-modal-qr-placeholder {
1061
+ margin: auto;
1062
+ }
1063
+ }
1064
+
1065
+ /* QR Placeholder */
1066
+ @keyframes placeholderAnimate {
1067
+ 0% { background-position: 200% 0; }
1068
+ 100% { background-position: -200% 0; }
1069
+ }
1070
+
1071
+ /* Spinner */
1072
+ @keyframes spinLeft {
1073
+ 0% {
1074
+ transform: rotate(20deg);
1075
+ }
1076
+ 50% {
1077
+ transform: rotate(160deg);
1078
+ }
1079
+ 100% {
1080
+ transform: rotate(20deg);
1081
+ }
1082
+ }
1083
+ @keyframes spinRight {
1084
+ 0% {
1085
+ transform: rotate(160deg);
1086
+ }
1087
+ 50% {
1088
+ transform: rotate(20deg);
1089
+ }
1090
+ 100% {
1091
+ transform: rotate(160deg);
1092
+ }
1093
+ }
1094
+ @keyframes spin {
1095
+ 0% {
1096
+ transform: rotate(0deg);
1097
+ }
1098
+ 100% {
1099
+ transform: rotate(2520deg);
1100
+ }
1101
+ }
1102
+
1103
+ .spinner {
1104
+ position: relative;
1105
+ width: 1.5em;
1106
+ height: 1.5em;
1107
+ margin: auto;
1108
+ animation: spin 10s linear infinite;
1109
+ }
1110
+ .spinner::before {
1111
+ content: "";
1112
+ position: absolute;
1113
+ top: 0;
1114
+ bottom: 0;
1115
+ left: 0;
1116
+ right: 0;
932
1117
  }
933
- function getIsRemoteAssociationSupported() {
934
- return typeof window !== "undefined" && window.isSecureContext && typeof document !== "undefined" && !/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
1118
+ .right, .rightWrapper, .left, .leftWrapper {
1119
+ position: absolute;
1120
+ top: 0;
1121
+ overflow: hidden;
1122
+ width: .75em;
1123
+ height: 1.5em;
935
1124
  }
936
- function isWebView(userAgentString) {
937
- return /(WebView|Version\/.+(Chrome)\/(\d+)\.(\d+)\.(\d+)\.(\d+)|; wv\).+(Chrome)\/(\d+)\.(\d+)\.(\d+)\.(\d+))/i.test(userAgentString);
1125
+ .left, .leftWrapper {
1126
+ left: 0;
938
1127
  }
939
- function isSolanaMobileWebShell(userAgentString) {
940
- return userAgentString.includes("Solana Mobile Web Shell");
1128
+ .right {
1129
+ left: -12px;
941
1130
  }
942
- function getIsPwaLaunchedAsApp() {
943
- const isAndroidTwa = typeof document !== "undefined" && document.referrer.startsWith("android-app://");
944
- if (typeof window == "undefined") return isAndroidTwa;
945
- const isStandalone = window.matchMedia("(display-mode: standalone)").matches;
946
- const isFullscreen = window.matchMedia("(display-mode: fullscreen)").matches;
947
- const isMinimalUI = window.matchMedia("(display-mode: minimal-ui)").matches;
948
- return isAndroidTwa || isStandalone || isFullscreen || isMinimalUI;
1131
+ .rightWrapper {
1132
+ right: 0;
949
1133
  }
950
- async function checkLocalNetworkAccessPermission() {
951
- if (typeof navigator !== "undefined" && isSolanaMobileWebShell(navigator.userAgent)) return;
952
- try {
953
- const lnaPermission = await navigator.permissions.query({ name: "loopback-network" });
954
- if (lnaPermission.state === "granted") return;
955
- else if (lnaPermission.state === "denied") {
956
- const modal = new LoopbackPermissionBlockedModal();
957
- modal.init();
958
- modal.open();
959
- throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_LOOPBACK_ACCESS_BLOCKED, "Local Network Access permission denied");
960
- } else if (lnaPermission.state === "prompt") {
961
- const modal = new LoopbackPermissionModal();
962
- if (await new Promise((resolve, reject) => {
963
- modal.addEventListener("close", (event) => {
964
- if (event) reject(new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_ASSOCIATION_CANCELLED, "Wallet connection cancelled by user", { event }));
965
- });
966
- lnaPermission.onchange = () => {
967
- lnaPermission.onchange = null;
968
- resolve(lnaPermission.state);
969
- };
970
- modal.init();
971
- modal.open();
972
- }) === "granted") {
973
- const modal = new LocalConnectionModal();
974
- await new Promise((resolve, reject) => {
975
- modal.addEventListener("close", (event) => {
976
- if (event) reject(new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_ASSOCIATION_CANCELLED, "Wallet connection cancelled by user", { event }));
977
- });
978
- modal.initWithCallback(async () => {
979
- resolve(true);
980
- });
981
- modal.open();
982
- });
983
- return;
984
- } else return await checkLocalNetworkAccessPermission();
985
- }
986
- throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_LOOPBACK_ACCESS_BLOCKED, "Local Network Access permission unknown");
987
- } catch (e) {
988
- if (e instanceof TypeError && (e.message.includes("loopback-network") || e.message.includes("local-network-access"))) return;
989
- if (e instanceof SolanaMobileWalletAdapterError) throw e;
990
- throw new SolanaMobileWalletAdapterError(SolanaMobileWalletAdapterErrorCode.ERROR_LOOPBACK_ACCESS_BLOCKED, e instanceof Error ? e.message : "Local Network Access permission unknown");
991
- }
1134
+ .circle {
1135
+ border: .125em solid #A8B6B8;
1136
+ width: 1.25em; /* 1.5em - 2*0.125em border */
1137
+ height: 1.25em; /* 1.5em - 2*0.125em border */
1138
+ border-radius: 0.75em; /* 0.5*1.5em spinner size 8 */
1139
+ }
1140
+ .left {
1141
+ transform-origin: 100% 50%;
1142
+ animation: spinLeft 2.5s cubic-bezier(.2,0,.8,1) infinite;
992
1143
  }
1144
+ .right {
1145
+ transform-origin: 100% 50%;
1146
+ animation: spinRight 2.5s cubic-bezier(.2,0,.8,1) infinite;
1147
+ }
1148
+ `;
993
1149
  //#endregion
994
1150
  //#region src/icon.ts
995
1151
  const icon = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03IDIuNUgxN0MxNy44Mjg0IDIuNSAxOC41IDMuMTcxNTcgMTguNSA0VjIwQzE4LjUgMjAuODI4NCAxNy44Mjg0IDIxLjUgMTcgMjEuNUg3QzYuMTcxNTcgMjEuNSA1LjUgMjAuODI4NCA1LjUgMjBWNEM1LjUgMy4xNzE1NyA2LjE3MTU3IDIuNSA3IDIuNVpNMyA0QzMgMS43OTA4NiA0Ljc5MDg2IDAgNyAwSDE3QzE5LjIwOTEgMCAyMSAxLjc5MDg2IDIxIDRWMjBDMjEgMjIuMjA5MSAxOS4yMDkxIDI0IDE3IDI0SDdDNC43OTA4NiAyNCAzIDIyLjIwOTEgMyAyMFY0Wk0xMSA0LjYxNTM4QzEwLjQ0NzcgNC42MTUzOCAxMCA1LjA2MzEgMTAgNS42MTUzOFY2LjM4NDYyQzEwIDYuOTM2OSAxMC40NDc3IDcuMzg0NjIgMTEgNy4zODQ2MkgxM0MxMy41NTIzIDcuMzg0NjIgMTQgNi45MzY5IDE0IDYuMzg0NjJWNS42MTUzOEMxNCA1LjA2MzEgMTMuNTUyMyA0LjYxNTM4IDEzIDQuNjE1MzhIMTFaIiBmaWxsPSIjRENCOEZGIi8+Cjwvc3ZnPgo=";
@@ -1255,9 +1411,9 @@ var LocalSolanaMobileWalletAdapterWallet = class {
1255
1411
  };
1256
1412
  #accountsToWalletStandardAccounts = (accounts) => {
1257
1413
  return accounts.map((account) => {
1258
- const publicKey = toUint8Array(account.address);
1414
+ const publicKey = base64ToUint8Array(account.address);
1259
1415
  return {
1260
- address: base58.encode(publicKey),
1416
+ address: base58FromUint8Array(publicKey),
1261
1417
  publicKey,
1262
1418
  label: account.label,
1263
1419
  icon: account.icon,
@@ -1270,11 +1426,11 @@ var LocalSolanaMobileWalletAdapterWallet = class {
1270
1426
  const { authToken, chain } = this.#assertIsAuthorized();
1271
1427
  try {
1272
1428
  const base64Transactions = transactions.map((tx) => {
1273
- return fromUint8Array(tx);
1429
+ return base64FromUint8Array(tx);
1274
1430
  });
1275
1431
  return await this.#transact(async (wallet) => {
1276
1432
  await this.#performReauthorization(wallet, authToken, chain);
1277
- return (await wallet.signTransactions({ payloads: base64Transactions })).signed_payloads.map(toUint8Array);
1433
+ return (await wallet.signTransactions({ payloads: base64Transactions })).signed_payloads.map(base64ToUint8Array);
1278
1434
  });
1279
1435
  } catch (e) {
1280
1436
  throw new Error(getErrorMessage(e), { cause: e });
@@ -1286,11 +1442,11 @@ var LocalSolanaMobileWalletAdapterWallet = class {
1286
1442
  return await this.#transact(async (wallet) => {
1287
1443
  const [capabilities] = await Promise.all([wallet.getCapabilities(), this.#performReauthorization(wallet, authToken, chain)]);
1288
1444
  if (capabilities.supports_sign_and_send_transactions) {
1289
- const base64Transaction = fromUint8Array(transaction);
1445
+ const base64Transaction = base64FromUint8Array(transaction);
1290
1446
  return (await wallet.signAndSendTransactions({
1291
1447
  ...options,
1292
1448
  payloads: [base64Transaction]
1293
- })).signatures.map(toUint8Array)[0];
1449
+ })).signatures.map(base64ToUint8Array)[0];
1294
1450
  } else throw new Error("connected wallet does not support signAndSendTransaction");
1295
1451
  });
1296
1452
  } catch (e) {
@@ -1312,15 +1468,15 @@ var LocalSolanaMobileWalletAdapterWallet = class {
1312
1468
  };
1313
1469
  #signMessage = async (...inputs) => {
1314
1470
  const { authToken, chain } = this.#assertIsAuthorized();
1315
- const addresses = inputs.map(({ account }) => fromUint8Array(new Uint8Array(account.publicKey)));
1316
- const messages = inputs.map(({ message }) => fromUint8Array(message));
1471
+ const addresses = inputs.map(({ account }) => base64FromUint8Array(new Uint8Array(account.publicKey)));
1472
+ const messages = inputs.map(({ message }) => base64FromUint8Array(message));
1317
1473
  try {
1318
1474
  return await this.#transact(async (wallet) => {
1319
1475
  await this.#performReauthorization(wallet, authToken, chain);
1320
1476
  return (await wallet.signMessages({
1321
1477
  addresses,
1322
1478
  payloads: messages
1323
- })).signed_payloads.map(toUint8Array).map((signedMessage) => {
1479
+ })).signed_payloads.map(base64ToUint8Array).map((signedMessage) => {
1324
1480
  return {
1325
1481
  signedMessage,
1326
1482
  signature: signedMessage.slice(-SIGNATURE_LENGTH_IN_BYTES)
@@ -1349,13 +1505,13 @@ var LocalSolanaMobileWalletAdapterWallet = class {
1349
1505
  const signedInAccount = authorizationResult.accounts.find((acc) => acc.address == signedInAddress);
1350
1506
  return {
1351
1507
  account: {
1352
- ...signedInAccount ?? { address: base58.encode(toUint8Array(signedInAddress)) },
1353
- publicKey: toUint8Array(signedInAddress),
1508
+ ...signedInAccount ?? { address: base58FromUint8Array(base64ToUint8Array(signedInAddress)) },
1509
+ publicKey: base64ToUint8Array(signedInAddress),
1354
1510
  chains: signedInAccount?.chains ?? this.#chains,
1355
1511
  features: signedInAccount?.features ?? authorizationResult.capabilities.features
1356
1512
  },
1357
- signedMessage: toUint8Array(authorizationResult.sign_in_result.signed_message),
1358
- signature: toUint8Array(authorizationResult.sign_in_result.signature)
1513
+ signedMessage: base64ToUint8Array(authorizationResult.sign_in_result.signed_message),
1514
+ signature: base64ToUint8Array(authorizationResult.sign_in_result.signature)
1359
1515
  };
1360
1516
  } catch (e) {
1361
1517
  throw new Error(getErrorMessage(e), { cause: e });
@@ -1608,9 +1764,9 @@ var RemoteSolanaMobileWalletAdapterWallet = class {
1608
1764
  };
1609
1765
  #accountsToWalletStandardAccounts = (accounts) => {
1610
1766
  return accounts.map((account) => {
1611
- const publicKey = toUint8Array(account.address);
1767
+ const publicKey = base64ToUint8Array(account.address);
1612
1768
  return {
1613
- address: base58.encode(publicKey),
1769
+ address: base58FromUint8Array(publicKey),
1614
1770
  publicKey,
1615
1771
  label: account.label,
1616
1772
  icon: account.icon,
@@ -1624,7 +1780,7 @@ var RemoteSolanaMobileWalletAdapterWallet = class {
1624
1780
  try {
1625
1781
  return await this.#transact(async (wallet) => {
1626
1782
  await this.#performReauthorization(wallet, authToken, chain);
1627
- return (await wallet.signTransactions({ payloads: transactions.map(fromUint8Array) })).signed_payloads.map(toUint8Array);
1783
+ return (await wallet.signTransactions({ payloads: transactions.map(base64FromUint8Array) })).signed_payloads.map(base64ToUint8Array);
1628
1784
  });
1629
1785
  } catch (e) {
1630
1786
  throw new Error(getErrorMessage(e), { cause: e });
@@ -1637,8 +1793,8 @@ var RemoteSolanaMobileWalletAdapterWallet = class {
1637
1793
  const [capabilities] = await Promise.all([wallet.getCapabilities(), this.#performReauthorization(wallet, authToken, chain)]);
1638
1794
  if (capabilities.supports_sign_and_send_transactions) return (await wallet.signAndSendTransactions({
1639
1795
  ...options,
1640
- payloads: [fromUint8Array(transaction)]
1641
- })).signatures.map(toUint8Array)[0];
1796
+ payloads: [base64FromUint8Array(transaction)]
1797
+ })).signatures.map(base64ToUint8Array)[0];
1642
1798
  else throw new Error("connected wallet does not support signAndSendTransaction");
1643
1799
  });
1644
1800
  } catch (e) {
@@ -1660,15 +1816,15 @@ var RemoteSolanaMobileWalletAdapterWallet = class {
1660
1816
  };
1661
1817
  #signMessage = async (...inputs) => {
1662
1818
  const { authToken, chain } = this.#assertIsAuthorized();
1663
- const addresses = inputs.map(({ account }) => fromUint8Array(new Uint8Array(account.publicKey)));
1664
- const messages = inputs.map(({ message }) => fromUint8Array(message));
1819
+ const addresses = inputs.map(({ account }) => base64FromUint8Array(new Uint8Array(account.publicKey)));
1820
+ const messages = inputs.map(({ message }) => base64FromUint8Array(message));
1665
1821
  try {
1666
1822
  return await this.#transact(async (wallet) => {
1667
1823
  await this.#performReauthorization(wallet, authToken, chain);
1668
1824
  return (await wallet.signMessages({
1669
1825
  addresses,
1670
1826
  payloads: messages
1671
- })).signed_payloads.map(toUint8Array).map((signedMessage) => {
1827
+ })).signed_payloads.map(base64ToUint8Array).map((signedMessage) => {
1672
1828
  return {
1673
1829
  signedMessage,
1674
1830
  signature: signedMessage.slice(-SIGNATURE_LENGTH_IN_BYTES)
@@ -1697,13 +1853,13 @@ var RemoteSolanaMobileWalletAdapterWallet = class {
1697
1853
  const signedInAccount = authorizationResult.accounts.find((acc) => acc.address == signedInAddress);
1698
1854
  return {
1699
1855
  account: {
1700
- ...signedInAccount ?? { address: base58.encode(toUint8Array(signedInAddress)) },
1701
- publicKey: toUint8Array(signedInAddress),
1856
+ ...signedInAccount ?? { address: base58FromUint8Array(base64ToUint8Array(signedInAddress)) },
1857
+ publicKey: base64ToUint8Array(signedInAddress),
1702
1858
  chains: signedInAccount?.chains ?? this.#chains,
1703
1859
  features: signedInAccount?.features ?? authorizationResult.capabilities.features
1704
1860
  },
1705
- signedMessage: toUint8Array(authorizationResult.sign_in_result.signed_message),
1706
- signature: toUint8Array(authorizationResult.sign_in_result.signature)
1861
+ signedMessage: base64ToUint8Array(authorizationResult.sign_in_result.signed_message),
1862
+ signature: base64ToUint8Array(authorizationResult.sign_in_result.signature)
1707
1863
  };
1708
1864
  } catch (e) {
1709
1865
  throw new Error(getErrorMessage(e), { cause: e });
@@ -1731,170 +1887,6 @@ function registerMwa(config) {
1731
1887
  }));
1732
1888
  }
1733
1889
  //#endregion
1734
- //#region src/embedded-modal/errorModal.ts
1735
- const WALLET_NOT_FOUND_ERROR_MESSAGE = "To use mobile wallet adapter, you must have a compatible mobile wallet application installed on your device.";
1736
- const BROWSER_NOT_SUPPORTED_ERROR_MESSAGE = "This browser appears to be incompatible with mobile wallet adapter. Open this page in a compatible mobile browser app and try again.";
1737
- var ErrorModal = class extends EmbeddedModal {
1738
- contentStyles = css;
1739
- contentHtml = ErrorDialogHtml;
1740
- initWithError(error) {
1741
- super.init();
1742
- this.populateError(error);
1743
- }
1744
- populateError(error) {
1745
- const errorMessageElement = this.dom?.getElementById("mobile-wallet-adapter-error-message");
1746
- const actionBtn = this.dom?.getElementById("mobile-wallet-adapter-error-action");
1747
- if (errorMessageElement) {
1748
- if (error.name === "SolanaMobileWalletAdapterError") switch (error.code) {
1749
- case "ERROR_WALLET_NOT_FOUND":
1750
- errorMessageElement.innerHTML = WALLET_NOT_FOUND_ERROR_MESSAGE;
1751
- if (actionBtn) actionBtn.addEventListener("click", () => {
1752
- window.location.href = "https://solanamobile.com/wallets";
1753
- });
1754
- return;
1755
- case "ERROR_BROWSER_NOT_SUPPORTED":
1756
- errorMessageElement.innerHTML = BROWSER_NOT_SUPPORTED_ERROR_MESSAGE;
1757
- if (actionBtn) actionBtn.style.display = "none";
1758
- return;
1759
- }
1760
- errorMessageElement.innerHTML = `An unexpected error occurred: ${error.message}`;
1761
- } else console.log("Failed to locate error dialog element");
1762
- }
1763
- };
1764
- const ErrorDialogHtml = `
1765
- <svg class="mobile-wallet-adapter-embedded-modal-error-icon" xmlns="http://www.w3.org/2000/svg" height="50px" viewBox="0 -960 960 960" width="50px" fill="#000000"><path d="M 280,-80 Q 197,-80 138.5,-138.5 80,-197 80,-280 80,-363 138.5,-421.5 197,-480 280,-480 q 83,0 141.5,58.5 58.5,58.5 58.5,141.5 0,83 -58.5,141.5 Q 363,-80 280,-80 Z M 824,-120 568,-376 Q 556,-389 542.5,-402.5 529,-416 516,-428 q 38,-24 61,-64 23,-40 23,-88 0,-75 -52.5,-127.5 Q 495,-760 420,-760 345,-760 292.5,-707.5 240,-655 240,-580 q 0,6 0.5,11.5 0.5,5.5 1.5,11.5 -18,2 -39.5,8 -21.5,6 -38.5,14 -2,-11 -3,-22 -1,-11 -1,-23 0,-109 75.5,-184.5 Q 311,-840 420,-840 q 109,0 184.5,75.5 75.5,75.5 75.5,184.5 0,43 -13.5,81.5 Q 653,-460 629,-428 l 251,252 z m -615,-61 71,-71 70,71 29,-28 -71,-71 71,-71 -28,-28 -71,71 -71,-71 -28,28 71,71 -71,71 z"/></svg>
1766
- <div class="mobile-wallet-adapter-embedded-modal-title">We can't find a wallet.</div>
1767
- <div id="mobile-wallet-adapter-error-message" class="mobile-wallet-adapter-embedded-modal-subtitle"></div>
1768
- <div>
1769
- <button data-error-action id="mobile-wallet-adapter-error-action" class="mobile-wallet-adapter-embedded-modal-error-action">
1770
- Find a wallet
1771
- </button>
1772
- </div>
1773
- `;
1774
- const css = `
1775
- .mobile-wallet-adapter-embedded-modal-content {
1776
- text-align: center;
1777
- }
1778
-
1779
- .mobile-wallet-adapter-embedded-modal-error-icon {
1780
- margin-top: 24px;
1781
- }
1782
-
1783
- .mobile-wallet-adapter-embedded-modal-title {
1784
- margin: 18px 100px auto 100px;
1785
- color: #000000;
1786
- font-size: 2.75em;
1787
- font-weight: 600;
1788
- }
1789
-
1790
- .mobile-wallet-adapter-embedded-modal-subtitle {
1791
- margin: 30px 60px 40px 60px;
1792
- color: #000000;
1793
- font-size: 1.25em;
1794
- font-weight: 400;
1795
- }
1796
-
1797
- .mobile-wallet-adapter-embedded-modal-error-action {
1798
- display: block;
1799
- width: 100%;
1800
- height: 56px;
1801
- /*margin-top: 40px;*/
1802
- font-size: 1.25em;
1803
- /*line-height: 24px;*/
1804
- /*letter-spacing: -1%;*/
1805
- background: #000000;
1806
- color: #FFFFFF;
1807
- border-radius: 18px;
1808
- }
1809
-
1810
- /* Smaller screens */
1811
- @media all and (max-width: 600px) {
1812
- .mobile-wallet-adapter-embedded-modal-title {
1813
- font-size: 1.5em;
1814
- margin-right: 12px;
1815
- margin-left: 12px;
1816
- }
1817
- .mobile-wallet-adapter-embedded-modal-subtitle {
1818
- margin-right: 12px;
1819
- margin-left: 12px;
1820
- }
1821
- }
1822
- `;
1823
- //#endregion
1824
- //#region src/createDefaultWalletNotFoundHandler.ts
1825
- async function defaultErrorModalWalletNotFoundHandler() {
1826
- if (typeof window !== "undefined") {
1827
- const userAgent = window.navigator.userAgent.toLowerCase();
1828
- const errorDialog = new ErrorModal();
1829
- if (userAgent.includes("wv")) errorDialog.initWithError({
1830
- name: "SolanaMobileWalletAdapterError",
1831
- code: "ERROR_BROWSER_NOT_SUPPORTED",
1832
- message: ""
1833
- });
1834
- else errorDialog.initWithError({
1835
- name: "SolanaMobileWalletAdapterError",
1836
- code: "ERROR_WALLET_NOT_FOUND",
1837
- message: ""
1838
- });
1839
- errorDialog.open();
1840
- }
1841
- }
1842
- function createDefaultWalletNotFoundHandler() {
1843
- return async () => {
1844
- defaultErrorModalWalletNotFoundHandler();
1845
- };
1846
- }
1847
- //#endregion
1848
- //#region src/createDefaultAuthorizationCache.ts
1849
- const CACHE_KEY = "SolanaMobileWalletAdapterDefaultAuthorizationCache";
1850
- function createDefaultAuthorizationCache() {
1851
- let storage;
1852
- try {
1853
- storage = window.localStorage;
1854
- } catch {}
1855
- return {
1856
- async clear() {
1857
- if (!storage) return;
1858
- try {
1859
- storage.removeItem(CACHE_KEY);
1860
- } catch {}
1861
- },
1862
- async get() {
1863
- if (!storage) return;
1864
- try {
1865
- const parsed = JSON.parse(storage.getItem(CACHE_KEY));
1866
- if (parsed && parsed.accounts) {
1867
- const parsedAccounts = parsed.accounts.map((account) => {
1868
- return {
1869
- ...account,
1870
- publicKey: "publicKey" in account ? new Uint8Array(Object.values(account.publicKey)) : base58.decode(account.address)
1871
- };
1872
- });
1873
- return {
1874
- ...parsed,
1875
- accounts: parsedAccounts
1876
- };
1877
- } else return parsed || void 0;
1878
- } catch {}
1879
- },
1880
- async set(authorization) {
1881
- if (!storage) return;
1882
- try {
1883
- storage.setItem(CACHE_KEY, JSON.stringify(authorization));
1884
- } catch {}
1885
- }
1886
- };
1887
- }
1888
- //#endregion
1889
- //#region src/createDefaultChainSelector.ts
1890
- function createDefaultChainSelector() {
1891
- return { async select(chains) {
1892
- if (chains.length === 1) return chains[0];
1893
- else if (chains.includes(SOLANA_MAINNET_CHAIN)) return SOLANA_MAINNET_CHAIN;
1894
- else return chains[0];
1895
- } };
1896
- }
1897
- //#endregion
1898
1890
  export { LocalSolanaMobileWalletAdapterWallet, RemoteSolanaMobileWalletAdapterWallet, SolanaMobileWalletAdapterRemoteWalletName, SolanaMobileWalletAdapterWalletName, createDefaultAuthorizationCache, createDefaultChainSelector, createDefaultWalletNotFoundHandler, defaultErrorModalWalletNotFoundHandler, registerMwa };
1899
1891
 
1900
1892
  //# sourceMappingURL=index.browser.js.map