@yieldfabric/wallet 0.2.5 → 0.2.7

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.cts CHANGED
@@ -2594,8 +2594,13 @@ interface OnboardingWizardProps {
2594
2594
  * linked to. One agreement should be consented to once, on the screen that
2595
2595
  * actually displays it. */
2596
2596
  sponsorshipConsent?: 'wizard' | 'host';
2597
+ /** Host-paid applications never offer personal plans/card capture, including
2598
+ * backend-paid apps whose end-user JWT deliberately has no sponsor tag.
2599
+ * Bank/account opening is deferred to the host's explicit post-consent action.
2600
+ * This controls onboarding UX only; server-side billing gates still apply. */
2601
+ billingMode?: 'automatic' | 'host';
2597
2602
  }
2598
- declare function OnboardingWizard({ initialPathname, chrome, onComplete, branding, invite, platform, onSelectPlatform, sponsorshipConsent, }: OnboardingWizardProps): react_jsx_runtime.JSX.Element;
2603
+ declare function OnboardingWizard({ initialPathname, chrome, onComplete, branding, invite, platform, onSelectPlatform, sponsorshipConsent, billingMode, }: OnboardingWizardProps): react_jsx_runtime.JSX.Element;
2599
2604
 
2600
2605
  /**
2601
2606
  * @file ui/onboarding/OnboardingPolicySection.tsx
package/dist/index.d.ts CHANGED
@@ -2594,8 +2594,13 @@ interface OnboardingWizardProps {
2594
2594
  * linked to. One agreement should be consented to once, on the screen that
2595
2595
  * actually displays it. */
2596
2596
  sponsorshipConsent?: 'wizard' | 'host';
2597
+ /** Host-paid applications never offer personal plans/card capture, including
2598
+ * backend-paid apps whose end-user JWT deliberately has no sponsor tag.
2599
+ * Bank/account opening is deferred to the host's explicit post-consent action.
2600
+ * This controls onboarding UX only; server-side billing gates still apply. */
2601
+ billingMode?: 'automatic' | 'host';
2597
2602
  }
2598
- declare function OnboardingWizard({ initialPathname, chrome, onComplete, branding, invite, platform, onSelectPlatform, sponsorshipConsent, }: OnboardingWizardProps): react_jsx_runtime.JSX.Element;
2603
+ declare function OnboardingWizard({ initialPathname, chrome, onComplete, branding, invite, platform, onSelectPlatform, sponsorshipConsent, billingMode, }: OnboardingWizardProps): react_jsx_runtime.JSX.Element;
2599
2604
 
2600
2605
  /**
2601
2606
  * @file ui/onboarding/OnboardingPolicySection.tsx
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * Source review requires written authorization; see package LICENSE.md and NOTICE.md.
6
6
  * Runtime use requires a separate express license.
7
7
  */
8
- import React54, { createContext, lazy, useContext, useState, useEffect, useRef, useCallback, useMemo, Suspense, useId, Component } from 'react';
8
+ import React39, { createContext, lazy, useContext, useState, useEffect, useRef, useCallback, useMemo, Suspense, useId, Component } from 'react';
9
9
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
10
  import { AvererSdkProvider, useAvererWallet, AvererWebSdk } from '@averer/averer-websdk';
11
11
  import sha3, { keccak256 } from 'js-sha3';
