@orangecheck/auth-client 2.28.0 → 2.30.0

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/index.d.mts CHANGED
@@ -166,6 +166,30 @@ interface OcLinkedIdentitiesProps {
166
166
  }
167
167
  declare function OcLinkedIdentities({ authOrigin, className, onChange, attestationLink, }: OcLinkedIdentitiesProps): React.ReactElement;
168
168
 
169
+ interface Floors {
170
+ sats_floor: number;
171
+ days_floor: number;
172
+ }
173
+ interface OcBondView extends Floors {
174
+ address: string;
175
+ outpoint: string;
176
+ sats: number;
177
+ confirmed_height: number;
178
+ checked_at: string;
179
+ checked_height: number;
180
+ created_at: string;
181
+ }
182
+ interface OcBondProps {
183
+ authOrigin?: string;
184
+ onChange?: (bond: OcBondView | null) => void;
185
+ className?: string;
186
+ }
187
+ declare function bondFloorsText(f: Floors): string;
188
+ declare function fetchOcBond(opts?: {
189
+ authOrigin?: string;
190
+ }): Promise<OcBondView | null>;
191
+ declare function OcBond({ authOrigin, onChange, className, }: OcBondProps): React.ReactElement;
192
+
169
193
  declare const TAB_SESSION_HEADER = "x-oc-tab-session";
170
194
  declare const TAB_SESSION_STORAGE_KEY = "oc_tab_session";
171
195
  declare const TAB_ACCOUNT_HINT_KEY = "oc-as";
@@ -269,4 +293,4 @@ declare function isSudoAccountMismatch(body: {
269
293
  reason?: string;
270
294
  } | null | undefined): boolean;
271
295
 
272
- export { DEFAULT_CONFIG, DISPLAY_IDENTITY_KINDS, type DisplayIdentity, type DisplayIdentityKind, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, type OcAccountSummary, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcLinkedIdentities, type OcLinkedIdentitiesProps, type OcLinkedIdentity, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type OcSignOutScope, type OcTabSession, type RedirectToSudoArgs, SUDO_ACCOUNT_MISMATCH_MESSAGE, TAB_ACCOUNT_HINT_KEY, TAB_ADOPT_HASH, TAB_SESSION_HEADER, TAB_SESSION_STORAGE_KEY, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterResult, type WebAuthnRegisterStatus, type WebAuthnRemoveResult, type WebAuthnRenameResult, type WebAuthnStepUpResult, buildAddAccountUrl, buildSignInUrl, clearTabSession, consumeTabAccountHint, consumeTabAdoptMarker, familyReturnTarget, fetchOcLinkedIdentities, handleSudoRequired, installTabFetchInterceptor, installTabLinkDecorator, isSudoAccountMismatch, readTabSession, redirectToSudo, safeReturnTo, tabSessionHeader, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister, writeTabSession };
296
+ export { DEFAULT_CONFIG, DISPLAY_IDENTITY_KINDS, type DisplayIdentity, type DisplayIdentityKind, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, type OcAccountSummary, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcBond, type OcBondProps, type OcBondView, OcLinkedIdentities, type OcLinkedIdentitiesProps, type OcLinkedIdentity, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type OcSignOutScope, type OcTabSession, type RedirectToSudoArgs, SUDO_ACCOUNT_MISMATCH_MESSAGE, TAB_ACCOUNT_HINT_KEY, TAB_ADOPT_HASH, TAB_SESSION_HEADER, TAB_SESSION_STORAGE_KEY, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterResult, type WebAuthnRegisterStatus, type WebAuthnRemoveResult, type WebAuthnRenameResult, type WebAuthnStepUpResult, bondFloorsText, buildAddAccountUrl, buildSignInUrl, clearTabSession, consumeTabAccountHint, consumeTabAdoptMarker, familyReturnTarget, fetchOcBond, fetchOcLinkedIdentities, handleSudoRequired, installTabFetchInterceptor, installTabLinkDecorator, isSudoAccountMismatch, readTabSession, redirectToSudo, safeReturnTo, tabSessionHeader, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister, writeTabSession };
package/dist/index.d.ts CHANGED
@@ -166,6 +166,30 @@ interface OcLinkedIdentitiesProps {
166
166
  }
167
167
  declare function OcLinkedIdentities({ authOrigin, className, onChange, attestationLink, }: OcLinkedIdentitiesProps): React.ReactElement;
