@bounded-sh/client 0.0.62 → 0.0.65
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/auth/providers/email-auth-provider.d.ts +4 -4
- package/dist/auth/providers/injected-wallet-provider.d.ts +1 -1
- package/dist/auth/providers/privy-expo-provider.d.ts +1 -1
- package/dist/auth/turnkey-signer-bridge.d.ts +5 -0
- package/dist/auth/turnkey-signing-capability.d.ts +20 -0
- package/dist/{email-auth-provider-vWv0rnbd.mjs → email-auth-provider-BLHNLu5l.mjs} +27 -30
- package/dist/email-auth-provider-BLHNLu5l.mjs.map +1 -0
- package/dist/{email-auth-provider-BxV1zZA_.js → email-auth-provider-CJVJsWXv.js} +27 -30
- package/dist/email-auth-provider-CJVJsWXv.js.map +1 -0
- package/dist/{email-auth-provider-BttT2sZK.js → email-auth-provider-DYtoSrdm.js} +27 -30
- package/dist/email-auth-provider-DYtoSrdm.js.map +1 -0
- package/dist/{email-auth-provider-Cb4VKA1E.mjs → email-auth-provider-wqNimboO.mjs} +27 -30
- package/dist/email-auth-provider-wqNimboO.mjs.map +1 -0
- package/dist/{guest-auth-provider-BBPpydtM.mjs → guest-auth-provider-C3EGlSSp.mjs} +2 -2
- package/dist/{guest-auth-provider-CeIZw5x6.mjs.map → guest-auth-provider-C3EGlSSp.mjs.map} +1 -1
- package/dist/{guest-auth-provider-CeIZw5x6.mjs → guest-auth-provider-CKkNZ-1p.mjs} +2 -2
- package/dist/{guest-auth-provider-BBPpydtM.mjs.map → guest-auth-provider-CKkNZ-1p.mjs.map} +1 -1
- package/dist/{guest-auth-provider-BcR-MQ0g.js → guest-auth-provider-CoI0r92a.js} +2 -2
- package/dist/{guest-auth-provider-BcR-MQ0g.js.map → guest-auth-provider-CoI0r92a.js.map} +1 -1
- package/dist/{guest-auth-provider-peD5Zasl.js → guest-auth-provider-UMP8Z_bK.js} +2 -2
- package/dist/{guest-auth-provider-peD5Zasl.js.map → guest-auth-provider-UMP8Z_bK.js.map} +1 -1
- package/dist/{index-DpJl_Cpa.mjs → index-Cgbr0abz.mjs} +2190 -2340
- package/dist/index-Cgbr0abz.mjs.map +1 -0
- package/dist/{index-DEDYfO2p.js → index-FkEGh6dx.js} +2192 -2344
- package/dist/index-FkEGh6dx.js.map +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{index.native-BSheiGj2.js → index.native-CAHw3k3_.js} +621 -323
- package/dist/index.native-CAHw3k3_.js.map +1 -0
- package/dist/{index.native-BIUs8t7F.mjs → index.native-wyaknPBR.mjs} +619 -319
- package/dist/index.native-wyaknPBR.mjs.map +1 -0
- package/dist/index.native.d.ts +0 -1
- package/dist/index.native.js +1 -2
- package/dist/index.native.js.map +1 -1
- package/dist/index.native.mjs +1 -1
- package/dist/{injected-evm-wallet-provider-DnOrVMDX.mjs → injected-evm-wallet-provider-B8x7dNuL.mjs} +2 -2
- package/dist/{injected-evm-wallet-provider-DnOrVMDX.mjs.map → injected-evm-wallet-provider-B8x7dNuL.mjs.map} +1 -1
- package/dist/{injected-evm-wallet-provider-7XawIUdJ.js → injected-evm-wallet-provider-BAToKWZo.js} +2 -2
- package/dist/{injected-evm-wallet-provider-7XawIUdJ.js.map → injected-evm-wallet-provider-BAToKWZo.js.map} +1 -1
- package/dist/{injected-evm-wallet-provider-B-9VXQcH.js → injected-evm-wallet-provider-D-7Eg6TS.js} +2 -2
- package/dist/{injected-evm-wallet-provider-B-9VXQcH.js.map → injected-evm-wallet-provider-D-7Eg6TS.js.map} +1 -1
- package/dist/{injected-evm-wallet-provider-BVsxOzYr.mjs → injected-evm-wallet-provider-pVKJtDHL.mjs} +2 -2
- package/dist/{injected-evm-wallet-provider-BVsxOzYr.mjs.map → injected-evm-wallet-provider-pVKJtDHL.mjs.map} +1 -1
- package/dist/{injected-wallet-provider-D574oPzH.js → injected-wallet-provider-28GE3rH9.js} +8 -75
- package/dist/injected-wallet-provider-28GE3rH9.js.map +1 -0
- package/dist/{injected-wallet-provider-ZkPzVj5W.mjs → injected-wallet-provider-5NeXEzui.mjs} +9 -76
- package/dist/injected-wallet-provider-5NeXEzui.mjs.map +1 -0
- package/dist/{injected-wallet-provider-Bqk33sir.mjs → injected-wallet-provider-BojBmTAQ.mjs} +9 -76
- package/dist/injected-wallet-provider-BojBmTAQ.mjs.map +1 -0
- package/dist/{injected-wallet-provider-BMDJntMD.js → injected-wallet-provider-DvwlPJea.js} +8 -75
- package/dist/injected-wallet-provider-DvwlPJea.js.map +1 -0
- package/dist/onramp.d.ts +4 -1
- package/package.json +2 -2
- package/dist/auth/crossmint-signer-bridge.d.ts +0 -45
- package/dist/auth/providers/phantom-wallet-provider.d.ts +0 -111
- package/dist/auth/providers/privy-wallet-provider.d.ts +0 -83
- package/dist/auth/providers/sol/sol-utils.d.ts +0 -2
- package/dist/auth/providers/solana-mobile-wallet-provider.d.ts +0 -151
- package/dist/email-auth-provider-BttT2sZK.js.map +0 -1
- package/dist/email-auth-provider-BxV1zZA_.js.map +0 -1
- package/dist/email-auth-provider-Cb4VKA1E.mjs.map +0 -1
- package/dist/email-auth-provider-vWv0rnbd.mjs.map +0 -1
- package/dist/index-DEDYfO2p.js.map +0 -1
- package/dist/index-DpJl_Cpa.mjs.map +0 -1
- package/dist/index.native-BIUs8t7F.mjs.map +0 -1
- package/dist/index.native-BSheiGj2.js.map +0 -1
- package/dist/injected-wallet-provider-BMDJntMD.js.map +0 -1
- package/dist/injected-wallet-provider-Bqk33sir.mjs.map +0 -1
- package/dist/injected-wallet-provider-D574oPzH.js.map +0 -1
- package/dist/injected-wallet-provider-ZkPzVj5W.mjs.map +0 -1
|
@@ -868,6 +868,8 @@ function getDefaultExportFromCjs (x) {
|
|
|
868
868
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
869
869
|
}
|
|
870
870
|
|
|
871
|
+
var safeBuffer = {exports: {}};
|
|
872
|
+
|
|
871
873
|
var buffer = {};
|
|
872
874
|
|
|
873
875
|
var base64Js = {};
|
|
@@ -3237,10 +3239,6 @@ function requireBuffer () {
|
|
|
3237
3239
|
return buffer;
|
|
3238
3240
|
}
|
|
3239
3241
|
|
|
3240
|
-
var bufferExports = requireBuffer();
|
|
3241
|
-
|
|
3242
|
-
var safeBuffer = {exports: {}};
|
|
3243
|
-
|
|
3244
3242
|
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
3245
3243
|
|
|
3246
3244
|
var hasRequiredSafeBuffer;
|
|
@@ -3454,173 +3452,505 @@ var basex = /*@__PURE__*/getDefaultExportFromCjs(srcExports);
|
|
|
3454
3452
|
var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
3455
3453
|
var bs58 = basex(ALPHABET);
|
|
3456
3454
|
|
|
3457
|
-
|
|
3458
|
-
|
|
3455
|
+
var bufferExports = requireBuffer();
|
|
3456
|
+
|
|
3457
|
+
// bounded-widget-modal.ts - the shared in-app WIDGET shell for Bounded's login
|
|
3458
|
+
// and signing surfaces. One Shadow-DOM overlay + panel that matches the Bounded
|
|
3459
|
+
// widget (Seal) look and MOTION: a backdrop fade, a panel rise on desktop, a
|
|
3460
|
+
// bottom-sheet on mobile, a height tween as content swaps, and a clean close.
|
|
3461
|
+
//
|
|
3462
|
+
// It hosts EITHER:
|
|
3463
|
+
// - NATIVE content (the login card the SDK renders itself), or
|
|
3464
|
+
// - an IFRAME (the Bounded-owned signer page, which must run on the single
|
|
3465
|
+
// signer origin because a WebAuthn passkey is bound to one origin).
|
|
3466
|
+
//
|
|
3467
|
+
// The modal is a warm singleton: it stays mounted (hidden) between uses so a
|
|
3468
|
+
// second open - or a signature right after login - is instant and, when it is
|
|
3469
|
+
// already open, a clean in-place view swap rather than a reopen.
|
|
3470
|
+
function hasDOM$3() {
|
|
3471
|
+
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
3472
|
+
}
|
|
3473
|
+
const OVERLAY_CSS = `
|
|
3474
|
+
:host{all:initial}
|
|
3475
|
+
*{box-sizing:border-box}
|
|
3476
|
+
.bw-ov{position:fixed;inset:0;z-index:2147483647;display:none;
|
|
3477
|
+
font-family:"Schibsted Grotesk","Helvetica Neue",Arial,sans-serif}
|
|
3478
|
+
.bw-ov.mounted{display:block}
|
|
3479
|
+
.bw-back{position:fixed;inset:0;background:rgba(4,4,5,.62);opacity:0;
|
|
3480
|
+
transition:opacity .24s ease;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px)}
|
|
3481
|
+
.bw-wrap{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;padding:20px}
|
|
3482
|
+
.bw-panel{position:relative;width:420px;max-width:calc(100vw - 28px);height:280px;
|
|
3483
|
+
border-radius:14px;overflow:hidden;background:#0e0f11;border:1px solid rgba(232,230,222,.08);
|
|
3484
|
+
box-shadow:0 1px 0 rgba(232,230,222,.03) inset,0 40px 90px -45px rgba(0,0,0,.85);
|
|
3485
|
+
opacity:0;transform:translateY(14px) scale(.98);will-change:transform,opacity,height;
|
|
3486
|
+
transition:opacity .28s cubic-bezier(.2,.8,.2,1),transform .28s cubic-bezier(.2,.8,.2,1),
|
|
3487
|
+
height .3s cubic-bezier(.2,.8,.2,1)}
|
|
3488
|
+
.bw-ov.show .bw-back{opacity:1}
|
|
3489
|
+
.bw-ov.show .bw-panel{opacity:1;transform:none}
|
|
3490
|
+
.bw-ov.closing .bw-back{opacity:0}
|
|
3491
|
+
.bw-ov.closing .bw-panel{opacity:0;transform:translateY(12px) scale(.99)}
|
|
3492
|
+
.bw-content{position:absolute;inset:0;overflow:hidden}
|
|
3493
|
+
.bw-frame{display:block;width:100%;height:100%;border:0;background:transparent;color-scheme:dark}
|
|
3494
|
+
/* editorial corner crop-marks, matching the reference frame */
|
|
3495
|
+
.bw-mk{position:absolute;width:13px;height:13px;pointer-events:none;z-index:2;
|
|
3496
|
+
border-color:rgba(232,230,222,.22);border-style:solid;border-width:0}
|
|
3497
|
+
.bw-mk.tl{top:11px;left:11px;border-top-width:1px;border-left-width:1px}
|
|
3498
|
+
.bw-mk.tr{top:11px;right:11px;border-top-width:1px;border-right-width:1px}
|
|
3499
|
+
.bw-mk.bl{bottom:11px;left:11px;border-bottom-width:1px;border-left-width:1px}
|
|
3500
|
+
.bw-mk.br{bottom:11px;right:11px;border-bottom-width:1px;border-right-width:1px}
|
|
3501
|
+
@media(max-width:560px){
|
|
3502
|
+
.bw-wrap{align-items:flex-end;padding:0}
|
|
3503
|
+
.bw-panel{width:100%;max-width:100%;border-radius:18px 18px 0 0;border-bottom:0}
|
|
3504
|
+
.bw-content{overflow-y:auto}
|
|
3505
|
+
.bw-ov.show .bw-panel{transform:none}
|
|
3506
|
+
.bw-ov:not(.show) .bw-panel,.bw-ov.closing .bw-panel{transform:translateY(18%)}
|
|
3507
|
+
}
|
|
3508
|
+
@media(prefers-reduced-motion:reduce){.bw-back,.bw-panel{transition:opacity .12s linear!important}}
|
|
3509
|
+
`;
|
|
3510
|
+
let modal = null;
|
|
3511
|
+
function getModal() {
|
|
3512
|
+
if (modal)
|
|
3513
|
+
return modal;
|
|
3514
|
+
const root = document.createElement("div");
|
|
3515
|
+
root.setAttribute("data-bounded-widget", "");
|
|
3516
|
+
const shadow = root.attachShadow({ mode: "open" });
|
|
3517
|
+
const style = document.createElement("style");
|
|
3518
|
+
style.textContent = OVERLAY_CSS;
|
|
3519
|
+
shadow.appendChild(style);
|
|
3520
|
+
const overlay = document.createElement("div");
|
|
3521
|
+
overlay.className = "bw-ov";
|
|
3522
|
+
const back = document.createElement("div");
|
|
3523
|
+
back.className = "bw-back";
|
|
3524
|
+
const wrap = document.createElement("div");
|
|
3525
|
+
wrap.className = "bw-wrap";
|
|
3526
|
+
const panel = document.createElement("div");
|
|
3527
|
+
panel.className = "bw-panel";
|
|
3528
|
+
const content = document.createElement("div");
|
|
3529
|
+
content.className = "bw-content";
|
|
3530
|
+
panel.appendChild(content);
|
|
3531
|
+
for (const corner of ["tl", "tr", "bl", "br"]) {
|
|
3532
|
+
const mk = document.createElement("span");
|
|
3533
|
+
mk.className = "bw-mk " + corner;
|
|
3534
|
+
panel.appendChild(mk);
|
|
3535
|
+
}
|
|
3536
|
+
wrap.appendChild(panel);
|
|
3537
|
+
overlay.appendChild(back);
|
|
3538
|
+
overlay.appendChild(wrap);
|
|
3539
|
+
shadow.appendChild(overlay);
|
|
3540
|
+
(document.body || document.documentElement).appendChild(root);
|
|
3541
|
+
const m = {
|
|
3542
|
+
root,
|
|
3543
|
+
overlay,
|
|
3544
|
+
panel,
|
|
3545
|
+
content,
|
|
3546
|
+
iframe: null,
|
|
3547
|
+
iframeOrigin: "",
|
|
3548
|
+
iframeReady: false,
|
|
3549
|
+
onBackdrop: null,
|
|
3550
|
+
onIframeMessage: null,
|
|
3551
|
+
chain: Promise.resolve(),
|
|
3552
|
+
fitObserver: null,
|
|
3553
|
+
};
|
|
3554
|
+
// The dismiss handler lives on `.bw-wrap`: it is the full-viewport flex layer
|
|
3555
|
+
// that sits ABOVE `.bw-back`, so it (not the backdrop element) receives clicks
|
|
3556
|
+
// outside the panel. Fire only when the click lands on the wrap itself, never
|
|
3557
|
+
// when it bubbles up from the panel or its content.
|
|
3558
|
+
wrap.addEventListener("click", (event) => {
|
|
3559
|
+
if (event.target === wrap && m.onBackdrop)
|
|
3560
|
+
m.onBackdrop();
|
|
3561
|
+
});
|
|
3562
|
+
window.addEventListener("message", (event) => {
|
|
3563
|
+
if (!m.iframe)
|
|
3564
|
+
return;
|
|
3565
|
+
if (event.origin !== m.iframeOrigin)
|
|
3566
|
+
return;
|
|
3567
|
+
if (event.source !== m.iframe.contentWindow)
|
|
3568
|
+
return;
|
|
3569
|
+
const d = event.data;
|
|
3570
|
+
if (!d || typeof d !== "object")
|
|
3571
|
+
return;
|
|
3572
|
+
if (m.onIframeMessage)
|
|
3573
|
+
m.onIframeMessage(d);
|
|
3574
|
+
});
|
|
3575
|
+
modal = m;
|
|
3576
|
+
return m;
|
|
3577
|
+
}
|
|
3578
|
+
function showModal(m) {
|
|
3579
|
+
m.overlay.classList.remove("closing");
|
|
3580
|
+
m.overlay.classList.add("mounted");
|
|
3581
|
+
// Force a reflow so the .show transition runs from the hidden state every open.
|
|
3582
|
+
void m.panel.offsetWidth;
|
|
3583
|
+
m.overlay.classList.add("show");
|
|
3584
|
+
}
|
|
3585
|
+
function hideModal(m, after) {
|
|
3586
|
+
m.overlay.classList.remove("show");
|
|
3587
|
+
m.overlay.classList.add("closing");
|
|
3588
|
+
window.setTimeout(() => {
|
|
3589
|
+
m.overlay.classList.remove("mounted", "closing");
|
|
3590
|
+
}, 260);
|
|
3591
|
+
}
|
|
3592
|
+
function setPanelHeight(m, px) {
|
|
3593
|
+
const h = Math.max(140, Math.min(680, Math.round(px)));
|
|
3594
|
+
m.panel.style.height = h + "px";
|
|
3595
|
+
}
|
|
3596
|
+
/** Get (or lazily create) the warm iframe for signer/hosted-page mode. */
|
|
3597
|
+
function ensureIframe(m, url, origin) {
|
|
3598
|
+
var _a;
|
|
3599
|
+
if (m.iframe && m.iframeOrigin === origin && m.iframe.src === url)
|
|
3600
|
+
return m.iframe;
|
|
3601
|
+
detachIframe(m);
|
|
3602
|
+
(_a = m.fitObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
3603
|
+
m.fitObserver = null;
|
|
3604
|
+
m.content.style.display = "none";
|
|
3605
|
+
const iframe = document.createElement("iframe");
|
|
3606
|
+
iframe.className = "bw-frame";
|
|
3607
|
+
iframe.setAttribute("title", "Bounded");
|
|
3608
|
+
// Grant the framed origin WebAuthn get + create so passkey enroll/sign run
|
|
3609
|
+
// inside the frame from the user's click (transient activation stays in-frame).
|
|
3610
|
+
iframe.setAttribute("allow", "publickey-credentials-get; publickey-credentials-create; clipboard-write");
|
|
3611
|
+
iframe.src = url;
|
|
3612
|
+
m.iframeOrigin = origin;
|
|
3613
|
+
m.iframeReady = false;
|
|
3614
|
+
m.panel.appendChild(iframe);
|
|
3615
|
+
m.iframe = iframe;
|
|
3616
|
+
return iframe;
|
|
3617
|
+
}
|
|
3618
|
+
function detachIframe(m) {
|
|
3619
|
+
if (m.iframe) {
|
|
3620
|
+
try {
|
|
3621
|
+
m.iframe.remove();
|
|
3622
|
+
}
|
|
3623
|
+
catch (_a) {
|
|
3624
|
+
/* ignore */
|
|
3625
|
+
}
|
|
3626
|
+
}
|
|
3627
|
+
m.iframe = null;
|
|
3628
|
+
m.iframeReady = false;
|
|
3629
|
+
m.iframeOrigin = "";
|
|
3630
|
+
m.onIframeMessage = null;
|
|
3631
|
+
}
|
|
3632
|
+
|
|
3633
|
+
// turnkey-wallet-widget.ts - runs one Turnkey signer exchange inside the shared
|
|
3634
|
+
// in-app WIDGET (bounded-widget-modal.ts). The Bounded-owned signer page is loaded
|
|
3635
|
+
// in a warm iframe behind the modal so signing feels native: an in-app card plus
|
|
3636
|
+
// the OS Face ID / Touch ID sheet, never a jarring popup.
|
|
3459
3637
|
//
|
|
3460
|
-
//
|
|
3461
|
-
//
|
|
3462
|
-
//
|
|
3463
|
-
//
|
|
3464
|
-
// ONLY on the Bounded signer page (one whitelisted origin) and talking to it via
|
|
3465
|
-
// postMessage.
|
|
3638
|
+
// WHY AN IFRAME: a WebAuthn passkey is bound to ONE origin, so passkey create/sign
|
|
3639
|
+
// MUST run on the single Bounded signer origin. The iframe carries the
|
|
3640
|
+
// publickey-credentials-{get,create} permission policy and the user's click lands
|
|
3641
|
+
// INSIDE it, giving WebAuthn the transient activation it needs.
|
|
3466
3642
|
//
|
|
3467
|
-
//
|
|
3468
|
-
//
|
|
3469
|
-
//
|
|
3470
|
-
//
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3643
|
+
// SAFARI / restricted embedders: cross-origin iframe passkey CREATE is unreliable
|
|
3644
|
+
// in Safari. The signer detects that and posts `fallbackPopup`; we then rerun the
|
|
3645
|
+
// SAME request through `popupFallback` (a real window). Callers pass a popup
|
|
3646
|
+
// implementation and never see the difference.
|
|
3647
|
+
/**
|
|
3648
|
+
* Run one signer exchange through the in-app widget. Resolves when `onResult`
|
|
3649
|
+
* accepts a result; falls back to `popupFallback` if the frame cannot run WebAuthn
|
|
3650
|
+
* (Safari cross-origin create) or cannot be mounted.
|
|
3651
|
+
*/
|
|
3652
|
+
async function runWidget(url, signerOrigin, ex, popupFallback) {
|
|
3653
|
+
if (!hasDOM$3())
|
|
3654
|
+
return popupFallback();
|
|
3655
|
+
const m = getModal();
|
|
3656
|
+
const requestId = String(ex.request.requestId);
|
|
3657
|
+
// Serialize: WebAuthn is modal, and one warm frame handles one request at a time.
|
|
3658
|
+
const run = m.chain.then(() => new Promise((resolve, reject) => {
|
|
3659
|
+
let settled = false;
|
|
3660
|
+
let usedFallback = false;
|
|
3661
|
+
const iframe = ensureIframe(m, url, signerOrigin);
|
|
3662
|
+
const send = () => {
|
|
3663
|
+
if (!iframe.contentWindow)
|
|
3664
|
+
return;
|
|
3665
|
+
try {
|
|
3666
|
+
iframe.contentWindow.postMessage(ex.request, signerOrigin);
|
|
3667
|
+
}
|
|
3668
|
+
catch (_a) {
|
|
3669
|
+
/* frame gone */
|
|
3670
|
+
}
|
|
3671
|
+
};
|
|
3672
|
+
let loadTimer = 0;
|
|
3673
|
+
let ceilingTimer = 0;
|
|
3674
|
+
const finish = (fn) => {
|
|
3675
|
+
if (settled)
|
|
3676
|
+
return;
|
|
3677
|
+
settled = true;
|
|
3678
|
+
m.onIframeMessage = null;
|
|
3679
|
+
m.onBackdrop = null;
|
|
3680
|
+
window.clearTimeout(loadTimer);
|
|
3681
|
+
window.clearTimeout(ceilingTimer);
|
|
3682
|
+
fn();
|
|
3683
|
+
};
|
|
3684
|
+
const goFallback = () => {
|
|
3685
|
+
if (usedFallback || settled)
|
|
3686
|
+
return;
|
|
3687
|
+
usedFallback = true;
|
|
3688
|
+
hideModal(m);
|
|
3689
|
+
finish(() => popupFallback().then(resolve, reject));
|
|
3690
|
+
};
|
|
3691
|
+
m.onBackdrop = () => {
|
|
3692
|
+
hideModal(m);
|
|
3693
|
+
finish(() => reject(new Error("cancelled")));
|
|
3694
|
+
};
|
|
3695
|
+
m.onIframeMessage = (d) => {
|
|
3696
|
+
if (d.type === "bounded:turnkey:ready") {
|
|
3697
|
+
m.iframeReady = true;
|
|
3698
|
+
send();
|
|
3699
|
+
return;
|
|
3700
|
+
}
|
|
3701
|
+
if (d.type === "bounded:turnkey:resize" && typeof d.height === "number") {
|
|
3702
|
+
setPanelHeight(m, d.height);
|
|
3703
|
+
return;
|
|
3704
|
+
}
|
|
3705
|
+
if (d.type === "bounded:turnkey:fallbackPopup" && d.requestId === requestId) {
|
|
3706
|
+
goFallback();
|
|
3707
|
+
return;
|
|
3708
|
+
}
|
|
3709
|
+
if (d.type === "bounded:turnkey:result" && d.requestId === requestId) {
|
|
3710
|
+
const outcome = ex.onResult(d);
|
|
3711
|
+
if ("error" in outcome) {
|
|
3712
|
+
hideModal(m);
|
|
3713
|
+
finish(() => reject(new Error(outcome.error)));
|
|
3714
|
+
return;
|
|
3715
|
+
}
|
|
3716
|
+
if (outcome.done) {
|
|
3717
|
+
hideModal(m);
|
|
3718
|
+
finish(() => resolve(outcome.value));
|
|
3719
|
+
}
|
|
3720
|
+
}
|
|
3721
|
+
};
|
|
3722
|
+
showModal(m);
|
|
3723
|
+
if (m.iframeReady)
|
|
3724
|
+
send();
|
|
3725
|
+
// If the frame never loads, degrade to the popup (best-effort - a post-load
|
|
3726
|
+
// popup may be blocked without a gesture, in which case the fallback rejects).
|
|
3727
|
+
loadTimer = window.setTimeout(() => {
|
|
3728
|
+
if (!m.iframeReady && !settled)
|
|
3729
|
+
goFallback();
|
|
3730
|
+
}, 8000);
|
|
3731
|
+
// Absolute ceiling so a stuck flow cannot hang forever.
|
|
3732
|
+
ceilingTimer = window.setTimeout(() => {
|
|
3733
|
+
if (!settled) {
|
|
3734
|
+
hideModal(m);
|
|
3735
|
+
finish(() => reject(new Error("Wallet approval timed out.")));
|
|
3736
|
+
}
|
|
3737
|
+
}, 5 * 60 * 1000);
|
|
3738
|
+
}));
|
|
3739
|
+
m.chain = run.then(() => undefined, () => undefined);
|
|
3740
|
+
return run;
|
|
3741
|
+
}
|
|
3742
|
+
|
|
3743
|
+
// turnkey-signing-capability.ts - the pure AS-02 (DS2-0112) signing-capability logic,
|
|
3744
|
+
// kept import-free (no DOM, no session, no @bounded-sh/core) so it is unit-testable.
|
|
3745
|
+
//
|
|
3746
|
+
// The hosted Turnkey signer refuses to sign unless the request carries an issuer-signed
|
|
3747
|
+
// SIGNING CAPABILITY bound to the app id, the requesting origin, and the EXACT payload
|
|
3748
|
+
// hash. `requestTurnkeySigningCapability` mints one for the given bytes and
|
|
3749
|
+
// `buildTurnkeySignRequest` assembles the signer request that carries it. The bridge
|
|
3750
|
+
// (turnkey-signer-bridge.ts) supplies the base url + id token and routes through both,
|
|
3751
|
+
// so a regression here (a dropped capability, a wrong route, a swallowed error) is
|
|
3752
|
+
// caught without a browser.
|
|
3753
|
+
// POST the Bounded id token + payload hash to the issuer's capability mint route and
|
|
3754
|
+
// return the issuer-signed capability for exactly these bytes. Credential-free: identity
|
|
3755
|
+
// is proven with the id token in the body (not an ambient cookie the cross-origin fetch
|
|
3756
|
+
// would not carry). Throws with the same stable messages the bridge relied on inline.
|
|
3757
|
+
async function requestTurnkeySigningCapability(opts) {
|
|
3758
|
+
const base = opts.baseUrl.replace(/\/$/, '');
|
|
3759
|
+
let res;
|
|
3760
|
+
try {
|
|
3761
|
+
res = await opts.fetchImpl(`${base}/wallet/turnkey/capability`, {
|
|
3762
|
+
method: 'POST',
|
|
3763
|
+
headers: { 'content-type': 'application/json' },
|
|
3764
|
+
body: JSON.stringify({ idToken: opts.idToken, messageHex: opts.messageHex }),
|
|
3765
|
+
});
|
|
3766
|
+
}
|
|
3767
|
+
catch (_a) {
|
|
3768
|
+
throw new Error('Could not reach the Bounded signer to authorize this signature.');
|
|
3769
|
+
}
|
|
3770
|
+
if (!res.ok) {
|
|
3771
|
+
let error = 'signing_capability_denied';
|
|
3772
|
+
try {
|
|
3773
|
+
const d = (await res.json());
|
|
3774
|
+
if (d && typeof d.error === 'string')
|
|
3775
|
+
error = d.error;
|
|
3776
|
+
}
|
|
3777
|
+
catch (_b) {
|
|
3778
|
+
/* keep the default marker */
|
|
3779
|
+
}
|
|
3780
|
+
throw new Error(`Turnkey signing was not authorized (${error}).`);
|
|
3781
|
+
}
|
|
3782
|
+
const d = (await res.json());
|
|
3783
|
+
if (!d || typeof d.capability !== 'string' || !d.capability) {
|
|
3784
|
+
throw new Error('Turnkey signing capability was malformed.');
|
|
3785
|
+
}
|
|
3786
|
+
return d.capability;
|
|
3787
|
+
}
|
|
3788
|
+
// Assemble the `bounded:turnkey:sign` postMessage request, carrying the issuer-signed
|
|
3789
|
+
// capability for the same bytes. Without the capability the hosted signer refuses
|
|
3790
|
+
// (capability_required), so it is a required field of every sign request.
|
|
3791
|
+
function buildTurnkeySignRequest(opts) {
|
|
3792
|
+
return {
|
|
3793
|
+
type: 'bounded:turnkey:sign',
|
|
3794
|
+
requestId: opts.requestId,
|
|
3795
|
+
messageHex: opts.messageHex,
|
|
3796
|
+
capability: opts.capability,
|
|
3797
|
+
};
|
|
3798
|
+
}
|
|
3799
|
+
|
|
3800
|
+
// turnkey-signer-bridge.ts - routes NON-CUSTODIAL Turnkey embedded-wallet signing
|
|
3801
|
+
// through the Bounded-owned signer page (auth.bounded.sh/wallet/turnkey/signer).
|
|
3802
|
+
//
|
|
3803
|
+
// TRANSPORT: by default the signer runs inside the in-app WIDGET (turnkey-wallet-
|
|
3804
|
+
// widget.ts) - an iframe behind a Shadow-DOM modal that matches the Bounded widget
|
|
3805
|
+
// look + motion, so signing feels native. Safari (unreliable at iframe passkey
|
|
3806
|
+
// CREATE) and any environment where the frame cannot mount fall back to a real
|
|
3807
|
+
// popup window; both transports speak the same postMessage protocol.
|
|
3808
|
+
//
|
|
3809
|
+
// Turnkey wallets produce raw detached signatures. The signer runs the Turnkey
|
|
3810
|
+
// browser SDK on the single Bounded origin and stamps an ed25519 signRawPayload
|
|
3811
|
+
// with the user's passkey. The app retains the transaction itself.
|
|
3812
|
+
//
|
|
3813
|
+
// ONE ORIGIN, ONE PASSKEY: a WebAuthn passkey is bound to a single origin, so ALL
|
|
3814
|
+
// Bounded apps (any subdomain / custom domain) sign through this one origin - giving
|
|
3815
|
+
// every user one wallet + one passkey that roams across every app.
|
|
3478
3816
|
function hasDOM$2() {
|
|
3479
3817
|
return typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
3480
3818
|
}
|
|
3819
|
+
// Safari (incl. iOS WebViews) is unreliable at running a WebAuthn CREATE inside a
|
|
3820
|
+
// cross-origin iframe, so the widget's automatic in-iframe passkey enrollment can
|
|
3821
|
+
// fail - and a post-failure popup would no longer have a user gesture to open with.
|
|
3822
|
+
// There we pick the popup up front, from the original click, so enrollment is solid.
|
|
3823
|
+
// Everywhere else the inline widget is used (buttery in-app modal).
|
|
3824
|
+
function preferPopup() {
|
|
3825
|
+
if (!hasDOM$2() || typeof navigator === 'undefined')
|
|
3826
|
+
return true;
|
|
3827
|
+
const ua = navigator.userAgent || '';
|
|
3828
|
+
return /^((?!chrome|android|crios|fxios|edg|edga|opr).)*safari/i.test(ua);
|
|
3829
|
+
}
|
|
3830
|
+
// Dispatch one signer exchange through the in-app WIDGET, degrading to the POPUP
|
|
3831
|
+
// when we cannot embed (Safari enrollment, or the frame never loads).
|
|
3832
|
+
async function deliver(url, origin, ex) {
|
|
3833
|
+
const popup = () => runPopup(url, origin, ex);
|
|
3834
|
+
if (preferPopup())
|
|
3835
|
+
return popup();
|
|
3836
|
+
return runWidget(url, origin, { request: ex.request, onResult: ex.onResult }, popup);
|
|
3837
|
+
}
|
|
3838
|
+
async function turnkeySignerPage() {
|
|
3839
|
+
const cfg = await core.getConfig();
|
|
3840
|
+
const base = (cfg.humanAuthApiUrl || 'https://auth.bounded.sh').replace(/\/$/, '');
|
|
3841
|
+
return { url: `${base}/wallet/turnkey/signer`, origin: new URL(base).origin };
|
|
3842
|
+
}
|
|
3843
|
+
function toHex(bytes) {
|
|
3844
|
+
let h = '';
|
|
3845
|
+
for (const b of bytes)
|
|
3846
|
+
h += b.toString(16).padStart(2, '0');
|
|
3847
|
+
return h;
|
|
3848
|
+
}
|
|
3849
|
+
function fromHex(hex) {
|
|
3850
|
+
const clean = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
3851
|
+
const out = new Uint8Array(clean.length / 2);
|
|
3852
|
+
for (let i = 0; i < out.length; i++)
|
|
3853
|
+
out[i] = parseInt(clean.substr(i * 2, 2), 16);
|
|
3854
|
+
return out;
|
|
3855
|
+
}
|
|
3481
3856
|
function decodeJwt$1(token) {
|
|
3482
3857
|
try {
|
|
3483
|
-
let
|
|
3484
|
-
const
|
|
3485
|
-
if (
|
|
3486
|
-
|
|
3487
|
-
else if (
|
|
3488
|
-
|
|
3489
|
-
return JSON.parse(
|
|
3858
|
+
let value = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/');
|
|
3859
|
+
const padding = value.length % 4;
|
|
3860
|
+
if (padding === 2)
|
|
3861
|
+
value += '==';
|
|
3862
|
+
else if (padding === 3)
|
|
3863
|
+
value += '=';
|
|
3864
|
+
return JSON.parse(getPlatform().atob(value));
|
|
3490
3865
|
}
|
|
3491
3866
|
catch (_a) {
|
|
3492
3867
|
return {};
|
|
3493
3868
|
}
|
|
3494
3869
|
}
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
// informative NO_EMBEDDED_WALLET error).
|
|
3498
|
-
function walletClaimsFromSession(chain = 'solana') {
|
|
3499
|
-
let idToken = null;
|
|
3870
|
+
function activeTurnkeyAddress() {
|
|
3871
|
+
let token = null;
|
|
3500
3872
|
try {
|
|
3501
|
-
|
|
3873
|
+
token = core.getActiveSessionManager().getIdToken();
|
|
3502
3874
|
}
|
|
3503
3875
|
catch (_a) {
|
|
3504
|
-
|
|
3876
|
+
token = null;
|
|
3505
3877
|
}
|
|
3506
|
-
if (!
|
|
3507
|
-
return null;
|
|
3508
|
-
const c = decodeJwt$1(idToken);
|
|
3509
|
-
const address = c['custom:walletAddress'];
|
|
3510
|
-
const evmAddress = c['custom:evmWalletAddress'];
|
|
3511
|
-
const email = c['email'];
|
|
3512
|
-
if (typeof email !== 'string' || !email)
|
|
3878
|
+
if (!token)
|
|
3513
3879
|
return null;
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
return Object.assign(Object.assign(Object.assign({ email }, (typeof address === 'string' && address ? { address } : {})), (typeof evmAddress === 'string' ? { evmAddress: evmAddress.toLowerCase() } : {})), { environment });
|
|
3521
|
-
}
|
|
3522
|
-
async function signerPageUrl() {
|
|
3523
|
-
const cfg = await core.getConfig();
|
|
3524
|
-
const base = (cfg.humanAuthApiUrl || 'https://auth.bounded.sh').replace(/\/$/, '');
|
|
3525
|
-
return { url: `${base}/wallet/signer`, origin: new URL(base).origin };
|
|
3880
|
+
const claims = decodeJwt$1(token);
|
|
3881
|
+
const address = claims['custom:walletAddress'];
|
|
3882
|
+
const provider = claims['custom:walletProvider'];
|
|
3883
|
+
return provider === 'turnkey' && typeof address === 'string' && address
|
|
3884
|
+
? address
|
|
3885
|
+
: null;
|
|
3526
3886
|
}
|
|
3527
3887
|
let requestSeq = 0;
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
*
|
|
3534
|
-
* Non-custodial: the popup gates signing behind an email OTP delivered to the
|
|
3535
|
-
* wallet's owner, and validates that the wallet address matches the account.
|
|
3536
|
-
*/
|
|
3537
|
-
async function signViaSignerPopup(action) {
|
|
3538
|
-
if (!hasDOM$2()) {
|
|
3539
|
-
throw new Error('Embedded-wallet signing is only available in the browser (popup-based).');
|
|
3540
|
-
}
|
|
3541
|
-
const isEvm = action.kind === 'evmTransaction';
|
|
3542
|
-
const claims = walletClaimsFromSession(isEvm ? 'evm' : 'solana');
|
|
3543
|
-
if (!claims)
|
|
3544
|
-
throw new Error(NO_EMBEDDED_WALLET);
|
|
3545
|
-
const { url, origin: signerOrigin } = await signerPageUrl();
|
|
3546
|
-
const requestId = `bsign_${Date.now()}_${++requestSeq}`;
|
|
3547
|
-
// Centered popup, sized for the OTP form (matches the OIDC login popup shape).
|
|
3548
|
-
const w = 420, h = 600;
|
|
3888
|
+
// Shared popup driver: open the signer page, do the ready/postMessage handshake, and
|
|
3889
|
+
// resolve when `onResult` accepts a result message. Origin + source are pinned.
|
|
3890
|
+
async function runPopup(url, signerOrigin, ex) {
|
|
3891
|
+
var _a, _b;
|
|
3892
|
+
const w = (_a = ex.width) !== null && _a !== void 0 ? _a : 420, h = (_b = ex.height) !== null && _b !== void 0 ? _b : 620;
|
|
3549
3893
|
const left = window.screenX + Math.max(0, (window.outerWidth - w) / 2);
|
|
3550
3894
|
const top = window.screenY + Math.max(0, (window.outerHeight - h) / 2);
|
|
3551
|
-
const popup = window.open(url, 'bounded-
|
|
3895
|
+
const popup = window.open(url, 'bounded-turnkey-signer', `width=${w},height=${h},left=${left},top=${top}`);
|
|
3552
3896
|
if (!popup) {
|
|
3553
|
-
throw new Error('Popup blocked
|
|
3554
|
-
}
|
|
3555
|
-
const request = {
|
|
3556
|
-
type: 'bounded:sign',
|
|
3557
|
-
requestId,
|
|
3558
|
-
environment: claims.environment, // may be undefined → page auto-detects
|
|
3559
|
-
email: claims.email,
|
|
3560
|
-
address: isEvm ? claims.evmAddress : claims.address,
|
|
3561
|
-
action,
|
|
3562
|
-
};
|
|
3897
|
+
throw new Error('Popup blocked - call this from a user gesture (e.g. a click handler) so the passkey approval window can open.');
|
|
3898
|
+
}
|
|
3563
3899
|
return await new Promise((resolve, reject) => {
|
|
3564
3900
|
let settled = false;
|
|
3565
|
-
let closeTimer;
|
|
3566
3901
|
let sentRequest = false;
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3902
|
+
let closeTimer;
|
|
3903
|
+
const cleanup = () => { settled = true; window.removeEventListener('message', onMsg); if (closeTimer)
|
|
3904
|
+
clearInterval(closeTimer); };
|
|
3905
|
+
const sendRequest = () => { if (sentRequest)
|
|
3906
|
+
return; sentRequest = true; try {
|
|
3907
|
+
popup.postMessage(ex.request, signerOrigin);
|
|
3908
|
+
}
|
|
3909
|
+
catch ( /* popup gone */_a) { /* popup gone */ } };
|
|
3910
|
+
const onMsg = (event) => {
|
|
3911
|
+
if (event.origin !== signerOrigin)
|
|
3575
3912
|
return;
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
}
|
|
3580
|
-
catch ( /* popup gone */_a) { /* popup gone */ }
|
|
3581
|
-
};
|
|
3582
|
-
const onMsg = (ev) => {
|
|
3583
|
-
if (ev.origin !== signerOrigin)
|
|
3584
|
-
return; // only trust the signer page origin
|
|
3585
|
-
if (ev.source !== popup)
|
|
3586
|
-
return; // only trust this signer popup window
|
|
3587
|
-
const d = ev.data;
|
|
3913
|
+
if (event.source !== popup)
|
|
3914
|
+
return;
|
|
3915
|
+
const d = event.data;
|
|
3588
3916
|
if (!d || typeof d !== 'object')
|
|
3589
3917
|
return;
|
|
3590
|
-
if (d.type === 'bounded:
|
|
3918
|
+
if (d.type === 'bounded:turnkey:ready') {
|
|
3591
3919
|
sendRequest();
|
|
3592
3920
|
return;
|
|
3593
3921
|
}
|
|
3594
|
-
if (d.type === 'bounded:
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3922
|
+
if (d.type === 'bounded:turnkey:result' && d.requestId === ex.request.requestId) {
|
|
3923
|
+
const outcome = ex.onResult(d);
|
|
3924
|
+
if ('error' in outcome) {
|
|
3925
|
+
cleanup();
|
|
3926
|
+
try {
|
|
3927
|
+
popup.close();
|
|
3928
|
+
}
|
|
3929
|
+
catch ( /* ignore */_a) { /* ignore */ }
|
|
3930
|
+
reject(new Error(outcome.error));
|
|
3931
|
+
return;
|
|
3932
|
+
}
|
|
3933
|
+
if (outcome.done) {
|
|
3934
|
+
cleanup();
|
|
3935
|
+
try {
|
|
3936
|
+
popup.close();
|
|
3937
|
+
}
|
|
3938
|
+
catch ( /* ignore */_b) { /* ignore */ }
|
|
3939
|
+
resolve(outcome.value);
|
|
3598
3940
|
}
|
|
3599
|
-
catch ( /* ignore */_a) { /* ignore */ }
|
|
3600
|
-
if (d.ok)
|
|
3601
|
-
resolve({ hash: d.hash, explorerLink: d.explorerLink, transactionId: d.transactionId });
|
|
3602
|
-
else
|
|
3603
|
-
reject(new Error(String(d.error || 'Wallet signing failed')));
|
|
3604
3941
|
}
|
|
3605
3942
|
};
|
|
3606
3943
|
window.addEventListener('message', onMsg);
|
|
3607
|
-
// Fallback: if the ready ping was missed (fast load / focus race), push the
|
|
3608
|
-
// request shortly after opening. The page ignores it until a bounded:sign
|
|
3609
|
-
// arrives and only acts on the first one, so a duplicate is harmless.
|
|
3610
3944
|
setTimeout(sendRequest, 1200);
|
|
3611
|
-
// If the user closes the popup before completing, reject (unless a result
|
|
3612
|
-
// just arrived — give any in-flight message a beat to settle first).
|
|
3613
3945
|
closeTimer = setInterval(() => {
|
|
3614
3946
|
if (popup.closed) {
|
|
3615
3947
|
clearInterval(closeTimer);
|
|
3616
3948
|
setTimeout(() => { if (!settled) {
|
|
3617
3949
|
cleanup();
|
|
3618
|
-
reject(new Error('Wallet approval window was closed before
|
|
3950
|
+
reject(new Error('Wallet approval window was closed before it completed.'));
|
|
3619
3951
|
} }, 400);
|
|
3620
3952
|
}
|
|
3621
3953
|
}, 500);
|
|
3622
|
-
// Overall safety timeout (OTP + signing). Generous — the user may take a
|
|
3623
|
-
// while to fetch the code from their email.
|
|
3624
3954
|
setTimeout(() => { if (!settled) {
|
|
3625
3955
|
cleanup();
|
|
3626
3956
|
try {
|
|
@@ -3631,80 +3961,135 @@ async function signViaSignerPopup(action) {
|
|
|
3631
3961
|
} }, 5 * 60 * 1000);
|
|
3632
3962
|
});
|
|
3633
3963
|
}
|
|
3634
|
-
//
|
|
3635
|
-
//
|
|
3636
|
-
//
|
|
3637
|
-
//
|
|
3638
|
-
//
|
|
3639
|
-
//
|
|
3640
|
-
//
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3964
|
+
// AS-02: the hosted signer refuses to sign unless the request carries an issuer-signed
|
|
3965
|
+
// SIGNING CAPABILITY bound to the app id, this origin, and the EXACT bytes (a bare postMessage
|
|
3966
|
+
// from any peer can no longer consent-phish a signature). Fetch one from the human-auth issuer
|
|
3967
|
+
// for exactly these bytes before posting the sign request. Credential-free: the caller proves
|
|
3968
|
+
// identity with the Bounded id token WE minted (a body secret, RS256-verified server-side), not
|
|
3969
|
+
// an ambient cookie - the issuer's session cookie is SameSite-scoped to its own origin and is
|
|
3970
|
+
// not sent on this cross-origin fetch, so the token is what carries the session's wallet.
|
|
3971
|
+
async function fetchSigningCapability(messageHex) {
|
|
3972
|
+
const cfg = await core.getConfig();
|
|
3973
|
+
const base = (cfg.humanAuthApiUrl || 'https://auth.bounded.sh').replace(/\/$/, '');
|
|
3974
|
+
let idToken = null;
|
|
3975
|
+
try {
|
|
3976
|
+
idToken = core.getActiveSessionManager().getIdToken();
|
|
3977
|
+
}
|
|
3978
|
+
catch (_a) {
|
|
3979
|
+
idToken = null;
|
|
3980
|
+
}
|
|
3981
|
+
if (!idToken) {
|
|
3982
|
+
throw new Error('This session has no Turnkey wallet. Sign in again to provision one.');
|
|
3983
|
+
}
|
|
3984
|
+
return requestTurnkeySigningCapability({
|
|
3985
|
+
baseUrl: base,
|
|
3986
|
+
idToken,
|
|
3987
|
+
messageHex,
|
|
3988
|
+
fetchImpl: (url, init) => fetch(url, init),
|
|
3989
|
+
});
|
|
3990
|
+
}
|
|
3991
|
+
function hasTurnkeyWallet() {
|
|
3992
|
+
return activeTurnkeyAddress() !== null;
|
|
3650
3993
|
}
|
|
3651
3994
|
/**
|
|
3652
|
-
*
|
|
3653
|
-
*
|
|
3995
|
+
* Open the Bounded Turnkey signer popup and sign `message` (raw bytes) with the
|
|
3996
|
+
* user's non-custodial Turnkey wallet, resolving with the ed25519 signature +
|
|
3997
|
+
* the wallet address. MUST be called from a USER GESTURE (click/tap) or the
|
|
3998
|
+
* browser blocks the popup.
|
|
3999
|
+
*
|
|
4000
|
+
* On the user's FIRST signature the popup transparently enrolls a device passkey
|
|
4001
|
+
* (Face ID / Touch ID) and creates their wallet - no email code. Subsequent
|
|
4002
|
+
* signatures are just a passkey approval.
|
|
3654
4003
|
*/
|
|
3655
|
-
function
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
}
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
if (
|
|
3678
|
-
throw new Error('
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
4004
|
+
async function signSolanaMessageViaTurnkey(message) {
|
|
4005
|
+
if (!hasDOM$2()) {
|
|
4006
|
+
throw new Error('Turnkey embedded-wallet signing is only available in the browser (popup-based).');
|
|
4007
|
+
}
|
|
4008
|
+
const { url, origin } = await turnkeySignerPage();
|
|
4009
|
+
const requestId = `tksign_${Date.now()}_${++requestSeq}`;
|
|
4010
|
+
const messageHex = toHex(message);
|
|
4011
|
+
// AS-02: obtain the issuer-signed capability for THESE exact bytes first; the signer will
|
|
4012
|
+
// refuse (capability_required) without it. Fetched per signature (each is single-payload).
|
|
4013
|
+
const capability = await fetchSigningCapability(messageHex);
|
|
4014
|
+
return await deliver(url, origin, {
|
|
4015
|
+
request: buildTurnkeySignRequest({ requestId, messageHex, capability }),
|
|
4016
|
+
onResult: (d) => {
|
|
4017
|
+
if (d.ok && typeof d.signatureHex === 'string' && typeof d.address === 'string') {
|
|
4018
|
+
return { done: true, value: { signature: fromHex(d.signatureHex), address: d.address, subOrgId: String(d.subOrgId || '') } };
|
|
4019
|
+
}
|
|
4020
|
+
return { error: String(d.error || 'Turnkey signing failed') };
|
|
4021
|
+
},
|
|
4022
|
+
});
|
|
4023
|
+
}
|
|
4024
|
+
function requireMatchingAddress(result) {
|
|
4025
|
+
const expected = activeTurnkeyAddress();
|
|
4026
|
+
if (!expected)
|
|
4027
|
+
throw new Error('This session has no Turnkey wallet. Sign in again to provision one.');
|
|
4028
|
+
if (result.address !== expected)
|
|
4029
|
+
throw new Error('Turnkey signer returned a different wallet address than the active session.');
|
|
4030
|
+
return expected;
|
|
4031
|
+
}
|
|
4032
|
+
async function signMessageWithTurnkey(message) {
|
|
4033
|
+
const result = await signSolanaMessageViaTurnkey(getPlatform().textEncode(message));
|
|
4034
|
+
requireMatchingAddress(result);
|
|
4035
|
+
return bs58.encode(result.signature);
|
|
4036
|
+
}
|
|
4037
|
+
async function signTransactionWithTurnkey(transaction) {
|
|
4038
|
+
const isLegacy = 'serializeMessage' in transaction;
|
|
4039
|
+
const message = isLegacy
|
|
4040
|
+
? transaction.serializeMessage()
|
|
4041
|
+
: transaction.message.serialize();
|
|
4042
|
+
const result = await signSolanaMessageViaTurnkey(new Uint8Array(message));
|
|
4043
|
+
const address = requireMatchingAddress(result);
|
|
4044
|
+
const { PublicKey } = await import('@solana/web3.js');
|
|
4045
|
+
if (isLegacy) {
|
|
4046
|
+
transaction.addSignature(new PublicKey(address), bufferExports.Buffer.from(result.signature));
|
|
3687
4047
|
}
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
4048
|
+
else {
|
|
4049
|
+
transaction.addSignature(new PublicKey(address), result.signature);
|
|
4050
|
+
}
|
|
4051
|
+
return transaction;
|
|
4052
|
+
}
|
|
4053
|
+
async function signAndSubmitTransactionWithTurnkey(transaction, feePayer) {
|
|
4054
|
+
var _a;
|
|
4055
|
+
const config = await core.getConfig();
|
|
4056
|
+
const rpcUrl = (_a = config.rpcUrl) === null || _a === void 0 ? void 0 : _a.trim();
|
|
4057
|
+
if (!rpcUrl)
|
|
4058
|
+
throw new Error('Turnkey transaction submission requires init({ rpcUrl }).');
|
|
4059
|
+
const { Connection, PublicKey } = await import('@solana/web3.js');
|
|
4060
|
+
const connection = new Connection(rpcUrl, 'confirmed');
|
|
4061
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
|
|
4062
|
+
const isLegacy = 'serializeMessage' in transaction;
|
|
4063
|
+
if (isLegacy) {
|
|
4064
|
+
const legacy = transaction;
|
|
4065
|
+
legacy.recentBlockhash = blockhash;
|
|
4066
|
+
legacy.lastValidBlockHeight = lastValidBlockHeight;
|
|
4067
|
+
if (!legacy.feePayer) {
|
|
4068
|
+
const address = activeTurnkeyAddress();
|
|
4069
|
+
if (!address)
|
|
4070
|
+
throw new Error('This session has no Turnkey wallet. Sign in again to provision one.');
|
|
4071
|
+
legacy.feePayer = feePayer !== null && feePayer !== void 0 ? feePayer : new PublicKey(address);
|
|
4072
|
+
}
|
|
4073
|
+
}
|
|
4074
|
+
else {
|
|
4075
|
+
transaction.message.recentBlockhash = blockhash;
|
|
3692
4076
|
}
|
|
3693
|
-
const
|
|
3694
|
-
|
|
3695
|
-
|
|
4077
|
+
const signed = await signTransactionWithTurnkey(transaction);
|
|
4078
|
+
const signature = await connection.sendRawTransaction(signed.serialize(), {
|
|
4079
|
+
skipPreflight: false,
|
|
4080
|
+
maxRetries: 3,
|
|
3696
4081
|
});
|
|
3697
|
-
const
|
|
3698
|
-
if (
|
|
3699
|
-
throw new Error(
|
|
3700
|
-
|
|
4082
|
+
const confirmation = await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight }, 'confirmed');
|
|
4083
|
+
if (confirmation.value.err) {
|
|
4084
|
+
throw new Error(`Turnkey transaction failed: ${JSON.stringify(confirmation.value.err)}`);
|
|
4085
|
+
}
|
|
4086
|
+
return signature;
|
|
3701
4087
|
}
|
|
3702
4088
|
|
|
3703
4089
|
// Same message the email provider uses when a hosted (OIDC) login has no
|
|
3704
4090
|
// embedded wallet — enable `auth.wallets` in policy to get one.
|
|
3705
|
-
const OIDC_NO_WALLET = 'This
|
|
3706
|
-
'
|
|
3707
|
-
'then sign from a user gesture.';
|
|
4091
|
+
const OIDC_NO_WALLET = 'This session has no Turnkey wallet. Sign in again to provision the default ' +
|
|
4092
|
+
'embedded wallet, or check whether the app explicitly sets auth.wallets:false.';
|
|
3708
4093
|
const PKCE_STORE_KEY = 'bounded.oidc.pkce';
|
|
3709
4094
|
const STORED_AUTH_METHOD_KEY$1 = 'bounded_last_auth_method';
|
|
3710
4095
|
const ISSUER_SESSION_KIND_KEY$1 = 'bounded_issuer_session_kind';
|
|
@@ -3730,10 +4115,8 @@ function decodeJwt(token) {
|
|
|
3730
4115
|
}
|
|
3731
4116
|
}
|
|
3732
4117
|
// A minimal AuthProvider so getSession()/logout() work for OIDC sessions, mirroring email.
|
|
3733
|
-
//
|
|
3734
|
-
//
|
|
3735
|
-
// through the Bounded signer popup; signMessage/signTransaction are structurally
|
|
3736
|
-
// unsupported for Crossmint smart wallets (sign+submit atomically, no raw sig).
|
|
4118
|
+
// Turnkey supplies the default Solana wallet and supports raw message and transaction
|
|
4119
|
+
// signatures through the Bounded signer window.
|
|
3737
4120
|
const oidcProviderSingleton = {
|
|
3738
4121
|
async login() {
|
|
3739
4122
|
const idToken = sessionManager().getIdToken();
|
|
@@ -3744,37 +4127,38 @@ const oidcProviderSingleton = {
|
|
|
3744
4127
|
return idToken ? userFromIdToken(idToken) : null;
|
|
3745
4128
|
},
|
|
3746
4129
|
async logout() { await sessionManager().clearSession(); },
|
|
3747
|
-
async signMessage(
|
|
3748
|
-
|
|
4130
|
+
async signMessage(message) {
|
|
4131
|
+
if (!hasTurnkeyWallet())
|
|
4132
|
+
throw new Error(OIDC_NO_WALLET);
|
|
4133
|
+
return signMessageWithTurnkey(message);
|
|
3749
4134
|
},
|
|
3750
|
-
async signTransaction(
|
|
3751
|
-
|
|
4135
|
+
async signTransaction(transaction) {
|
|
4136
|
+
if (!hasTurnkeyWallet())
|
|
4137
|
+
throw new Error(OIDC_NO_WALLET);
|
|
4138
|
+
return signTransactionWithTurnkey(transaction);
|
|
3752
4139
|
},
|
|
3753
|
-
async runTransaction(evm, sol,
|
|
4140
|
+
async runTransaction(evm, sol, _options) {
|
|
3754
4141
|
if (evm && sol)
|
|
3755
4142
|
throw new Error('A transaction cannot target EVM and Solana at the same time.');
|
|
3756
|
-
if (!
|
|
4143
|
+
if (!hasTurnkeyWallet())
|
|
3757
4144
|
throw new Error(OIDC_NO_WALLET);
|
|
3758
|
-
if (
|
|
3759
|
-
throw new Error('
|
|
3760
|
-
|
|
3761
|
-
throw new Error('This login has no embedded EVM wallet. Enable auth.wallets on an app with an EVM collection and sign in again.');
|
|
3762
|
-
return embeddedRunEvmTransaction(evm);
|
|
4145
|
+
if (evm)
|
|
4146
|
+
throw new Error('Turnkey embedded wallets currently support Solana only. Connect an EVM wallet for EVM transactions.');
|
|
4147
|
+
throw new Error('This Solana transaction shape is not supported by the Turnkey provider. Use a pre-built transaction.');
|
|
3763
4148
|
},
|
|
3764
|
-
async signAndSubmitTransaction(transaction,
|
|
3765
|
-
if (!
|
|
4149
|
+
async signAndSubmitTransaction(transaction, feePayer) {
|
|
4150
|
+
if (!hasTurnkeyWallet())
|
|
3766
4151
|
throw new Error(OIDC_NO_WALLET);
|
|
3767
|
-
return
|
|
4152
|
+
return signAndSubmitTransactionWithTurnkey(transaction, feePayer);
|
|
3768
4153
|
},
|
|
3769
4154
|
};
|
|
3770
4155
|
function userFromIdToken(idToken) {
|
|
3771
4156
|
const c = decodeJwt(idToken);
|
|
3772
4157
|
const id = c['custom:userId'] || c.sub || c['custom:walletAddress'] || '';
|
|
3773
4158
|
return {
|
|
3774
|
-
id,
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
: null,
|
|
4159
|
+
id,
|
|
4160
|
+
address: (c['custom:walletProvider'] === 'turnkey' && c['custom:walletAddress'] || null),
|
|
4161
|
+
evmAddress: null,
|
|
3778
4162
|
email: (c.email || null), provider: oidcProviderSingleton,
|
|
3779
4163
|
};
|
|
3780
4164
|
}
|
|
@@ -4497,7 +4881,7 @@ async function getAuthProvider(config) {
|
|
|
4497
4881
|
// manager as legacy email sessions. Human login should be started
|
|
4498
4882
|
// with loginWithRedirect(); this provider is kept as the restore and
|
|
4499
4883
|
// logout surface for those sessions.
|
|
4500
|
-
currentAuthProvider = new (await Promise.resolve().then(function () { return require('./email-auth-provider-
|
|
4884
|
+
currentAuthProvider = new (await Promise.resolve().then(function () { return require('./email-auth-provider-DYtoSrdm.js'); })).EmailAuthProvider();
|
|
4501
4885
|
break;
|
|
4502
4886
|
case "wallet":
|
|
4503
4887
|
case "phantom": {
|
|
@@ -4516,7 +4900,7 @@ async function getAuthProvider(config) {
|
|
|
4516
4900
|
if (!isWalletLoginEnabled(config)) {
|
|
4517
4901
|
throw walletLoginNotEnabledError(authMethod);
|
|
4518
4902
|
}
|
|
4519
|
-
const { InjectedWalletProvider } = await Promise.resolve().then(function () { return require('./injected-wallet-provider-
|
|
4903
|
+
const { InjectedWalletProvider } = await Promise.resolve().then(function () { return require('./injected-wallet-provider-DvwlPJea.js'); });
|
|
4520
4904
|
currentAuthProvider = new InjectedWalletProvider(resolveInjectedWalletConfig(config), rpcUrl, configuredNetwork);
|
|
4521
4905
|
break;
|
|
4522
4906
|
}
|
|
@@ -4529,7 +4913,7 @@ async function getAuthProvider(config) {
|
|
|
4529
4913
|
// Selecting authMethod:'evm-wallet' IS the opt-in — pass evmWalletConfig
|
|
4530
4914
|
// to point at a specific wallet or set chainId/domain.
|
|
4531
4915
|
const evmWalletConfig = ((_a = config.evmWalletConfig) !== null && _a !== void 0 ? _a : {});
|
|
4532
|
-
const { InjectedEvmWalletProvider } = await Promise.resolve().then(function () { return require('./injected-evm-wallet-provider-
|
|
4916
|
+
const { InjectedEvmWalletProvider } = await Promise.resolve().then(function () { return require('./injected-evm-wallet-provider-BAToKWZo.js'); });
|
|
4533
4917
|
currentAuthProvider = new InjectedEvmWalletProvider(evmWalletConfig);
|
|
4534
4918
|
break;
|
|
4535
4919
|
}
|
|
@@ -4557,7 +4941,7 @@ async function getAuthProvider(config) {
|
|
|
4557
4941
|
break;
|
|
4558
4942
|
case "guest":
|
|
4559
4943
|
// Anonymous auth: a device-local ed25519 keypair signs the challenge.
|
|
4560
|
-
currentAuthProvider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-
|
|
4944
|
+
currentAuthProvider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-CoI0r92a.js'); })).GuestAuthProvider();
|
|
4561
4945
|
break;
|
|
4562
4946
|
}
|
|
4563
4947
|
if (!currentAuthProvider) {
|
|
@@ -4613,7 +4997,7 @@ async function signInAnonymously() {
|
|
|
4613
4997
|
// Lazy-load the guest provider so its ed25519/web3 dependencies stay out of
|
|
4614
4998
|
// the main bundle for data-only apps. Specifier is a static string literal
|
|
4615
4999
|
// so bundle-splitting can see it.
|
|
4616
|
-
const provider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-
|
|
5000
|
+
const provider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-CoI0r92a.js'); })).GuestAuthProvider();
|
|
4617
5001
|
setAuthLoading(true); // reflect "signing in…" while the guest keypair session is minted
|
|
4618
5002
|
const commit = (user) => {
|
|
4619
5003
|
// No await/interleaving inside this block: provider/method/config/marker
|
|
@@ -5851,18 +6235,6 @@ async function list() {
|
|
|
5851
6235
|
*/
|
|
5852
6236
|
const apps = { create, list, buildCreateRedirectUrl };
|
|
5853
6237
|
|
|
5854
|
-
async function deserializeTransaction(tx) {
|
|
5855
|
-
// Literal specifier so bundlers can code-split the lazy chunk.
|
|
5856
|
-
const { Transaction, VersionedTransaction } = await import('@solana/web3.js');
|
|
5857
|
-
const buf = Buffer.isBuffer(tx) ? tx : Buffer.from(tx, 'base64');
|
|
5858
|
-
if ((buf[0] & 0x80) !== 0) {
|
|
5859
|
-
return VersionedTransaction.deserialize(buf);
|
|
5860
|
-
}
|
|
5861
|
-
else {
|
|
5862
|
-
return Transaction.from(buf);
|
|
5863
|
-
}
|
|
5864
|
-
}
|
|
5865
|
-
|
|
5866
6238
|
// bounded.onramp() - fund the signed-in user's wallet with Coinbase Onramp.
|
|
5867
6239
|
//
|
|
5868
6240
|
// Web-only. Opens Coinbase's hosted checkout (pay.coinbase.com) in a popup
|
|
@@ -5904,16 +6276,16 @@ async function readError(res) {
|
|
|
5904
6276
|
}
|
|
5905
6277
|
}
|
|
5906
6278
|
function sessionBody(options, extra) {
|
|
5907
|
-
return JSON.stringify(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(
|
|
6279
|
+
return JSON.stringify(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (options.asset ? { asset: options.asset } : {})), (options.amountUsd !== undefined ? { amountUsd: options.amountUsd } : {})), (options.minAmountOut !== undefined ? { minAmountOut: options.minAmountOut } : {})), (options.slippagePad !== undefined ? { slippagePad: options.slippagePad } : {})), extra));
|
|
5908
6280
|
}
|
|
5909
|
-
function resolveAddress(
|
|
5910
|
-
var _a
|
|
6281
|
+
function resolveAddress() {
|
|
6282
|
+
var _a;
|
|
5911
6283
|
const user = getCurrentUser();
|
|
5912
|
-
const address = (
|
|
6284
|
+
const address = (_a = user === null || user === void 0 ? void 0 : user.address) !== null && _a !== void 0 ? _a : undefined;
|
|
5913
6285
|
if (!address) {
|
|
5914
6286
|
throw new Error(user
|
|
5915
|
-
? 'onramp: the signed-in account has no wallet address
|
|
5916
|
-
: 'onramp: no signed-in user - call login() first
|
|
6287
|
+
? 'onramp: the signed-in account has no wallet address (create one via the embedded wallet flow)'
|
|
6288
|
+
: 'onramp: no signed-in user - call login() first');
|
|
5917
6289
|
}
|
|
5918
6290
|
return address;
|
|
5919
6291
|
}
|
|
@@ -5924,7 +6296,7 @@ function resolveAddress(options) {
|
|
|
5924
6296
|
async function onrampQuote(options = {}) {
|
|
5925
6297
|
if (!hasDOM())
|
|
5926
6298
|
throw new Error('onrampQuote is web-only');
|
|
5927
|
-
resolveAddress(
|
|
6299
|
+
resolveAddress();
|
|
5928
6300
|
const res = await authedFetch('/__bounded/onramp/session', {
|
|
5929
6301
|
method: 'POST',
|
|
5930
6302
|
headers: { 'content-type': 'application/json' },
|
|
@@ -5982,7 +6354,7 @@ async function onramp(options = {}) {
|
|
|
5982
6354
|
var _a;
|
|
5983
6355
|
if (!hasDOM())
|
|
5984
6356
|
throw new Error('onramp() is web-only');
|
|
5985
|
-
resolveAddress(
|
|
6357
|
+
resolveAddress();
|
|
5986
6358
|
// Open the window synchronously so the click's user-activation window is not
|
|
5987
6359
|
// consumed by the fetch below (same hard-won pattern as loginWithPopup).
|
|
5988
6360
|
let popup = null;
|
|
@@ -6205,84 +6577,12 @@ class PrivyExpoProvider {
|
|
|
6205
6577
|
setCurrentUser(user);
|
|
6206
6578
|
return user;
|
|
6207
6579
|
}
|
|
6208
|
-
async runTransaction(_evmTransactionData,
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
]);
|
|
6215
|
-
if (!solTransactionData) {
|
|
6216
|
-
throw new Error('Solana transaction data is required');
|
|
6217
|
-
}
|
|
6218
|
-
const wallet = await this.getWalletOrThrow();
|
|
6219
|
-
const rpcUrl = this.getRpcUrl(solTransactionData.network);
|
|
6220
|
-
const connection = new Connection(rpcUrl, 'confirmed');
|
|
6221
|
-
const remainingAccounts = core.convertRemainingAccounts(solTransactionData.txArgs[0].remainingAccounts);
|
|
6222
|
-
const app_id = solTransactionData.appId;
|
|
6223
|
-
if (!app_id) {
|
|
6224
|
-
throw new Error('App ID is required');
|
|
6225
|
-
}
|
|
6226
|
-
// Create a mock wallet adapter for Anchor (only publicKey needed for building TX)
|
|
6227
|
-
const walletPublicKey = new PublicKey(wallet.address);
|
|
6228
|
-
const walletAdapter = {
|
|
6229
|
-
publicKey: walletPublicKey,
|
|
6230
|
-
signTransaction: async (tx) => tx,
|
|
6231
|
-
signAllTransactions: async (txs) => txs,
|
|
6232
|
-
};
|
|
6233
|
-
const ProviderClass = programSdk[['Anch', 'orProvider'].join('')];
|
|
6234
|
-
const programProvider = new ProviderClass(connection, walletAdapter, ProviderClass.defaultOptions());
|
|
6235
|
-
const finalDeduped = [];
|
|
6236
|
-
for (const acc of remainingAccounts) {
|
|
6237
|
-
const existing = finalDeduped.find((d) => d.pubkey.equals(acc.pubkey));
|
|
6238
|
-
if (existing) {
|
|
6239
|
-
existing.isSigner = existing.isSigner || acc.isSigner;
|
|
6240
|
-
existing.isWritable = existing.isWritable || acc.isWritable;
|
|
6241
|
-
}
|
|
6242
|
-
else {
|
|
6243
|
-
finalDeduped.push(acc);
|
|
6244
|
-
}
|
|
6245
|
-
}
|
|
6246
|
-
const { tx, blockhash, lastValidBlockHeight } = await core.buildSetDocumentsTransaction(connection, solTransactionData.txArgs[0].idl, programProvider, walletPublicKey, {
|
|
6247
|
-
app_id,
|
|
6248
|
-
documents: solTransactionData.txArgs[0].setDocumentData,
|
|
6249
|
-
delete_paths: solTransactionData.txArgs[0].deletePaths,
|
|
6250
|
-
txData: solTransactionData.txArgs[0].txData,
|
|
6251
|
-
}, finalDeduped, solTransactionData.lutKey, solTransactionData.preInstructions, false, solTransactionData.additionalLutAddresses);
|
|
6252
|
-
// Set blockhash
|
|
6253
|
-
const isLegacyTx = 'recentBlockhash' in tx &&
|
|
6254
|
-
!('message' in tx && 'staticAccountKeys' in tx.message);
|
|
6255
|
-
if (isLegacyTx) {
|
|
6256
|
-
tx.recentBlockhash = blockhash;
|
|
6257
|
-
tx.lastValidBlockHeight = lastValidBlockHeight;
|
|
6258
|
-
}
|
|
6259
|
-
else {
|
|
6260
|
-
tx.message.recentBlockhash = blockhash;
|
|
6261
|
-
}
|
|
6262
|
-
try {
|
|
6263
|
-
if ((options === null || options === void 0 ? void 0 : options.shouldSubmitTx) === false) {
|
|
6264
|
-
// Sign only — don't submit
|
|
6265
|
-
const signed = await wallet.signTransaction(tx);
|
|
6266
|
-
return {
|
|
6267
|
-
signedTransaction: signed.signedTransaction,
|
|
6268
|
-
blockNumber: 0,
|
|
6269
|
-
gasUsed: '0',
|
|
6270
|
-
data: '',
|
|
6271
|
-
};
|
|
6272
|
-
}
|
|
6273
|
-
// Sign and submit
|
|
6274
|
-
const { signature, txInfo } = await this.signAndSubmitInternal(tx, wallet, connection);
|
|
6275
|
-
return {
|
|
6276
|
-
transactionSignature: signature,
|
|
6277
|
-
blockNumber: (txInfo === null || txInfo === void 0 ? void 0 : txInfo.slot) || 0,
|
|
6278
|
-
gasUsed: ((_a = txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta) === null || _a === void 0 ? void 0 : _a.fee.toString()) || '0',
|
|
6279
|
-
data: txInfo === null || txInfo === void 0 ? void 0 : txInfo.meta,
|
|
6280
|
-
};
|
|
6281
|
-
}
|
|
6282
|
-
catch (err) {
|
|
6283
|
-
console.error(err);
|
|
6284
|
-
throw err;
|
|
6285
|
-
}
|
|
6580
|
+
async runTransaction(_evmTransactionData, _solTransactionData, _options) {
|
|
6581
|
+
// Client-side Solana transaction building is retired: the realtime
|
|
6582
|
+
// worker returns a fully-built (and, when sponsored, partially-signed)
|
|
6583
|
+
// transaction on its 202, which the SDK validates and signs via
|
|
6584
|
+
// signTransaction. This provider serves no EVM payload either.
|
|
6585
|
+
throw new Error('runTransaction is not supported by this provider; Bounded returns pre-built Solana transactions that are signed with signTransaction.');
|
|
6286
6586
|
}
|
|
6287
6587
|
async signMessage(message) {
|
|
6288
6588
|
await this.ensureReady();
|
|
@@ -6443,7 +6743,6 @@ exports.BUILD_DELEGATED_REVIEW_CAPABILITY_SCHEMA = BUILD_DELEGATED_REVIEW_CAPABI
|
|
|
6443
6743
|
exports.BUILD_REVIEW_CAPABILITY_REFRESH_SCHEMA = BUILD_REVIEW_CAPABILITY_REFRESH_SCHEMA;
|
|
6444
6744
|
exports.BUILD_REVIEW_CAPABILITY_SCHEMA = BUILD_REVIEW_CAPABILITY_SCHEMA;
|
|
6445
6745
|
exports.BuildsApiError = BuildsApiError;
|
|
6446
|
-
exports.EMBEDDED_WALLET_UNSUPPORTED = EMBEDDED_WALLET_UNSUPPORTED;
|
|
6447
6746
|
exports.FAILURE_REASONS = FAILURE_REASONS;
|
|
6448
6747
|
exports.NON_TERMINAL_STATES = NON_TERMINAL_STATES;
|
|
6449
6748
|
exports.OffchainAuthProvider = OffchainAuthProvider;
|
|
@@ -6458,16 +6757,12 @@ exports.builds = builds;
|
|
|
6458
6757
|
exports.completeLoginFromRedirect = completeLoginFromRedirect;
|
|
6459
6758
|
exports.completeLoginInPopup = completeLoginInPopup;
|
|
6460
6759
|
exports.confirmAndCheckTransaction = confirmAndCheckTransaction;
|
|
6461
|
-
exports.deserializeTransaction = deserializeTransaction;
|
|
6462
|
-
exports.embeddedRunEvmTransaction = embeddedRunEvmTransaction;
|
|
6463
|
-
exports.embeddedSignAndSubmit = embeddedSignAndSubmit;
|
|
6464
6760
|
exports.getAuthLoading = getAuthLoading;
|
|
6465
6761
|
exports.getAuthProvider = getAuthProvider;
|
|
6466
6762
|
exports.getCurrentUser = getCurrentUser;
|
|
6467
6763
|
exports.getIdToken = getIdToken;
|
|
6468
6764
|
exports.getPlatform = getPlatform;
|
|
6469
|
-
exports.
|
|
6470
|
-
exports.hasEmbeddedWallet = hasEmbeddedWallet;
|
|
6765
|
+
exports.hasTurnkeyWallet = hasTurnkeyWallet;
|
|
6471
6766
|
exports.init = init;
|
|
6472
6767
|
exports.login = login;
|
|
6473
6768
|
exports.loginWithPopup = loginWithPopup;
|
|
@@ -6484,8 +6779,11 @@ exports.resolveSolanaRpcUrl = resolveSolanaRpcUrl;
|
|
|
6484
6779
|
exports.setAuthLoading = setAuthLoading;
|
|
6485
6780
|
exports.setCurrentUser = setCurrentUser;
|
|
6486
6781
|
exports.setPlatform = setPlatform;
|
|
6782
|
+
exports.signAndSubmitTransactionWithTurnkey = signAndSubmitTransactionWithTurnkey;
|
|
6487
6783
|
exports.signInAnonymously = signInAnonymously;
|
|
6784
|
+
exports.signMessageWithTurnkey = signMessageWithTurnkey;
|
|
6785
|
+
exports.signTransactionWithTurnkey = signTransactionWithTurnkey;
|
|
6488
6786
|
exports.useAuth = useAuth;
|
|
6489
6787
|
exports.useBuildRun = useBuildRun;
|
|
6490
6788
|
exports.useQuery = useQuery;
|
|
6491
|
-
//# sourceMappingURL=index.native-
|
|
6789
|
+
//# sourceMappingURL=index.native-CAHw3k3_.js.map
|