@@ -9985,7 +9985,7 @@ function WizardProvider({
9985
9985
  const [planSelection, setPlanSelection] = useState(
9986
9986
  readOnboardingPlanSelectionHint
9987
9987
  );
9988
- const pendingSponsorshipRef = React54.useRef(
9988
+ const pendingSponsorshipRef = React39.useRef(
9989
9989
  pendingSponsorship
9990
9990
  );
9991
9991
  const stageSponsorship = useCallback((groupId, destination) => {
@@ -11199,8 +11199,8 @@ var DynamicCompleter = ({ sdk, action, onError }) => {
11199
11199
  const ctx = sdk.useDynamicContext();
11200
11200
  const wallet = ctx.primaryWallet;
11201
11201
  const dynamicUser = ctx.user;
11202
- const [done, setDone] = React54.useState(false);
11203
- React54.useEffect(() => {
11202
+ const [done, setDone] = React39.useState(false);
11203
+ React39.useEffect(() => {
11204
11204
  if (done || !wallet?.address) return;
11205
11205
  setDone(true);
11206
11206
  (async () => {
@@ -11625,8 +11625,8 @@ var KycFlow3 = ({ onComplete, onError, instanceId }) => {
11625
11625
  const settings = config?.kyc.settings[providerId];
11626
11626
  const publishableKey = settings?.publishable_key;
11627
11627
  const requiredForCompletion = settings?.required_for_completion ?? false;
11628
- const [stage, setStage] = React54.useState({ kind: "idle" });
11629
- React54.useEffect(() => {
11628
+ const [stage, setStage] = React39.useState({ kind: "idle" });
11629
+ React39.useEffect(() => {
11630
11630
  let cancelled = false;
11631
11631
  (async () => {
11632
11632
  try {
@@ -11650,7 +11650,7 @@ var KycFlow3 = ({ onComplete, onError, instanceId }) => {
11650
11650
  cancelled = true;
11651
11651
  };
11652
11652
  }, []);
11653
- React54.useEffect(() => {
11653
+ React39.useEffect(() => {
11654
11654
  if (stage.kind !== "pending-poll") return;
11655
11655
  let cancelled = false;
11656
11656
  const pollOnce = async () => {
@@ -11902,14 +11902,14 @@ function useIdentityStatusPoll(opts) {
11902
11902
  provider,
11903
11903
  credentialType
11904
11904
  } = opts;
11905
- const [stuckHint, setStuckHint] = React54.useState(false);
11906
- const onVerifiedRef = React54.useRef(onVerified);
11907
- const onRejectedRef = React54.useRef(onRejected);
11908
- React54.useEffect(() => {
11905
+ const [stuckHint, setStuckHint] = React39.useState(false);
11906
+ const onVerifiedRef = React39.useRef(onVerified);
11907
+ const onRejectedRef = React39.useRef(onRejected);
11908
+ React39.useEffect(() => {
11909
11909
  onVerifiedRef.current = onVerified;
11910
11910
  onRejectedRef.current = onRejected;
11911
11911
  }, [onVerified, onRejected]);
11912
- React54.useEffect(() => {
11912
+ React39.useEffect(() => {
11913
11913
  if (!active) {
11914
11914
  setStuckHint(false);
11915
11915
  return;
@@ -12047,12 +12047,12 @@ var KycFlow4 = ({ onComplete, onError, instanceId, subject }) => {
12047
12047
  const groupId = subject?.kind === "group" ? subject.id : void 0;
12048
12048
  const configuredLevel = config?.kyc.settings[providerId]?.level_name?.trim();
12049
12049
  const levelName = configuredLevel || "id-and-liveness";
12050
- const [token, setToken] = React54.useState(null);
12051
- const [stage, setStage] = React54.useState({ kind: "init" });
12052
- const [attempt, setAttempt] = React54.useState(0);
12053
- const submittedRef = React54.useRef(false);
12054
- const applicantIdRef = React54.useRef(void 0);
12055
- React54.useEffect(() => {
12050
+ const [token, setToken] = React39.useState(null);
12051
+ const [stage, setStage] = React39.useState({ kind: "init" });
12052
+ const [attempt, setAttempt] = React39.useState(0);
12053
+ const submittedRef = React39.useRef(false);
12054
+ const applicantIdRef = React39.useRef(void 0);
12055
+ React39.useEffect(() => {
12056
12056
  let cancelled = false;
12057
12057
  submittedRef.current = false;
12058
12058
  (async () => {
@@ -12367,6 +12367,47 @@ function OnboardingChooseMethod({ chrome } = {}) {
12367
12367
  /* @__PURE__ */ jsx("p", { className: "text-[10px] text-text-secondary text-center pt-2", children: messages.legal.agreementText })
12368
12368
  ] }) });
12369
12369
  }
12370
+ function FloatField({
12371
+ label,
12372
+ type,
12373
+ value,
12374
+ onChange,
12375
+ autoComplete,
12376
+ required,
12377
+ minLength,
12378
+ maxLength,
12379
+ adornment,
12380
+ disabled
12381
+ }) {
12382
+ const id = useId();
12383
+ return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
12384
+ /* @__PURE__ */ jsx(
12385
+ "input",
12386
+ {
12387
+ id,
12388
+ type,
12389
+ required,
12390
+ minLength,
12391
+ maxLength,
12392
+ autoComplete,
12393
+ placeholder: " ",
12394
+ value,
12395
+ disabled,
12396
+ onChange: (e) => onChange(e.target.value),
12397
+ className: "\n peer w-full bg-transparent border-0 border-b border-border-default\n rounded-none px-0 pt-4 pb-1.5 text-[14px] text-text-primary\n focus:outline-none focus:border-border-strong transition-colors\n disabled:opacity-60 disabled:cursor-not-allowed\n "
12398
+ }
12399
+ ),
12400
+ /* @__PURE__ */ jsx(
12401
+ "label",
12402
+ {
12403
+ htmlFor: id,
12404
+ className: "\n absolute left-0 pointer-events-none transition-all duration-200\n text-[10px] text-text-secondary top-0\n peer-placeholder-shown:text-[13px] peer-placeholder-shown:top-4\n peer-focus:text-[10px] peer-focus:top-0 peer-focus:text-text-secondary\n ",
12405
+ children: label
12406
+ }
12407
+ ),
12408
+ adornment && /* @__PURE__ */ jsx("span", { className: "absolute right-0 top-4 pointer-events-none", children: adornment })
12409
+ ] });
12410
+ }
12370
12411
  init_authService();
12371
12412
  init_tokenManager();
12372
12413
  init_ProviderConfigContext();
@@ -12604,44 +12645,6 @@ function OnboardingEmailSignup({ chrome } = {}) {
12604
12645
  ] })
12605
12646
  ] }) });
12606
12647
  }
12607
- function FloatField({
12608
- label,
12609
- type,
12610
- value,
12611
- onChange,
12612
- autoComplete,
12613
- required,
12614
- minLength,
12615
- maxLength,
12616
- adornment,
12617
- disabled
12618
- }) {
12619
- return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
12620
- /* @__PURE__ */ jsx(
12621
- "input",
12622
- {
12623
- type,
12624
- required,
12625
- minLength,
12626
- maxLength,
12627
- autoComplete,
12628
- placeholder: " ",
12629
- value,
12630
- disabled,
12631
- onChange: (e) => onChange(e.target.value),
12632
- className: "\n peer w-full bg-transparent border-0 border-b border-border-default\n rounded-none px-0 pt-4 pb-1.5 text-[14px] text-text-primary\n focus:outline-none focus:border-border-strong transition-colors\n disabled:opacity-60 disabled:cursor-not-allowed\n "
12633
- }
12634
- ),
12635
- /* @__PURE__ */ jsx(
12636
- "span",
12637
- {
12638
- className: "\n absolute left-0 pointer-events-none transition-all duration-200\n text-[10px] text-text-secondary top-0\n peer-placeholder-shown:text-[13px] peer-placeholder-shown:top-4\n peer-focus:text-[10px] peer-focus:top-0 peer-focus:text-text-secondary\n ",
12639
- children: label
12640
- }
12641
- ),
12642
- adornment && /* @__PURE__ */ jsx("span", { className: "absolute right-0 top-4 pointer-events-none", children: adornment })
12643
- ] });
12644
- }
12645
12648
  init_authService();
12646
12649
  init_onboardingClient();
12647
12650
  function EmailVerify({ chrome } = {}) {
@@ -12802,7 +12805,7 @@ function EmailVerify({ chrome } = {}) {
12802
12805
  /* @__PURE__ */ jsx(ProgressRail, { phase, verified: !!status?.verified || phase === "success" }),
12803
12806
  phase === "loading" && !status ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-border-default bg-surface-alt/70 p-4 text-center text-[12px] text-text-secondary", children: "Checking email status..." }) : phase === "success" ? /* @__PURE__ */ jsx(SuccessPanel, { notice }) : status?.is_synthetic ? /* @__PURE__ */ jsxs("form", { onSubmit: submitRealEmail, className: "space-y-4", children: [
12804
12807
  /* @__PURE__ */ jsx(
12805
- FloatField2,
12808
+ FloatField,
12806
12809
  {
12807
12810
  label: "Email",
12808
12811
  type: "email",
@@ -12925,38 +12928,6 @@ function CodeField({
12925
12928
  }
12926
12929
  );
12927
12930
  }
12928
- function FloatField2({
12929
- label,
12930
- type,
12931
- value,
12932
- onChange,
12933
- autoComplete,
12934
- disabled,
12935
- required
12936
- }) {
12937
- return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
12938
- /* @__PURE__ */ jsx(
12939
- "input",
12940
- {
12941
- type,
12942
- required,
12943
- autoComplete,
12944
- placeholder: " ",
12945
- value,
12946
- disabled,
12947
- onChange: (e) => onChange(e.target.value),
12948
- className: "\n peer w-full bg-transparent border-0 border-b border-border-default\n rounded-none px-0 pt-4 pb-1.5 text-[14px] text-text-primary\n focus:outline-none focus:border-border-strong transition-colors\n disabled:opacity-60\n "
12949
- }
12950
- ),
12951
- /* @__PURE__ */ jsx(
12952
- "span",
12953
- {
12954
- className: "\n absolute left-0 pointer-events-none transition-all duration-200\n text-[10px] text-text-secondary top-0\n peer-placeholder-shown:text-[13px] peer-placeholder-shown:top-4\n peer-focus:text-[10px] peer-focus:top-0 peer-focus:text-text-secondary\n ",
12955
- children: label
12956
- }
12957
- )
12958
- ] });
12959
- }
12960
12931
  function friendlyEmailError(err, action) {
12961
12932
  const message = err instanceof Error ? err.message : String(err);
12962
12933
  if (message.includes("email delivery unavailable") || message.includes("503")) {
@@ -16047,7 +16018,7 @@ function Field({
16047
16018
  value,
16048
16019
  copyable
16049
16020
  }) {
16050
- const [copied, setCopied] = React54.useState(false);
16021
+ const [copied, setCopied] = React39.useState(false);
16051
16022
  return /* @__PURE__ */ jsxs("div", { children: [
16052
16023
  /* @__PURE__ */ jsx("p", { className: "text-[10px] uppercase tracking-wider text-text-secondary", children: label }),
16053
16024
  /* @__PURE__ */ jsxs("div", { className: "mt-0.5 flex items-center gap-2", children: [
@@ -16111,14 +16082,16 @@ var STAGE_COPY = {
16111
16082
  not_applicable: { title: "Finishing up", body: "" }
16112
16083
  };
16113
16084
  var AccountOpeningPanel = ({ onContinue, continueLabel = "Continue" }) => {
16114
- const [status, setStatus] = React54.useState(null);
16115
- const [impatient, setImpatient] = React54.useState(false);
16116
- const activationStarted = React54.useRef(false);
16117
- const onContinueRef = React54.useRef(onContinue);
16118
- React54.useEffect(() => {
16085
+ const [status, setStatus] = React39.useState(null);
16086
+ const [impatient, setImpatient] = React39.useState(false);
16087
+ const [unavailable, setUnavailable] = React39.useState(false);
16088
+ const [attempt, setAttempt] = React39.useState(0);
16089
+ const activationStarted = React39.useRef(false);
16090
+ const onContinueRef = React39.useRef(onContinue);
16091
+ React39.useEffect(() => {
16119
16092
  onContinueRef.current = onContinue;
16120
16093
  }, [onContinue]);
16121
- React54.useEffect(() => {
16094
+ React39.useEffect(() => {
16122
16095
  let cancelled = false;
16123
16096
  let timer;
16124
16097
  const startedAt = Date.now();
@@ -16126,8 +16099,9 @@ var AccountOpeningPanel = ({ onContinue, continueLabel = "Continue" }) => {
16126
16099
  if (cancelled) return;
16127
16100
  let terminal = false;
16128
16101
  try {
16129
- const next = await fetchAccountOpeningStatus();
16102
+ const next = await withDeadline(fetchAccountOpeningStatus(), "Account opening status");
16130
16103
  if (cancelled) return;
16104
+ setUnavailable(false);
16131
16105
  setStatus(next);
16132
16106
  if (next.status === "not_started") {
16133
16107
  onContinueRef.current();
@@ -16144,6 +16118,8 @@ var AccountOpeningPanel = ({ onContinue, continueLabel = "Continue" }) => {
16144
16118
  );
16145
16119
  }
16146
16120
  } catch {
16121
+ if (cancelled) return;
16122
+ setUnavailable(true);
16147
16123
  }
16148
16124
  if (cancelled || terminal) return;
16149
16125
  const waited = Date.now() - startedAt;
@@ -16155,8 +16131,20 @@ var AccountOpeningPanel = ({ onContinue, continueLabel = "Continue" }) => {
16155
16131
  cancelled = true;
16156
16132
  if (timer !== void 0) window.clearTimeout(timer);
16157
16133
  };
16158
- }, []);
16159
- if (!status) return null;
16134
+ }, [attempt]);
16135
+ if (unavailable || !status) {
16136
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4 text-center", role: "status", "aria-live": "polite", children: [
16137
+ /* @__PURE__ */ jsx("p", { children: unavailable ? "We couldn\u2019t check your account right now." : "Checking your account\u2026" }),
16138
+ unavailable && /* @__PURE__ */ jsxs(Fragment, { children: [
16139
+ /* @__PURE__ */ jsx("p", { className: "text-[12px] text-text-secondary", children: "You can try again or continue. Your account details will be available when setup finishes." }),
16140
+ /* @__PURE__ */ jsx("button", { type: "button", className: "min-h-[44px] w-full rounded-lg bg-cta px-4 py-2.5 text-on-cta", onClick: () => {
16141
+ setUnavailable(false);
16142
+ setAttempt((value) => value + 1);
16143
+ }, children: "Try again" }),
16144
+ /* @__PURE__ */ jsx("button", { type: "button", className: "min-h-[44px] w-full", onClick: onContinue, children: continueLabel })
16145
+ ] })
16146
+ ] });
16147
+ }
16160
16148
  if (status.status === "ready" && status.account) {
16161
16149
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", role: "status", "aria-live": "polite", children: [
16162
16150
  /* @__PURE__ */ jsxs("div", { children: [
@@ -16214,13 +16202,13 @@ var AccountOpeningPanel = ({ onContinue, continueLabel = "Continue" }) => {
16214
16202
  init_authService();
16215
16203
  var WALLET_AWAKENING_MS = 1100;
16216
16204
  var TOTAL_MS = 3e3;
16217
- function OnboardingWelcomeMoment({ chrome } = {}) {
16205
+ function OnboardingWelcomeMoment({ chrome, deferAccountOpening = false } = {}) {
16218
16206
  const navigate = useWizardNavigate();
16219
16207
  const { messages } = useBranding();
16220
16208
  const [name, setName] = useState("");
16221
16209
  const [walletShort, setWalletShort] = useState(null);
16222
16210
  const [phase, setPhase] = useState("wallet");
16223
- const [accountOpened, setAccountOpened] = useState(false);
16211
+ const [accountOpened, setAccountOpened] = useState(deferAccountOpening);
16224
16212
  useEffect(() => {
16225
16213
  let cancelled = false;
16226
16214
  (async () => {
@@ -17392,7 +17380,8 @@ function OnboardingWizard({
17392
17380
  invite,
17393
17381
  platform,
17394
17382
  onSelectPlatform,
17395
- sponsorshipConsent = "wizard"
17383
+ sponsorshipConsent = "wizard",
17384
+ billingMode = "automatic"
17396
17385
  }) {
17397
17386
  return /* @__PURE__ */ jsx(BrandingProvider, { branding, children: /* @__PURE__ */ jsx(
17398
17387
  WizardProvider,
@@ -17406,7 +17395,8 @@ function OnboardingWizard({
17406
17395
  {
17407
17396
  chrome,
17408
17397
  onSelectPlatform,
17409
- sponsorshipConsent
17398
+ sponsorshipConsent,
17399
+ billingMode
17410
17400
  }
17411
17401
  )
17412
17402
  }
@@ -17436,7 +17426,8 @@ function gateToPath(status) {
17436
17426
  function WizardRouter({
17437
17427
  chrome,
17438
17428
  onSelectPlatform,
17439
- sponsorshipConsent = "wizard"
17429
+ sponsorshipConsent = "wizard",
17430
+ billingMode = "automatic"
17440
17431
  }) {
17441
17432
  const pathname = useWizardPathname();
17442
17433
  const { config } = useProviderConfig();
@@ -17445,7 +17436,7 @@ function WizardRouter({
17445
17436
  const effectivePlatform = wizardPlatform ?? config?.platform?.group_id ?? pendingSponsorship?.groupId;
17446
17437
  const primaryKycId = config?.kyc.primary;
17447
17438
  const identityRequired = !!(primaryKycId && config?.kyc.enabled.includes(primaryKycId) && config?.kyc.settings[primaryKycId]?.required_for_completion);
17448
- const planApplicable = !effectivePlatform && !personalSessionHasGroupPayer();
17439
+ const planApplicable = billingMode !== "host" && !effectivePlatform && !personalSessionHasGroupPayer();
17449
17440
  const allowedIdentityProviders = userIdentityStatusScopes(config);
17450
17441
  const gate = useOnboardingState(
17451
17442
  identityRequired,
@@ -17456,11 +17447,14 @@ function WizardRouter({
17456
17447
  identityRequired && primaryKycVerifiesEmail(config)
17457
17448
  );
17458
17449
  const hostOwnsSponsorshipConsent = sponsorshipConsent === "host";
17459
- React54.useEffect(() => {
17450
+ React39.useEffect(() => {
17460
17451
  if (hostOwnsSponsorshipConsent && pendingSponsorship) {
17461
17452
  discardSponsorship();
17462
17453
  }
17463
17454
  }, [hostOwnsSponsorshipConsent, pendingSponsorship, discardSponsorship]);
17455
+ if (!planApplicable && ["/onboarding", "/onboarding/pricing", "/onboarding/plan", "/onboarding/card"].includes(pathname)) {
17456
+ return /* @__PURE__ */ jsx(WizardRedirect, { to: "/onboarding/choose", replace: true });
17457
+ }
17464
17458
  const sponsorshipContext = !hostOwnsSponsorshipConsent && !!effectivePlatform && (pendingSponsorship !== null || authService.isAuthenticated() && !authService.hasExactSponsoredSession(effectivePlatform));
17465
17459
  const exactSponsorship = !!effectivePlatform && authService.hasExactSponsoredSession(effectivePlatform);
17466
17460
  const gateCanAnswer = authService.isAuthenticated() && !!tokenManager.getAccessToken();
@@ -17544,7 +17538,7 @@ function WizardRouter({
17544
17538
  }
17545
17539
  );
17546
17540
  if (pathname === "/onboarding/welcome")
17547
- return /* @__PURE__ */ jsx(OnboardingWelcomeMoment, { chrome });
17541
+ return /* @__PURE__ */ jsx(OnboardingWelcomeMoment, { chrome, deferAccountOpening: billingMode === "host" });
17548
17542
  if (pathname === "/onboarding")
17549
17543
  return /* @__PURE__ */ jsx(SelectPlan, { chrome, platformPlansAvailable: !!onSelectPlatform });
17550
17544
  if (pathname.startsWith("/onboarding/"))
@@ -17672,7 +17666,7 @@ function builtinProviderDisplayName(id) {
17672
17666
  }
17673
17667
  }
17674
17668
  function useProviderDisplayName(config) {
17675
- return React54.useCallback(
17669
+ return React39.useCallback(
17676
17670
  (id) => {
17677
17671
  const labelled = config?.kyc?.settings?.[id]?.label ?? config?.auth?.settings?.[id]?.label;
17678
17672
  const trimmed = typeof labelled === "string" ? labelled.trim() : "";
@@ -18008,7 +18002,7 @@ var OnboardingPolicySection = ({
18008
18002
  )
18009
18003
  ] }) }) : /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
18010
18004
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-2.5 gap-y-1.5 rounded-lg border border-primary/20 bg-primary/[0.04] px-3.5 py-2.5", children: [
18011
- journeySteps.map((step, i) => /* @__PURE__ */ jsxs(React54.Fragment, { children: [
18005
+ journeySteps.map((step, i) => /* @__PURE__ */ jsxs(React39.Fragment, { children: [
18012
18006
  i > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-[12px] text-text-muted/60", children: "\u203A" }),
18013
18007
  /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5", children: [
18014
18008
  /* @__PURE__ */ jsx("span", { className: "flex h-4 w-4 items-center justify-center rounded-full bg-primary/20 text-[9px] font-bold text-primary", children: i + 1 }),
@@ -21196,11 +21190,11 @@ var SaveButton = ({ onClick, busy, disabled, saved = false, classNames }) => /*
21196
21190
  );
21197
21191
  function useSavedFlash(ms = 1800) {
21198
21192
  const [saved, setSaved] = useState(false);
21199
- const timer = React54.useRef(null);
21193
+ const timer = React39.useRef(null);
21200
21194
  useEffect(() => () => {
21201
21195
  if (timer.current) clearTimeout(timer.current);
21202
21196
  }, []);
21203
- const flash = React54.useCallback(() => {
21197
+ const flash = React39.useCallback(() => {
21204
21198
  setSaved(true);
21205
21199
  if (timer.current) clearTimeout(timer.current);
21206
21200
  timer.current = setTimeout(() => setSaved(false), ms);
@@ -24953,17 +24947,17 @@ function ActiveEnvironmentBadge({
24953
24947
  configuredTestChains
24954
24948
  );
24955
24949
  const canChoose = Boolean(activeChainId && options.length > 1);
24956
- const [busyChainId, setBusyChainId] = React54.useState(null);
24957
- const [pendingLiveChainId, setPendingLiveChainId] = React54.useState(null);
24958
- const [error, setError] = React54.useState(null);
24959
- const switchingRef = React54.useRef(false);
24960
- const confirmLiveRef = React54.useRef(null);
24961
- const liveWarningId = React54.useId();
24950
+ const [busyChainId, setBusyChainId] = React39.useState(null);
24951
+ const [pendingLiveChainId, setPendingLiveChainId] = React39.useState(null);
24952
+ const [error, setError] = React39.useState(null);
24953
+ const switchingRef = React39.useRef(false);
24954
+ const confirmLiveRef = React39.useRef(null);
24955
+ const liveWarningId = React39.useId();
24962
24956
  const label = modeLabel(environment.mode);
24963
24957
  const modeCounts = { test: 0, live: 0, unknown: 0 };
24964
24958
  for (const option of options) modeCounts[option.mode] += 1;
24965
24959
  const pendingLive = options.find((option) => option.chainId === pendingLiveChainId) ?? null;
24966
- React54.useEffect(() => {
24960
+ React39.useEffect(() => {
24967
24961
  if (pendingLiveChainId) confirmLiveRef.current?.focus();
24968
24962
  }, [pendingLiveChainId]);
24969
24963
  async function switchTo(option) {
@@ -25723,7 +25717,7 @@ function WalletMenu({
25723
25717
  const secondaryItems = items.filter((item) => item.placement === "secondary");
25724
25718
  const activeActor = actors.find((actor) => actor.active) ?? actors[0];
25725
25719
  const userName = identity.name ?? "You";
25726
- const renderCard = (cardItems) => /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-[24px] border border-border-light bg-raised shadow-sm", children: cardItems.map((item, index) => /* @__PURE__ */ jsxs(React54.Fragment, { children: [
25720
+ const renderCard = (cardItems) => /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-[24px] border border-border-light bg-raised shadow-sm", children: cardItems.map((item, index) => /* @__PURE__ */ jsxs(React39.Fragment, { children: [
25727
25721
  index > 0 && /* @__PURE__ */ jsx("div", { className: "mx-4 border-t border-border-light" }),
25728
25722
  /* @__PURE__ */ jsx(
25729
25723
  WalletMenuRow,
@@ -25973,7 +25967,7 @@ function ActorsPane({
25973
25967
  error && /* @__PURE__ */ jsx(ErrorBanner, { children: error }),
25974
25968
  /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-[22px] border border-border-light bg-raised", children: actors.map((actor, index) => {
25975
25969
  const ActorIcon = actor.icon;
25976
- return /* @__PURE__ */ jsxs(React54.Fragment, { children: [
25970
+ return /* @__PURE__ */ jsxs(React39.Fragment, { children: [
25977
25971
  index > 0 && /* @__PURE__ */ jsx("div", { className: "mx-4 border-t border-border-light" }),
25978
25972
  /* @__PURE__ */ jsxs(
25979
25973
  "button",
@@ -27968,8 +27962,9 @@ var BillingCenter = ({ dense = false }) => {
27968
27962
  setLoadError(null);
27969
27963
  try {
27970
27964
  const s = await billingService.getMyBilling();
27965
+ setNotConfigured(s === null);
27971
27966
  if (s === null) {
27972
- setNotConfigured(true);
27967
+ setSummary(null);
27973
27968
  } else {
27974
27969
  setSummary(s);
27975
27970
  setItems(s.recent_line_items);
@@ -27983,7 +27978,7 @@ var BillingCenter = ({ dense = false }) => {
27983
27978
  }, []);
27984
27979
  useEffect(() => {
27985
27980
  void load();
27986
- void billingService.getGasPricing().then(setPricing);
27981
+ void billingService.getGasPricing().then(setPricing).catch(() => setPricing(null));
27987
27982
  }, [load]);
27988
27983
  useEffect(() => {
27989
27984
  const reloadAfterCheckout = () => void load();
@@ -28028,18 +28023,6 @@ var BillingCenter = ({ dense = false }) => {
28028
28023
  }
28029
28024
  }, [load]);
28030
28025
  const outerClass = dense ? "px-1 py-2" : "mx-auto max-w-5xl px-4 py-6";
28031
- if (notConfigured) {
28032
- return /* @__PURE__ */ jsxs("div", { className: outerClass, children: [
28033
- !dense && /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
28034
- /* @__PURE__ */ jsxs("h1", { className: "text-lg font-semibold text-text-primary max-sm:sr-only", children: [
28035
- "Usage & billing",
28036
- !isLiveMode() && paymentsUrlMap() && /* @__PURE__ */ jsx("span", { className: "ml-2 align-middle inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-semibold uppercase tracking-wider bg-amber-500/15 text-amber-600 ring-1 ring-amber-500/40", children: "Test mode" })
28037
- ] }),
28038
- /* @__PURE__ */ jsx("p", { className: "text-sm text-text-muted", children: "Metered AI and on-chain usage." })
28039
- ] }),
28040
- /* @__PURE__ */ jsx("div", { className: `${CARD} px-4 py-10 text-center text-[13px] text-text-muted`, children: "Billing is not enabled on this deployment." })
28041
- ] });
28042
- }
28043
28026
  const totals = summary?.period_totals ?? [];
28044
28027
  const payableTotal = totals.reduce((acc, t) => acc + t.amount_usd_micros, 0);
28045
28028
  const personalTotal = summary?.spend?.period_usd_micros ?? payableTotal;
@@ -28115,6 +28098,18 @@ var BillingCenter = ({ dense = false }) => {
28115
28098
  const creditExhausted = prepaidCreditsEnabled && creditPlanId != null && creditBalanceMicros <= 0;
28116
28099
  const creditLow = prepaidCreditsEnabled && creditPlanId != null && creditBalanceMicros > 0 && creditGrantMicros != null && creditBalanceMicros < creditGrantMicros * 0.15;
28117
28100
  const recoveryAction = summary ? billingRecoveryAction(summary) : null;
28101
+ if (notConfigured) {
28102
+ return /* @__PURE__ */ jsxs("div", { className: outerClass, children: [
28103
+ !dense && /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
28104
+ /* @__PURE__ */ jsxs("h1", { className: "text-lg font-semibold text-text-primary max-sm:sr-only", children: [
28105
+ "Usage & billing",
28106
+ !isLiveMode() && paymentsUrlMap() && /* @__PURE__ */ jsx("span", { className: "ml-2 align-middle inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-semibold uppercase tracking-wider bg-amber-500/15 text-amber-600 ring-1 ring-amber-500/40", children: "Test mode" })
28107
+ ] }),
28108
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-text-muted", children: "Metered AI and on-chain usage." })
28109
+ ] }),
28110
+ /* @__PURE__ */ jsx("div", { className: `${CARD} px-4 py-10 text-center text-[13px] text-text-muted`, children: "Billing is not enabled on this deployment." })
28111
+ ] });
28112
+ }
28118
28113
  return /* @__PURE__ */ jsxs("div", { className: outerClass, children: [
28119
28114
  !dense && /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
28120
28115
  /* @__PURE__ */ jsxs("h1", { className: "text-lg font-semibold text-text-primary max-sm:sr-only", children: [
@@ -29796,25 +29791,25 @@ function BusinessVerificationSection({
29796
29791
  initialStatus
29797
29792
  }) {
29798
29793
  const { config } = useProviderConfig();
29799
- const [status, setStatus] = React54.useState(initialStatus ?? "not_required");
29800
- const [flowInstance, setFlowInstance] = React54.useState(null);
29801
- const [error, setError] = React54.useState(null);
29802
- const [busy, setBusy] = React54.useState(false);
29803
- const kybInstances = React54.useMemo(
29794
+ const [status, setStatus] = React39.useState(initialStatus ?? "not_required");
29795
+ const [flowInstance, setFlowInstance] = React39.useState(null);
29796
+ const [error, setError] = React39.useState(null);
29797
+ const [busy, setBusy] = React39.useState(false);
29798
+ const kybInstances = React39.useMemo(
29804
29799
  () => (config?.kyc.enabled ?? []).filter(
29805
29800
  (id) => config?.kyc.settings[id]?.subject === "group"
29806
29801
  ),
29807
29802
  [config]
29808
29803
  );
29809
29804
  const entityDefault = config?.kyc.entity_default_profile ?? null;
29810
- const refreshStatus = React54.useCallback(async () => {
29805
+ const refreshStatus = React39.useCallback(async () => {
29811
29806
  try {
29812
29807
  const s = await getIdentityStatus({ groupId });
29813
29808
  setStatus(s.status === "unverified" ? "unverified" : s.status);
29814
29809
  } catch {
29815
29810
  }
29816
29811
  }, [groupId]);
29817
- React54.useEffect(() => {
29812
+ React39.useEffect(() => {
29818
29813
  if (initialStatus !== void 0) setStatus(initialStatus);
29819
29814
  }, [initialStatus]);
29820
29815
  const startFlow = async (bindFirst) => {
@@ -31002,7 +30997,7 @@ var IncomingPaymentsInbox = ({
31002
30997
  ...hookOptions
31003
30998
  }) => {
31004
30999
  const inbox = useIncomingPayments(hookOptions);
31005
- const allPayments = React54.useMemo(
31000
+ const allPayments = React39.useMemo(
31006
31001
  () => [
31007
31002
  ...inbox.payments,
31008
31003
  ...inbox.contracts.flatMap((c) => c.payments ?? [])
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yieldfabric/wallet",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Reusable YieldFabric wallet — login, signing, profile, and key management",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "YieldFabric Technologies Ltd",
@@ -112,6 +112,6 @@
112
112
  "axios": "1.20.0",
113
113
  "uuid": "11.1.1",
114
114
  "esbuild": "0.28.1",
115
- "sharp": "0.35.4"
115
+ "sharp": "0.35.5"
116
116
  }
117
117
  }