168
168
 
169
+ interface Floors {
170
+ sats_floor: number;
171
+ days_floor: number;
172
+ }
173
+ interface OcBondView extends Floors {
174
+ address: string;
175
+ outpoint: string;
176
+ sats: number;
177
+ confirmed_height: number;
178
+ checked_at: string;
179
+ checked_height: number;
180
+ created_at: string;
181
+ }
182
+ interface OcBondProps {
183
+ authOrigin?: string;
184
+ onChange?: (bond: OcBondView | null) => void;
185
+ className?: string;
186
+ }
187
+ declare function bondFloorsText(f: Floors): string;
188
+ declare function fetchOcBond(opts?: {
189
+ authOrigin?: string;
190
+ }): Promise<OcBondView | null>;
191
+ declare function OcBond({ authOrigin, onChange, className, }: OcBondProps): React.ReactElement;
192
+
169
193
  declare const TAB_SESSION_HEADER = "x-oc-tab-session";
170
194
  declare const TAB_SESSION_STORAGE_KEY = "oc_tab_session";
171
195
  declare const TAB_ACCOUNT_HINT_KEY = "oc-as";
@@ -269,4 +293,4 @@ declare function isSudoAccountMismatch(body: {
269
293
  reason?: string;
270
294
  } | null | undefined): boolean;
271
295
 
272
- export { DEFAULT_CONFIG, DISPLAY_IDENTITY_KINDS, type DisplayIdentity, type DisplayIdentityKind, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, type OcAccountSummary, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcLinkedIdentities, type OcLinkedIdentitiesProps, type OcLinkedIdentity, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type OcSignOutScope, type OcTabSession, type RedirectToSudoArgs, SUDO_ACCOUNT_MISMATCH_MESSAGE, TAB_ACCOUNT_HINT_KEY, TAB_ADOPT_HASH, TAB_SESSION_HEADER, TAB_SESSION_STORAGE_KEY, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterResult, type WebAuthnRegisterStatus, type WebAuthnRemoveResult, type WebAuthnRenameResult, type WebAuthnStepUpResult, buildAddAccountUrl, buildSignInUrl, clearTabSession, consumeTabAccountHint, consumeTabAdoptMarker, familyReturnTarget, fetchOcLinkedIdentities, handleSudoRequired, installTabFetchInterceptor, installTabLinkDecorator, isSudoAccountMismatch, readTabSession, redirectToSudo, safeReturnTo, tabSessionHeader, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister, writeTabSession };
296
+ export { DEFAULT_CONFIG, DISPLAY_IDENTITY_KINDS, type DisplayIdentity, type DisplayIdentityKind, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, type OcAccountSummary, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcBond, type OcBondProps, type OcBondView, OcLinkedIdentities, type OcLinkedIdentitiesProps, type OcLinkedIdentity, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type OcSignOutScope, type OcTabSession, type RedirectToSudoArgs, SUDO_ACCOUNT_MISMATCH_MESSAGE, TAB_ACCOUNT_HINT_KEY, TAB_ADOPT_HASH, TAB_SESSION_HEADER, TAB_SESSION_STORAGE_KEY, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterResult, type WebAuthnRegisterStatus, type WebAuthnRemoveResult, type WebAuthnRenameResult, type WebAuthnStepUpResult, bondFloorsText, buildAddAccountUrl, buildSignInUrl, clearTabSession, consumeTabAccountHint, consumeTabAdoptMarker, familyReturnTarget, fetchOcBond, fetchOcLinkedIdentities, handleSudoRequired, installTabFetchInterceptor, installTabLinkDecorator, isSudoAccountMismatch, readTabSession, redirectToSudo, safeReturnTo, tabSessionHeader, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister, writeTabSession };
package/dist/index.js CHANGED
@@ -1196,6 +1196,7 @@ var signinSize = (px) => `calc(${px}px * var(--oc-signin-scale, 1))`;
1196
1196
  var signinRadius = (px) => `var(--oc-signin-radius, ${px}px)`;
1197
1197
  var SIGNIN_BUTTON_RADIUS = "var(--oc-signin-button-radius, 6px)";
1198
1198
  var SIGNIN_STRONG = "var(--oc-signin-strong, 600)";
1199
+ var SIGNIN_ARROW = "var(--oc-signin-arrow, inline)";
1199
1200
  var DEFAULT_AUTH_ORIGIN = "https://ochk.io";
