@swype-org/deposit 0.3.20 → 0.3.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-VMXCXXVN.js → chunk-JD7GTL6D.js} +158 -17
- package/dist/chunk-JD7GTL6D.js.map +1 -0
- package/dist/index.cjs +156 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -4
- package/dist/index.d.ts +23 -4
- package/dist/index.js +1 -1
- package/dist/react.cjs +156 -15
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/dist/{types-Ds07N2zN.d.cts → types-iQf3f-_m.d.cts} +13 -0
- package/dist/{types-Ds07N2zN.d.ts → types-iQf3f-_m.d.ts} +13 -0
- package/package.json +1 -1
- package/dist/chunk-VMXCXXVN.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -98,7 +98,19 @@ function parseIframeReady(data) {
|
|
|
98
98
|
if (msg.type !== "blink:iframe-ready") {
|
|
99
99
|
return null;
|
|
100
100
|
}
|
|
101
|
-
return { type: "blink:iframe-ready" };
|
|
101
|
+
return { type: "blink:iframe-ready", capabilities: parseCapabilities(msg.capabilities) };
|
|
102
|
+
}
|
|
103
|
+
function parseCapabilities(value) {
|
|
104
|
+
if (!Array.isArray(value)) {
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
return value.filter((entry) => typeof entry === "string");
|
|
108
|
+
}
|
|
109
|
+
function buildViewportMessage(viewportLvh, safeAreaBottom) {
|
|
110
|
+
return { type: "blink:viewport", viewportLvh, safeAreaBottom };
|
|
111
|
+
}
|
|
112
|
+
function buildRevealMessage() {
|
|
113
|
+
return { type: "blink:reveal" };
|
|
102
114
|
}
|
|
103
115
|
function buildSignedPayloadMessage(merchantId, payload, signature) {
|
|
104
116
|
return {
|
|
@@ -322,13 +334,20 @@ function attachRpcHost(options) {
|
|
|
322
334
|
});
|
|
323
335
|
}
|
|
324
336
|
}
|
|
325
|
-
|
|
337
|
+
let lastAdvertisedKey = null;
|
|
338
|
+
function advertiseWallets(snapshot, opts) {
|
|
326
339
|
const wallets = snapshot.map((entry) => ({
|
|
327
340
|
uuid: entry.info.uuid,
|
|
328
341
|
rdns: entry.info.rdns,
|
|
329
342
|
name: entry.info.name,
|
|
330
343
|
icon: entry.info.icon
|
|
331
344
|
}));
|
|
345
|
+
const key = JSON.stringify(wallets.map((w) => [w.uuid, w.rdns, w.name, w.icon]));
|
|
346
|
+
if (!opts?.force && key === lastAdvertisedKey) {
|
|
347
|
+
log("skipping identical re-advertisement", { count: wallets.length });
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
lastAdvertisedKey = key;
|
|
332
351
|
console.info("[blink-bridge:parent] advertising wallets", wallets.map((w) => ({
|
|
333
352
|
rdns: w.rdns,
|
|
334
353
|
name: w.name
|
|
@@ -409,7 +428,7 @@ function attachRpcHost(options) {
|
|
|
409
428
|
if (!message) return;
|
|
410
429
|
switch (message.type) {
|
|
411
430
|
case "blink:bridge-hello": {
|
|
412
|
-
advertiseWallets(discoverer.list());
|
|
431
|
+
advertiseWallets(discoverer.list(), { force: true });
|
|
413
432
|
discoverer.requestProviders();
|
|
414
433
|
return;
|
|
415
434
|
}
|
|
@@ -505,6 +524,34 @@ function normalizeProviderError(err) {
|
|
|
505
524
|
return { code: -32603, message: typeof err === "string" ? err : "Provider error" };
|
|
506
525
|
}
|
|
507
526
|
|
|
527
|
+
// src/viewportMetrics.ts
|
|
528
|
+
function measureViewportMetrics() {
|
|
529
|
+
const unavailable = { viewportLvh: 0, safeAreaBottom: 0 };
|
|
530
|
+
if (typeof document === "undefined" || typeof window === "undefined" || typeof window.getComputedStyle !== "function" || !document.body) {
|
|
531
|
+
return unavailable;
|
|
532
|
+
}
|
|
533
|
+
try {
|
|
534
|
+
const probe = document.createElement("div");
|
|
535
|
+
probe.style.cssText = "position:fixed;top:0;left:0;width:0;visibility:hidden;pointer-events:none;height:100lvh;padding-bottom:env(safe-area-inset-bottom,0px)";
|
|
536
|
+
document.body.appendChild(probe);
|
|
537
|
+
let viewportLvh = 0;
|
|
538
|
+
let safeAreaBottom = 0;
|
|
539
|
+
try {
|
|
540
|
+
const computed = window.getComputedStyle(probe);
|
|
541
|
+
viewportLvh = Math.round(Number.parseFloat(computed.height) || 0);
|
|
542
|
+
safeAreaBottom = Math.round(Number.parseFloat(computed.paddingBottom) || 0);
|
|
543
|
+
} finally {
|
|
544
|
+
probe.remove();
|
|
545
|
+
}
|
|
546
|
+
if (viewportLvh <= 0) {
|
|
547
|
+
viewportLvh = Math.round(window.innerHeight || 0);
|
|
548
|
+
}
|
|
549
|
+
return { viewportLvh, safeAreaBottom };
|
|
550
|
+
} catch {
|
|
551
|
+
return unavailable;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
508
555
|
// src/iframe.ts
|
|
509
556
|
var STYLE_ID = "blink-deposit-styles";
|
|
510
557
|
var CLOSE_DURATION_MS = 280;
|
|
@@ -525,6 +572,8 @@ var STYLES = `
|
|
|
525
572
|
[data-blink-overlay][data-blink-mobile-sheet] [data-blink-container]{width:100%;max-width:100%;height:79vh;border-radius:24px 24px 0 0;box-shadow:0 -8px 40px rgba(0,0,0,.25);animation:blink-slide-up-full .35s cubic-bezier(.32,.72,0,1);padding-bottom:env(safe-area-inset-bottom,0px)}
|
|
526
573
|
[data-blink-overlay][data-blink-mobile-sheet][data-blink-closing] [data-blink-container]{opacity:1;animation:blink-slide-down-full ${CLOSE_DURATION_MS}ms ease-in forwards}
|
|
527
574
|
@media(max-width:${MOBILE_SHEET_MAX_VIEWPORT_PX}px){[data-blink-overlay]{align-items:flex-end;touch-action:none;overscroll-behavior:contain}[data-blink-container]{width:100%;max-width:100%;height:79vh;border-radius:24px 24px 0 0;box-shadow:0 -8px 40px rgba(0,0,0,.25);animation:blink-slide-up-full .35s cubic-bezier(.32,.72,0,1);padding-bottom:env(safe-area-inset-bottom,0px)}[data-blink-overlay][data-blink-closing] [data-blink-container]{opacity:1;animation:blink-slide-down-full ${CLOSE_DURATION_MS}ms ease-in forwards}}
|
|
575
|
+
[data-blink-overlay][data-blink-fluid] [data-blink-container],[data-blink-overlay][data-blink-fluid][data-blink-mobile-sheet] [data-blink-container]{width:100%;max-width:100%;height:100%;max-height:100%;border-radius:0;box-shadow:none;animation:none;background:transparent;padding-bottom:0}
|
|
576
|
+
[data-blink-overlay][data-blink-fluid][data-blink-closing] [data-blink-container]{animation:none;transition:none;opacity:1}
|
|
528
577
|
`;
|
|
529
578
|
function createIframe(url, containerElement, options) {
|
|
530
579
|
ensureStyles();
|
|
@@ -536,6 +585,9 @@ function createIframe(url, containerElement, options) {
|
|
|
536
585
|
if (shouldUseMobileSheetLayout()) {
|
|
537
586
|
overlay.setAttribute("data-blink-mobile-sheet", "");
|
|
538
587
|
}
|
|
588
|
+
if (options?.fluid) {
|
|
589
|
+
overlay.setAttribute("data-blink-fluid", "");
|
|
590
|
+
}
|
|
539
591
|
if (hidden) {
|
|
540
592
|
overlay.style.display = "none";
|
|
541
593
|
}
|
|
@@ -564,6 +616,37 @@ function createIframe(url, containerElement, options) {
|
|
|
564
616
|
};
|
|
565
617
|
attachBridge();
|
|
566
618
|
iframe.addEventListener("load", attachBridge);
|
|
619
|
+
function postReveal() {
|
|
620
|
+
if (closed) return;
|
|
621
|
+
iframe.contentWindow?.postMessage(buildRevealMessage(), iframeOrigin);
|
|
622
|
+
}
|
|
623
|
+
function postViewportMetrics() {
|
|
624
|
+
if (closed || !options?.fluid) return;
|
|
625
|
+
const metrics = measureViewportMetrics();
|
|
626
|
+
if (metrics.viewportLvh <= 0) return;
|
|
627
|
+
iframe.contentWindow?.postMessage(
|
|
628
|
+
buildViewportMessage(metrics.viewportLvh, metrics.safeAreaBottom),
|
|
629
|
+
iframeOrigin
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
let viewportPostScheduled = false;
|
|
633
|
+
const onViewportChange = () => {
|
|
634
|
+
if (viewportPostScheduled) return;
|
|
635
|
+
viewportPostScheduled = true;
|
|
636
|
+
requestAnimationFrame(() => {
|
|
637
|
+
viewportPostScheduled = false;
|
|
638
|
+
postViewportMetrics();
|
|
639
|
+
});
|
|
640
|
+
};
|
|
641
|
+
if (options?.fluid) {
|
|
642
|
+
window.addEventListener("resize", onViewportChange);
|
|
643
|
+
window.addEventListener("orientationchange", onViewportChange);
|
|
644
|
+
}
|
|
645
|
+
const onLoadReveal = () => {
|
|
646
|
+
postViewportMetrics();
|
|
647
|
+
if (!hidden) postReveal();
|
|
648
|
+
};
|
|
649
|
+
iframe.addEventListener("load", onLoadReveal);
|
|
567
650
|
let savedOverflow = "";
|
|
568
651
|
let scrollLocked = false;
|
|
569
652
|
const onBackdropClick = (event) => {
|
|
@@ -594,6 +677,8 @@ function createIframe(url, containerElement, options) {
|
|
|
594
677
|
overlay.removeEventListener("click", onBackdropClick);
|
|
595
678
|
overlay.removeEventListener("touchmove", onTouchMove);
|
|
596
679
|
document.removeEventListener("keydown", onKeyDown);
|
|
680
|
+
window.removeEventListener("resize", onViewportChange);
|
|
681
|
+
window.removeEventListener("orientationchange", onViewportChange);
|
|
597
682
|
}
|
|
598
683
|
function unlockScroll() {
|
|
599
684
|
if (!scrollLocked) return;
|
|
@@ -619,6 +704,7 @@ function createIframe(url, containerElement, options) {
|
|
|
619
704
|
}
|
|
620
705
|
function detachBridge() {
|
|
621
706
|
iframe.removeEventListener("load", attachBridge);
|
|
707
|
+
iframe.removeEventListener("load", onLoadReveal);
|
|
622
708
|
if (rpcHostHandle) {
|
|
623
709
|
rpcHostHandle.detach();
|
|
624
710
|
rpcHostHandle = null;
|
|
@@ -649,6 +735,14 @@ function createIframe(url, containerElement, options) {
|
|
|
649
735
|
overlay.style.display = "";
|
|
650
736
|
lockScroll();
|
|
651
737
|
attachDismissalListeners();
|
|
738
|
+
postViewportMetrics();
|
|
739
|
+
postReveal();
|
|
740
|
+
},
|
|
741
|
+
postReveal() {
|
|
742
|
+
postReveal();
|
|
743
|
+
},
|
|
744
|
+
downgradeToFixed() {
|
|
745
|
+
overlay.removeAttribute("data-blink-fluid");
|
|
652
746
|
},
|
|
653
747
|
onClose(callback) {
|
|
654
748
|
closeCallback = callback;
|
|
@@ -824,6 +918,8 @@ var DEFAULT_WEBVIEW_BASE_URL = "https://pay.blink.cash";
|
|
|
824
918
|
var SANDBOX_WEBVIEW_BASE_URL = "https://pay-sandbox.blink.cash";
|
|
825
919
|
var IFRAME_READY_TIMEOUT_MS = 2e3;
|
|
826
920
|
var WARM_IFRAME_READY_TIMEOUT_MS = 6e4;
|
|
921
|
+
var LAYOUT_FLUID_CAPABILITY = "layout-fluid";
|
|
922
|
+
var IFRAME_NOT_READY = { ready: false, fluidCapable: false };
|
|
827
923
|
function resolveWebviewBaseUrl(config) {
|
|
828
924
|
if (config.webviewBaseUrl) return config.webviewBaseUrl;
|
|
829
925
|
return config.environment === "sandbox" ? SANDBOX_WEBVIEW_BASE_URL : DEFAULT_WEBVIEW_BASE_URL;
|
|
@@ -894,7 +990,10 @@ var Deposit = class {
|
|
|
894
990
|
const webviewBaseUrl = resolveWebviewBaseUrl(this.config);
|
|
895
991
|
this.hostedOrigin = this.config.hostedFlowOrigin ?? new URL(webviewBaseUrl).origin;
|
|
896
992
|
const preloadUrl = this.buildPreloadUrl(webviewBaseUrl);
|
|
897
|
-
const iframe = createIframe(preloadUrl, this.config.containerElement, {
|
|
993
|
+
const iframe = createIframe(preloadUrl, this.config.containerElement, {
|
|
994
|
+
hidden: true,
|
|
995
|
+
fluid: this.isFluidLayout()
|
|
996
|
+
});
|
|
898
997
|
const ready = this.waitForIframeReady(iframe, WARM_IFRAME_READY_TIMEOUT_MS);
|
|
899
998
|
this.warmIframe = iframe;
|
|
900
999
|
this.warmIframeReady = ready.promise;
|
|
@@ -930,6 +1029,8 @@ var Deposit = class {
|
|
|
930
1029
|
preloadUrl.searchParams.set("merchantId", this.config.merchantId);
|
|
931
1030
|
}
|
|
932
1031
|
this.applyFullWidgetParam(preloadUrl);
|
|
1032
|
+
this.applyLayoutParam(preloadUrl);
|
|
1033
|
+
this.applyViewportParams(preloadUrl);
|
|
933
1034
|
return preloadUrl.toString();
|
|
934
1035
|
}
|
|
935
1036
|
/**
|
|
@@ -1075,6 +1176,35 @@ var Deposit = class {
|
|
|
1075
1176
|
url.searchParams.set("enableFullWidget", "false");
|
|
1076
1177
|
}
|
|
1077
1178
|
}
|
|
1179
|
+
/** Fluid is the default; `layout: 'fixed'` opts back into the legacy container. */
|
|
1180
|
+
isFluidLayout() {
|
|
1181
|
+
return this.config.layout !== "fixed";
|
|
1182
|
+
}
|
|
1183
|
+
/**
|
|
1184
|
+
* Marks the hosted-flow URL as fluid-layout: the iframe spans the full
|
|
1185
|
+
* viewport and the hosted flow renders the card/sheet chrome itself.
|
|
1186
|
+
* Only applied to preload URLs — the URL-param fallback path exists
|
|
1187
|
+
* precisely because the webview never signalled ready, so it cannot be
|
|
1188
|
+
* assumed to understand fluid layout and gets the fixed container.
|
|
1189
|
+
*/
|
|
1190
|
+
applyLayoutParam(url) {
|
|
1191
|
+
if (this.isFluidLayout()) {
|
|
1192
|
+
url.searchParams.set("layout", "fluid");
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
/**
|
|
1196
|
+
* Seeds the merchant page's large-viewport height and safe-area bottom
|
|
1197
|
+
* inset onto the fluid preload URL so the hosted flow can size the sheet
|
|
1198
|
+
* before its JS boots. `blink:viewport` messages keep the values fresh
|
|
1199
|
+
* afterwards (rotation, window resize) — see iframe.ts.
|
|
1200
|
+
*/
|
|
1201
|
+
applyViewportParams(url) {
|
|
1202
|
+
if (!this.isFluidLayout()) return;
|
|
1203
|
+
const metrics = measureViewportMetrics();
|
|
1204
|
+
if (metrics.viewportLvh <= 0) return;
|
|
1205
|
+
url.searchParams.set("viewportLvh", String(metrics.viewportLvh));
|
|
1206
|
+
url.searchParams.set("safeAreaBottom", String(metrics.safeAreaBottom));
|
|
1207
|
+
}
|
|
1078
1208
|
setStatus(status) {
|
|
1079
1209
|
if (this._status === status) return;
|
|
1080
1210
|
this.log(`Status: ${this._status} \u2192 ${status}`);
|
|
@@ -1098,7 +1228,7 @@ var Deposit = class {
|
|
|
1098
1228
|
iframeReadyPromise = Promise.race([
|
|
1099
1229
|
warm.ready,
|
|
1100
1230
|
new Promise(
|
|
1101
|
-
(resolve) => setTimeout(() => resolve(
|
|
1231
|
+
(resolve) => setTimeout(() => resolve(IFRAME_NOT_READY), IFRAME_READY_TIMEOUT_MS)
|
|
1102
1232
|
)
|
|
1103
1233
|
]).then((ready) => {
|
|
1104
1234
|
warm.cancelReady();
|
|
@@ -1108,7 +1238,8 @@ var Deposit = class {
|
|
|
1108
1238
|
} else {
|
|
1109
1239
|
preloadIframe = createIframe(
|
|
1110
1240
|
this.buildPreloadUrl(webviewBaseUrl),
|
|
1111
|
-
this.config.containerElement
|
|
1241
|
+
this.config.containerElement,
|
|
1242
|
+
{ fluid: this.isFluidLayout() }
|
|
1112
1243
|
);
|
|
1113
1244
|
iframeReadyPromise = this.waitForIframeReady(preloadIframe).promise;
|
|
1114
1245
|
}
|
|
@@ -1138,7 +1269,11 @@ var Deposit = class {
|
|
|
1138
1269
|
this.log("Request superseded or iframe dismissed during signer call");
|
|
1139
1270
|
return;
|
|
1140
1271
|
}
|
|
1141
|
-
if (iframeReady) {
|
|
1272
|
+
if (iframeReady.ready) {
|
|
1273
|
+
if (this.isFluidLayout() && !iframeReady.fluidCapable) {
|
|
1274
|
+
preloadIframe.downgradeToFixed();
|
|
1275
|
+
this.log("Webview lacks layout-fluid capability \u2014 downgraded to fixed container");
|
|
1276
|
+
}
|
|
1142
1277
|
const contentWindow = preloadIframe.contentWindow;
|
|
1143
1278
|
if (contentWindow) {
|
|
1144
1279
|
contentWindow.postMessage(
|
|
@@ -1193,8 +1328,10 @@ var Deposit = class {
|
|
|
1193
1328
|
}
|
|
1194
1329
|
}
|
|
1195
1330
|
/**
|
|
1196
|
-
* Resolves true when the iframe posts
|
|
1197
|
-
*
|
|
1331
|
+
* Resolves `{ ready: true, ... }` when the iframe posts
|
|
1332
|
+
* `blink:iframe-ready` (with `fluidCapable` reflecting its advertised
|
|
1333
|
+
* capabilities), or `{ ready: false, fluidCapable: false }` on timeout.
|
|
1334
|
+
* `cancel()` settles the promise as not-ready immediately and releases
|
|
1198
1335
|
* the listener + timer — used to reap the generous warm-up wait once it no
|
|
1199
1336
|
* longer matters (warm iframe consumed or discarded).
|
|
1200
1337
|
*/
|
|
@@ -1205,25 +1342,29 @@ var Deposit = class {
|
|
|
1205
1342
|
const handler = (event) => {
|
|
1206
1343
|
if (event.origin !== this.hostedOrigin) return;
|
|
1207
1344
|
if (event.source !== iframeHandle.contentWindow) return;
|
|
1208
|
-
|
|
1209
|
-
|
|
1345
|
+
const readyMessage = parseIframeReady(event.data);
|
|
1346
|
+
if (readyMessage) {
|
|
1347
|
+
finish({
|
|
1348
|
+
ready: true,
|
|
1349
|
+
fluidCapable: readyMessage.capabilities.includes(LAYOUT_FLUID_CAPABILITY)
|
|
1350
|
+
});
|
|
1210
1351
|
}
|
|
1211
1352
|
};
|
|
1212
1353
|
window.addEventListener("message", handler);
|
|
1213
1354
|
const timeout = setTimeout(() => {
|
|
1214
1355
|
this.log("Iframe ready timeout \u2014 falling back to URL params");
|
|
1215
|
-
finish(
|
|
1356
|
+
finish(IFRAME_NOT_READY);
|
|
1216
1357
|
}, timeoutMs);
|
|
1217
1358
|
let settled = false;
|
|
1218
|
-
finish = (
|
|
1359
|
+
finish = (result) => {
|
|
1219
1360
|
if (settled) return;
|
|
1220
1361
|
settled = true;
|
|
1221
1362
|
window.removeEventListener("message", handler);
|
|
1222
1363
|
clearTimeout(timeout);
|
|
1223
|
-
resolve(
|
|
1364
|
+
resolve(result);
|
|
1224
1365
|
};
|
|
1225
1366
|
});
|
|
1226
|
-
return { promise, cancel: () => finish(
|
|
1367
|
+
return { promise, cancel: () => finish(IFRAME_NOT_READY) };
|
|
1227
1368
|
}
|
|
1228
1369
|
startMessageListener(iframeHandle, onComplete) {
|
|
1229
1370
|
const handler = (event) => {
|