@swype-org/deposit 0.3.26 → 0.3.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +171 -0
- package/dist/{chunk-S3SPMEXQ.js → chunk-MJSD7JWR.js} +534 -98
- package/dist/chunk-MJSD7JWR.js.map +1 -0
- package/dist/index.cjs +533 -97
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +142 -5
- package/dist/index.d.ts +142 -5
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +532 -96
- 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-BjnQ2ux2.d.cts → types-QRkKxsoP.d.cts} +128 -1
- package/dist/{types-BjnQ2ux2.d.ts → types-QRkKxsoP.d.ts} +128 -1
- package/package.json +1 -1
- package/dist/chunk-S3SPMEXQ.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -106,21 +106,84 @@ function parseCapabilities(value) {
|
|
|
106
106
|
}
|
|
107
107
|
return value.filter((entry) => typeof entry === "string");
|
|
108
108
|
}
|
|
109
|
-
function buildViewportMessage(viewportLvh, safeAreaBottom) {
|
|
110
|
-
return {
|
|
109
|
+
function buildViewportMessage(viewportLvh, safeAreaBottom, embedMaxHeightPx) {
|
|
110
|
+
return {
|
|
111
|
+
type: "blink:viewport",
|
|
112
|
+
viewportLvh,
|
|
113
|
+
safeAreaBottom,
|
|
114
|
+
...embedMaxHeightPx === void 0 ? {} : { embedMaxHeightPx }
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
var MAX_CONTENT_HEIGHT_PX = 2e4;
|
|
118
|
+
function parseContentHeight(data) {
|
|
119
|
+
if (!data || typeof data !== "object") {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
const msg = data;
|
|
123
|
+
if (msg.type !== "blink:content-height") {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
const raw = msg.heightPx;
|
|
127
|
+
if (typeof raw !== "number" || !Number.isFinite(raw)) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
const heightPx = Math.round(raw);
|
|
131
|
+
if (heightPx <= 0 || heightPx > MAX_CONTENT_HEIGHT_PX) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
type: "blink:content-height",
|
|
136
|
+
heightPx,
|
|
137
|
+
...parseWidthHint("preferredWidthPx", msg.preferredWidthPx),
|
|
138
|
+
...parseWidthHint("minWidthPx", msg.minWidthPx)
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function parseWidthHint(key, value) {
|
|
142
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return {};
|
|
143
|
+
const px = Math.round(value);
|
|
144
|
+
if (px <= 0 || px > MAX_CONTENT_HEIGHT_PX) return {};
|
|
145
|
+
return { [key]: px };
|
|
111
146
|
}
|
|
112
147
|
function buildRevealMessage() {
|
|
113
148
|
return { type: "blink:reveal" };
|
|
114
149
|
}
|
|
115
|
-
function buildSignedPayloadMessage(merchantId, payload, signature) {
|
|
150
|
+
function buildSignedPayloadMessage(merchantId, payload, signature, balance) {
|
|
116
151
|
return {
|
|
117
152
|
type: "blink:signed-payload",
|
|
118
153
|
merchantId,
|
|
119
154
|
payload,
|
|
120
|
-
signature
|
|
155
|
+
signature,
|
|
156
|
+
...balance === void 0 ? {} : { balance }
|
|
121
157
|
};
|
|
122
158
|
}
|
|
123
159
|
|
|
160
|
+
// src/brandParam.ts
|
|
161
|
+
var BRAND_COLOR_PARAM_KEYS = {
|
|
162
|
+
colorPrimary: "p",
|
|
163
|
+
colorBackground: "bg",
|
|
164
|
+
colorText: "t",
|
|
165
|
+
colorDanger: "d",
|
|
166
|
+
colorBorder: "b"
|
|
167
|
+
};
|
|
168
|
+
function normalizeBrandHex(value) {
|
|
169
|
+
if (typeof value !== "string") return null;
|
|
170
|
+
const hex = value.trim().toLowerCase();
|
|
171
|
+
if (!/^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/.test(hex)) return null;
|
|
172
|
+
const digits = hex.slice(1);
|
|
173
|
+
if (digits.length === 6) return `#${digits}`;
|
|
174
|
+
return `#${digits[0]}${digits[0]}${digits[1]}${digits[1]}${digits[2]}${digits[2]}`;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// src/balanceParam.ts
|
|
178
|
+
var MAX_BALANCE_USD = 1e12;
|
|
179
|
+
function normalizeDisplayBalance(value) {
|
|
180
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
|
181
|
+
if (value < 0 || value >= MAX_BALANCE_USD) return null;
|
|
182
|
+
const cents = Math.floor(Number((value * 100).toPrecision(15)));
|
|
183
|
+
if (cents < 0 || cents >= MAX_BALANCE_USD * 100) return null;
|
|
184
|
+
return (cents / 100).toFixed(2);
|
|
185
|
+
}
|
|
186
|
+
|
|
124
187
|
// src/walletBridge/discover.ts
|
|
125
188
|
function createWalletDiscoverer() {
|
|
126
189
|
if (typeof window === "undefined") {
|
|
@@ -552,6 +615,84 @@ function measureViewportMetrics() {
|
|
|
552
615
|
}
|
|
553
616
|
}
|
|
554
617
|
|
|
618
|
+
// src/iframeCore.ts
|
|
619
|
+
function createFrameElement(url) {
|
|
620
|
+
const iframe = document.createElement("iframe");
|
|
621
|
+
iframe.src = url;
|
|
622
|
+
const iframeOrigin = new URL(url).origin;
|
|
623
|
+
iframe.allow = `publickey-credentials-get ${iframeOrigin}; publickey-credentials-create ${iframeOrigin}; clipboard-write ${iframeOrigin}; web-share ${iframeOrigin}`;
|
|
624
|
+
return { iframe, iframeOrigin };
|
|
625
|
+
}
|
|
626
|
+
function attachFrameBridges(options) {
|
|
627
|
+
const { iframe, iframeOrigin, postViewport, getEmbedMaxHeightPx, shouldRevealOnLoad } = options;
|
|
628
|
+
let detached = false;
|
|
629
|
+
const discoverer = createWalletDiscoverer();
|
|
630
|
+
let rpcHostHandle = null;
|
|
631
|
+
const attachBridge = () => {
|
|
632
|
+
if (rpcHostHandle) return;
|
|
633
|
+
if (!iframe.contentWindow) return;
|
|
634
|
+
rpcHostHandle = attachRpcHost({
|
|
635
|
+
iframeWindow: iframe.contentWindow,
|
|
636
|
+
iframeOrigin,
|
|
637
|
+
discoverer
|
|
638
|
+
});
|
|
639
|
+
};
|
|
640
|
+
attachBridge();
|
|
641
|
+
iframe.addEventListener("load", attachBridge);
|
|
642
|
+
function postReveal() {
|
|
643
|
+
if (detached) return;
|
|
644
|
+
iframe.contentWindow?.postMessage(buildRevealMessage(), iframeOrigin);
|
|
645
|
+
}
|
|
646
|
+
function postViewportMetrics() {
|
|
647
|
+
if (detached || !postViewport) return;
|
|
648
|
+
const metrics = measureViewportMetrics();
|
|
649
|
+
if (metrics.viewportLvh <= 0) return;
|
|
650
|
+
iframe.contentWindow?.postMessage(
|
|
651
|
+
buildViewportMessage(
|
|
652
|
+
metrics.viewportLvh,
|
|
653
|
+
metrics.safeAreaBottom,
|
|
654
|
+
getEmbedMaxHeightPx?.()
|
|
655
|
+
),
|
|
656
|
+
iframeOrigin
|
|
657
|
+
);
|
|
658
|
+
}
|
|
659
|
+
let viewportPostScheduled = false;
|
|
660
|
+
const onViewportChange = () => {
|
|
661
|
+
if (viewportPostScheduled) return;
|
|
662
|
+
viewportPostScheduled = true;
|
|
663
|
+
requestAnimationFrame(() => {
|
|
664
|
+
viewportPostScheduled = false;
|
|
665
|
+
postViewportMetrics();
|
|
666
|
+
});
|
|
667
|
+
};
|
|
668
|
+
if (postViewport) {
|
|
669
|
+
window.addEventListener("resize", onViewportChange);
|
|
670
|
+
window.addEventListener("orientationchange", onViewportChange);
|
|
671
|
+
}
|
|
672
|
+
const onLoadReveal = () => {
|
|
673
|
+
postViewportMetrics();
|
|
674
|
+
if (shouldRevealOnLoad()) postReveal();
|
|
675
|
+
};
|
|
676
|
+
iframe.addEventListener("load", onLoadReveal);
|
|
677
|
+
return {
|
|
678
|
+
postReveal,
|
|
679
|
+
postViewportMetrics,
|
|
680
|
+
detach() {
|
|
681
|
+
if (detached) return;
|
|
682
|
+
detached = true;
|
|
683
|
+
iframe.removeEventListener("load", attachBridge);
|
|
684
|
+
iframe.removeEventListener("load", onLoadReveal);
|
|
685
|
+
window.removeEventListener("resize", onViewportChange);
|
|
686
|
+
window.removeEventListener("orientationchange", onViewportChange);
|
|
687
|
+
if (rpcHostHandle) {
|
|
688
|
+
rpcHostHandle.detach();
|
|
689
|
+
rpcHostHandle = null;
|
|
690
|
+
}
|
|
691
|
+
discoverer.destroy();
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
|
|
555
696
|
// src/iframe.ts
|
|
556
697
|
var STYLE_ID = "blink-deposit-styles";
|
|
557
698
|
var CLOSE_DURATION_MS = 280;
|
|
@@ -593,60 +734,20 @@ function createIframe(url, containerElement, options) {
|
|
|
593
734
|
}
|
|
594
735
|
const container = document.createElement("div");
|
|
595
736
|
container.setAttribute("data-blink-container", "");
|
|
596
|
-
const iframe =
|
|
597
|
-
iframe.src = url;
|
|
598
|
-
const iframeOrigin = new URL(url).origin;
|
|
599
|
-
iframe.allow = `publickey-credentials-get ${iframeOrigin}; publickey-credentials-create ${iframeOrigin}; clipboard-write ${iframeOrigin}`;
|
|
737
|
+
const { iframe, iframeOrigin } = createFrameElement(url);
|
|
600
738
|
const handle = document.createElement("div");
|
|
601
739
|
container.appendChild(handle);
|
|
602
740
|
container.appendChild(iframe);
|
|
603
741
|
overlay.appendChild(container);
|
|
604
742
|
const mountTarget = containerElement ?? document.body;
|
|
605
743
|
mountTarget.appendChild(overlay);
|
|
606
|
-
const
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
iframeOrigin,
|
|
614
|
-
discoverer
|
|
615
|
-
});
|
|
616
|
-
};
|
|
617
|
-
attachBridge();
|
|
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);
|
|
744
|
+
const bridges = attachFrameBridges({
|
|
745
|
+
iframe,
|
|
746
|
+
iframeOrigin,
|
|
747
|
+
// Only fluid needs them: the legacy fixed overlay sizes the iframe itself.
|
|
748
|
+
postViewport: options?.fluid === true,
|
|
749
|
+
shouldRevealOnLoad: () => !hidden
|
|
750
|
+
});
|
|
650
751
|
let savedOverflow = "";
|
|
651
752
|
let scrollLocked = false;
|
|
652
753
|
const onBackdropClick = (event) => {
|
|
@@ -677,8 +778,6 @@ function createIframe(url, containerElement, options) {
|
|
|
677
778
|
overlay.removeEventListener("click", onBackdropClick);
|
|
678
779
|
overlay.removeEventListener("touchmove", onTouchMove);
|
|
679
780
|
document.removeEventListener("keydown", onKeyDown);
|
|
680
|
-
window.removeEventListener("resize", onViewportChange);
|
|
681
|
-
window.removeEventListener("orientationchange", onViewportChange);
|
|
682
781
|
}
|
|
683
782
|
function unlockScroll() {
|
|
684
783
|
if (!scrollLocked) return;
|
|
@@ -689,7 +788,7 @@ function createIframe(url, containerElement, options) {
|
|
|
689
788
|
if (closed) return;
|
|
690
789
|
closed = true;
|
|
691
790
|
removeListeners();
|
|
692
|
-
|
|
791
|
+
bridges.detach();
|
|
693
792
|
overlay.setAttribute("data-blink-closing", "");
|
|
694
793
|
let removed = false;
|
|
695
794
|
const removeOverlay = () => {
|
|
@@ -702,15 +801,6 @@ function createIframe(url, containerElement, options) {
|
|
|
702
801
|
container.addEventListener("animationend", removeOverlay, { once: true });
|
|
703
802
|
setTimeout(removeOverlay, CLOSE_DURATION_MS + 50);
|
|
704
803
|
}
|
|
705
|
-
function detachBridge() {
|
|
706
|
-
iframe.removeEventListener("load", attachBridge);
|
|
707
|
-
iframe.removeEventListener("load", onLoadReveal);
|
|
708
|
-
if (rpcHostHandle) {
|
|
709
|
-
rpcHostHandle.detach();
|
|
710
|
-
rpcHostHandle = null;
|
|
711
|
-
}
|
|
712
|
-
discoverer.destroy();
|
|
713
|
-
}
|
|
714
804
|
return {
|
|
715
805
|
get contentWindow() {
|
|
716
806
|
return iframe.contentWindow;
|
|
@@ -735,15 +825,17 @@ function createIframe(url, containerElement, options) {
|
|
|
735
825
|
overlay.style.display = "";
|
|
736
826
|
lockScroll();
|
|
737
827
|
attachDismissalListeners();
|
|
738
|
-
postViewportMetrics();
|
|
739
|
-
postReveal();
|
|
828
|
+
bridges.postViewportMetrics();
|
|
829
|
+
bridges.postReveal();
|
|
740
830
|
},
|
|
741
831
|
postReveal() {
|
|
742
|
-
postReveal();
|
|
832
|
+
bridges.postReveal();
|
|
743
833
|
},
|
|
744
834
|
downgradeToFixed() {
|
|
745
835
|
overlay.removeAttribute("data-blink-fluid");
|
|
746
836
|
},
|
|
837
|
+
applyContentHeight() {
|
|
838
|
+
},
|
|
747
839
|
onClose(callback) {
|
|
748
840
|
closeCallback = callback;
|
|
749
841
|
},
|
|
@@ -752,7 +844,7 @@ function createIframe(url, containerElement, options) {
|
|
|
752
844
|
if (!closed) {
|
|
753
845
|
closed = true;
|
|
754
846
|
removeListeners();
|
|
755
|
-
|
|
847
|
+
bridges.detach();
|
|
756
848
|
overlay.remove();
|
|
757
849
|
unlockScroll();
|
|
758
850
|
}
|
|
@@ -789,6 +881,117 @@ function shouldUseMobileSheetLayout() {
|
|
|
789
881
|
return shortestScreenSide > 0 && shortestScreenSide <= MOBILE_SHEET_MAX_SCREEN_PX;
|
|
790
882
|
}
|
|
791
883
|
|
|
884
|
+
// src/embeddedIframe.ts
|
|
885
|
+
var EMBED_STYLE_ID = "blink-deposit-embed-styles";
|
|
886
|
+
var EMBED_STYLES = `
|
|
887
|
+
[data-blink-embed]{display:block;width:100%;position:relative}
|
|
888
|
+
[data-blink-embed][data-blink-embed-hidden]{height:0;overflow:hidden;visibility:hidden;pointer-events:none}
|
|
889
|
+
[data-blink-embed] iframe{display:block;width:100%;height:0;border:none;background:transparent;color-scheme:light}
|
|
890
|
+
`;
|
|
891
|
+
function createEmbeddedIframe(url, containerElement, options) {
|
|
892
|
+
ensureEmbedStyles();
|
|
893
|
+
if (!containerElement.isConnected) {
|
|
894
|
+
console.warn(
|
|
895
|
+
"[blink] The containerElement passed to Deposit is not in the document. Embedded mode renders into it for the life of the instance, so it must be a stable node \u2014 render the slot once and hide it with `visibility: hidden` (NOT `display: none`, which removes its layout and leaves the warming flow unable to measure itself) instead of unmounting it, or construct a new Deposit against the new node."
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
let closed = false;
|
|
899
|
+
let hidden = options?.hidden === true;
|
|
900
|
+
let closeCallback = null;
|
|
901
|
+
const readEmbedMaxHeightPx = () => typeof options?.embedMaxHeightPx === "function" ? options.embedMaxHeightPx() : options?.embedMaxHeightPx;
|
|
902
|
+
const wrapper = document.createElement("div");
|
|
903
|
+
wrapper.setAttribute("data-blink-embed", "");
|
|
904
|
+
if (hidden) {
|
|
905
|
+
wrapper.setAttribute("data-blink-embed-hidden", "");
|
|
906
|
+
}
|
|
907
|
+
const { iframe, iframeOrigin } = createFrameElement(url);
|
|
908
|
+
iframe.setAttribute("scrolling", "no");
|
|
909
|
+
const initialBudget = readEmbedMaxHeightPx();
|
|
910
|
+
if (initialBudget !== void 0) {
|
|
911
|
+
iframe.style.height = `${initialBudget}px`;
|
|
912
|
+
}
|
|
913
|
+
wrapper.appendChild(iframe);
|
|
914
|
+
containerElement.appendChild(wrapper);
|
|
915
|
+
const bridges = attachFrameBridges({
|
|
916
|
+
iframe,
|
|
917
|
+
iframeOrigin,
|
|
918
|
+
// Embedded always needs them: the flow has no usable viewport of its own,
|
|
919
|
+
// so the basis it sizes against can only come from here.
|
|
920
|
+
postViewport: true,
|
|
921
|
+
getEmbedMaxHeightPx: readEmbedMaxHeightPx,
|
|
922
|
+
shouldRevealOnLoad: () => !hidden
|
|
923
|
+
});
|
|
924
|
+
function teardown() {
|
|
925
|
+
closed = true;
|
|
926
|
+
bridges.detach();
|
|
927
|
+
wrapper.remove();
|
|
928
|
+
}
|
|
929
|
+
return {
|
|
930
|
+
get contentWindow() {
|
|
931
|
+
return iframe.contentWindow;
|
|
932
|
+
},
|
|
933
|
+
close() {
|
|
934
|
+
if (closed) return;
|
|
935
|
+
teardown();
|
|
936
|
+
closeCallback?.();
|
|
937
|
+
},
|
|
938
|
+
isClosed() {
|
|
939
|
+
return closed;
|
|
940
|
+
},
|
|
941
|
+
isHidden() {
|
|
942
|
+
return hidden;
|
|
943
|
+
},
|
|
944
|
+
reveal() {
|
|
945
|
+
if (closed || !hidden) return;
|
|
946
|
+
hidden = false;
|
|
947
|
+
wrapper.removeAttribute("data-blink-embed-hidden");
|
|
948
|
+
warnIfContainerNotRendered(containerElement);
|
|
949
|
+
bridges.postViewportMetrics();
|
|
950
|
+
bridges.postReveal();
|
|
951
|
+
},
|
|
952
|
+
postReveal() {
|
|
953
|
+
bridges.postReveal();
|
|
954
|
+
},
|
|
955
|
+
downgradeToFixed() {
|
|
956
|
+
},
|
|
957
|
+
applyContentHeight(heightPx) {
|
|
958
|
+
if (closed) return;
|
|
959
|
+
const budget = readEmbedMaxHeightPx();
|
|
960
|
+
const capped = budget === void 0 ? heightPx : Math.min(heightPx, budget);
|
|
961
|
+
iframe.style.height = `${Math.max(0, Math.round(capped))}px`;
|
|
962
|
+
},
|
|
963
|
+
onClose(callback) {
|
|
964
|
+
closeCallback = callback;
|
|
965
|
+
},
|
|
966
|
+
destroy() {
|
|
967
|
+
closeCallback = null;
|
|
968
|
+
if (!closed) teardown();
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
function warnIfContainerNotRendered(containerElement) {
|
|
973
|
+
if (typeof containerElement.getBoundingClientRect !== "function") return;
|
|
974
|
+
const rect = containerElement.getBoundingClientRect();
|
|
975
|
+
if (rect.width > 0 || rect.height > 0) return;
|
|
976
|
+
const display = typeof getComputedStyle === "function" ? getComputedStyle(containerElement).display : "";
|
|
977
|
+
console.warn(
|
|
978
|
+
`[blink] The containerElement has no layout at the moment the flow is revealed${display === "none" ? " (display: none)" : ""}. A display:none subtree cannot be measured, so the flow may report no height and the panel stays blank at its budget height. Hide the slot with \`visibility: hidden\` (plus \`height: 0; overflow: hidden\`) instead of \`display: none\`, so it keeps its box while it warms up.`
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
function ensureEmbedStyles() {
|
|
982
|
+
const existingStyle = document.getElementById(EMBED_STYLE_ID);
|
|
983
|
+
if (existingStyle) {
|
|
984
|
+
if (existingStyle.textContent !== EMBED_STYLES) {
|
|
985
|
+
existingStyle.textContent = EMBED_STYLES;
|
|
986
|
+
}
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
const style = document.createElement("style");
|
|
990
|
+
style.id = EMBED_STYLE_ID;
|
|
991
|
+
style.textContent = EMBED_STYLES;
|
|
992
|
+
document.head.appendChild(style);
|
|
993
|
+
}
|
|
994
|
+
|
|
792
995
|
// src/signer.ts
|
|
793
996
|
var DEFAULT_SIGNER_TIMEOUT_MS = 15e3;
|
|
794
997
|
async function callSigner(signer, request, timeoutMs) {
|
|
@@ -919,6 +1122,13 @@ var SANDBOX_WEBVIEW_BASE_URL = "https://pay-sandbox.blink.cash";
|
|
|
919
1122
|
var IFRAME_READY_TIMEOUT_MS = 2e3;
|
|
920
1123
|
var WARM_IFRAME_READY_TIMEOUT_MS = 6e4;
|
|
921
1124
|
var LAYOUT_FLUID_CAPABILITY = "layout-fluid";
|
|
1125
|
+
var DEFAULT_EMBED_MAX_HEIGHT_FRACTION = 0.9;
|
|
1126
|
+
function dismissedError() {
|
|
1127
|
+
return new DepositError(
|
|
1128
|
+
"DEPOSIT_DISMISSED",
|
|
1129
|
+
"The deposit was dismissed before the transfer completed."
|
|
1130
|
+
);
|
|
1131
|
+
}
|
|
922
1132
|
var IFRAME_NOT_READY = { ready: false, fluidCapable: false };
|
|
923
1133
|
function resolveWebviewBaseUrl(config) {
|
|
924
1134
|
if (config.webviewBaseUrl) return config.webviewBaseUrl;
|
|
@@ -939,11 +1149,20 @@ var Deposit = class {
|
|
|
939
1149
|
warmIframe = null;
|
|
940
1150
|
warmIframeReady = null;
|
|
941
1151
|
warmIframeReadyCancel = null;
|
|
1152
|
+
/** Resolved embedded-vs-overlay decision; see {@link Deposit.isEmbedded}. */
|
|
1153
|
+
embeddedResolved = null;
|
|
1154
|
+
/**
|
|
1155
|
+
* Settles the in-flight `requestDeposit()` as a dismissal. Non-null exactly
|
|
1156
|
+
* while a flow is in progress, so {@link Deposit.close} can reject the promise
|
|
1157
|
+
* the caller is awaiting instead of tearing the frame down under it.
|
|
1158
|
+
*/
|
|
1159
|
+
dismissActiveFlow = null;
|
|
942
1160
|
listeners = {
|
|
943
1161
|
complete: /* @__PURE__ */ new Set(),
|
|
944
1162
|
error: /* @__PURE__ */ new Set(),
|
|
945
1163
|
close: /* @__PURE__ */ new Set(),
|
|
946
|
-
"status-change": /* @__PURE__ */ new Set()
|
|
1164
|
+
"status-change": /* @__PURE__ */ new Set(),
|
|
1165
|
+
resize: /* @__PURE__ */ new Set()
|
|
947
1166
|
};
|
|
948
1167
|
/** Current phase of the deposit flow. */
|
|
949
1168
|
get status() {
|
|
@@ -961,10 +1180,40 @@ var Deposit = class {
|
|
|
961
1180
|
get isActive() {
|
|
962
1181
|
return this._status === "signer-loading" || this._status === "iframe-active";
|
|
963
1182
|
}
|
|
1183
|
+
/**
|
|
1184
|
+
* How this instance will actually present: `'embedded'` renders inline in
|
|
1185
|
+
* `containerElement`, `'overlay'` covers the page.
|
|
1186
|
+
*
|
|
1187
|
+
* Not simply an echo of the config — a host that asked for `'embedded'` gets
|
|
1188
|
+
* `'overlay'` on mobile, where a phone-sized method panel cannot hold the
|
|
1189
|
+
* flow (see {@link Deposit.isEmbedded}). Read it when laying out the panel:
|
|
1190
|
+
* on `'overlay'` no `resize` event ever fires, so a panel sized from those
|
|
1191
|
+
* reports would sit empty behind the overlay — collapse or skip it.
|
|
1192
|
+
*
|
|
1193
|
+
* Live until the SDK builds its first (warm-up) frame and fixed from then on,
|
|
1194
|
+
* so re-read it on resize rather than caching it at mount.
|
|
1195
|
+
*/
|
|
1196
|
+
get presentation() {
|
|
1197
|
+
return this.isEmbedded() ? "embedded" : "overlay";
|
|
1198
|
+
}
|
|
964
1199
|
constructor(config) {
|
|
965
1200
|
if (!config.signer || typeof config.signer !== "string" && typeof config.signer !== "function") {
|
|
966
1201
|
throw new DepositError("INVALID_REQUEST", "DepositConfig.signer is required (URL string or SignerFunction).");
|
|
967
1202
|
}
|
|
1203
|
+
if (config.presentation === "embedded") {
|
|
1204
|
+
if (!config.containerElement) {
|
|
1205
|
+
throw new DepositError(
|
|
1206
|
+
"INVALID_REQUEST",
|
|
1207
|
+
'DepositConfig.containerElement is required when presentation is "embedded".'
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
if (config.layout === "fixed") {
|
|
1211
|
+
throw new DepositError(
|
|
1212
|
+
"INVALID_REQUEST",
|
|
1213
|
+
'DepositConfig.layout "fixed" is an overlay-only escape hatch and cannot be combined with presentation "embedded".'
|
|
1214
|
+
);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
968
1217
|
this.config = config;
|
|
969
1218
|
this.log("Deposit instance created", {
|
|
970
1219
|
signer: typeof config.signer === "string" ? config.signer : "<function>"
|
|
@@ -990,10 +1239,7 @@ var Deposit = class {
|
|
|
990
1239
|
const webviewBaseUrl = resolveWebviewBaseUrl(this.config);
|
|
991
1240
|
this.hostedOrigin = this.config.hostedFlowOrigin ?? new URL(webviewBaseUrl).origin;
|
|
992
1241
|
const preloadUrl = this.buildPreloadUrl(webviewBaseUrl);
|
|
993
|
-
const iframe =
|
|
994
|
-
hidden: true,
|
|
995
|
-
fluid: this.isFluidLayout()
|
|
996
|
-
});
|
|
1242
|
+
const iframe = this.createPresentedIframe(preloadUrl, { hidden: true });
|
|
997
1243
|
const ready = this.waitForIframeReady(iframe, WARM_IFRAME_READY_TIMEOUT_MS);
|
|
998
1244
|
this.warmIframe = iframe;
|
|
999
1245
|
this.warmIframeReady = ready.promise;
|
|
@@ -1022,6 +1268,83 @@ var Deposit = class {
|
|
|
1022
1268
|
window.addEventListener("load", whenIdle, { once: true });
|
|
1023
1269
|
}
|
|
1024
1270
|
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Whether the flow renders inline in the host's element rather than as an
|
|
1273
|
+
* overlay.
|
|
1274
|
+
*
|
|
1275
|
+
* `presentation: 'embedded'` is a request, not a guarantee: **on mobile the
|
|
1276
|
+
* flow presents as the normal overlay** even for an embedded host. An
|
|
1277
|
+
* aggregator's method panel is a narrow, short column on a phone, and the
|
|
1278
|
+
* flow inside it is a payment journey with a keypad, wallet lists and a QR
|
|
1279
|
+
* code — it needs the screen. The overlay is exactly what a phone user gets
|
|
1280
|
+
* from every other Blink integration, and the host's own dialog stays behind
|
|
1281
|
+
* it. Desktop keeps the inline card, where the panel has room.
|
|
1282
|
+
*
|
|
1283
|
+
* **The decision lives with the frame.** Read live until a frame is built,
|
|
1284
|
+
* then committed for good ({@link Deposit.createPresentedIframe}) — `preload()`
|
|
1285
|
+
* warms a frame from these same predicates and the flow that later adopts it
|
|
1286
|
+
* must agree, because a frame warmed at `layout=embed` handed to the overlay
|
|
1287
|
+
* presenter (or the reverse) is a blank modal. Committing at frame creation
|
|
1288
|
+
* rather than at construction matters: a host that constructs `Deposit` before
|
|
1289
|
+
* layout settles — a widget mounting inside a transition, a background or
|
|
1290
|
+
* prerendered tab — reports a zero-width viewport, and `(max-width: 640px)`
|
|
1291
|
+
* matches at zero, so caching then would lock a desktop user into the overlay
|
|
1292
|
+
* over a viewport that never existed. The warm-up already waits for `load`
|
|
1293
|
+
* plus an idle callback, so by the time it commits the measurement is real.
|
|
1294
|
+
*/
|
|
1295
|
+
isEmbedded() {
|
|
1296
|
+
if (this.config.presentation !== "embedded") return false;
|
|
1297
|
+
if (this.embeddedResolved !== null) return this.embeddedResolved;
|
|
1298
|
+
if (typeof window === "undefined") return true;
|
|
1299
|
+
const viewportWidth = window.visualViewport?.width ?? window.innerWidth;
|
|
1300
|
+
if (!(viewportWidth > 0)) return true;
|
|
1301
|
+
return !shouldUseMobileSheetLayout();
|
|
1302
|
+
}
|
|
1303
|
+
/**
|
|
1304
|
+
* The host's height budget for the inline iframe. Explicit config wins;
|
|
1305
|
+
* otherwise most of the host viewport, which keeps a tall flow from
|
|
1306
|
+
* outgrowing the page it is embedded in.
|
|
1307
|
+
*/
|
|
1308
|
+
resolveEmbedMaxHeightPx() {
|
|
1309
|
+
if (this.config.embedMaxHeightPx !== void 0) return this.config.embedMaxHeightPx;
|
|
1310
|
+
if (typeof window === "undefined") return void 0;
|
|
1311
|
+
const derived = Math.round(window.innerHeight * DEFAULT_EMBED_MAX_HEIGHT_FRACTION);
|
|
1312
|
+
return derived > 0 ? derived : void 0;
|
|
1313
|
+
}
|
|
1314
|
+
/** Build the iframe for the configured presentation. */
|
|
1315
|
+
createPresentedIframe(url, options) {
|
|
1316
|
+
if (this.config.presentation === "embedded" && this.embeddedResolved === null) {
|
|
1317
|
+
this.embeddedResolved = this.isEmbedded();
|
|
1318
|
+
if (!this.embeddedResolved) {
|
|
1319
|
+
this.log("Mobile device: presenting the embedded flow as an overlay");
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
if (this.isEmbedded()) {
|
|
1323
|
+
return createEmbeddedIframe(url, this.config.containerElement, {
|
|
1324
|
+
hidden: options.hidden,
|
|
1325
|
+
// A getter, not a value: the default is derived from the host
|
|
1326
|
+
// viewport, which changes on rotation and window resize.
|
|
1327
|
+
embedMaxHeightPx: () => this.resolveEmbedMaxHeightPx()
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
return createIframe(url, this.overlayMountTarget(), {
|
|
1331
|
+
hidden: options.hidden,
|
|
1332
|
+
fluid: this.isFluidLayout()
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1336
|
+
* Where the overlay mounts. `containerElement` means two different things by
|
|
1337
|
+
* presentation: an overlay mount point (`presentation: 'overlay'`) or the
|
|
1338
|
+
* aggregator's inline panel slot (`'embedded'`). When an embedded flow
|
|
1339
|
+
* presents as an overlay on mobile, that slot must NOT be the mount point —
|
|
1340
|
+
* `position: fixed` resolves against the nearest transformed/filtered/
|
|
1341
|
+
* contained ancestor, and an aggregator's animated dialog is exactly that, so
|
|
1342
|
+
* the "full-screen" overlay would end up positioned inside their panel.
|
|
1343
|
+
* Falls through to `document.body`.
|
|
1344
|
+
*/
|
|
1345
|
+
overlayMountTarget() {
|
|
1346
|
+
return this.config.presentation === "embedded" ? void 0 : this.config.containerElement;
|
|
1347
|
+
}
|
|
1025
1348
|
buildPreloadUrl(webviewBaseUrl) {
|
|
1026
1349
|
const preloadUrl = new URL(webviewBaseUrl);
|
|
1027
1350
|
preloadUrl.searchParams.set("preload", "true");
|
|
@@ -1087,6 +1410,7 @@ var Deposit = class {
|
|
|
1087
1410
|
const settle = (fn) => {
|
|
1088
1411
|
if (this.requestId !== currentRequestId || settled) return;
|
|
1089
1412
|
settled = true;
|
|
1413
|
+
this.dismissActiveFlow = null;
|
|
1090
1414
|
fn();
|
|
1091
1415
|
};
|
|
1092
1416
|
const onComplete = (result) => {
|
|
@@ -1112,6 +1436,12 @@ var Deposit = class {
|
|
|
1112
1436
|
reject(error);
|
|
1113
1437
|
});
|
|
1114
1438
|
};
|
|
1439
|
+
this.dismissActiveFlow = () => {
|
|
1440
|
+
settle(() => {
|
|
1441
|
+
this.cleanup();
|
|
1442
|
+
reject(dismissedError());
|
|
1443
|
+
});
|
|
1444
|
+
};
|
|
1115
1445
|
if (this.config.flowTimeoutMs != null && this.config.flowTimeoutMs > 0) {
|
|
1116
1446
|
this.flowTimer = setTimeout(() => {
|
|
1117
1447
|
onError(
|
|
@@ -1138,9 +1468,29 @@ var Deposit = class {
|
|
|
1138
1468
|
/** No-op — retained for API compatibility with the popup-based SDK. */
|
|
1139
1469
|
focus() {
|
|
1140
1470
|
}
|
|
1141
|
-
/**
|
|
1471
|
+
/**
|
|
1472
|
+
* Close the deposit iframe without waiting for completion — the host's own
|
|
1473
|
+
* back button or dialog chrome.
|
|
1474
|
+
*
|
|
1475
|
+
* This **settles a flow in progress** by rejecting its `requestDeposit()`
|
|
1476
|
+
* promise with `DEPOSIT_DISMISSED`, exactly as the flow's own close control
|
|
1477
|
+
* does. It has to: `cleanup()` destroys the frame through `destroy()`, which
|
|
1478
|
+
* drops the handle's close callback on purpose, so without this the caller's
|
|
1479
|
+
* `await` never returns. An aggregator whose back button awaited that promise
|
|
1480
|
+
* to restore its method list was left showing an empty panel — the flow gone,
|
|
1481
|
+
* its own list still not rendered, and no error to explain why.
|
|
1482
|
+
*
|
|
1483
|
+
* The rejection code is the same `DEPOSIT_DISMISSED` the in-flow control
|
|
1484
|
+
* produces, so a host writes one dismissal branch rather than one per
|
|
1485
|
+
* affordance. What it deliberately does not do is report an error: no `error`
|
|
1486
|
+
* event, and `status` lands on 'idle' as it always has, because the host
|
|
1487
|
+
* initiated this. With no flow in progress it is a plain teardown, unchanged.
|
|
1488
|
+
*/
|
|
1142
1489
|
close() {
|
|
1143
1490
|
this.log("close() called");
|
|
1491
|
+
const dismiss = this.dismissActiveFlow;
|
|
1492
|
+
this.dismissActiveFlow = null;
|
|
1493
|
+
dismiss?.();
|
|
1144
1494
|
this.cleanup();
|
|
1145
1495
|
this.setStatus("idle");
|
|
1146
1496
|
this.emit("close");
|
|
@@ -1193,10 +1543,80 @@ var Deposit = class {
|
|
|
1193
1543
|
if (theme === "dark" || theme === "system") {
|
|
1194
1544
|
url.searchParams.set("appearance", theme);
|
|
1195
1545
|
}
|
|
1546
|
+
this.applyBrandParam(url);
|
|
1547
|
+
}
|
|
1548
|
+
/**
|
|
1549
|
+
* Appends the merchant's brand colors as `brand=p-0f62fe.bg-ffffff…`.
|
|
1550
|
+
*
|
|
1551
|
+
* On the URL rather than a message because the hosted flow's loading shell
|
|
1552
|
+
* paints from its entry chunk, hundreds of ms before React mounts: a palette
|
|
1553
|
+
* that arrived by `postMessage` would show Blink's own card color first and
|
|
1554
|
+
* then become the merchant's. Unreserved characters only, so the param costs
|
|
1555
|
+
* ~50 bytes of the URL budget rather than triple that in percent-encoding.
|
|
1556
|
+
*
|
|
1557
|
+
* Validated here purely so the merchant sees the complaint in their OWN
|
|
1558
|
+
* console — the hosted flow re-validates everything it decodes, since the URL
|
|
1559
|
+
* is host-controlled input that ends up in a stylesheet. Silence would be the
|
|
1560
|
+
* worst outcome: a dropped color that nobody is told about looks like the SDK
|
|
1561
|
+
* ignoring the config.
|
|
1562
|
+
*/
|
|
1563
|
+
applyBrandParam(url) {
|
|
1564
|
+
const variables = this.config.appearance?.variables;
|
|
1565
|
+
if (!variables) return;
|
|
1566
|
+
const accepted = {};
|
|
1567
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
1568
|
+
if (value === void 0 || value === null) continue;
|
|
1569
|
+
if (!BRAND_COLOR_PARAM_KEYS[key]) {
|
|
1570
|
+
console.error(
|
|
1571
|
+
`[blink] appearance.variables.${key} is not a supported brand color. Supported: ${Object.keys(BRAND_COLOR_PARAM_KEYS).join(", ")}.`
|
|
1572
|
+
);
|
|
1573
|
+
continue;
|
|
1574
|
+
}
|
|
1575
|
+
const hex = normalizeBrandHex(value);
|
|
1576
|
+
if (!hex) {
|
|
1577
|
+
console.error(
|
|
1578
|
+
`[blink] appearance.variables.${key} must be opaque hex (#rgb or #rrggbb); received ${JSON.stringify(value)}. Ignoring it.`
|
|
1579
|
+
);
|
|
1580
|
+
continue;
|
|
1581
|
+
}
|
|
1582
|
+
accepted[key] = hex;
|
|
1583
|
+
}
|
|
1584
|
+
const encoded = Object.keys(BRAND_COLOR_PARAM_KEYS).filter((key) => accepted[key] !== void 0).map((key) => `${BRAND_COLOR_PARAM_KEYS[key]}-${accepted[key].slice(1)}`).join(".");
|
|
1585
|
+
if (encoded) url.searchParams.set("brand", encoded);
|
|
1586
|
+
}
|
|
1587
|
+
/**
|
|
1588
|
+
* Normalizes the display-only {@link DepositRequest.balance} for the wire,
|
|
1589
|
+
* or returns `undefined` to omit it everywhere — the `blink:signed-payload`
|
|
1590
|
+
* sibling field and the legacy fallback URL param alike. Additive wire
|
|
1591
|
+
* discipline: an unset or rejected balance leaves both channels
|
|
1592
|
+
* byte-for-byte what they always were, and old webviews ignore the field
|
|
1593
|
+
* by construction.
|
|
1594
|
+
*
|
|
1595
|
+
* Validated here purely so the merchant sees the complaint in their OWN
|
|
1596
|
+
* console (same rationale as {@link applyBrandParam}); the hosted flow
|
|
1597
|
+
* re-validates whatever arrives, since both channels are host-controlled
|
|
1598
|
+
* input. A rejected balance never blocks the deposit — the flow proceeds
|
|
1599
|
+
* without the subtitle.
|
|
1600
|
+
*/
|
|
1601
|
+
normalizeRequestBalance(balance) {
|
|
1602
|
+
if (balance === void 0 || balance === null) return void 0;
|
|
1603
|
+
const normalized = normalizeDisplayBalance(balance);
|
|
1604
|
+
if (normalized === null) {
|
|
1605
|
+
const received = typeof balance === "number" ? String(balance) : JSON.stringify(balance) ?? String(balance);
|
|
1606
|
+
console.error(
|
|
1607
|
+
`[blink] balance must be a finite number >= 0 and < 1e12 (USD, display only); received ${received}. Ignoring it.`
|
|
1608
|
+
);
|
|
1609
|
+
return void 0;
|
|
1610
|
+
}
|
|
1611
|
+
return normalized;
|
|
1196
1612
|
}
|
|
1197
|
-
/**
|
|
1613
|
+
/**
|
|
1614
|
+
* Fluid is the default; `layout: 'fixed'` opts back into the legacy
|
|
1615
|
+
* container. Embedded is a separate presentation and never fluid — the
|
|
1616
|
+
* constructor rejects the combination outright.
|
|
1617
|
+
*/
|
|
1198
1618
|
isFluidLayout() {
|
|
1199
|
-
return this.config.layout !== "fixed";
|
|
1619
|
+
return !this.isEmbedded() && this.config.layout !== "fixed";
|
|
1200
1620
|
}
|
|
1201
1621
|
/**
|
|
1202
1622
|
* Marks the hosted-flow URL as fluid-layout: the iframe spans the full
|
|
@@ -1206,6 +1626,10 @@ var Deposit = class {
|
|
|
1206
1626
|
* assumed to understand fluid layout and gets the fixed container.
|
|
1207
1627
|
*/
|
|
1208
1628
|
applyLayoutParam(url) {
|
|
1629
|
+
if (this.isEmbedded()) {
|
|
1630
|
+
url.searchParams.set("layout", "embed");
|
|
1631
|
+
return;
|
|
1632
|
+
}
|
|
1209
1633
|
if (this.isFluidLayout()) {
|
|
1210
1634
|
url.searchParams.set("layout", "fluid");
|
|
1211
1635
|
}
|
|
@@ -1217,7 +1641,14 @@ var Deposit = class {
|
|
|
1217
1641
|
* afterwards (rotation, window resize) — see iframe.ts.
|
|
1218
1642
|
*/
|
|
1219
1643
|
applyViewportParams(url) {
|
|
1220
|
-
|
|
1644
|
+
const embedded = this.isEmbedded();
|
|
1645
|
+
if (!this.isFluidLayout() && !embedded) return;
|
|
1646
|
+
if (embedded) {
|
|
1647
|
+
const embedMaxHeightPx = this.resolveEmbedMaxHeightPx();
|
|
1648
|
+
if (embedMaxHeightPx !== void 0) {
|
|
1649
|
+
url.searchParams.set("embedMaxHeight", String(embedMaxHeightPx));
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1221
1652
|
const metrics = measureViewportMetrics();
|
|
1222
1653
|
if (metrics.viewportLvh <= 0) return;
|
|
1223
1654
|
url.searchParams.set("viewportLvh", String(metrics.viewportLvh));
|
|
@@ -1237,6 +1668,7 @@ var Deposit = class {
|
|
|
1237
1668
|
signer: typeof this.config.signer === "string" ? this.config.signer : "<function>"
|
|
1238
1669
|
});
|
|
1239
1670
|
const signerRequest = buildSignerRequest(request, webviewBaseUrl);
|
|
1671
|
+
const displayBalance = this.normalizeRequestBalance(request.balance);
|
|
1240
1672
|
let preloadIframe;
|
|
1241
1673
|
let iframeReadyPromise;
|
|
1242
1674
|
const warm = this.takeWarmIframe();
|
|
@@ -1254,21 +1686,12 @@ var Deposit = class {
|
|
|
1254
1686
|
});
|
|
1255
1687
|
this.log("Reusing warm preload iframe");
|
|
1256
1688
|
} else {
|
|
1257
|
-
preloadIframe =
|
|
1258
|
-
this.buildPreloadUrl(webviewBaseUrl),
|
|
1259
|
-
this.config.containerElement,
|
|
1260
|
-
{ fluid: this.isFluidLayout() }
|
|
1261
|
-
);
|
|
1689
|
+
preloadIframe = this.createPresentedIframe(this.buildPreloadUrl(webviewBaseUrl), {});
|
|
1262
1690
|
iframeReadyPromise = this.waitForIframeReady(preloadIframe).promise;
|
|
1263
1691
|
}
|
|
1264
1692
|
this.iframe = preloadIframe;
|
|
1265
1693
|
preloadIframe.onClose(() => {
|
|
1266
|
-
onError(
|
|
1267
|
-
new DepositError(
|
|
1268
|
-
"DEPOSIT_DISMISSED",
|
|
1269
|
-
"The deposit was dismissed before the transfer completed."
|
|
1270
|
-
)
|
|
1271
|
-
);
|
|
1694
|
+
onError(dismissedError());
|
|
1272
1695
|
this.cleanup();
|
|
1273
1696
|
this.emit("close");
|
|
1274
1697
|
});
|
|
@@ -1298,7 +1721,8 @@ var Deposit = class {
|
|
|
1298
1721
|
buildSignedPayloadMessage(
|
|
1299
1722
|
signerResponse.merchantId,
|
|
1300
1723
|
signerResponse.payload,
|
|
1301
|
-
signerResponse.signature
|
|
1724
|
+
signerResponse.signature,
|
|
1725
|
+
displayBalance
|
|
1302
1726
|
),
|
|
1303
1727
|
this.hostedOrigin
|
|
1304
1728
|
);
|
|
@@ -1312,17 +1736,19 @@ var Deposit = class {
|
|
|
1312
1736
|
hostedUrl.searchParams.set("merchantId", signerResponse.merchantId);
|
|
1313
1737
|
hostedUrl.searchParams.set("payload", signerResponse.payload);
|
|
1314
1738
|
hostedUrl.searchParams.set("signature", signerResponse.signature);
|
|
1739
|
+
if (displayBalance !== void 0) {
|
|
1740
|
+
hostedUrl.searchParams.set("balance", displayBalance);
|
|
1741
|
+
}
|
|
1315
1742
|
this.applyFullWidgetParam(hostedUrl);
|
|
1743
|
+
if (this.isEmbedded()) {
|
|
1744
|
+
this.applyLayoutParam(hostedUrl);
|
|
1745
|
+
this.applyViewportParams(hostedUrl);
|
|
1746
|
+
}
|
|
1316
1747
|
const targetUrl = hostedUrl.toString();
|
|
1317
|
-
const iframeHandle =
|
|
1748
|
+
const iframeHandle = this.createPresentedIframe(targetUrl, {});
|
|
1318
1749
|
this.iframe = iframeHandle;
|
|
1319
1750
|
iframeHandle.onClose(() => {
|
|
1320
|
-
onError(
|
|
1321
|
-
new DepositError(
|
|
1322
|
-
"DEPOSIT_DISMISSED",
|
|
1323
|
-
"The deposit was dismissed before the transfer completed."
|
|
1324
|
-
)
|
|
1325
|
-
);
|
|
1751
|
+
onError(dismissedError());
|
|
1326
1752
|
this.cleanup();
|
|
1327
1753
|
this.emit("close");
|
|
1328
1754
|
});
|
|
@@ -1398,6 +1824,16 @@ var Deposit = class {
|
|
|
1398
1824
|
iframeHandle.close();
|
|
1399
1825
|
return;
|
|
1400
1826
|
}
|
|
1827
|
+
const contentHeight = parseContentHeight(event.data);
|
|
1828
|
+
if (contentHeight) {
|
|
1829
|
+
iframeHandle.applyContentHeight(contentHeight.heightPx);
|
|
1830
|
+
this.emit("resize", {
|
|
1831
|
+
heightPx: contentHeight.heightPx,
|
|
1832
|
+
...contentHeight.preferredWidthPx === void 0 ? {} : { preferredWidthPx: contentHeight.preferredWidthPx },
|
|
1833
|
+
...contentHeight.minWidthPx === void 0 ? {} : { minWidthPx: contentHeight.minWidthPx }
|
|
1834
|
+
});
|
|
1835
|
+
return;
|
|
1836
|
+
}
|
|
1401
1837
|
const message = parseTransferComplete(event.data);
|
|
1402
1838
|
if (!message) {
|
|
1403
1839
|
return;
|
|
@@ -1475,7 +1911,7 @@ function detectMerchantColorScheme() {
|
|
|
1475
1911
|
var Checkout = Deposit;
|
|
1476
1912
|
|
|
1477
1913
|
// src/index.ts
|
|
1478
|
-
var VERSION = "0.3.
|
|
1914
|
+
var VERSION = "0.3.32";
|
|
1479
1915
|
|
|
1480
1916
|
exports.ALLOWED_RPC_METHODS = ALLOWED_RPC_METHODS;
|
|
1481
1917
|
exports.BRIDGE_PROTOCOL_VERSION = BRIDGE_PROTOCOL_VERSION;
|