1200
1201
  async function fetchOcLinkedIdentities(opts) {
1201
1202
  const authOrigin = opts?.authOrigin ?? DEFAULT_AUTH_ORIGIN;
@@ -2371,7 +2372,7 @@ function OcSignIn({
2371
2372
  {
2372
2373
  active: path === "email",
2373
2374
  onClick: () => setPath("email"),
2374
- children: "email"
2375
+ children: "Email"
2375
2376
  }
2376
2377
  ),
2377
2378
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2379,7 +2380,7 @@ function OcSignIn({
2379
2380
  {
2380
2381
  active: path === "wallet",
2381
2382
  onClick: () => setPath("wallet"),
2382
- children: "bitcoin wallet"
2383
+ children: "Bitcoin wallet"
2383
2384
  }
2384
2385
  )
2385
2386
  ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -2388,7 +2389,7 @@ function OcSignIn({
2388
2389
  {
2389
2390
  active: path === "wallet",
2390
2391
  onClick: () => setPath("wallet"),
2391
- children: "bitcoin wallet"
2392
+ children: "Bitcoin wallet"
2392
2393
  }
2393
2394
  ),
2394
2395
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2396,7 +2397,7 @@ function OcSignIn({
2396
2397
  {
2397
2398
  active: path === "email",
2398
2399
  onClick: () => setPath("email"),
2399
- children: "email"
2400
+ children: "Email"
2400
2401
  }
2401
2402
  )
2402
2403
  ] })
@@ -2758,7 +2759,7 @@ function WalletFlow({
2758
2759
  address.trim(),
2759
2760
  ", sign the text below, and paste the signature back here. Nothing is spent."
2760
2761
  ] }),
2761
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: ids.message, children: "message to sign" }),
2762
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: ids.message, children: "Message to sign" }),
2762
2763
  /* @__PURE__ */ jsxRuntime.jsx(
2763
2764
  "textarea",
2764
2765
  {
@@ -2770,10 +2771,10 @@ function WalletFlow({
2770
2771
  style: { ...inputStyle2, resize: "vertical" }
2771
2772
  }
2772
2773
  ),
2773
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void copyMessage(), style: linkButtonStyle, children: copied === "copied" ? "copied" : "copy message" }),
2774
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void copyMessage(), style: linkButtonStyle, children: copied === "copied" ? "Copied" : "Copy message" }),
2774
2775
  copied === "failed" && /* @__PURE__ */ jsxRuntime.jsx(Hint, { children: "Couldn't copy here. Select the text above and copy it." }),
2775
2776
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 14 }, children: [
2776
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: ids.signature, children: "signature" }),
2777
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: ids.signature, children: "Signature" }),
2777
2778
  /* @__PURE__ */ jsxRuntime.jsx(
2778
2779
  "textarea",
2779
2780
  {
@@ -2799,7 +2800,7 @@ function WalletFlow({
2799
2800
  type: "submit",
2800
2801
  disabled: submitting || !pasted.trim(),
2801
2802
  style: submitStyle(submitting || !pasted.trim()),
2802
- children: submitting ? "checking\u2026" : "sign me in \u2192"
2803
+ children: submitting ? "Checking\u2026" : /* @__PURE__ */ jsxRuntime.jsx(Submit, { children: "Sign me in" })
2803
2804
  }
2804
2805
  ),
2805
2806
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2813,7 +2814,7 @@ function WalletFlow({
2813
2814
  setCopied("idle");
2814
2815
  },
2815
2816
  style: linkButtonStyle,
2816
- children: "use a different address"
2817
+ children: "Use a different address"
2817
2818
  }
2818
2819
  )
2819
2820
  ] });
