@bounded-sh/client 0.0.59 → 0.0.61
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/{email-auth-provider-N-dfsNnE.js → email-auth-provider-9BwSziWj.js} +2 -2
- package/dist/{email-auth-provider-N-dfsNnE.js.map → email-auth-provider-9BwSziWj.js.map} +1 -1
- package/dist/{email-auth-provider-DhAMOILG.mjs → email-auth-provider-B3XaJw-G.mjs} +2 -2
- package/dist/{email-auth-provider-deB_ADc5.mjs.map → email-auth-provider-B3XaJw-G.mjs.map} +1 -1
- package/dist/{email-auth-provider-BSw9FRjg.js → email-auth-provider-BttT2sZK.js} +2 -2
- package/dist/{email-auth-provider-BSw9FRjg.js.map → email-auth-provider-BttT2sZK.js.map} +1 -1
- package/dist/{email-auth-provider-deB_ADc5.mjs → email-auth-provider-Cb4VKA1E.mjs} +2 -2
- package/dist/{email-auth-provider-DhAMOILG.mjs.map → email-auth-provider-Cb4VKA1E.mjs.map} +1 -1
- package/dist/{guest-auth-provider-D9wbogwi.mjs → guest-auth-provider-BBPpydtM.mjs} +2 -2
- package/dist/{guest-auth-provider-B78Ugfar.mjs.map → guest-auth-provider-BBPpydtM.mjs.map} +1 -1
- package/dist/{guest-auth-provider-B78Ugfar.mjs → guest-auth-provider-BBSFawAr.mjs} +2 -2
- package/dist/{guest-auth-provider-D9wbogwi.mjs.map → guest-auth-provider-BBSFawAr.mjs.map} +1 -1
- package/dist/{guest-auth-provider-Czl48mOP.js → guest-auth-provider-BcR-MQ0g.js} +2 -2
- package/dist/{guest-auth-provider-Czl48mOP.js.map → guest-auth-provider-BcR-MQ0g.js.map} +1 -1
- package/dist/{guest-auth-provider-BFodq9Rc.js → guest-auth-provider-Di0TRg-z.js} +2 -2
- package/dist/{guest-auth-provider-BFodq9Rc.js.map → guest-auth-provider-Di0TRg-z.js.map} +1 -1
- package/dist/{index-uu8hKP-p.js → index-C_L497w1.js} +191 -51
- package/dist/index-C_L497w1.js.map +1 -0
- package/dist/{index-SHt4VZZV.mjs → index-L2R6C5Vl.mjs} +190 -52
- package/dist/index-L2R6C5Vl.mjs.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{index.native-D-8IAEy-.mjs → index.native-BIUs8t7F.mjs} +182 -51
- package/dist/index.native-BIUs8t7F.mjs.map +1 -0
- package/dist/{index.native-D48QQ0-q.js → index.native-BSheiGj2.js} +183 -50
- package/dist/index.native-BSheiGj2.js.map +1 -0
- package/dist/index.native.d.ts +2 -2
- package/dist/index.native.js +3 -1
- package/dist/index.native.js.map +1 -1
- package/dist/index.native.mjs +1 -1
- package/dist/{injected-evm-wallet-provider-HQMOL_mZ.js → injected-evm-wallet-provider-7XawIUdJ.js} +2 -2
- package/dist/{injected-evm-wallet-provider-HQMOL_mZ.js.map → injected-evm-wallet-provider-7XawIUdJ.js.map} +1 -1
- package/dist/{injected-evm-wallet-provider-UWvcy-LO.mjs → injected-evm-wallet-provider-DSFDC8fh.mjs} +2 -2
- package/dist/{injected-evm-wallet-provider-UWvcy-LO.mjs.map → injected-evm-wallet-provider-DSFDC8fh.mjs.map} +1 -1
- package/dist/{injected-evm-wallet-provider-CItxws1D.js → injected-evm-wallet-provider-DgWUaVtt.js} +2 -2
- package/dist/{injected-evm-wallet-provider-CItxws1D.js.map → injected-evm-wallet-provider-DgWUaVtt.js.map} +1 -1
- package/dist/{injected-evm-wallet-provider-CJsLX16m.mjs → injected-evm-wallet-provider-DnOrVMDX.mjs} +2 -2
- package/dist/{injected-evm-wallet-provider-CJsLX16m.mjs.map → injected-evm-wallet-provider-DnOrVMDX.mjs.map} +1 -1
- package/dist/{injected-wallet-provider-CmXqreEE.js → injected-wallet-provider-BMDJntMD.js} +2 -2
- package/dist/{injected-wallet-provider-CmXqreEE.js.map → injected-wallet-provider-BMDJntMD.js.map} +1 -1
- package/dist/{injected-wallet-provider-BihII94U.mjs → injected-wallet-provider-DfJvN3sV.mjs} +2 -2
- package/dist/{injected-wallet-provider-BihII94U.mjs.map → injected-wallet-provider-DfJvN3sV.mjs.map} +1 -1
- package/dist/{injected-wallet-provider-CNYAynIB.mjs → injected-wallet-provider-ZkPzVj5W.mjs} +2 -2
- package/dist/{injected-wallet-provider-CNYAynIB.mjs.map → injected-wallet-provider-ZkPzVj5W.mjs.map} +1 -1
- package/dist/{injected-wallet-provider-CVeZgfEt.js → injected-wallet-provider-oCRGuls5.js} +2 -2
- package/dist/{injected-wallet-provider-CVeZgfEt.js.map → injected-wallet-provider-oCRGuls5.js.map} +1 -1
- package/dist/onramp.d.ts +51 -9
- package/package.json +2 -2
- package/dist/index-SHt4VZZV.mjs.map +0 -1
- package/dist/index-uu8hKP-p.js.map +0 -1
- package/dist/index.native-D-8IAEy-.mjs.map +0 -1
- package/dist/index.native-D48QQ0-q.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -30,8 +30,8 @@ export type { TurnkeySignResult, TurnkeyWallet } from "./auth/turnkey-signer-bri
|
|
|
30
30
|
export { startTurnkeyEmailLogin } from "./auth/turnkey-auth";
|
|
31
31
|
export type { TurnkeyEmailLoginHandle } from "./auth/turnkey-auth";
|
|
32
32
|
export { getIdToken } from "./utils";
|
|
33
|
-
export { onramp } from "./onramp";
|
|
34
|
-
export type { OnrampOptions, OnrampResult } from "./onramp";
|
|
33
|
+
export { onramp, onrampQuote, onrampStatus } from "./onramp";
|
|
34
|
+
export type { OnrampOptions, OnrampResult, OnrampQuoteInfo, OnrampTransaction } from "./onramp";
|
|
35
35
|
export { setPlatform, getPlatform } from "./platform";
|
|
36
36
|
export type { PlatformAdapter, StorageAdapter } from "./platform";
|
|
37
37
|
export { OffchainAuthProvider, OffchainAuthProviderConfig, } from "./auth/providers/offchain-auth-provider";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-C_L497w1.js');
|
|
4
4
|
var core = require('@bounded-sh/core');
|
|
5
5
|
require('react');
|
|
6
6
|
|
|
@@ -40,6 +40,8 @@ exports.logout = index.logout;
|
|
|
40
40
|
exports.onAuthLoadingChanged = index.onAuthLoadingChanged;
|
|
41
41
|
exports.onAuthStateChanged = index.onAuthStateChanged;
|
|
42
42
|
exports.onramp = index.onramp;
|
|
43
|
+
exports.onrampQuote = index.onrampQuote;
|
|
44
|
+
exports.onrampStatus = index.onrampStatus;
|
|
43
45
|
exports.openBoundedWidget = index.openBoundedWidget;
|
|
44
46
|
exports.requestEip6963Providers = index.requestEip6963Providers;
|
|
45
47
|
exports.setPlatform = index.setPlatform;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { a2 as BUILD_DELEGATED_REVIEW_CAPABILITY_SCHEMA, a1 as BUILD_REVIEW_CAPABILITY_REFRESH_SCHEMA, a0 as BUILD_REVIEW_CAPABILITY_SCHEMA, W as BuildsApiError, $ as FAILURE_REASONS, X as NON_TERMINAL_STATES, S as OffchainAuthProvider, _ as PARK_REASONS, T as PrivyExpoProvider, Z as RUN_STATES, Y as TERMINAL_STATES, I as apps, V as builds, A as completeLoginFromRedirect, C as completeLoginInPopup, k as defaultInjectedEvmProvider, d as defaultInjectedProvider, J as deserializeTransaction, q as getAuthLoading, v as getAuthProvider, m as getCurrentUser, N as getIdToken, L as getOrCreateTurnkeyWallet, g as getPlatform, l as init, t as login, B as loginWithPopup, x as loginWithPrivy, z as loginWithRedirect, y as loginWithWallet, u as logout, p as onAuthLoadingChanged, o as onAuthStateChanged, O as onramp, P as onrampQuote, Q as onrampStatus, D as openBoundedWidget, U as requestEip6963Providers, R as setPlatform, w as signInAnonymously, K as signSolanaMessageViaTurnkey, M as startTurnkeyEmailLogin, F as useAuth, H as useBuildRun, G as useQuery } from './index-L2R6C5Vl.mjs';
|
|
2
2
|
export * from '@bounded-sh/core';
|
|
3
3
|
export { BoundedDeclineError, DECLINE_EVENT_NAME, RATE_LIMIT_EVENT_NAME, ScopedClientReadOnlyError, aggregate, count, createClient, deriveDecline, dispatchDeclineEvent, dispatchRateLimitEvent, docId, get, getConfig, getFiles, getMany, queryAggregate, runExpression, runExpressionMany, runQuery, runQueryMany, search, set, setFile, setMany, signAndSubmitTransaction, signMessage, signTransaction, subscribe } from '@bounded-sh/core';
|
|
4
4
|
import 'react';
|
|
@@ -3686,6 +3686,7 @@ const OIDC_NO_WALLET = 'This login has no embedded wallet. Enable `"auth": { "wa
|
|
|
3686
3686
|
'then sign from a user gesture.';
|
|
3687
3687
|
const PKCE_STORE_KEY = 'bounded.oidc.pkce';
|
|
3688
3688
|
const STORED_AUTH_METHOD_KEY$1 = 'bounded_last_auth_method';
|
|
3689
|
+
const ISSUER_SESSION_KIND_KEY$1 = 'bounded_issuer_session_kind';
|
|
3689
3690
|
// Active session store (Web on web, RN on React Native) — selected by config,
|
|
3690
3691
|
// not by `typeof window` (truthy on RN). OIDC redirect/popup is web-only, but the
|
|
3691
3692
|
// session it mints is read back through this same selector everywhere.
|
|
@@ -4192,6 +4193,13 @@ async function exchangeCode(code, verifier, redirectUri) {
|
|
|
4192
4193
|
getPlatform().storage.setItem(STORED_AUTH_METHOD_KEY$1, 'email');
|
|
4193
4194
|
}
|
|
4194
4195
|
catch ( /* storage unavailable */_b) { /* storage unavailable */ }
|
|
4196
|
+
// OIDC login does establish the issuer's Better Auth browser cookie. Record
|
|
4197
|
+
// that fact separately from the provider name so logout clears the cookie
|
|
4198
|
+
// and returns through the registered app origin.
|
|
4199
|
+
try {
|
|
4200
|
+
getPlatform().storage.setItem(ISSUER_SESSION_KIND_KEY$1, 'hosted');
|
|
4201
|
+
}
|
|
4202
|
+
catch ( /* storage unavailable */_c) { /* storage unavailable */ }
|
|
4195
4203
|
setCurrentUser(user);
|
|
4196
4204
|
setAuthProviderInstance(oidcProviderSingleton);
|
|
4197
4205
|
return user;
|
|
@@ -4208,6 +4216,7 @@ const objectIdentityKeys = new WeakMap();
|
|
|
4208
4216
|
let nextObjectIdentityKey = 1;
|
|
4209
4217
|
// --- localStorage helpers: track which auth method created the active session ---
|
|
4210
4218
|
const STORED_AUTH_METHOD_KEY = 'bounded_last_auth_method';
|
|
4219
|
+
const ISSUER_SESSION_KIND_KEY = 'bounded_issuer_session_kind';
|
|
4211
4220
|
function getStoredAuthMethod() {
|
|
4212
4221
|
try {
|
|
4213
4222
|
return getPlatform().storage.getItem(STORED_AUTH_METHOD_KEY);
|
|
@@ -4224,11 +4233,25 @@ function setStoredAuthMethod(method) {
|
|
|
4224
4233
|
else {
|
|
4225
4234
|
getPlatform().storage.removeItem(STORED_AUTH_METHOD_KEY);
|
|
4226
4235
|
}
|
|
4236
|
+
// Non-email providers cannot own a Better Auth browser session. Clear
|
|
4237
|
+
// any prior hosted/inline classification when the active provider is
|
|
4238
|
+
// replaced or the session is removed.
|
|
4239
|
+
if (method !== 'email') {
|
|
4240
|
+
getPlatform().storage.removeItem(ISSUER_SESSION_KIND_KEY);
|
|
4241
|
+
}
|
|
4227
4242
|
}
|
|
4228
4243
|
catch (_a) {
|
|
4229
4244
|
// storage might not be available
|
|
4230
4245
|
}
|
|
4231
4246
|
}
|
|
4247
|
+
function getIssuerSessionKind() {
|
|
4248
|
+
try {
|
|
4249
|
+
return getPlatform().storage.getItem(ISSUER_SESSION_KIND_KEY);
|
|
4250
|
+
}
|
|
4251
|
+
catch (_a) {
|
|
4252
|
+
return null;
|
|
4253
|
+
}
|
|
4254
|
+
}
|
|
4232
4255
|
function getStoredIdToken() {
|
|
4233
4256
|
try {
|
|
4234
4257
|
return getActiveSessionManager().getIdToken();
|
|
@@ -4453,7 +4476,7 @@ async function getAuthProvider(config) {
|
|
|
4453
4476
|
// manager as legacy email sessions. Human login should be started
|
|
4454
4477
|
// with loginWithRedirect(); this provider is kept as the restore and
|
|
4455
4478
|
// logout surface for those sessions.
|
|
4456
|
-
currentAuthProvider = new (await import('./email-auth-provider-
|
|
4479
|
+
currentAuthProvider = new (await import('./email-auth-provider-Cb4VKA1E.mjs')).EmailAuthProvider();
|
|
4457
4480
|
break;
|
|
4458
4481
|
case "wallet":
|
|
4459
4482
|
case "phantom": {
|
|
@@ -4472,7 +4495,7 @@ async function getAuthProvider(config) {
|
|
|
4472
4495
|
if (!isWalletLoginEnabled(config)) {
|
|
4473
4496
|
throw walletLoginNotEnabledError(authMethod);
|
|
4474
4497
|
}
|
|
4475
|
-
const { InjectedWalletProvider } = await import('./injected-wallet-provider-
|
|
4498
|
+
const { InjectedWalletProvider } = await import('./injected-wallet-provider-ZkPzVj5W.mjs');
|
|
4476
4499
|
currentAuthProvider = new InjectedWalletProvider(resolveInjectedWalletConfig(config), rpcUrl, configuredNetwork);
|
|
4477
4500
|
break;
|
|
4478
4501
|
}
|
|
@@ -4485,7 +4508,7 @@ async function getAuthProvider(config) {
|
|
|
4485
4508
|
// Selecting authMethod:'evm-wallet' IS the opt-in — pass evmWalletConfig
|
|
4486
4509
|
// to point at a specific wallet or set chainId/domain.
|
|
4487
4510
|
const evmWalletConfig = ((_a = config.evmWalletConfig) !== null && _a !== void 0 ? _a : {});
|
|
4488
|
-
const { InjectedEvmWalletProvider } = await import('./injected-evm-wallet-provider-
|
|
4511
|
+
const { InjectedEvmWalletProvider } = await import('./injected-evm-wallet-provider-DnOrVMDX.mjs');
|
|
4489
4512
|
currentAuthProvider = new InjectedEvmWalletProvider(evmWalletConfig);
|
|
4490
4513
|
break;
|
|
4491
4514
|
}
|
|
@@ -4513,7 +4536,7 @@ async function getAuthProvider(config) {
|
|
|
4513
4536
|
break;
|
|
4514
4537
|
case "guest":
|
|
4515
4538
|
// Anonymous auth: a device-local ed25519 keypair signs the challenge.
|
|
4516
|
-
currentAuthProvider = new (await import('./guest-auth-provider-
|
|
4539
|
+
currentAuthProvider = new (await import('./guest-auth-provider-BBPpydtM.mjs')).GuestAuthProvider();
|
|
4517
4540
|
break;
|
|
4518
4541
|
}
|
|
4519
4542
|
if (!currentAuthProvider) {
|
|
@@ -4569,7 +4592,7 @@ async function signInAnonymously() {
|
|
|
4569
4592
|
// Lazy-load the guest provider so its ed25519/web3 dependencies stay out of
|
|
4570
4593
|
// the main bundle for data-only apps. Specifier is a static string literal
|
|
4571
4594
|
// so bundle-splitting can see it.
|
|
4572
|
-
const provider = new (await import('./guest-auth-provider-
|
|
4595
|
+
const provider = new (await import('./guest-auth-provider-BBPpydtM.mjs')).GuestAuthProvider();
|
|
4573
4596
|
setAuthLoading(true); // reflect "signing in…" while the guest keypair session is minted
|
|
4574
4597
|
const commit = (user) => {
|
|
4575
4598
|
// No await/interleaving inside this block: provider/method/config/marker
|
|
@@ -4754,7 +4777,7 @@ function getCurrentAuthMethod() {
|
|
|
4754
4777
|
// allowlist here: on a trusted origin we end the issuer session with a
|
|
4755
4778
|
// top-level bounce; anywhere else (custom domains, http dev) we keep the
|
|
4756
4779
|
// local-only logout instead of stranding the user on the issuer origin.
|
|
4757
|
-
function issuerLogoutBounceUrl(issuerBase) {
|
|
4780
|
+
function issuerLogoutBounceUrl(issuerBase, idTokenHint) {
|
|
4758
4781
|
if (typeof window === 'undefined' || typeof document === 'undefined')
|
|
4759
4782
|
return null; // RN/Node: no shared cookie jar to clear this way
|
|
4760
4783
|
try {
|
|
@@ -4777,12 +4800,27 @@ function issuerLogoutBounceUrl(issuerBase) {
|
|
|
4777
4800
|
if (!trusted)
|
|
4778
4801
|
return null;
|
|
4779
4802
|
const base = issuerBase.replace(/\/$/, '');
|
|
4780
|
-
|
|
4803
|
+
// #228: send the id_token_hint so the issuer can bind the post-logout redirect to this
|
|
4804
|
+
// session + app + registered origin. Without it the issuer safely falls back to its own
|
|
4805
|
+
// origin (it no longer trusts a bare suffix match), so the return-to-app bounce is a no-op.
|
|
4806
|
+
const hint = idTokenHint ? `&id_token_hint=${encodeURIComponent(idTokenHint)}` : '';
|
|
4807
|
+
return `${base}/logout?redirect_uri=${encodeURIComponent(here.href)}${hint}`;
|
|
4781
4808
|
}
|
|
4782
4809
|
catch (_b) {
|
|
4783
4810
|
return null;
|
|
4784
4811
|
}
|
|
4785
4812
|
}
|
|
4813
|
+
// #228 helper, deliberately OUTSIDE logout(): the logout body is source-guarded
|
|
4814
|
+
// against any `catch` so a revokeSession failure can never be swallowed, and a
|
|
4815
|
+
// missing id token is the one benign absence worth tolerating here.
|
|
4816
|
+
function idTokenHintOrNull(sm) {
|
|
4817
|
+
try {
|
|
4818
|
+
return sm.getIdToken();
|
|
4819
|
+
}
|
|
4820
|
+
catch (_a) {
|
|
4821
|
+
return null; /* no id token to hint with */
|
|
4822
|
+
}
|
|
4823
|
+
}
|
|
4786
4824
|
async function logout$1(options) {
|
|
4787
4825
|
// Re-initialize the provider if it was cleared by a prior logout — the exact mirror
|
|
4788
4826
|
// of login()'s self-heal above. A hosted popup/redirect login (loginWithPopup /
|
|
@@ -4807,17 +4845,20 @@ async function logout$1(options) {
|
|
|
4807
4845
|
const sm = getActiveSessionManager();
|
|
4808
4846
|
const refreshToken = sm.getRefreshToken();
|
|
4809
4847
|
const sessionIssuer = sm.getIssuer();
|
|
4848
|
+
// #228: capture the id token NOW, before currentAuthProvider.logout() clears the session, so we
|
|
4849
|
+
// can hand it to the issuer /logout as an id_token_hint (which binds the post-logout redirect).
|
|
4850
|
+
const idTokenHint = idTokenHintOrNull(sm);
|
|
4810
4851
|
if (refreshToken)
|
|
4811
4852
|
await revokeSession(refreshToken, sessionIssuer !== null && sessionIssuer !== void 0 ? sessionIssuer : undefined);
|
|
4812
|
-
//
|
|
4813
|
-
//
|
|
4814
|
-
//
|
|
4815
|
-
//
|
|
4816
|
-
//
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4853
|
+
// Only OIDC-hosted sessions own an issuer browser cookie. Turnkey-native
|
|
4854
|
+
// email OTP is also an email auth method, but it mints the app session
|
|
4855
|
+
// inline and has no issuer cookie to clear. Use the explicit session-kind
|
|
4856
|
+
// marker when present. The auth-method fallback preserves correct logout
|
|
4857
|
+
// behavior for hosted sessions created by older SDK versions.
|
|
4858
|
+
const issuerSessionKind = getIssuerSessionKind();
|
|
4859
|
+
const wasHosted = issuerSessionKind === 'hosted'
|
|
4860
|
+
|| (issuerSessionKind === null
|
|
4861
|
+
&& (currentAuthMethod === 'email' || getStoredAuthMethod() === 'email'));
|
|
4821
4862
|
await currentAuthProvider.logout();
|
|
4822
4863
|
setStoredAuthMethod(null);
|
|
4823
4864
|
currentAuthProvider = null;
|
|
@@ -4827,7 +4868,7 @@ async function logout$1(options) {
|
|
|
4827
4868
|
const issuerBase = sessionIssuer
|
|
4828
4869
|
|| (await getConfig()).humanAuthApiUrl
|
|
4829
4870
|
|| 'https://auth.bounded.sh';
|
|
4830
|
-
const bounce = issuerLogoutBounceUrl(issuerBase);
|
|
4871
|
+
const bounce = issuerLogoutBounceUrl(issuerBase, idTokenHint);
|
|
4831
4872
|
// Local state is already cleared, so even if the navigation is stopped
|
|
4832
4873
|
// (tab close, extension) the app-side logout has fully happened.
|
|
4833
4874
|
if (bounce)
|
|
@@ -5810,30 +5851,117 @@ async function deserializeTransaction(tx) {
|
|
|
5810
5851
|
// session is bound server-side to the caller's verified Bounded JWT, and the
|
|
5811
5852
|
// destination defaults to that user's embedded wallet.
|
|
5812
5853
|
//
|
|
5854
|
+
// Amount semantics:
|
|
5855
|
+
// amountUsd - exact fiat in; the fee/output breakdown comes back as `quote`.
|
|
5856
|
+
// minAmountOut - a FLOOR on crypto received. The platform quotes Coinbase's
|
|
5857
|
+
// worst-fee payment method (card) and pads by `slippagePad` (default 1%),
|
|
5858
|
+
// so cheaper methods overshoot the floor rather than undershooting it. The
|
|
5859
|
+
// floor holds unless the market moves more than the pad while the user sits
|
|
5860
|
+
// on the checkout screen - which is why completion is VERIFIED: after the
|
|
5861
|
+
// popup closes we poll the platform's status leg and resolve with the
|
|
5862
|
+
// actual filled amount when Coinbase reports it.
|
|
5863
|
+
//
|
|
5813
5864
|
// Works on Bounded-served origins (<app>.bounded.page / custom domains). On a
|
|
5814
5865
|
// local dev origin the session endpoint does not exist; we fail with a clear
|
|
5815
5866
|
// error rather than guessing a host.
|
|
5816
5867
|
function hasDOM() {
|
|
5817
5868
|
return typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
5818
5869
|
}
|
|
5870
|
+
async function authedFetch(path, init) {
|
|
5871
|
+
const idToken = await getIdToken();
|
|
5872
|
+
if (!idToken)
|
|
5873
|
+
throw new Error('onramp: no active session - call login() first');
|
|
5874
|
+
return fetch(`${window.location.origin}${path}`, Object.assign(Object.assign({}, init), { headers: Object.assign(Object.assign({}, init === null || init === void 0 ? void 0 : init.headers), { Authorization: `Bearer ${idToken}` }) }));
|
|
5875
|
+
}
|
|
5876
|
+
async function readError(res) {
|
|
5877
|
+
var _a;
|
|
5878
|
+
try {
|
|
5879
|
+
return (_a = (await res.json()).error) !== null && _a !== void 0 ? _a : '';
|
|
5880
|
+
}
|
|
5881
|
+
catch (_b) {
|
|
5882
|
+
return '';
|
|
5883
|
+
}
|
|
5884
|
+
}
|
|
5885
|
+
function sessionBody(options, extra) {
|
|
5886
|
+
return JSON.stringify(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (options.asset ? { asset: options.asset } : {})), (options.address ? { address: options.address } : {})), (options.amountUsd !== undefined ? { amountUsd: options.amountUsd } : {})), (options.minAmountOut !== undefined ? { minAmountOut: options.minAmountOut } : {})), (options.slippagePad !== undefined ? { slippagePad: options.slippagePad } : {})), extra));
|
|
5887
|
+
}
|
|
5888
|
+
function resolveAddress(options) {
|
|
5889
|
+
var _a, _b;
|
|
5890
|
+
const user = getCurrentUser();
|
|
5891
|
+
const address = (_b = (_a = options.address) !== null && _a !== void 0 ? _a : user === null || user === void 0 ? void 0 : user.address) !== null && _b !== void 0 ? _b : undefined;
|
|
5892
|
+
if (!address) {
|
|
5893
|
+
throw new Error(user
|
|
5894
|
+
? 'onramp: the signed-in account has no wallet address - pass { address } explicitly'
|
|
5895
|
+
: 'onramp: no signed-in user - call login() first or pass { address }');
|
|
5896
|
+
}
|
|
5897
|
+
return address;
|
|
5898
|
+
}
|
|
5819
5899
|
/**
|
|
5820
|
-
*
|
|
5900
|
+
* Preview a quote (fees + exact/floor output) WITHOUT opening any window or
|
|
5901
|
+
* consuming a session. Show this to the user, then call onramp() to check out.
|
|
5902
|
+
*/
|
|
5903
|
+
async function onrampQuote(options = {}) {
|
|
5904
|
+
if (!hasDOM())
|
|
5905
|
+
throw new Error('onrampQuote is web-only');
|
|
5906
|
+
resolveAddress(options);
|
|
5907
|
+
const res = await authedFetch('/__bounded/onramp/session', {
|
|
5908
|
+
method: 'POST',
|
|
5909
|
+
headers: { 'content-type': 'application/json' },
|
|
5910
|
+
body: sessionBody(options, { quoteOnly: true }),
|
|
5911
|
+
});
|
|
5912
|
+
if (!res.ok)
|
|
5913
|
+
throw new Error(`onrampQuote: failed (${res.status}${await readError(res).then((e) => (e ? `: ${e}` : ''))})`);
|
|
5914
|
+
return (await res.json());
|
|
5915
|
+
}
|
|
5916
|
+
/** The signed-in user's recent onramp transactions (newest first). */
|
|
5917
|
+
async function onrampStatus(sinceMs) {
|
|
5918
|
+
if (!hasDOM())
|
|
5919
|
+
throw new Error('onrampStatus is web-only');
|
|
5920
|
+
const res = await authedFetch(`/__bounded/onramp/status${sinceMs ? `?since=${Math.floor(sinceMs)}` : ''}`);
|
|
5921
|
+
if (!res.ok)
|
|
5922
|
+
throw new Error(`onrampStatus: failed (${res.status})`);
|
|
5923
|
+
return (await res.json()).transactions;
|
|
5924
|
+
}
|
|
5925
|
+
function isSuccess(t) {
|
|
5926
|
+
return /SUCCESS|COMPLETED/i.test(t.status);
|
|
5927
|
+
}
|
|
5928
|
+
function isPending(t) {
|
|
5929
|
+
return /PROGRESS|PENDING|CREATED/i.test(t.status);
|
|
5930
|
+
}
|
|
5931
|
+
async function verifyCompletion(openedAt, asset, timeoutMs) {
|
|
5932
|
+
const deadline = Date.now() + timeoutMs;
|
|
5933
|
+
// 60s of clock-skew slack on `since`: Coinbase stamps server-side.
|
|
5934
|
+
const since = openedAt - 60000;
|
|
5935
|
+
for (;;) {
|
|
5936
|
+
let sawPending = false;
|
|
5937
|
+
try {
|
|
5938
|
+
const txs = await onrampStatus(since);
|
|
5939
|
+
const done = txs.find((t) => isSuccess(t) && (t.asset === null || t.asset === asset));
|
|
5940
|
+
if (done)
|
|
5941
|
+
return done;
|
|
5942
|
+
sawPending = txs.some(isPending);
|
|
5943
|
+
}
|
|
5944
|
+
catch ( /* transient - keep polling until the deadline */_a) { /* transient - keep polling until the deadline */ }
|
|
5945
|
+
// No completed fill and nothing in flight: one grace poll cycle still
|
|
5946
|
+
// runs (Coinbase's record can lag the redirect), but don't burn the
|
|
5947
|
+
// full window when the user plainly abandoned checkout.
|
|
5948
|
+
if (Date.now() >= deadline)
|
|
5949
|
+
return null;
|
|
5950
|
+
if (!sawPending && Date.now() >= openedAt + 12000 && Date.now() - openedAt > timeoutMs / 2)
|
|
5951
|
+
return null;
|
|
5952
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
5953
|
+
}
|
|
5954
|
+
}
|
|
5955
|
+
/**
|
|
5956
|
+
* Open Coinbase Onramp for the signed-in user. Resolves after the window
|
|
5957
|
+
* closes, with completion VERIFIED against Coinbase when possible.
|
|
5821
5958
|
* Call from a click handler - popup blockers require user activation.
|
|
5822
5959
|
*/
|
|
5823
5960
|
async function onramp(options = {}) {
|
|
5824
|
-
var _a
|
|
5961
|
+
var _a;
|
|
5825
5962
|
if (!hasDOM())
|
|
5826
5963
|
throw new Error('onramp() is web-only');
|
|
5827
|
-
|
|
5828
|
-
const address = (_b = (_a = options.address) !== null && _a !== void 0 ? _a : user === null || user === void 0 ? void 0 : user.address) !== null && _b !== void 0 ? _b : undefined;
|
|
5829
|
-
if (!address) {
|
|
5830
|
-
throw new Error(user
|
|
5831
|
-
? 'onramp(): the signed-in account has no wallet address - pass { address } explicitly'
|
|
5832
|
-
: 'onramp(): no signed-in user - call login() first or pass { address }');
|
|
5833
|
-
}
|
|
5834
|
-
const idToken = await getIdToken();
|
|
5835
|
-
if (!idToken)
|
|
5836
|
-
throw new Error('onramp(): no active session - call login() first');
|
|
5964
|
+
resolveAddress(options);
|
|
5837
5965
|
// Open the window synchronously so the click's user-activation window is not
|
|
5838
5966
|
// consumed by the fetch below (same hard-won pattern as loginWithPopup).
|
|
5839
5967
|
let popup = null;
|
|
@@ -5846,21 +5974,17 @@ async function onramp(options = {}) {
|
|
|
5846
5974
|
}
|
|
5847
5975
|
let session;
|
|
5848
5976
|
try {
|
|
5849
|
-
const res = await
|
|
5977
|
+
const res = await authedFetch('/__bounded/onramp/session', {
|
|
5850
5978
|
method: 'POST',
|
|
5851
|
-
headers: {
|
|
5852
|
-
body:
|
|
5979
|
+
headers: { 'content-type': 'application/json' },
|
|
5980
|
+
body: sessionBody(options),
|
|
5853
5981
|
});
|
|
5854
5982
|
if (!res.ok) {
|
|
5855
|
-
|
|
5856
|
-
try {
|
|
5857
|
-
detail = (_c = (await res.json()).error) !== null && _c !== void 0 ? _c : '';
|
|
5858
|
-
}
|
|
5859
|
-
catch ( /* keep status only */_d) { /* keep status only */ }
|
|
5983
|
+
const detail = await readError(res);
|
|
5860
5984
|
if (res.status === 404) {
|
|
5861
|
-
throw new Error('onramp
|
|
5985
|
+
throw new Error('onramp: session endpoint not found - onramp works on Bounded-served origins (your deployed app URL), not local dev servers');
|
|
5862
5986
|
}
|
|
5863
|
-
throw new Error(`onramp
|
|
5987
|
+
throw new Error(`onramp: session mint failed (${res.status}${detail ? `: ${detail}` : ''})`);
|
|
5864
5988
|
}
|
|
5865
5989
|
session = (await res.json());
|
|
5866
5990
|
}
|
|
@@ -5868,40 +5992,47 @@ async function onramp(options = {}) {
|
|
|
5868
5992
|
try {
|
|
5869
5993
|
popup === null || popup === void 0 ? void 0 : popup.close();
|
|
5870
5994
|
}
|
|
5871
|
-
catch ( /* ignore */
|
|
5995
|
+
catch ( /* ignore */_b) { /* ignore */ }
|
|
5872
5996
|
throw error;
|
|
5873
5997
|
}
|
|
5998
|
+
const openedAt = Date.now();
|
|
5999
|
+
const base = Object.assign({ address: session.address, asset: session.asset }, (session.quote ? { quote: session.quote } : {}));
|
|
5874
6000
|
if (popup) {
|
|
5875
6001
|
try {
|
|
5876
6002
|
popup.location.replace(session.url);
|
|
5877
6003
|
}
|
|
5878
|
-
catch (
|
|
6004
|
+
catch (_c) {
|
|
5879
6005
|
try {
|
|
5880
6006
|
popup.location.href = session.url;
|
|
5881
6007
|
}
|
|
5882
|
-
catch (
|
|
6008
|
+
catch (_d) {
|
|
5883
6009
|
try {
|
|
5884
6010
|
popup.close();
|
|
5885
6011
|
}
|
|
5886
|
-
catch ( /* ignore */
|
|
5887
|
-
throw new Error('onramp
|
|
6012
|
+
catch ( /* ignore */_e) { /* ignore */ }
|
|
6013
|
+
throw new Error('onramp: popup failed to navigate - retry with { newTab: true }');
|
|
5888
6014
|
}
|
|
5889
6015
|
}
|
|
5890
|
-
|
|
6016
|
+
await new Promise((resolve) => {
|
|
5891
6017
|
const timer = setInterval(() => {
|
|
5892
6018
|
if (popup.closed) {
|
|
5893
6019
|
clearInterval(timer);
|
|
5894
|
-
resolve(
|
|
6020
|
+
resolve();
|
|
5895
6021
|
}
|
|
5896
6022
|
}, 500);
|
|
5897
6023
|
});
|
|
6024
|
+
const fill = await verifyCompletion(openedAt, session.asset, (_a = options.completionTimeoutMs) !== null && _a !== void 0 ? _a : 24000);
|
|
6025
|
+
if (fill) {
|
|
6026
|
+
return Object.assign(Object.assign(Object.assign(Object.assign({}, base), { status: 'completed' }), (fill.amountOut !== null ? { actualOut: fill.amountOut } : {})), (fill.txHash ? { txHash: fill.txHash } : {}));
|
|
6027
|
+
}
|
|
6028
|
+
return Object.assign(Object.assign({}, base), { status: 'closed' });
|
|
5898
6029
|
}
|
|
5899
6030
|
// New-tab path (popup was blocked or explicitly requested): cross-origin tab
|
|
5900
|
-
// close is not observable, so resolve immediately.
|
|
6031
|
+
// close is not observable, so resolve immediately; verify via onrampStatus().
|
|
5901
6032
|
const tab = window.open(session.url, '_blank');
|
|
5902
6033
|
if (!tab)
|
|
5903
|
-
throw new Error('onramp
|
|
5904
|
-
return { status: 'opened'
|
|
6034
|
+
throw new Error('onramp: window.open was blocked - call onramp() from a click handler');
|
|
6035
|
+
return Object.assign(Object.assign({}, base), { status: 'opened' });
|
|
5905
6036
|
}
|
|
5906
6037
|
|
|
5907
6038
|
/**
|
|
@@ -6287,5 +6418,5 @@ class PrivyExpoProvider {
|
|
|
6287
6418
|
}
|
|
6288
6419
|
}
|
|
6289
6420
|
|
|
6290
|
-
export { useAuth as A, useQuery as B, useBuildRun as C, apps as D, EMBEDDED_WALLET_UNSUPPORTED as E, deserializeTransaction as F, getIdToken as G, onramp as H,
|
|
6291
|
-
//# sourceMappingURL=index.native-
|
|
6421
|
+
export { useAuth as A, useQuery as B, useBuildRun as C, apps as D, EMBEDDED_WALLET_UNSUPPORTED as E, deserializeTransaction as F, getIdToken as G, onramp as H, onrampQuote as I, onrampStatus as J, setPlatform as K, builds as L, BuildsApiError as M, NON_TERMINAL_STATES as N, OffchainAuthProvider as O, PrivyExpoProvider as P, PARK_REASONS as Q, RUN_STATES as R, FAILURE_REASONS as S, TERMINAL_STATES as T, BUILD_REVIEW_CAPABILITY_SCHEMA as U, BUILD_REVIEW_CAPABILITY_REFRESH_SCHEMA as V, BUILD_DELEGATED_REVIEW_CAPABILITY_SCHEMA as W, hasEmbeddedEvmWallet as a, embeddedSignAndSubmit as b, setAuthLoading as c, bufferExports as d, embeddedRunEvmTransaction as e, bs58 as f, getPlatform as g, hasEmbeddedWallet as h, confirmAndCheckTransaction as i, init as j, getCurrentUser as k, onAuthLoadingChanged as l, getAuthLoading as m, normalizeSolanaRpcUrl as n, onAuthStateChanged as o, login as p, logout as q, resolveSolanaRpcUrl as r, setCurrentUser as s, getAuthProvider as t, signInAnonymously as u, loginWithPrivy as v, loginWithRedirect as w, completeLoginFromRedirect as x, loginWithPopup as y, completeLoginInPopup as z };
|
|
6422
|
+
//# sourceMappingURL=index.native-BIUs8t7F.mjs.map
|