@swype-org/react-sdk 0.1.9 → 0.1.11

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
@@ -387,8 +387,9 @@ declare function useTransferSigning(pollIntervalMs?: number, options?: UseTransf
387
387
 
388
388
  declare function fetchProviders(apiBaseUrl: string, token: string): Promise<Provider[]>;
389
389
  declare function fetchChains(apiBaseUrl: string, token: string): Promise<Chain[]>;
390
- declare function fetchAccounts(apiBaseUrl: string, token: string): Promise<Account[]>;
390
+ declare function fetchAccounts(apiBaseUrl: string, token: string, credentialId: string): Promise<Account[]>;
391
391
  interface CreateTransferParams {
392
+ credentialId: string;
392
393
  sourceType: SourceType;
393
394
  sourceId: string;
394
395
  destination: Destination;
package/dist/index.d.ts CHANGED
@@ -387,8 +387,9 @@ declare function useTransferSigning(pollIntervalMs?: number, options?: UseTransf
387
387
 
388
388
  declare function fetchProviders(apiBaseUrl: string, token: string): Promise<Provider[]>;
389
389
  declare function fetchChains(apiBaseUrl: string, token: string): Promise<Chain[]>;
390
- declare function fetchAccounts(apiBaseUrl: string, token: string): Promise<Account[]>;
390
+ declare function fetchAccounts(apiBaseUrl: string, token: string, credentialId: string): Promise<Account[]>;
391
391
  interface CreateTransferParams {
392
+ credentialId: string;
392
393
  sourceType: SourceType;
393
394
  sourceId: string;
394
395
  destination: Destination;
package/dist/index.js CHANGED
@@ -175,8 +175,9 @@ async function fetchChains(apiBaseUrl, token) {
175
175
  const data = await res.json();
176
176
  return data.items;
177
177
  }
178
- async function fetchAccounts(apiBaseUrl, token) {
179
- const res = await fetch(`${apiBaseUrl}/v1/accounts`, {
178
+ async function fetchAccounts(apiBaseUrl, token, credentialId) {
179
+ const params = new URLSearchParams({ credentialId });
180
+ const res = await fetch(`${apiBaseUrl}/v1/accounts?${params.toString()}`, {
180
181
  headers: { Authorization: `Bearer ${token}` }
181
182
  });
182
183
  if (!res.ok) await throwApiError(res);
@@ -186,6 +187,7 @@ async function fetchAccounts(apiBaseUrl, token) {
186
187
  async function createTransfer(apiBaseUrl, token, params) {
187
188
  const body = {
188
189
  id: crypto.randomUUID(),
190
+ credentialId: params.credentialId,
189
191
  sources: [{ [params.sourceType]: params.sourceId }],
190
192
  destinations: [
191
193
  {
@@ -558,6 +560,27 @@ async function getWalletClient(config, parameters = {}) {
558
560
  const client = await getConnectorClient(config, parameters);
559
561
  return client.extend(walletActions);
560
562
  }
563
+
564
+ // src/passkeyRpId.ts
565
+ function normalizeConfiguredDomain(value) {
566
+ return value.replace(/^https?:\/\//, "").replace(/\/.*$/, "").replace(/^\./, "").trim();
567
+ }
568
+ function resolveRootDomainFromHostname(hostname) {
569
+ const trimmedHostname = hostname.trim().toLowerCase();
570
+ if (!trimmedHostname) {
571
+ return "localhost";
572
+ }
573
+ if (trimmedHostname === "localhost" || /^\d{1,3}(?:\.\d{1,3}){3}$/.test(trimmedHostname)) {
574
+ return trimmedHostname;
575
+ }
576
+ const parts = trimmedHostname.split(".").filter(Boolean);
577
+ if (parts.length < 2) {
578
+ return trimmedHostname;
579
+ }
580
+ return parts.slice(-2).join(".");
581
+ }
582
+
583
+ // src/hooks.ts
561
584
  var WALLET_CLIENT_MAX_ATTEMPTS = 15;
562
585
  var WALLET_CLIENT_POLL_MS = 200;
563
586
  var ACTION_POLL_INTERVAL_MS = 500;
@@ -608,10 +631,10 @@ function readEnvValue(name) {
608
631
  function resolvePasskeyRpId() {
609
632
  const configuredDomain = readEnvValue("VITE_DOMAIN") ?? readEnvValue("SWYPE_DOMAIN");
610
633
  if (configuredDomain) {
611
- return configuredDomain.replace(/^https?:\/\//, "").replace(/\/.*$/, "").replace(/^\./, "").trim();
634
+ return normalizeConfiguredDomain(configuredDomain);
612
635
  }
613
636
  if (typeof window !== "undefined") {
614
- return window.location.hostname;
637
+ return resolveRootDomainFromHostname(window.location.hostname);
615
638
  }
616
639
  return "localhost";
617
640
  }
@@ -1931,6 +1954,7 @@ function AdvancedSettings({
1931
1954
  )
1932
1955
  ] });
1933
1956
  }
1957
+ var ACTIVE_CREDENTIAL_STORAGE_KEY = "swype_active_credential_id";
1934
1958
  function isMobile() {
1935
1959
  if (typeof navigator === "undefined") return false;
1936
1960
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
@@ -2034,8 +2058,13 @@ function SwypePayment({
2034
2058
  const [transfer, setTransfer] = useState(null);
2035
2059
  const [creatingTransfer, setCreatingTransfer] = useState(false);
2036
2060
  const [registeringPasskey, setRegisteringPasskey] = useState(false);
2061
+ const [activeCredentialId, setActiveCredentialId] = useState(() => {
2062
+ if (typeof window === "undefined") return null;
2063
+ return window.localStorage.getItem(ACTIVE_CREDENTIAL_STORAGE_KEY);
2064
+ });
2037
2065
  const [mobileFlow, setMobileFlow] = useState(false);
2038
2066
  const pollingTransferIdRef = useRef(null);
2067
+ const mobileSigningTransferIdRef = useRef(null);
2039
2068
  const [selectSourceChainName, setSelectSourceChainName] = useState("");
2040
2069
  const [selectSourceTokenSymbol, setSelectSourceTokenSymbol] = useState("");
2041
2070
  const initializedSelectSourceActionRef = useRef(null);
@@ -2058,7 +2087,7 @@ function SwypePayment({
2058
2087
  if (!token || cancelled) return;
2059
2088
  const { config } = await fetchUserConfig(apiBaseUrl, token);
2060
2089
  if (cancelled) return;
2061
- if (!config.passkey) {
2090
+ if (!config.passkey || !activeCredentialId) {
2062
2091
  setStep("register-passkey");
2063
2092
  } else if (depositAmount != null && depositAmount > 0) {
2064
2093
  setStep("ready");
@@ -2079,7 +2108,7 @@ function SwypePayment({
2079
2108
  return () => {
2080
2109
  cancelled = true;
2081
2110
  };
2082
- }, [ready, authenticated, step, depositAmount, apiBaseUrl, getAccessToken]);
2111
+ }, [ready, authenticated, step, depositAmount, apiBaseUrl, getAccessToken, activeCredentialId]);
2083
2112
  const loadingDataRef = useRef(false);
2084
2113
  useEffect(() => {
2085
2114
  if (!authenticated) return;
@@ -2090,11 +2119,15 @@ function SwypePayment({
2090
2119
  setLoadingData(true);
2091
2120
  setError(null);
2092
2121
  try {
2122
+ if (!activeCredentialId) {
2123
+ setStep("register-passkey");
2124
+ return;
2125
+ }
2093
2126
  const token = await getAccessToken();
2094
2127
  if (!token) throw new Error("Not authenticated");
2095
2128
  const [prov, accts, chn] = await Promise.all([
2096
2129
  fetchProviders(apiBaseUrl, token),
2097
- fetchAccounts(apiBaseUrl, token),
2130
+ fetchAccounts(apiBaseUrl, token, activeCredentialId),
2098
2131
  fetchChains(apiBaseUrl, token)
2099
2132
  ]);
2100
2133
  if (cancelled) return;
@@ -2126,7 +2159,7 @@ function SwypePayment({
2126
2159
  cancelled = true;
2127
2160
  loadingDataRef.current = false;
2128
2161
  };
2129
- }, [authenticated, accounts.length, apiBaseUrl, getAccessToken]);
2162
+ }, [authenticated, accounts.length, apiBaseUrl, getAccessToken, activeCredentialId]);
2130
2163
  useEffect(() => {
2131
2164
  if (!polling.transfer) return;
2132
2165
  if (polling.transfer.status === "COMPLETED") {
@@ -2139,6 +2172,27 @@ function SwypePayment({
2139
2172
  setError("Transfer failed.");
2140
2173
  }
2141
2174
  }, [polling.transfer, onComplete]);
2175
+ useEffect(() => {
2176
+ if (!mobileFlow) return;
2177
+ const polledTransfer = polling.transfer;
2178
+ if (!polledTransfer) return;
2179
+ if (polledTransfer.status !== "AUTHORIZED") return;
2180
+ if (transferSigning.signing) return;
2181
+ if (mobileSigningTransferIdRef.current === polledTransfer.id) return;
2182
+ mobileSigningTransferIdRef.current = polledTransfer.id;
2183
+ const sign = async () => {
2184
+ try {
2185
+ const signedTransfer = await transferSigning.signTransfer(polledTransfer.id);
2186
+ setTransfer(signedTransfer);
2187
+ } catch (err) {
2188
+ mobileSigningTransferIdRef.current = null;
2189
+ const msg = err instanceof Error ? err.message : "Failed to sign transfer";
2190
+ setError(msg);
2191
+ onError?.(msg);
2192
+ }
2193
+ };
2194
+ void sign();
2195
+ }, [mobileFlow, polling.transfer, transferSigning, onError]);
2142
2196
  useEffect(() => {
2143
2197
  if (!mobileFlow || !polling.isPolling) return;
2144
2198
  const handleVisibility = () => {
@@ -2200,6 +2254,11 @@ function SwypePayment({
2200
2254
  setError("No account or provider selected.");
2201
2255
  return;
2202
2256
  }
2257
+ if (!activeCredentialId) {
2258
+ setError("Create a passkey on this device before continuing.");
2259
+ setStep("register-passkey");
2260
+ return;
2261
+ }
2203
2262
  setStep("processing");
2204
2263
  setError(null);
2205
2264
  setCreatingTransfer(true);
@@ -2235,6 +2294,7 @@ function SwypePayment({
2235
2294
  }
2236
2295
  }
2237
2296
  const t = await createTransfer(apiBaseUrl, token, {
2297
+ credentialId: activeCredentialId,
2238
2298
  sourceType: effectiveSourceType,
2239
2299
  sourceId: effectiveSourceId,
2240
2300
  destination,
@@ -2268,6 +2328,7 @@ function SwypePayment({
2268
2328
  amount,
2269
2329
  sourceId,
2270
2330
  sourceType,
2331
+ activeCredentialId,
2271
2332
  destination,
2272
2333
  apiBaseUrl,
2273
2334
  getAccessToken,
@@ -2285,6 +2346,7 @@ function SwypePayment({
2285
2346
  setAmount(depositAmount != null ? depositAmount.toString() : "");
2286
2347
  setMobileFlow(false);
2287
2348
  pollingTransferIdRef.current = null;
2349
+ mobileSigningTransferIdRef.current = null;
2288
2350
  setConnectingNewAccount(false);
2289
2351
  setSelectedWalletId(null);
2290
2352
  setAdvancedSettings({ asset: null, chain: null });
@@ -2465,6 +2527,8 @@ function SwypePayment({
2465
2527
  if (!token) throw new Error("Not authenticated");
2466
2528
  const { credentialId, publicKey } = await createPasskeyCredential("Swype User");
2467
2529
  await registerPasskey(apiBaseUrl, token, credentialId, publicKey);
2530
+ setActiveCredentialId(credentialId);
2531
+ window.localStorage.setItem(ACTIVE_CREDENTIAL_STORAGE_KEY, credentialId);
2468
2532
  if (depositAmount != null && depositAmount > 0) {
2469
2533
  setStep("ready");
2470
2534
  } else {