@@ -2821,7 +2822,7 @@ function WalletFlow({
2821
2822
  const noBrowserWallet = wallets !== null && wallets.length === 0;
2822
2823
  return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: signIn, "data-oc-signin-wallet": "", children: [
2823
2824
  /* @__PURE__ */ jsxRuntime.jsx(FlowHeader, { children: "Your wallet signs a short message to prove you hold the address. Nothing is spent and your key never leaves the wallet. Works with browser wallets, or any wallet that can sign a message, like Sparrow." }),
2824
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: ids.address, children: "bitcoin address" }),
2825
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: ids.address, children: "Bitcoin address" }),
2825
2826
  /* @__PURE__ */ jsxRuntime.jsx(
2826
2827
  "input",
2827
2828
  {
@@ -2842,7 +2843,7 @@ function WalletFlow({
2842
2843
  }
2843
2844
  ),
2844
2845
  wallets && wallets.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 12 }, children: [
2845
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: ids.wallet, children: "sign with" }),
2846
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: ids.wallet, children: "Sign with" }),
2846
2847
  /* @__PURE__ */ jsxRuntime.jsx(
2847
2848
  "select",
2848
2849
  {
@@ -2861,7 +2862,7 @@ function WalletFlow({
2861
2862
  type: "submit",
2862
2863
  disabled: submitting || !address.trim(),
2863
2864
  style: submitStyle(submitting || !address.trim()),
2864
- children: submitting ? "waiting for wallet\u2026" : noBrowserWallet ? "get the message to sign \u2192" : "sign in with wallet \u2192"
2865
+ children: submitting ? "Waiting for wallet\u2026" : noBrowserWallet ? /* @__PURE__ */ jsxRuntime.jsx(Submit, { children: "Get the message to sign" }) : /* @__PURE__ */ jsxRuntime.jsx(Submit, { children: "Sign in with wallet" })
2865
2866
  }
2866
2867
  ),
2867
2868
  noBrowserWallet && /* @__PURE__ */ jsxRuntime.jsx(Hint, { children: "No browser wallet found here. You can sign with any wallet and paste." })
@@ -2959,7 +2960,7 @@ function EmailFlow({ authOrigin, add, credentials, onSuccess }) {
2959
2960
  if (stage === "enter") {
2960
2961
  return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: start, "data-oc-signin-email": "", children: [
2961
2962
  /* @__PURE__ */ jsxRuntime.jsx(FlowHeader, { children: "We email you a 6-digit code. No password, and no wallet needed to start. Link a Bitcoin address any time \u2014 that is the identity you hold yourself." }),
2962
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: `${uid}-email`, children: "email" }),
2963
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: `${uid}-email`, children: "Email" }),
2963
2964
  /* @__PURE__ */ jsxRuntime.jsx(
2964
2965
  "input",
2965
2966
  {
@@ -2978,7 +2979,7 @@ function EmailFlow({ authOrigin, add, credentials, onSuccess }) {
2978
2979
  }
2979
2980
  ),
2980
2981
  emailError && /* @__PURE__ */ jsxRuntime.jsx(ErrorLine2, { children: emailError }),
2981
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", disabled: submitting, style: submitStyle(submitting), children: submitting ? "sending\u2026" : "send one-time code \u2192" })
2982
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", disabled: submitting, style: submitStyle(submitting), children: submitting ? "Sending\u2026" : /* @__PURE__ */ jsxRuntime.jsx(Submit, { children: "Send one-time code" }) })
2982
2983
  ] });
2983
2984
  }
2984
2985
  return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: verify, "data-oc-signin-email-verify": "", children: [
@@ -2987,7 +2988,7 @@ function EmailFlow({ authOrigin, add, credentials, onSuccess }) {
2987
2988
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--foreground, #fafafa)" }, children: email }),
2988
2989
  ". It expires in 10 minutes."
2989
2990
  ] }),
2990
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: `${uid}-code`, children: "one-time code" }),
2991
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: `${uid}-code`, children: "One-time code" }),
2991
2992
  /* @__PURE__ */ jsxRuntime.jsx(
2992
2993
  "input",
2993
2994
  {
@@ -3016,7 +3017,7 @@ function EmailFlow({ authOrigin, add, credentials, onSuccess }) {
3016
3017
  type: "submit",
3017
3018
  disabled: submitting || code.length !== 6,
3018
3019
  style: submitStyle(submitting || code.length !== 6),
3019
- children: submitting ? "verifying\u2026" : "verify \xB7 sign me in \u2192"
3020
+ children: submitting ? "Verifying\u2026" : /* @__PURE__ */ jsxRuntime.jsx(Submit, { children: "Verify \xB7 sign me in" })
3020
3021
  }
3021
3022
  ),
3022
3023
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
@@ -3027,7 +3028,7 @@ function EmailFlow({ authOrigin, add, credentials, onSuccess }) {
3027
3028
  onClick: () => void resend(),
3028
3029
  disabled: submitting,
3029
3030
  style: linkButtonStyle,
3030
- children: "send a new code"
3031
+ children: "Send a new code"
3031
3032
  }
3032
3033
  ),
