@capxul/sdk-react 3.2.0 → 4.0.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.
@@ -40,11 +40,11 @@ function useCapxulClientOrNull() {
40
40
  const capxulKeys = {
41
41
  root: ["capxul"],
42
42
  profile: ["capxul", "profile"],
43
- usernameAvailability: (username) => [
43
+ handleAvailability: (handle) => [
44
44
  "capxul",
45
45
  "profile",
46
- "username-availability",
47
- username
46
+ "handle-availability",
47
+ handle
48
48
  ],
49
49
  account: ["capxul", "account"],
50
50
  provisioning: ["capxul", "provisioning"],
package/dist/index.d.mts CHANGED
@@ -220,7 +220,7 @@ type ProfileDraft = {
220
220
  readonly displayName: string;
221
221
  readonly country: string;
222
222
  readonly withdrawalAddress: string;
223
- readonly username?: string;
223
+ readonly handle?: string;
224
224
  readonly payoutAddresses?: readonly PayoutDraftEntry[];
225
225
  };
226
226
  type OrganizationDraft = {
@@ -295,23 +295,23 @@ declare function acknowledgeOnboardingDestination(destination: {
295
295
  }, ownerId: string): boolean;
296
296
  declare function clearOnboardingJourney(): void;
297
297
  //#endregion
298
- //#region src/headless/onboarding/use-capxul-username-availability.d.ts
299
- type UsernameAvailability = {
298
+ //#region src/headless/onboarding/use-capxul-handle-availability.d.ts
299
+ type HandleAvailability = {
300
300
  readonly available: boolean;
301
301
  readonly normalized: string;
302
302
  };
303
- type UseCapxulUsernameAvailabilityReturn = UseQueryResult<UsernameAvailability, CapxulError>;
303
+ type UseCapxulHandleAvailabilityReturn = UseQueryResult<HandleAvailability, CapxulError>;
304
304
  /**
305
- * #1062: debounced availability probe for the username the user is typing.
305
+ * #1062: debounced availability probe for the handle the user is typing.
306
306
  * Disabled until the candidate reaches the 3-character floor; a malformed or
307
307
  * reserved candidate surfaces as the query's error (INVALID_INPUT with the
308
- * boundary's message), not as `available: false` — only a username someone
308
+ * boundary's message), not as `available: false` — only a handle someone
309
309
  * else owns is "taken".
310
310
  */
311
- declare function useCapxulUsernameAvailability(username: string, options?: {
311
+ declare function useCapxulHandleAvailability(handle: string, options?: {
312
312
  readonly enabled?: boolean;
313
313
  readonly debounceMs?: number;
314
- }): UseCapxulUsernameAvailabilityReturn;
314
+ }): UseCapxulHandleAvailabilityReturn;
315
315
  //#endregion
316
316
  //#region src/headless/media/use-capxul-image-upload.d.ts
317
317
  type ImageUploadTarget = {
@@ -622,16 +622,17 @@ declare const CapxulActivity: typeof Root$5 & {
622
622
  };
623
623
  //#endregion
624
624
  //#region src/headless/send-money/use-recipient-resolution.d.ts
625
- type SendMoneyRecipientMethod = "username" | "email-address";
626
- type SendMoneyRecipientStatus = "empty" | "checking" | "found" | "not-found" | "failed";
625
+ type SendMoneyRecipientStatus = "empty" | "invalid" | "checking" | "known-party" | "new-email" | "external-warning" | "external-ready" | "not-found" | "failed";
627
626
  interface SendMoneyRecipientSlice {
628
- readonly method: SendMoneyRecipientMethod;
629
- readonly setMethod: (method: SendMoneyRecipientMethod) => void;
630
627
  readonly value: string;
631
628
  readonly change: (text: string) => void;
632
- /** ADR-0023 R1: the status IS the failure code; the app owns the sentence. */
633
629
  readonly status: SendMoneyRecipientStatus;
634
630
  readonly label: string | null;
631
+ readonly kind: "person" | "organization" | "external_address" | "unresolved" | null;
632
+ readonly isCapxulAccount: boolean | null;
633
+ readonly publicValue: string | null;
634
+ readonly requiresAcknowledgement: boolean;
635
+ readonly acknowledgeExternalAddress: () => void;
635
636
  }
636
637
  //#endregion
637
638
  //#region src/headless/send-money/use-send-money.d.ts
@@ -997,7 +998,7 @@ declare const CapxulPayrollRun: typeof Root & {
997
998
  declare const capxulKeys: {
998
999
  root: readonly ["capxul"];
999
1000
  profile: readonly ["capxul", "profile"];
1000
- usernameAvailability: (username: string) => readonly ["capxul", "profile", "username-availability", string];
1001
+ handleAvailability: (handle: string) => readonly ["capxul", "profile", "handle-availability", string];
1001
1002
  account: readonly ["capxul", "account"];
1002
1003
  provisioning: readonly ["capxul", "provisioning"];
1003
1004
  binding: readonly ["capxul", "binding"];
@@ -1023,4 +1024,4 @@ declare const capxulKeys: {
1023
1024
  payment: (paymentId: string | undefined) => readonly ["capxul", "payments", string];
1024
1025
  };
1025
1026
  //#endregion
1026
- export { type AccountFailure, type AccountProgress, type ActionResult, type ActivityDetailSlice, type ActivityExportSlice, type ActivityFilterValues, type ActivityFiltersSlice, type ActivityLoadMoreSlice, type ActivityReceipt, type ActivityRow, type ActivityRowsSlice, type ActivitySearchSlice, type ActivitySummarySlice, type AuthenticatedState, type AuthenticationSlots, type CanReason, CapxulActivity, type CapxulActivityProps, type CapxulAuth, CapxulAuthenticationController, type CapxulBootstrapState, type CapxulBootstrapStatus, CapxulContacts, type CapxulContactsProps, CapxulDashboardAccess, type CapxulDashboardAccessProps, CapxulOnboardingController, CapxulOrgMember, type CapxulOrgMemberProps, CapxulPayroll, type CapxulPayrollProps, CapxulPayrollRun, type CapxulPayrollRunBlockedReason, type CapxulPayrollRunProps, CapxulProvider, type CapxulProviderProps, type CapxulSend, CapxulSendMoney, type CapxulSendMoneyBlockedReason, type CapxulSendMoneyProps, type Contact, type ContactRelationship, type ContactRow, type ContactsActor, type ContactsAddBlockedReason, type ContactsAddError, type ContactsAddSlice, type ContactsListOptions, type ContactsListSlice, type ContactsRefusal, type ContactsSummarySlice, type ControllerAction, type CreateOrganizationFailure, type CreateOrganizationSubmission, type CsvExport, type DashboardAccessErrorSlice, type DashboardAccessPhase, type DashboardAccessRedirectSlice, type DashboardScope, type Destination, type FaultedState, type ImageUploadInput, type ImageUploadTarget, type InvocationOptions, type NavigationAction, type OnboardingControllerProps, type OnboardingIntent, type OnboardingJourney, type OnboardingJourneyPosition, type OnboardingOrigin, type OnboardingStep, type OrgFailure, type OrgMemberAction, type OrgMemberCanSlice, type OrgMemberStanding, type OrgMemberStandingSlice, type OrgProgress, type OrganizationDetails, type OrganizationDraft, type OtpPendingState, type PayoutDraftChain, type PayoutDraftEntry, type PayrollGroupRow, type PayrollGroupsSlice, type PayrollRecipientOption, type PayrollRunActionsSlice, type PayrollRunAmountEntry, type PayrollRunAmountsSlice, type PayrollRunAssetSlice, type PayrollRunGroupOption, type PayrollRunPrefill, type PayrollRunRecipientsSlice, type PayrollRunStatus, type PayrollRunSummarySlice, type PayrollSummarySlice, type PendingAuthState, type ProfileDetails, type ProfileDraft, type ProfileSlotProps, type ReadyDestination, type RetryAction, type SendActor, type SendMoneyActionsSlice, type SendMoneyAmountSlice, type SendMoneyAssetError, type SendMoneyAssetOption, type SendMoneyAssetSlice, type SendMoneyRecipientMethod, type SendMoneyRecipientSlice, type SendMoneyRecipientStatus, type SendMoneySourceError, type SendMoneySourceOption, type SendMoneySourceSlice, type SendResult, type SentPayment, type SentPayrollRun, type SignedOutState, type Slot, type SummaryWindow, type UseCapxulAccountBalanceOptions, type UseCapxulAccountBalanceReturn, type UseCapxulAccountFundReturn, type UseCapxulCreateCommitmentReturn, type UseCapxulCreateOrgReturn, type UseCapxulImageUploadReturn, type UseCapxulInviteMemberReturn, type UseCapxulOrgMembersOptions, type UseCapxulOrgMembersReturn, type UseCapxulOrgRolesOptions, type UseCapxulOrgRolesReturn, type UseCapxulOrgTreasuryOptions, type UseCapxulOrgTreasuryReturn, type UseCapxulOrgsReturn, type UseCapxulPayReturn, type UseCapxulPaymentReturn, type UseCapxulPaymentsReturn, type UseCapxulProfileReturn, type UseCapxulRedirectPaymentReturn, type UseCapxulUsernameAvailabilityReturn, type UsernameAvailability, acknowledgeOnboardingDestination, activeOnboardingRecovery, capxulKeys, clearOnboardingJourney, currentOnboardingJourneyId, entered, invalidateOnboardingJourneyObservation, isClaimed, isRestoring, loadOnboardingJourney, onboardingJourneyPosition, saveOnboardingJourney, startOnboardingJourney, useCapxul, useCapxulAccountBalance, useCapxulAccountFund, useCapxulActivity, useCapxulActivityDetail, useCapxulAnnotateMovement, useCapxulAuth, useCapxulCancelPayment, useCapxulClaimPayment, useCapxulClientOrNull, useCapxulCreateCommitment, useCapxulCreateOrg, useCapxulDestination, useCapxulHoldings, useCapxulIdentity, useCapxulImageUpload, useCapxulInviteMember, useCapxulOrgMembers, useCapxulOrgRoles, useCapxulOrgTreasury, useCapxulOrganizationPay, useCapxulOrganizationPayBatch, useCapxulOrgs, useCapxulPay, useCapxulPayment, useCapxulPayments, useCapxulPermission, useCapxulPermissionAssign, useCapxulPermissionChange, useCapxulPermissionCreate, useCapxulPermissionReplace, useCapxulPermissionRevoke, useCapxulPermissions, useCapxulProfile, useCapxulRedirectPayment, useCapxulSend, useCapxulTransitions, useCapxulUsernameAvailability };
1027
+ export { type AccountFailure, type AccountProgress, type ActionResult, type ActivityDetailSlice, type ActivityExportSlice, type ActivityFilterValues, type ActivityFiltersSlice, type ActivityLoadMoreSlice, type ActivityReceipt, type ActivityRow, type ActivityRowsSlice, type ActivitySearchSlice, type ActivitySummarySlice, type AuthenticatedState, type AuthenticationSlots, type CanReason, CapxulActivity, type CapxulActivityProps, type CapxulAuth, CapxulAuthenticationController, type CapxulBootstrapState, type CapxulBootstrapStatus, CapxulContacts, type CapxulContactsProps, CapxulDashboardAccess, type CapxulDashboardAccessProps, CapxulOnboardingController, CapxulOrgMember, type CapxulOrgMemberProps, CapxulPayroll, type CapxulPayrollProps, CapxulPayrollRun, type CapxulPayrollRunBlockedReason, type CapxulPayrollRunProps, CapxulProvider, type CapxulProviderProps, type CapxulSend, CapxulSendMoney, type CapxulSendMoneyBlockedReason, type CapxulSendMoneyProps, type Contact, type ContactRelationship, type ContactRow, type ContactsActor, type ContactsAddBlockedReason, type ContactsAddError, type ContactsAddSlice, type ContactsListOptions, type ContactsListSlice, type ContactsRefusal, type ContactsSummarySlice, type ControllerAction, type CreateOrganizationFailure, type CreateOrganizationSubmission, type CsvExport, type DashboardAccessErrorSlice, type DashboardAccessPhase, type DashboardAccessRedirectSlice, type DashboardScope, type Destination, type FaultedState, type HandleAvailability, type ImageUploadInput, type ImageUploadTarget, type InvocationOptions, type NavigationAction, type OnboardingControllerProps, type OnboardingIntent, type OnboardingJourney, type OnboardingJourneyPosition, type OnboardingOrigin, type OnboardingStep, type OrgFailure, type OrgMemberAction, type OrgMemberCanSlice, type OrgMemberStanding, type OrgMemberStandingSlice, type OrgProgress, type OrganizationDetails, type OrganizationDraft, type OtpPendingState, type PayoutDraftChain, type PayoutDraftEntry, type PayrollGroupRow, type PayrollGroupsSlice, type PayrollRecipientOption, type PayrollRunActionsSlice, type PayrollRunAmountEntry, type PayrollRunAmountsSlice, type PayrollRunAssetSlice, type PayrollRunGroupOption, type PayrollRunPrefill, type PayrollRunRecipientsSlice, type PayrollRunStatus, type PayrollRunSummarySlice, type PayrollSummarySlice, type PendingAuthState, type ProfileDetails, type ProfileDraft, type ProfileSlotProps, type ReadyDestination, type RetryAction, type SendActor, type SendMoneyActionsSlice, type SendMoneyAmountSlice, type SendMoneyAssetError, type SendMoneyAssetOption, type SendMoneyAssetSlice, type SendMoneyRecipientSlice, type SendMoneyRecipientStatus, type SendMoneySourceError, type SendMoneySourceOption, type SendMoneySourceSlice, type SendResult, type SentPayment, type SentPayrollRun, type SignedOutState, type Slot, type SummaryWindow, type UseCapxulAccountBalanceOptions, type UseCapxulAccountBalanceReturn, type UseCapxulAccountFundReturn, type UseCapxulCreateCommitmentReturn, type UseCapxulCreateOrgReturn, type UseCapxulHandleAvailabilityReturn, type UseCapxulImageUploadReturn, type UseCapxulInviteMemberReturn, type UseCapxulOrgMembersOptions, type UseCapxulOrgMembersReturn, type UseCapxulOrgRolesOptions, type UseCapxulOrgRolesReturn, type UseCapxulOrgTreasuryOptions, type UseCapxulOrgTreasuryReturn, type UseCapxulOrgsReturn, type UseCapxulPayReturn, type UseCapxulPaymentReturn, type UseCapxulPaymentsReturn, type UseCapxulProfileReturn, type UseCapxulRedirectPaymentReturn, acknowledgeOnboardingDestination, activeOnboardingRecovery, capxulKeys, clearOnboardingJourney, currentOnboardingJourneyId, entered, invalidateOnboardingJourneyObservation, isClaimed, isRestoring, loadOnboardingJourney, onboardingJourneyPosition, saveOnboardingJourney, startOnboardingJourney, useCapxul, useCapxulAccountBalance, useCapxulAccountFund, useCapxulActivity, useCapxulActivityDetail, useCapxulAnnotateMovement, useCapxulAuth, useCapxulCancelPayment, useCapxulClaimPayment, useCapxulClientOrNull, useCapxulCreateCommitment, useCapxulCreateOrg, useCapxulDestination, useCapxulHandleAvailability, useCapxulHoldings, useCapxulIdentity, useCapxulImageUpload, useCapxulInviteMember, useCapxulOrgMembers, useCapxulOrgRoles, useCapxulOrgTreasury, useCapxulOrganizationPay, useCapxulOrganizationPayBatch, useCapxulOrgs, useCapxulPay, useCapxulPayment, useCapxulPayments, useCapxulPermission, useCapxulPermissionAssign, useCapxulPermissionChange, useCapxulPermissionCreate, useCapxulPermissionReplace, useCapxulPermissionRevoke, useCapxulPermissions, useCapxulProfile, useCapxulRedirectPayment, useCapxulSend, useCapxulTransitions };
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { a as useCapxulAuth, c as useCapxulIdentityOrNull, d as capxulKeys, f as useCapxulClientOrNull, i as entered, l as useCapxulSend, n as CapxulOnboardingController, o as useCapxulDestination, p as useCapxul, r as CapxulProvider, s as useCapxulIdentity, t as CapxulAuthenticationController, u as useCapxulTransitions } from "./controllers-BSDuWapk.mjs";
2
+ import { a as useCapxulAuth, c as useCapxulIdentityOrNull, d as capxulKeys, f as useCapxulClientOrNull, i as entered, l as useCapxulSend, n as CapxulOnboardingController, o as useCapxulDestination, p as useCapxul, r as CapxulProvider, s as useCapxulIdentity, t as CapxulAuthenticationController, u as useCapxulTransitions } from "./controllers-BgkCs0nW.mjs";
3
3
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
4
  import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
5
- import { CAPXUL_OPERATIONS, CapxulError, Errors, PAYMENT_DIRECTIONS, PAYMENT_STATUSES, fingerprintPaymentIntent, formatMoney, isCapxulError, isClaimed, isClaimed as isClaimed$1, isMoneyParseError, isRestoring, isRestoring as isRestoring$1, parseMoney, paymentPhase, resolveIdentityDestination } from "@capxul/sdk";
5
+ import { CAPXUL_OPERATIONS, CapxulError, EVM_ADDRESS_RE, Errors, HANDLE_RE, PAYMENT_DIRECTIONS, PAYMENT_STATUSES, fingerprintPaymentIntent, formatMoney, isCapxulError, isClaimed, isClaimed as isClaimed$1, isMoneyParseError, isRestoring, isRestoring as isRestoring$1, parseMoney, paymentPhase, resolveIdentityDestination, toEvmAddress, toPartyId } from "@capxul/sdk";
6
6
  import { Fragment, jsx } from "react/jsx-runtime";
7
7
  //#region src/internal/require-bootstrapped-client.ts
8
8
  /**
@@ -38,7 +38,7 @@ function useCapxulProfile() {
38
38
  const client = useCapxulClientOrNull();
39
39
  const identity = useCapxulIdentityOrNull();
40
40
  return useQuery({
41
- queryKey: capxulKeys.profile,
41
+ queryKey: [...capxulKeys.profile, identity?.phase === "authenticated" ? identity.session.authUserId : null],
42
42
  queryFn: async () => unwrapCapxulResult(await requireBootstrappedClient(client, CAPXUL_OPERATIONS.identity.loadCurrent).identity.loadCurrent()),
43
43
  enabled: client !== null && identity?.phase === "authenticated"
44
44
  });
@@ -733,10 +733,10 @@ function isProfileDraft(value) {
733
733
  "displayName",
734
734
  "country",
735
735
  "withdrawalAddress",
736
- "username",
736
+ "handle",
737
737
  "payoutAddresses"
738
738
  ]) || !isDraftText(value.displayName) || !isDraftText(value.country) || !isDraftText(value.withdrawalAddress)) return false;
739
- if (value.username !== void 0 && !isDraftText(value.username)) return false;
739
+ if (value.handle !== void 0 && !isDraftText(value.handle)) return false;
740
740
  if (value.payoutAddresses !== void 0 && !isPayoutDraftList(value.payoutAddresses)) return false;
741
741
  return true;
742
742
  }
@@ -790,21 +790,21 @@ function useDebouncedValue(value, delayMs) {
790
790
  return debounced;
791
791
  }
792
792
  //#endregion
793
- //#region src/headless/onboarding/use-capxul-username-availability.ts
793
+ //#region src/headless/onboarding/use-capxul-handle-availability.ts
794
794
  /**
795
- * #1062: debounced availability probe for the username the user is typing.
795
+ * #1062: debounced availability probe for the handle the user is typing.
796
796
  * Disabled until the candidate reaches the 3-character floor; a malformed or
797
797
  * reserved candidate surfaces as the query's error (INVALID_INPUT with the
798
- * boundary's message), not as `available: false` — only a username someone
798
+ * boundary's message), not as `available: false` — only a handle someone
799
799
  * else owns is "taken".
800
800
  */
801
- function useCapxulUsernameAvailability(username, options) {
801
+ function useCapxulHandleAvailability(handle, options) {
802
802
  const client = useCapxulClientOrNull();
803
- const candidate = useDebouncedValue(username.trim(), options?.debounceMs ?? 300);
803
+ const candidate = useDebouncedValue(handle.trim(), options?.debounceMs ?? 300);
804
804
  return useQuery({
805
- queryKey: capxulKeys.usernameAvailability(candidate),
805
+ queryKey: capxulKeys.handleAvailability(candidate),
806
806
  queryFn: async () => {
807
- return unwrapCapxulResult(await requireBootstrappedClient(client, CAPXUL_OPERATIONS.identity.usernameAvailable).identity.usernameAvailable(candidate));
807
+ return unwrapCapxulResult(await requireBootstrappedClient(client, CAPXUL_OPERATIONS.identity.handleAvailable).identity.handleAvailable(candidate));
808
808
  },
809
809
  enabled: client !== null && candidate.length >= 3 && (options?.enabled ?? true)
810
810
  });
@@ -1329,7 +1329,7 @@ function useActivitySummary(actor, window) {
1329
1329
  //#region src/headless/activity/rows.ts
1330
1330
  /**
1331
1331
  * A Movement's phase is DERIVED, not asserted: `movementItems` returns `null`
1332
- * for any Movement whose `canonicalState` is not `"finalized"`
1332
+ * for any Movement whose `canonicalState` is not `"included"`
1333
1333
  * (`activityList.ts:120`), so a Movement that reaches a page is finished and
1334
1334
  * carries no verdict of its own.
1335
1335
  */
@@ -1753,67 +1753,126 @@ function useSignerStatus(client) {
1753
1753
  }
1754
1754
  //#endregion
1755
1755
  //#region src/headless/send-money/use-recipient-resolution.ts
1756
- function toTargetReference(method, text) {
1756
+ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1757
+ const PARTY_ID_RE = /^party_[0-9A-Za-z]+$/;
1758
+ const RESOLVE_DEBOUNCE_MS = 400;
1759
+ function parseRecipient(text) {
1757
1760
  const trimmed = text.trim();
1758
- if (trimmed === "") return null;
1759
- return method === "username" ? {
1760
- kind: "handle",
1761
- handle: trimmed.replace(/^@/, "")
1762
- } : {
1763
- kind: "email",
1764
- email: trimmed
1761
+ if (trimmed === "") return { status: "empty" };
1762
+ if (PARTY_ID_RE.test(trimmed)) return {
1763
+ status: "valid",
1764
+ reference: {
1765
+ kind: "party",
1766
+ partyId: toPartyId(trimmed)
1767
+ }
1765
1768
  };
1769
+ if (EVM_ADDRESS_RE.test(trimmed)) return {
1770
+ status: "valid",
1771
+ reference: {
1772
+ kind: "address",
1773
+ address: toEvmAddress(trimmed)
1774
+ }
1775
+ };
1776
+ if (EMAIL_RE.test(trimmed)) return {
1777
+ status: "valid",
1778
+ reference: {
1779
+ kind: "email",
1780
+ email: trimmed.toLowerCase()
1781
+ }
1782
+ };
1783
+ const handle = trimmed.replace(/^@/, "").toLowerCase();
1784
+ if (HANDLE_RE.test(handle)) return {
1785
+ status: "valid",
1786
+ reference: {
1787
+ kind: "handle",
1788
+ handle
1789
+ }
1790
+ };
1791
+ return { status: "invalid" };
1766
1792
  }
1767
- /** How long the engine waits after the last keystroke before resolving. */
1768
- const RESOLVE_DEBOUNCE_MS = 400;
1769
- function useRecipientResolution(client) {
1770
- const [method, setMethodState] = useState("email-address");
1793
+ function sameReference(left, right) {
1794
+ return JSON.stringify(left) === JSON.stringify(right);
1795
+ }
1796
+ function publicRecipientValue(value) {
1797
+ if (value === null) return null;
1798
+ if (value.status === "known_party") return value.handle ?? value.label;
1799
+ return value.status === "external_address" ? value.safeAddress : null;
1800
+ }
1801
+ function recipientStatus(parsed, settled, acknowledged) {
1802
+ if (parsed.status === "empty" || parsed.status === "invalid") return parsed.status;
1803
+ if (settled === null) return "checking";
1804
+ if (!settled.ok) return settled.error.code === "INVALID_INPUT" ? "not-found" : "failed";
1805
+ if (settled.value.status === "known_party") return "known-party";
1806
+ if (settled.value.status === "new_email") return "new-email";
1807
+ return acknowledged ? "external-ready" : "external-warning";
1808
+ }
1809
+ function useRecipientResolution(client, scope, organizationId) {
1771
1810
  const [text, setText] = useState("");
1772
- const reference = useMemo(() => toTargetReference(method, text), [method, text]);
1811
+ const parsed = useMemo(() => parseRecipient(text), [text]);
1812
+ const reference = parsed.status === "valid" ? parsed.reference : null;
1773
1813
  const debouncedReference = useDebouncedValue(reference, RESOLVE_DEBOUNCE_MS);
1814
+ const debouncedText = useDebouncedValue(text, RESOLVE_DEBOUNCE_MS);
1774
1815
  const [outcome, setOutcome] = useState(null);
1816
+ const [acknowledgedOutcome, setAcknowledgedOutcome] = useState(null);
1817
+ const capturedAcknowledgement = useRef(null);
1818
+ const change = useCallback((next) => {
1819
+ if (next === text) return;
1820
+ setAcknowledgedOutcome(null);
1821
+ setOutcome(null);
1822
+ setText(next);
1823
+ }, [text]);
1775
1824
  useEffect(() => {
1776
1825
  if (debouncedReference === null || client === null) {
1777
1826
  setOutcome(null);
1778
1827
  return;
1779
1828
  }
1780
1829
  const controller = new AbortController();
1781
- setOutcome({
1782
- reference: debouncedReference,
1783
- status: "checking",
1784
- label: null
1785
- });
1830
+ setOutcome(null);
1786
1831
  client.targets.resolve(debouncedReference, { signal: controller.signal }).then((result) => {
1787
- if (controller.signal.aborted) return;
1788
- setOutcome(result.ok ? {
1789
- reference: debouncedReference,
1790
- status: "found",
1791
- label: result.value.label
1792
- } : {
1793
- reference: debouncedReference,
1794
- status: result.error.code === "INVALID_INPUT" ? "not-found" : "failed",
1795
- label: null
1832
+ if (!controller.signal.aborted) setOutcome({
1833
+ client,
1834
+ scope,
1835
+ text: debouncedText,
1836
+ input: debouncedReference,
1837
+ result
1796
1838
  });
1797
1839
  });
1798
1840
  return () => controller.abort();
1799
- }, [client, debouncedReference]);
1800
- const setMethod = useCallback((next) => {
1801
- setMethodState(next);
1802
- setText("");
1803
- }, []);
1804
- const settled = outcome !== null && outcome.reference === debouncedReference ? outcome : null;
1805
- const status = reference === null ? "empty" : reference !== debouncedReference || settled === null ? "checking" : settled.status;
1806
- const resolvedReference = status === "found" ? settled?.reference ?? null : null;
1841
+ }, [
1842
+ client,
1843
+ scope,
1844
+ debouncedReference,
1845
+ debouncedText
1846
+ ]);
1847
+ const settled = reference !== null && debouncedReference !== null && outcome !== null && outcome.client === client && outcome.scope === scope && outcome.text === text && sameReference(reference, debouncedReference) && sameReference(outcome.input, debouncedReference) ? outcome.result : null;
1848
+ const status = recipientStatus(parsed, settled, acknowledgedOutcome === outcome);
1849
+ const ready = settled?.ok === true && (settled.value.status !== "external_address" || status === "external-ready");
1850
+ const value = settled?.ok === true ? settled.value : null;
1851
+ const acknowledgeExternalAddress = useCallback(() => {
1852
+ if (value?.status !== "external_address" || outcome === null) return;
1853
+ setAcknowledgedOutcome(outcome);
1854
+ if (capturedAcknowledgement.current === outcome) return;
1855
+ capturedAcknowledgement.current = outcome;
1856
+ client?._internal.captureExternalAddressAcknowledged(value.safeAddress, organizationId);
1857
+ }, [
1858
+ client,
1859
+ organizationId,
1860
+ value,
1861
+ outcome
1862
+ ]);
1807
1863
  return {
1808
1864
  slice: {
1809
- method,
1810
- setMethod,
1811
1865
  value: text,
1812
- change: setText,
1866
+ change,
1813
1867
  status,
1814
- label: status === "found" ? settled?.label ?? null : null
1868
+ label: value?.label ?? null,
1869
+ kind: value?.kind ?? null,
1870
+ isCapxulAccount: value?.isCapxulAccount ?? null,
1871
+ publicValue: publicRecipientValue(value),
1872
+ requiresAcknowledgement: status === "external-warning",
1873
+ acknowledgeExternalAddress
1815
1874
  },
1816
- resolvedReference,
1875
+ resolvedReference: ready && value !== null ? value.reference : null,
1817
1876
  trimmed: text.trim()
1818
1877
  };
1819
1878
  }
@@ -1858,7 +1917,11 @@ function useSendMoney(input) {
1858
1917
  const parsed = useMemo(() => selectedAssetMoney === null || amountText.trim() === "" ? null : parseMoney(amountText, selectedAssetMoney), [amountText, selectedAssetMoney]);
1859
1918
  const parsedMoney = parsed !== null && !isMoneyParseError(parsed) ? parsed : null;
1860
1919
  const amountError = parsed !== null && isMoneyParseError(parsed) ? parsed.reason : null;
1861
- const recipient = useRecipientResolution(client);
1920
+ const recipient = useRecipientResolution(client, JSON.stringify([
1921
+ actor.kind,
1922
+ orgId,
1923
+ account?.id
1924
+ ]), orgId);
1862
1925
  const resolvedReference = recipient.resolvedReference;
1863
1926
  const personalPay = useCapxulPay();
1864
1927
  const organizationPay = useCapxulOrganizationPay(orgId);
@@ -1870,6 +1933,7 @@ function useSendMoney(input) {
1870
1933
  if (parsedMoney === null || resolvedReference === null) return;
1871
1934
  const amount = parsedMoney;
1872
1935
  const sentRecipient = recipient.trimmed;
1936
+ const externalAddressAcknowledged = recipient.slice.status === "external-ready";
1873
1937
  const callbacks = {
1874
1938
  onSuccess: (payment) => onSent({
1875
1939
  payment,
@@ -1885,7 +1949,8 @@ function useSendMoney(input) {
1885
1949
  submitGate.current = true;
1886
1950
  personalPay.mutate({
1887
1951
  to: resolvedReference,
1888
- amount
1952
+ amount,
1953
+ ...externalAddressAcknowledged ? { externalAddressAcknowledged: true } : {}
1889
1954
  }, callbacks);
1890
1955
  return;
1891
1956
  }
@@ -1894,7 +1959,8 @@ function useSendMoney(input) {
1894
1959
  organizationPay.mutate({
1895
1960
  permissionId: selectedSource.id,
1896
1961
  to: resolvedReference,
1897
- amount
1962
+ amount,
1963
+ ...externalAddressAcknowledged ? { externalAddressAcknowledged: true } : {}
1898
1964
  }, callbacks);
1899
1965
  }, [
1900
1966
  actor.kind,
@@ -1905,6 +1971,7 @@ function useSendMoney(input) {
1905
1971
  parsedMoney,
1906
1972
  personalPay,
1907
1973
  recipient.trimmed,
1974
+ recipient.slice.status,
1908
1975
  resolvedReference,
1909
1976
  selectedSource
1910
1977
  ]);
@@ -2968,4 +3035,4 @@ const CapxulPayrollRun = Object.assign(Root, {
2968
3035
  Actions
2969
3036
  });
2970
3037
  //#endregion
2971
- export { CapxulActivity, CapxulAuthenticationController, CapxulContacts, CapxulDashboardAccess, CapxulOnboardingController, CapxulOrgMember, CapxulPayroll, CapxulPayrollRun, CapxulProvider, CapxulSendMoney, acknowledgeOnboardingDestination, activeOnboardingRecovery, capxulKeys, clearOnboardingJourney, currentOnboardingJourneyId, entered, invalidateOnboardingJourneyObservation, isClaimed, isRestoring, loadOnboardingJourney, onboardingJourneyPosition, saveOnboardingJourney, startOnboardingJourney, useCapxul, useCapxulAccountBalance, useCapxulAccountFund, useCapxulActivity, useCapxulActivityDetail, useCapxulAnnotateMovement, useCapxulAuth, useCapxulCancelPayment, useCapxulClaimPayment, useCapxulClientOrNull, useCapxulCreateCommitment, useCapxulCreateOrg, useCapxulDestination, useCapxulHoldings, useCapxulIdentity, useCapxulImageUpload, useCapxulInviteMember, useCapxulOrgMembers, useCapxulOrgRoles, useCapxulOrgTreasury, useCapxulOrganizationPay, useCapxulOrganizationPayBatch, useCapxulOrgs, useCapxulPay, useCapxulPayment, useCapxulPayments, useCapxulPermission, useCapxulPermissionAssign, useCapxulPermissionChange, useCapxulPermissionCreate, useCapxulPermissionReplace, useCapxulPermissionRevoke, useCapxulPermissions, useCapxulProfile, useCapxulRedirectPayment, useCapxulSend, useCapxulTransitions, useCapxulUsernameAvailability };
3038
+ export { CapxulActivity, CapxulAuthenticationController, CapxulContacts, CapxulDashboardAccess, CapxulOnboardingController, CapxulOrgMember, CapxulPayroll, CapxulPayrollRun, CapxulProvider, CapxulSendMoney, acknowledgeOnboardingDestination, activeOnboardingRecovery, capxulKeys, clearOnboardingJourney, currentOnboardingJourneyId, entered, invalidateOnboardingJourneyObservation, isClaimed, isRestoring, loadOnboardingJourney, onboardingJourneyPosition, saveOnboardingJourney, startOnboardingJourney, useCapxul, useCapxulAccountBalance, useCapxulAccountFund, useCapxulActivity, useCapxulActivityDetail, useCapxulAnnotateMovement, useCapxulAuth, useCapxulCancelPayment, useCapxulClaimPayment, useCapxulClientOrNull, useCapxulCreateCommitment, useCapxulCreateOrg, useCapxulDestination, useCapxulHandleAvailability, useCapxulHoldings, useCapxulIdentity, useCapxulImageUpload, useCapxulInviteMember, useCapxulOrgMembers, useCapxulOrgRoles, useCapxulOrgTreasury, useCapxulOrganizationPay, useCapxulOrganizationPayBatch, useCapxulOrgs, useCapxulPay, useCapxulPayment, useCapxulPayments, useCapxulPermission, useCapxulPermissionAssign, useCapxulPermissionChange, useCapxulPermissionCreate, useCapxulPermissionReplace, useCapxulPermissionRevoke, useCapxulPermissions, useCapxulProfile, useCapxulRedirectPayment, useCapxulSend, useCapxulTransitions };
@@ -1,4 +1,4 @@
1
- import { n as CapxulOnboardingController, r as CapxulProvider, t as CapxulAuthenticationController } from "../controllers-BSDuWapk.mjs";
1
+ import { n as CapxulOnboardingController, r as CapxulProvider, t as CapxulAuthenticationController } from "../controllers-BgkCs0nW.mjs";
2
2
  import "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  import { createCapxulTestClient } from "@capxul/sdk/testing";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capxul/sdk-react",
3
- "version": "3.2.0",
3
+ "version": "4.0.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/Xelmar-tech/infrastructure.git",
@@ -26,7 +26,7 @@
26
26
  "access": "public"
27
27
  },
28
28
  "dependencies": {
29
- "@capxul/sdk": "3.2.0"
29
+ "@capxul/sdk": "4.0.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@tanstack/react-query": "^5.66.9",
@@ -43,8 +43,8 @@
43
43
  "vite": "npm:@voidzero-dev/vite-plus-core@0.3.0",
44
44
  "vite-plus": "0.3.0",
45
45
  "vitest": "4.1.11",
46
- "@capxul/errors": "0.2.0",
47
- "@capxul/types": "0.2.3",
46
+ "@capxul/errors": "0.3.0",
47
+ "@capxul/types": "0.3.0",
48
48
  "@capxul/typescript-config": "0.0.0"
49
49
  },
50
50
  "peerDependencies": {