3033
3034
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -3041,12 +3042,18 @@ function EmailFlow({ authOrigin, add, credentials, onSuccess }) {
3041
3042
  setResent(false);
3042
3043
  },
3043
3044
  style: linkButtonStyle,
3044
- children: "use a different email"
3045
+ children: "Use a different email"
3045
3046
  }
3046
3047
  )
3047
3048
  ] })
3048
3049
  ] });
3049
3050
  }
3051
+ function Submit({ children }) {
3052
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3053
+ children,
3054
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: { display: SIGNIN_ARROW }, children: " \u2192" })
3055
+ ] });
3056
+ }
3050
3057
  function FlowHeader({
3051
3058
  label,
3052
3059
  children
@@ -3200,6 +3207,297 @@ function Hint({ children }) {
3200
3207
  }
3201
3208
  );
3202
3209
  }
3210
+ var DEFAULT_AUTH_ORIGIN2 = "https://ochk.io";
3211
+ var MIN_CONFIRMATIONS = 6;
3212
+ var n = (v) => v.toLocaleString("en-US");
3213
+ function bondFloorsText(f) {
3214
+ const sats = f.sats_floor > 0 ? `at least ${n(f.sats_floor)} sats` : "under 1,000 sats";
3215
+ const days = f.days_floor > 0 ? `held ${f.days_floor} days or more` : "held under 7 days";
3216
+ return `${sats}, ${days}`;
3217
+ }
3218
+ var short = (outpoint) => {
3219
+ const [txid = "", vout = ""] = outpoint.split(":");
3220
+ return `${txid.slice(0, 8)}\u2026${txid.slice(-4)}:${vout}`;
3221
+ };
3222
+ var REFUSAL = {
3223
+ invalid_address: "that isn't a Bitcoin address we can read",
3224
+ chain_unavailable: "couldn't read the chain just now \xB7 nothing changed, try again in a minute",
3225
+ sig_invalid: "that signature isn't from this coin's address \xB7 sign with the wallet that holds it",
3226
+ bond_expired: "the message expired \xB7 start again",
3227
+ bond_not_yet_valid: "your device's clock looks wrong",
3228
+ bond_subject_mismatch: "that message was for another account \xB7 start again",
3229
+ bond_malformed: "the signed message changed on the way \xB7 start again",
3230
+ coin_not_found: "that coin doesn't exist on-chain",
3231
+ coin_address_mismatch: "that coin isn't at this address",
3232
+ coin_unconfirmed: "that coin isn't confirmed yet",
3233
+ coin_too_recent: "that coin needs six confirmations first, about an hour",
3234
+ coin_spent: "that coin has been spent \xB7 pick one still in your wallet",
3235
+ coin_backs_another_account: "that coin already backs another orangecheck account",
3236
+ not_authenticated: "your session ended \xB7 sign in again"
3237
+ };
3238
+ var refusal = (reason) => reason && REFUSAL[reason] || "your backing didn't save \xB7 nothing changed, try again";
3239
+ async function fetchOcBond(opts) {
3240
+ const r = await fetch(`${opts?.authOrigin ?? DEFAULT_AUTH_ORIGIN2}/api/auth/bond`, {
3241
+ credentials: "include"
3242
+ });
3243
+ const j = await r.json().catch(() => ({}));
3244
+ if (!r.ok || !j.ok) throw new Error(`http_${r.status}`);
3245
+ return j.bond ?? null;
3246
+ }
3247
+ function OcBond({
3248
+ authOrigin = DEFAULT_AUTH_ORIGIN2,
3249
+ onChange,
3250
+ className
3251
+ }) {
3252
+ const [bond, setBond] = React4__namespace.useState(void 0);
3253
+ const [loadErr, setLoadErr] = React4__namespace.useState(false);
3254
+ const [nonce, setNonce] = React4__namespace.useState(0);
3255
+ const [adding, setAdding] = React4__namespace.useState(false);
3256
+ const [busy, setBusy] = React4__namespace.useState(false);
3257
+ const [err, setErr] = React4__namespace.useState(null);
3258
+ React4__namespace.useEffect(() => {
3259
+ let alive = true;
3260
+ fetchOcBond({ authOrigin }).then(
3261
+ (b) => alive && setBond(b),
3262
+ () => alive && setLoadErr(true)
3263
+ );
3264
+ return () => {
3265
+ alive = false;
3266
+ };
3267
+ }, [authOrigin, nonce]);
3268
+ const call = React4__namespace.useCallback(
3269
+ async (method, body) => {
3270
+ const r = await fetch(`${authOrigin}/api/auth/bond`, {
3271
+ method,
3272
+ credentials: "include",
3273
+ headers: body ? { "Content-Type": "application/json" } : void 0,
3274
+ body: body ? JSON.stringify(body) : void 0
3275
+ });
3276
+ const j = await r.json().catch(() => ({}));
3277
+ return { ok: r.ok && j.ok === true, ...j };
3278
+ },
3279
+ [authOrigin]
3280
+ );
3281
+ async function release() {
3282
+ setBusy(true);
3283
+ setErr(null);
3284
+ const j = await call("DELETE").catch(() => ({ ok: false, reason: "network" }));
3285
+ setBusy(false);
3286
+ if (!j.ok) return setErr(refusal(j.reason));
3287
+ setBond(null);
3288
+ onChange?.(null);
3289
+ }
3290
+ if (loadErr) {
3291
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-oc-bond": "", style: panelStyle("warn"), role: "alert", children: [
3292
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: bodyStyle, children: "couldn't read your backing \xB7 nothing was changed" }),
3293
+ /* @__PURE__ */ jsxRuntime.jsx(
3294
+ "button",
3295
+ {
3296
+ type: "button",
3297
+ style: ghostBtnStyle(false),
3298
+ onClick: () => {
3299
+ setLoadErr(false);
3300
+ setNonce((x) => x + 1);
3301
+ },
3302
+ children: "try again"
3303
+ }
3304
+ )
3305
+ ] });
3306
+ }
3307
+ if (bond === void 0) {
3308
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, "data-oc-bond": "", style: panelStyle(), children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: hintStyle, children: [
3309
+ "> ",
3310
+ "reading your backing\u2026"
3311
+ ] }) });
3312
+ }
3313
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-oc-bond": "", style: { display: "grid", gap: 16 }, children: [
3314
+ bond && !adding ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: panelStyle("success"), children: [
3315
+ /* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { tone: "success", children: "\xA7 backed by bitcoin" }),
3316
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { ...bodyStyle, color: V.foreground }, children: [
3317
+ "apps see a coin ",
3318
+ bondFloorsText(bond),
3319
+ "."
3320
+ ] }),
3321
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: bodyStyle, children: [
3322
+ "coin ",
3323
+ short(bond.outpoint),
3324
+ ", ",
3325
+ n(bond.sats),
3326
+ " sats \xB7 last found unspent at block ",
3327
+ n(bond.checked_height),
3328
+ " \xB7 only you and orangecheck see this line"
3329
+ ] }),
3330
+ /* @__PURE__ */ jsxRuntime.jsxs(FormButtons, { children: [
3331
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: ghostBtnStyle(busy), disabled: busy, onClick: () => setAdding(true), children: "use another coin" }),
3332
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: dangerBtnStyle(busy), disabled: busy, onClick: () => void release(), children: "stop backing" })
3333
+ ] }),
3334
+ err ? /* @__PURE__ */ jsxRuntime.jsx(ErrorLine, { children: err }) : null
3335
+ ] }) : null,
3336
+ !bond && !adding ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: panelStyle(), children: [
3337
+ /* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "\xA7 not backed" }),
3338
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: bodyStyle, children: "your account works everywhere as it is. apps that want to keep out bots can ask for a backed account: one coin you hold, that never moves and that they never see." }),
3339
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: primaryBtnStyle(false), onClick: () => setAdding(true), children: "back it with a coin" })
3340
+ ] }) : null,
3341
+ adding ? /* @__PURE__ */ jsxRuntime.jsx(
3342
+ BondForm,
3343
+ {
3344
+ call,
3345
+ onCancel: () => setAdding(false),
3346
+ onDone: (b) => {
3347
+ setBond(b);
3348
+ setAdding(false);
3349
+ onChange?.(b);
3350
+ }
3351
+ }
3352
+ ) : null,
3353
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: hintStyle, children: [
3354
+ "> ",
3355
+ "apps see that a coin backs you, in rough steps, and a number unique to each app, so they can't compare notes. an app can block that number; getting past it means moving the coin, and a moved coin starts its age again."
3356
+ ] })
3357
+ ] });
3358
+ }
3359
+ function BondForm({
3360
+ call,
3361
+ onCancel,
3362
+ onDone
3363
+ }) {
3364
+ const [address, setAddress] = React4__namespace.useState("");
3365
+ const [coins, setCoins] = React4__namespace.useState(null);
3366
+ const [chosen, setChosen] = React4__namespace.useState("");
3367
+ const [message, setMessage] = React4__namespace.useState(null);
3368
+ const [busy, setBusy] = React4__namespace.useState(false);
3369
+ const [err, setErr] = React4__namespace.useState(null);
3370
+ async function run(fn) {
3371
+ setBusy(true);
3372
+ setErr(null);
3373
+ try {
3374
+ await fn();
3375
+ } catch {
3376
+ setErr(refusal("chain_unavailable"));
3377
+ } finally {
3378
+ setBusy(false);
3379
+ }
3380
+ }
3381
+ const findCoins = () => run(async () => {
3382
+ const j = await call("POST", { action: "coins", address: address.trim() });
3383
+ if (!j.ok) return setErr(refusal(j.reason));
3384
+ const list = j.coins ?? [];
3385
+ setCoins(list);
3386
+ setChosen(list.find((c) => c.age_blocks >= MIN_CONFIRMATIONS)?.outpoint ?? "");
3387
+ });
3388
+ const getMessage = () => run(async () => {
3389
+ const j = await call("POST", { action: "message", address: address.trim(), outpoint: chosen });
3390
+ if (!j.ok || typeof j.message !== "string") return setErr(refusal(j.reason));
3391
+ setMessage(j.message);
3392
+ });
3393
+ const submit = (signature) => run(async () => {
3394
+ const j = await call("POST", { action: "bond", message, signature });
3395
+ if (!j.ok || !j.bond) return setErr(refusal(j.reason));
3396
+ onDone(j.bond);
3397
+ });
3398
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: panelStyle("accent"), "data-oc-bond-form": "", children: [
3399
+ /* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "\xA7 back your account with a coin" }),
3400
+ message ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3401
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: bodyStyle, children: [
3402
+ "sign with the wallet that holds",
3403
+ " ",
3404
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { wordBreak: "break-all", color: V.foreground }, children: address.trim() }),
3405
+ ". the coin doesn't move and nothing is spent."
3406
+ ] }),
3407
+ /* @__PURE__ */ jsxRuntime.jsx(
3408
+ LazyWalletButton,
3409
+ {
3410
+ address: address.trim(),
3411
+ message,
3412
+ showManual: true,
3413
+ onSigned: (sig) => void submit(sig),
3414
+ onError: (e) => setErr(e.message ?? "the wallet refused to sign")
3415
+ }
3416
+ )
3417
+ ] }) : coins ? coins.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { style: bodyStyle, children: "no confirmed coins at that address \xB7 send some sats there and wait for six confirmations, about an hour. the longer a coin sits, the more it says." }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "radiogroup", "aria-label": "pick one coin", style: { display: "grid", gap: 8 }, children: [
3418
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: bodyStyle, children: "pick one coin \xB7 value spread over several coins doesn't add up" }),
3419
+ coins.map((c) => {
3420
+ const young = c.age_blocks < MIN_CONFIRMATIONS;
3421
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3422
+ "label",
3423
+ {
3424
+ style: {
3425
+ ...panelStyle(chosen === c.outpoint ? "accent" : "default"),
3426
+ padding: "0.75rem",
3427
+ display: "flex",
3428
+ gap: 10,
3429
+ alignItems: "flex-start",
3430
+ cursor: young ? "not-allowed" : "pointer",
3431
+ opacity: young ? 0.6 : 1
3432
+ },
3433
+ children: [
3434
+ /* @__PURE__ */ jsxRuntime.jsx(
3435
+ "input",
3436
+ {
3437
+ type: "radio",
3438
+ name: "oc-bond-coin",
3439
+ value: c.outpoint,
3440
+ checked: chosen === c.outpoint,
3441
+ disabled: young,
3442
+ onChange: () => setChosen(c.outpoint)
3443
+ }
3444
+ ),
3445
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "grid", gap: 2, minWidth: 0 }, children: [
3446
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: V.foreground, fontSize: 13 }, children: [
3447
+ n(c.sats),
3448
+ " sats, held ",
3449
+ Math.floor(c.age_blocks / 144),
3450
+ " days"
3451
+ ] }),
3452
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: hintStyle, children: young ? "too recent: needs six confirmations" : `apps would see ${bondFloorsText(c)}` }),
3453
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { ...hintStyle, wordBreak: "break-all" }, children: short(c.outpoint) })
3454
+ ] })
3455
+ ]
3456
+ },
3457
+ c.outpoint
3458
+ );
3459
+ })
3460
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3461
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: bodyStyle, children: "which address holds the coin? use one that holds nothing else of yours: orangecheck learns its address and amount. apps never do." }),
3462
+ /* @__PURE__ */ jsxRuntime.jsx(
3463
+ "input",
3464
+ {
3465
+ style: inputStyle,
3466
+ value: address,
3467
+ onChange: (e) => setAddress(e.target.value),
3468
+ placeholder: "bc1q\u2026",
3469
+ spellCheck: false,
3470
+ autoComplete: "off",
3471
+ "aria-label": "Bitcoin address"
3472
+ }
3473
+ )
3474
+ ] }),
3475
+ err ? /* @__PURE__ */ jsxRuntime.jsx(ErrorLine, { children: err }) : null,
3476
+ /* @__PURE__ */ jsxRuntime.jsxs(FormButtons, { children: [
3477
+ !coins && !message ? /* @__PURE__ */ jsxRuntime.jsx(
3478
+ "button",
3479
+ {
3480
+ type: "button",
3481
+ style: primaryBtnStyle(busy || address.trim().length < 14),
3482
+ disabled: busy || address.trim().length < 14,
3483
+ onClick: () => void findCoins(),
3484
+ children: "find its coins"
3485
+ }
3486
+ ) : null,
3487
+ coins && coins.length > 0 && !message ? /* @__PURE__ */ jsxRuntime.jsx(
3488
+ "button",
3489
+ {
3490
+ type: "button",
3491
+ style: primaryBtnStyle(busy || !chosen),
3492
+ disabled: busy || !chosen,
3493
+ onClick: () => void getMessage(),
3494
+ children: "continue"
3495
+ }
3496
+ ) : null,
3497
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", style: ghostBtnStyle(busy), disabled: busy, onClick: onCancel, children: "cancel" })
3498
+ ] })
3499
+ ] });
3500
+ }
3203
3501
  function resolveAuthOrigin(opts) {
3204
3502
  if (!opts) return resolveConfig(void 0).authOrigin;
3205
3503
  return resolveConfig(opts).authOrigin;
@@ -3439,6 +3737,7 @@ exports.DISPLAY_IDENTITY_KINDS = DISPLAY_IDENTITY_KINDS;
3439
3737
  exports.OcAccountChip = OcAccountChip;
3440
3738
  exports.OcAccountPill = OcAccountPill;
3441
3739
  exports.OcAddressInput = OcAddressInput;
3740
+ exports.OcBond = OcBond;
3442
3741
  exports.OcLinkedIdentities = OcLinkedIdentities;
3443
3742
  exports.OcSessionProvider = OcSessionProvider;
3444
3743
  exports.OcSignIn = OcSignIn;
@@ -3448,12 +3747,14 @@ exports.TAB_ACCOUNT_HINT_KEY = TAB_ACCOUNT_HINT_KEY;
3448
3747
  exports.TAB_ADOPT_HASH = TAB_ADOPT_HASH;
3449
3748
  exports.TAB_SESSION_HEADER = TAB_SESSION_HEADER;
3450
3749
  exports.TAB_SESSION_STORAGE_KEY = TAB_SESSION_STORAGE_KEY;
3750
+ exports.bondFloorsText = bondFloorsText;
3451
3751
  exports.buildAddAccountUrl = buildAddAccountUrl;
3452
3752
  exports.buildSignInUrl = buildSignInUrl;
3453
3753
  exports.clearTabSession = clearTabSession;
3454
3754
  exports.consumeTabAccountHint = consumeTabAccountHint;
3455
3755
  exports.consumeTabAdoptMarker = consumeTabAdoptMarker;
3456
3756
  exports.familyReturnTarget = familyReturnTarget;
3757
+ exports.fetchOcBond = fetchOcBond;
3457
3758
  exports.fetchOcLinkedIdentities = fetchOcLinkedIdentities;
3458
3759
  exports.handleSudoRequired = handleSudoRequired;
3459
3760
  exports.installTabFetchInterceptor = installTabFetchInterceptor;