@pollar/react 0.9.0 → 0.10.0-rc.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.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { WalletId, AuthState, pollarPaths, PollarClient, PollarClientConfig, PollarAdapters, OnStorageDegrade, PollarLoginOptions, SessionsState, TransactionState, TxBuildBody, BuildOutcome, SubmitOutcome, SignOutcome, StellarNetwork, WalletBalanceState, EnabledAssetsState, TrustlineOutcome, TxHistoryState, PollarAdapter, KycStatus as KycStatus$1, RampQuote, KycProvider, KycStartResponse, RampDirection, PaymentInstructions, EnabledAssetRecord, WalletBalanceRecord, DistributionRulesState, DistributionRule } from '@pollar/core';
3
- export { SessionsState } from '@pollar/core';
2
+ import { WalletId, AuthState, pollarPaths, PollarClient, PollarClientConfig, PollarAdapters, OnStorageDegrade, WalletInfo, PollarLoginOptions, SessionsState, TransactionState, TxBuildBody, BuildOutcome, SubmitOutcome, SignOutcome, StellarNetwork, WalletBalanceState, EnabledAssetsState, TrustlineOutcome, TxHistoryState, PollarAdapter, KycStatus as KycStatus$1, RampQuote, KycProvider, KycStartResponse, RampDirection, PaymentInstructions, EnabledAssetRecord, WalletBalanceRecord, DistributionRulesState, DistributionRule } from '@pollar/core';
3
+ export { AuthProviderContext, PollarAuthProvider, SessionsState } from '@pollar/core';
4
4
  import { ReactNode } from 'react';
5
5
 
6
6
  type ConfigResponse = pollarPaths['/applications/config']['get']['responses'][200]['content']['application/json'];
@@ -23,6 +23,24 @@ interface RenderWalletsProps {
23
23
  * with whatever the slot returns (typically a kit-powered wallet grid).
24
24
  */
25
25
  type RenderWalletsSlot = (props: RenderWalletsProps) => ReactNode;
26
+ /**
27
+ * Presentation metadata for a custom login provider button in the LoginModal
28
+ * (e.g. Privy, Magic). Pairs with a {@link PollarAuthProvider} registered on the
29
+ * client via its `providers` config: clicking the button calls
30
+ * `client.login({ provider: id })`, and the provider opens its own UI.
31
+ *
32
+ * Logic (the actual login) lives in the `PollarAuthProvider`; this is only the
33
+ * button's look. Keeping them separate means React never needs to know how a
34
+ * provider authenticates.
35
+ */
36
+ interface CustomLoginProvider {
37
+ /** Must match the `id` of a registered `PollarAuthProvider`. */
38
+ id: string;
39
+ /** Button label, e.g. "Continue with Privy". */
40
+ label: string;
41
+ /** Optional icon URL rendered in the button. */
42
+ iconUrl?: string;
43
+ }
26
44
  interface LoginButtonProps {
27
45
  onSuccess?: () => void;
28
46
  onError?: (error: Error) => void;
@@ -36,7 +54,14 @@ interface AuthModalProps {
36
54
  }
37
55
 
38
56
  interface PollarContextValue {
39
- walletAddress: string;
57
+ /**
58
+ * The authenticated user's wallet as a discriminated union over `custody`
59
+ * (`internal` | `smart` | `external`), or `null` when unauthenticated. Every
60
+ * field is meaningful for any login method — `custody` is always present and
61
+ * strictly determines the shape of `provider`. Use `wallet.address` for the
62
+ * on-chain address and `wallet.provider` for the wallet/login provider.
63
+ */
64
+ wallet: WalletInfo | null;
40
65
  getClient: () => PollarClient;
41
66
  openLoginModal: () => void;
42
67
  isAuthenticated: boolean;
@@ -55,6 +80,8 @@ interface PollarContextValue {
55
80
  styles: PollarStyles;
56
81
  /** UI slot for wallet picker (forwarded from provider props). */
57
82
  renderWallets?: RenderWalletsSlot;
83
+ /** Custom login provider buttons (forwarded from `ui.customProviders`). */
84
+ customProviders?: CustomLoginProvider[];
58
85
  openTxModal: () => void;
59
86
  tx: TransactionState;
60
87
  buildTx: (operation: TxBuildBody['operation'], params: TxBuildBody['params'], options?: TxBuildBody['options']) => Promise<BuildOutcome>;
@@ -66,7 +93,6 @@ interface PollarContextValue {
66
93
  buildAndSignAndSubmitTx: (operation: TxBuildBody['operation'], params: TxBuildBody['params'], options?: TxBuildBody['options']) => Promise<SubmitOutcome>;
67
94
  /** Alias of `buildAndSignAndSubmitTx`. */
68
95
  runTx: (operation: TxBuildBody['operation'], params: TxBuildBody['params'], options?: TxBuildBody['options']) => Promise<SubmitOutcome>;
69
- walletType: WalletId | null;
70
96
  network: StellarNetwork;
71
97
  setNetwork: (network: StellarNetwork) => void;
72
98
  walletBalance: WalletBalanceState;
@@ -128,6 +154,12 @@ interface PollarProviderProps {
128
154
  ui?: {
129
155
  /** Replaces the default Freighter/Albedo wallet picker. */
130
156
  renderWallets?: RenderWalletsSlot;
157
+ /**
158
+ * Custom login provider buttons (e.g. Privy) shown in the LoginModal. Each
159
+ * must match a {@link PollarAuthProvider} registered on the client; clicking
160
+ * one calls `client.login({ provider: id })` and the provider opens its own UI.
161
+ */
162
+ customProviders?: CustomLoginProvider[];
131
163
  };
132
164
  adapters?: PollarAdapters;
133
165
  /**
@@ -252,11 +284,15 @@ interface LoginModalTemplateProps {
252
284
  github: boolean;
253
285
  apple: boolean;
254
286
  };
287
+ /** Custom login provider buttons (e.g. Privy). Each calls `onCustomLogin(id)`. */
288
+ customProviders?: CustomLoginProvider[];
255
289
  appName: string;
256
290
  email?: string;
257
291
  onEmailChange?: (email: string) => void;
258
292
  onEmailSubmit?: () => void;
259
293
  onSocialLogin?: (provider: 'google' | 'github') => void;
294
+ /** Triggers a custom provider login by id (wraps `client.login({ provider: id })`). */
295
+ onCustomLogin?: (id: string) => void;
260
296
  onWalletConnect?: (id: WalletId) => void;
261
297
  /** Log in with an existing passkey (returning user). */
262
298
  onLoginSmartWallet?: () => void;
@@ -271,7 +307,7 @@ interface LoginModalTemplateProps {
271
307
  onCancel: () => void;
272
308
  onRetry: () => void;
273
309
  }
274
- declare function LoginModalTemplate({ theme, accentColor, logoUrl, emailEnabled, embeddedWallets, smartWallet, providers, appName, email, onEmailChange, onEmailSubmit, onSocialLogin, onWalletConnect, onLoginSmartWallet, onCreateSmartWallet, renderWallets, authState, codeInputKey, onCodeSubmit, onBack, onCancel, onRetry, }: LoginModalTemplateProps): react_jsx_runtime.JSX.Element;
310
+ declare function LoginModalTemplate({ theme, accentColor, logoUrl, emailEnabled, embeddedWallets, smartWallet, providers, customProviders, appName, email, onEmailChange, onEmailSubmit, onSocialLogin, onCustomLogin, onWalletConnect, onLoginSmartWallet, onCreateSmartWallet, renderWallets, authState, codeInputKey, onCodeSubmit, onBack, onCancel, onRetry, }: LoginModalTemplateProps): react_jsx_runtime.JSX.Element;
275
311
 
276
312
  type KycStep = 'select_provider' | 'verifying' | 'polling' | 'done';
277
313
  interface KycModalTemplateProps {
@@ -447,4 +483,4 @@ interface DistributionRulesModalTemplateProps {
447
483
  }
448
484
  declare function DistributionRulesModalTemplate({ theme, accentColor, state, claimingId, claimErrors, claimedIds, onRefresh, onClaim, onClose, }: DistributionRulesModalTemplateProps): react_jsx_runtime.JSX.Element;
449
485
 
450
- export { type AuthModalProps, DistributionRulesModal, DistributionRulesModalTemplate, EnabledAssetsModal, EnabledAssetsModalTemplate, type EnabledAssetsModalTemplateProps, KycModal, KycModalTemplate, KycStatus, type KycStep, type LoginButtonProps, LoginModalTemplate, type PollarConfig, PollarProvider, type PollarStyles, type RampStep, RampWidget, RampWidgetTemplate, ReceiveModal, ReceiveModalTemplate, type ReceiveModalTemplateProps, type RenderWalletsProps, type RenderWalletsSlot, RouteDisplay, SendModal, SendModalTemplate, type SendModalTemplateProps, SessionsModal, SessionsModalTemplate, type SessionsModalTemplateProps, TransactionModalTemplate, type TransactionModalTemplateProps, TxHistoryModalTemplate, TxStatusView, type TxStatusViewProps, WalletBalanceModal, WalletBalanceModalTemplate, type WalletBalanceModalTemplateProps, WalletButton, WalletButtonTemplate, type WalletButtonTemplateProps, createPollarAdapterHook, usePollar };
486
+ export { type AuthModalProps, type CustomLoginProvider, DistributionRulesModal, DistributionRulesModalTemplate, EnabledAssetsModal, EnabledAssetsModalTemplate, type EnabledAssetsModalTemplateProps, KycModal, KycModalTemplate, KycStatus, type KycStep, type LoginButtonProps, LoginModalTemplate, type PollarConfig, PollarProvider, type PollarStyles, type RampStep, RampWidget, RampWidgetTemplate, ReceiveModal, ReceiveModalTemplate, type ReceiveModalTemplateProps, type RenderWalletsProps, type RenderWalletsSlot, RouteDisplay, SendModal, SendModalTemplate, type SendModalTemplateProps, SessionsModal, SessionsModalTemplate, type SessionsModalTemplateProps, TransactionModalTemplate, type TransactionModalTemplateProps, TxHistoryModalTemplate, TxStatusView, type TxStatusViewProps, WalletBalanceModal, WalletBalanceModalTemplate, type WalletBalanceModalTemplateProps, WalletButton, WalletButtonTemplate, type WalletButtonTemplateProps, createPollarAdapterHook, usePollar };
package/dist/index.js CHANGED
@@ -1035,7 +1035,7 @@ var PollarModalFooter = () => {
1035
1035
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
1036
1036
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-footer-version", children: [
1037
1037
  "v",
1038
- "0.9.0"
1038
+ "0.10.0-rc.0"
1039
1039
  ] })
1040
1040
  ] })
1041
1041
  ] });
@@ -1340,54 +1340,63 @@ function EnabledAssetsModalTemplate({
1340
1340
  const isLoading = enabledAssets.step === "loading";
1341
1341
  const data = enabledAssets.step === "loaded" ? enabledAssets.data : null;
1342
1342
  const busy = busyKey !== null;
1343
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-card pollar-asset-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
1344
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
1345
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: "Trustlines" }),
1346
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
1347
- /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "pollar-modal-refresh-btn", onClick: onRefresh, disabled: isLoading || busy, children: [
1348
- /* @__PURE__ */ jsxRuntime.jsxs(
1349
- "svg",
1350
- {
1351
- className: `pollar-modal-refresh-icon${isLoading ? " spinning" : ""}`,
1352
- width: "13",
1353
- height: "13",
1354
- viewBox: "0 0 13 13",
1355
- fill: "none",
1356
- "aria-hidden": true,
1357
- children: [
1358
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M11.5 6.5a5 5 0 11-1.5-3.536", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1359
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1360
- ]
1361
- }
1362
- ),
1363
- "Refresh"
1343
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1344
+ "div",
1345
+ {
1346
+ className: "pollar-modal-card pollar-asset-modal",
1347
+ "data-theme": theme,
1348
+ style: cssVars,
1349
+ onClick: (e) => e.stopPropagation(),
1350
+ children: [
1351
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
1352
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: "Trustlines" }),
1353
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
1354
+ /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "pollar-modal-refresh-btn", onClick: onRefresh, disabled: isLoading || busy, children: [
1355
+ /* @__PURE__ */ jsxRuntime.jsxs(
1356
+ "svg",
1357
+ {
1358
+ className: `pollar-modal-refresh-icon${isLoading ? " spinning" : ""}`,
1359
+ width: "13",
1360
+ height: "13",
1361
+ viewBox: "0 0 13 13",
1362
+ fill: "none",
1363
+ "aria-hidden": true,
1364
+ children: [
1365
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M11.5 6.5a5 5 0 11-1.5-3.536", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
1366
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 1v3h-3", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1367
+ ]
1368
+ }
1369
+ ),
1370
+ "Refresh"
1371
+ ] }),
1372
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
1373
+ ] })
1364
1374
  ] }),
1365
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
1366
- ] })
1367
- ] }),
1368
- walletAddress && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-asset-address", children: cropAddress(walletAddress) }),
1369
- isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
1370
- enabledAssets.step === "error" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: enabledAssets.message }),
1371
- actionError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-action-error", children: actionError }),
1372
- data && !data.exists && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-empty", children: [
1373
- "Account not found on ",
1374
- data.network,
1375
- "."
1376
- ] }),
1377
- data && data.assets.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "No trustlines found." }),
1378
- data && data.assets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-asset-list", children: data.assets.map((a) => /* @__PURE__ */ jsxRuntime.jsx(
1379
- AssetItem,
1380
- {
1381
- record: a,
1382
- busy: busyKey === assetKey(a),
1383
- disabled: busy && busyKey !== assetKey(a),
1384
- onToggle: onToggleTrustline
1385
- },
1386
- assetKey(a)
1387
- )) }),
1388
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-asset-add-custom", onClick: onAddCustom, disabled: busy, children: "+ Add custom trustline" }),
1389
- /* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
1390
- ] });
1375
+ walletAddress && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-asset-address", children: cropAddress(walletAddress) }),
1376
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "Loading\u2026" }),
1377
+ enabledAssets.step === "error" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-error", children: enabledAssets.message }),
1378
+ actionError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-action-error", children: actionError }),
1379
+ data && !data.exists && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-empty", children: [
1380
+ "Account not found on ",
1381
+ data.network,
1382
+ "."
1383
+ ] }),
1384
+ data && data.assets.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "No trustlines found." }),
1385
+ data && data.assets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-asset-list", children: data.assets.map((a) => /* @__PURE__ */ jsxRuntime.jsx(
1386
+ AssetItem,
1387
+ {
1388
+ record: a,
1389
+ busy: busyKey === assetKey(a),
1390
+ disabled: busy && busyKey !== assetKey(a),
1391
+ onToggle: onToggleTrustline
1392
+ },
1393
+ assetKey(a)
1394
+ )) }),
1395
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-asset-add-custom", onClick: onAddCustom, disabled: busy, children: "+ Add custom trustline" }),
1396
+ /* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
1397
+ ]
1398
+ }
1399
+ );
1391
1400
  }
1392
1401
  function isValidIssuer(issuer) {
1393
1402
  return issuer.length === 56 && issuer.startsWith("G");
@@ -1413,79 +1422,89 @@ function CustomTrustlineModalTemplate({
1413
1422
  const trimmedLimit = limit.trim();
1414
1423
  onSubmit({ code: code.trim(), issuer: issuer.trim(), ...trimmedLimit ? { limit: trimmedLimit } : {} });
1415
1424
  };
1416
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-card pollar-asset-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
1417
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
1418
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
1419
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-modal-back", onClick: onBack, disabled: busy, "aria-label": "Back", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 3L5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
1420
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: "Add custom trustline" })
1421
- ] }),
1422
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
1423
- ] }),
1424
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-asset-custom-hint", children: "Custom trustlines aren't sponsored \u2014 your wallet pays the 0.5 XLM reserve and the transaction fee." }),
1425
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-field", children: [
1426
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-label", htmlFor: "pollar-trustline-code", children: "Asset code" }),
1427
- /* @__PURE__ */ jsxRuntime.jsx(
1428
- "input",
1429
- {
1430
- id: "pollar-trustline-code",
1431
- className: "pollar-input",
1432
- value: code,
1433
- onChange: (e) => setCode(e.target.value),
1434
- placeholder: "USDC",
1435
- maxLength: 12,
1436
- autoComplete: "off",
1437
- spellCheck: false,
1438
- disabled: busy
1439
- }
1440
- )
1441
- ] }),
1442
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-field", children: [
1443
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-label", htmlFor: "pollar-trustline-issuer", children: "Issuer" }),
1444
- /* @__PURE__ */ jsxRuntime.jsx(
1445
- "input",
1446
- {
1447
- id: "pollar-trustline-issuer",
1448
- className: "pollar-input",
1449
- value: issuer,
1450
- onChange: (e) => setIssuer(e.target.value),
1451
- placeholder: "G\u2026",
1452
- autoComplete: "off",
1453
- spellCheck: false,
1454
- disabled: busy
1455
- }
1456
- ),
1457
- issuer.trim().length > 0 && !issuerOk && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-field-error", children: "Issuer must be a 56-character Stellar address starting with G." })
1458
- ] }),
1459
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-field", children: [
1460
- /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-label", htmlFor: "pollar-trustline-limit", children: [
1461
- "Limit ",
1462
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-label-optional", children: "(optional)" })
1463
- ] }),
1464
- /* @__PURE__ */ jsxRuntime.jsx(
1465
- "input",
1466
- {
1467
- id: "pollar-trustline-limit",
1468
- className: "pollar-input",
1469
- value: limit,
1470
- onChange: (e) => setLimit(e.target.value),
1471
- placeholder: "Maximum",
1472
- inputMode: "decimal",
1473
- autoComplete: "off",
1474
- spellCheck: false,
1475
- disabled: busy
1476
- }
1477
- )
1478
- ] }),
1479
- actionError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-action-error", children: actionError }),
1480
- /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-asset-submit", onClick: submit, disabled: !canSubmit, children: busy ? "Enabling\u2026" : "Enable trustline" }),
1481
- /* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
1482
- ] });
1425
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1426
+ "div",
1427
+ {
1428
+ className: "pollar-modal-card pollar-asset-modal",
1429
+ "data-theme": theme,
1430
+ style: cssVars,
1431
+ onClick: (e) => e.stopPropagation(),
1432
+ children: [
1433
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
1434
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header-actions", children: [
1435
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-modal-back", onClick: onBack, disabled: busy, "aria-label": "Back", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 3L5 8l5 5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
1436
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: "Add custom trustline" })
1437
+ ] }),
1438
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
1439
+ ] }),
1440
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-asset-custom-hint", children: "Custom trustlines aren't sponsored \u2014 your wallet pays the 0.5 XLM reserve and the transaction fee." }),
1441
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-field", children: [
1442
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-label", htmlFor: "pollar-trustline-code", children: "Asset code" }),
1443
+ /* @__PURE__ */ jsxRuntime.jsx(
1444
+ "input",
1445
+ {
1446
+ id: "pollar-trustline-code",
1447
+ className: "pollar-input",
1448
+ value: code,
1449
+ onChange: (e) => setCode(e.target.value),
1450
+ placeholder: "USDC",
1451
+ maxLength: 12,
1452
+ autoComplete: "off",
1453
+ spellCheck: false,
1454
+ disabled: busy
1455
+ }
1456
+ )
1457
+ ] }),
1458
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-field", children: [
1459
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-label", htmlFor: "pollar-trustline-issuer", children: "Issuer" }),
1460
+ /* @__PURE__ */ jsxRuntime.jsx(
1461
+ "input",
1462
+ {
1463
+ id: "pollar-trustline-issuer",
1464
+ className: "pollar-input",
1465
+ value: issuer,
1466
+ onChange: (e) => setIssuer(e.target.value),
1467
+ placeholder: "G\u2026",
1468
+ autoComplete: "off",
1469
+ spellCheck: false,
1470
+ disabled: busy
1471
+ }
1472
+ ),
1473
+ issuer.trim().length > 0 && !issuerOk && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-field-error", children: "Issuer must be a 56-character Stellar address starting with G." })
1474
+ ] }),
1475
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-field", children: [
1476
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-label", htmlFor: "pollar-trustline-limit", children: [
1477
+ "Limit ",
1478
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-label-optional", children: "(optional)" })
1479
+ ] }),
1480
+ /* @__PURE__ */ jsxRuntime.jsx(
1481
+ "input",
1482
+ {
1483
+ id: "pollar-trustline-limit",
1484
+ className: "pollar-input",
1485
+ value: limit,
1486
+ onChange: (e) => setLimit(e.target.value),
1487
+ placeholder: "Maximum",
1488
+ inputMode: "decimal",
1489
+ autoComplete: "off",
1490
+ spellCheck: false,
1491
+ disabled: busy
1492
+ }
1493
+ )
1494
+ ] }),
1495
+ actionError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-action-error", children: actionError }),
1496
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-asset-submit", onClick: submit, disabled: !canSubmit, children: busy ? "Enabling\u2026" : "Enable trustline" }),
1497
+ /* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
1498
+ ]
1499
+ }
1500
+ );
1483
1501
  }
1484
1502
  function assetKey2(record) {
1485
1503
  return record.code + (record.issuer ?? "");
1486
1504
  }
1487
1505
  function EnabledAssetsModal({ onClose }) {
1488
- const { enabledAssets, refreshAssets, setTrustline, walletAddress, styles } = usePollar();
1506
+ const { enabledAssets, refreshAssets, setTrustline, wallet, styles } = usePollar();
1507
+ const walletAddress = wallet?.address ?? "";
1489
1508
  const { theme = "light", accentColor = "#005DB4" } = styles;
1490
1509
  const [view, setView] = react.useState("list");
1491
1510
  const [busyKey, setBusyKey] = react.useState(null);
@@ -1872,6 +1891,7 @@ var AUTH_STATE_MESSAGES = {
1872
1891
  verifying_email_code: "Verifying\u2026",
1873
1892
  opening_oauth: "Redirecting\u2026",
1874
1893
  connecting_wallet: "Connecting wallet\u2026",
1894
+ signing_wallet_challenge: "Confirm in your wallet\u2026",
1875
1895
  wallet_not_installed: "Wallet not installed",
1876
1896
  authenticating_wallet: "Signing in with wallet\u2026",
1877
1897
  creating_passkey: "Waiting for passkey\u2026",
@@ -1887,6 +1907,7 @@ function authStateToStatus(step) {
1887
1907
  "verifying_email_code",
1888
1908
  "opening_oauth",
1889
1909
  "connecting_wallet",
1910
+ "signing_wallet_challenge",
1890
1911
  "authenticating_wallet",
1891
1912
  "creating_passkey",
1892
1913
  "deploying_smart_account",
@@ -1907,11 +1928,13 @@ function LoginModalTemplate({
1907
1928
  embeddedWallets,
1908
1929
  smartWallet = false,
1909
1930
  providers,
1931
+ customProviders = [],
1910
1932
  appName,
1911
1933
  email = "",
1912
1934
  onEmailChange,
1913
1935
  onEmailSubmit,
1914
1936
  onSocialLogin,
1937
+ onCustomLogin,
1915
1938
  onWalletConnect,
1916
1939
  onLoginSmartWallet,
1917
1940
  onCreateSmartWallet,
@@ -1998,27 +2021,8 @@ function LoginModalTemplate({
1998
2021
  ] }) : showPasskeyChooser ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1999
2022
  /* @__PURE__ */ jsxRuntime.jsx(BackButton, { onClick: () => setShowPasskeyChooser(false) }),
2000
2023
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-wallet-section", children: [
2001
- /* @__PURE__ */ jsxRuntime.jsx(
2002
- "button",
2003
- {
2004
- type: "button",
2005
- disabled: isLoading,
2006
- className: "pollar-btn-primary",
2007
- style: { width: "100%" },
2008
- onClick: onCreateSmartWallet,
2009
- children: "Create a new wallet"
2010
- }
2011
- ),
2012
- /* @__PURE__ */ jsxRuntime.jsx(
2013
- "button",
2014
- {
2015
- type: "button",
2016
- disabled: isLoading,
2017
- className: "pollar-wallet-entry-btn",
2018
- onClick: onLoginSmartWallet,
2019
- children: "Log in with an existing wallet"
2020
- }
2021
- )
2024
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", disabled: isLoading, className: "pollar-btn-primary", onClick: onCreateSmartWallet, children: "Create a new wallet" }),
2025
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", disabled: isLoading, className: "pollar-wallet-entry-btn", onClick: onLoginSmartWallet, children: "Log in with an existing wallet" })
2022
2026
  ] })
2023
2027
  ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2024
2028
  emailEnabled && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-email-section", children: [
@@ -2040,13 +2044,13 @@ function LoginModalTemplate({
2040
2044
  type: "button",
2041
2045
  disabled: isLoading || !email,
2042
2046
  className: "pollar-btn-primary",
2043
- style: { marginTop: "0.75rem", width: "100%" },
2047
+ style: { marginTop: "0.75rem" },
2044
2048
  onClick: onEmailSubmit,
2045
2049
  children: "Submit"
2046
2050
  }
2047
2051
  )
2048
2052
  ] }),
2049
- emailEnabled && enabledSocial.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-divider", children: [
2053
+ emailEnabled && (enabledSocial.length > 0 || customProviders.length > 0) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-divider", children: [
2050
2054
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-divider-line" }),
2051
2055
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-divider-label", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-divider-text", children: "or continue with" }) })
2052
2056
  ] }),
@@ -2054,6 +2058,20 @@ function LoginModalTemplate({
2054
2058
  enabledSocial.some(([key]) => key === "google") && /* @__PURE__ */ jsxRuntime.jsx(GoogleButton, { disabled: isLoading, onClick: () => onSocialLogin?.("google") }),
2055
2059
  enabledSocial.some(([key]) => key === "github") && /* @__PURE__ */ jsxRuntime.jsx(GithubButton, { disabled: isLoading, onClick: () => onSocialLogin?.("github") })
2056
2060
  ] }),
2061
+ customProviders.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-social-list", children: customProviders.map((p) => /* @__PURE__ */ jsxRuntime.jsxs(
2062
+ "button",
2063
+ {
2064
+ type: "button",
2065
+ disabled: isLoading,
2066
+ className: "pollar-wallet-entry-btn",
2067
+ onClick: () => onCustomLogin?.(p.id),
2068
+ children: [
2069
+ p.iconUrl && /* @__PURE__ */ jsxRuntime.jsx("img", { src: p.iconUrl, alt: "", className: "pollar-wallet-list-icon" }),
2070
+ p.label
2071
+ ]
2072
+ },
2073
+ p.id
2074
+ )) }),
2057
2075
  (embeddedWallets || smartWallet) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-wallet-section", children: [
2058
2076
  embeddedWallets && /* @__PURE__ */ jsxRuntime.jsxs(
2059
2077
  "button",
@@ -2123,7 +2141,7 @@ function LoginModalTemplate({
2123
2141
  }
2124
2142
  function LoginModal({ onClose }) {
2125
2143
  const [email, setEmail] = react.useState("");
2126
- const { getClient, styles, appConfig: config, renderWallets } = usePollar();
2144
+ const { getClient, styles, appConfig: config, renderWallets, customProviders } = usePollar();
2127
2145
  const [authState, setAuthState] = react.useState(() => getClient().getAuthState());
2128
2146
  const [codeInputKey, setCodeInputKey] = react.useState(0);
2129
2147
  const pendingEmail = react.useRef(null);
@@ -2173,6 +2191,9 @@ function LoginModal({ onClose }) {
2173
2191
  function handleSocialLogin(provider) {
2174
2192
  getClient().login({ provider });
2175
2193
  }
2194
+ function handleCustomLogin(id) {
2195
+ getClient().login({ provider: id });
2196
+ }
2176
2197
  function handleWalletConnect(type) {
2177
2198
  getClient().loginWallet(type);
2178
2199
  }
@@ -2211,11 +2232,13 @@ function LoginModal({ onClose }) {
2211
2232
  github: !!providers?.github,
2212
2233
  apple: !!providers?.apple
2213
2234
  },
2235
+ ...customProviders !== void 0 && { customProviders },
2214
2236
  appName: config.application?.name ?? "Pollar",
2215
2237
  email,
2216
2238
  onEmailChange: setEmail,
2217
2239
  onEmailSubmit: handleEmailSubmit,
2218
2240
  onSocialLogin: handleSocialLogin,
2241
+ onCustomLogin: handleCustomLogin,
2219
2242
  onWalletConnect: handleWalletConnect,
2220
2243
  onLoginSmartWallet: handleLoginSmartWallet,
2221
2244
  onCreateSmartWallet: handleCreateSmartWallet,
@@ -2544,7 +2567,8 @@ var MOCK_PAYMENT = {
2544
2567
  expiresAt: new Date(Date.now() + 30 * 60 * 1e3).toISOString()
2545
2568
  };
2546
2569
  function RampWidget({ onClose }) {
2547
- const { getClient, walletAddress, styles } = usePollar();
2570
+ const { getClient, wallet, styles } = usePollar();
2571
+ const walletAddress = wallet?.address ?? "";
2548
2572
  const [step, setStep] = react.useState("input");
2549
2573
  const [direction, setDirection] = react.useState("onramp");
2550
2574
  const [amount, setAmount] = react.useState("");
@@ -2747,7 +2771,8 @@ function ReceiveModalTemplate({
2747
2771
  );
2748
2772
  }
2749
2773
  function ReceiveModal({ onClose }) {
2750
- const { walletAddress, styles } = usePollar();
2774
+ const { wallet, styles } = usePollar();
2775
+ const walletAddress = wallet?.address ?? "";
2751
2776
  const { theme = "light", accentColor = "#005DB4" } = styles;
2752
2777
  const [copied, setCopied] = react.useState(false);
2753
2778
  const copyTimerRef = react.useRef(null);
@@ -3155,10 +3180,11 @@ function SendModal({ onClose }) {
3155
3180
  buildTx,
3156
3181
  signAndSubmitTx,
3157
3182
  tx: transaction,
3158
- walletType,
3183
+ wallet,
3159
3184
  network,
3160
3185
  styles
3161
3186
  } = usePollar();
3187
+ const walletType = wallet?.custody === "external" ? wallet.provider : null;
3162
3188
  const { theme = "light", accentColor = "#005DB4" } = styles;
3163
3189
  const [step, setStep] = react.useState("form");
3164
3190
  const [amount, setAmount] = react.useState("");
@@ -3567,7 +3593,8 @@ function TransactionModalTemplate({
3567
3593
  ] });
3568
3594
  }
3569
3595
  function TransactionModal({ onClose }) {
3570
- const { getClient, styles, tx: transaction, network, walletType } = usePollar();
3596
+ const { getClient, styles, tx: transaction, network, wallet } = usePollar();
3597
+ const walletType = wallet?.custody === "external" ? wallet.provider : null;
3571
3598
  const { theme = "light", accentColor = "#005DB4" } = styles;
3572
3599
  const [showXdr, setShowXdr] = react.useState(false);
3573
3600
  const [copied, setCopied] = react.useState(false);
@@ -3889,7 +3916,8 @@ function WalletBalanceModalTemplate({
3889
3916
  ] });
3890
3917
  }
3891
3918
  function WalletBalanceModal({ onClose }) {
3892
- const { walletBalance, refreshWalletBalance, walletAddress, styles } = usePollar();
3919
+ const { walletBalance, refreshWalletBalance, wallet, styles } = usePollar();
3920
+ const walletAddress = wallet?.address ?? "";
3893
3921
  const { theme = "light", accentColor = "#005DB4" } = styles;
3894
3922
  react.useEffect(() => {
3895
3923
  void refreshWalletBalance();
@@ -4057,14 +4085,14 @@ function PollarProvider({
4057
4085
  const refreshWalletBalance = react.useCallback(() => pollarClient.refreshBalance(), [pollarClient, walletAddress]);
4058
4086
  const refreshAssets = react.useCallback(() => pollarClient.refreshAssets(), [pollarClient, walletAddress]);
4059
4087
  const renderWallets = ui?.renderWallets;
4088
+ const customProviders = ui?.customProviders;
4060
4089
  const contextValue = react.useMemo(() => {
4061
4090
  const styles = resolvedConfig.styles ?? {};
4062
4091
  return {
4063
4092
  // session
4064
- walletAddress,
4093
+ wallet: pollarClient.getWallet(),
4065
4094
  isAuthenticated: !!walletAddress,
4066
4095
  verified,
4067
- walletType: pollarClient.getWalletType(),
4068
4096
  // client
4069
4097
  getClient,
4070
4098
  // auth
@@ -4114,6 +4142,7 @@ function PollarProvider({
4114
4142
  appConfig: resolvedConfig,
4115
4143
  styles,
4116
4144
  renderWallets,
4145
+ customProviders,
4117
4146
  adapters
4118
4147
  };
4119
4148
  }, [
@@ -4131,7 +4160,8 @@ function PollarProvider({
4131
4160
  networkState,
4132
4161
  resolvedConfig,
4133
4162
  adapters,
4134
- renderWallets
4163
+ renderWallets,
4164
+ customProviders
4135
4165
  ]);
4136
4166
  return /* @__PURE__ */ jsxRuntime.jsxs(PollarContext.Provider, { value: contextValue, children: [
4137
4167
  children,
@@ -4484,7 +4514,7 @@ function WalletButtonTemplate({
4484
4514
  function WalletButton() {
4485
4515
  const {
4486
4516
  getClient,
4487
- walletAddress,
4517
+ wallet,
4488
4518
  styles,
4489
4519
  openLoginModal,
4490
4520
  openTxHistoryModal,
@@ -4495,9 +4525,10 @@ function WalletButton() {
4495
4525
  openKycModal,
4496
4526
  openRampModal,
4497
4527
  openDistributionRulesModal,
4498
- tx: transaction,
4499
- walletType
4528
+ tx: transaction
4500
4529
  } = usePollar();
4530
+ const walletAddress = wallet?.address ?? "";
4531
+ const walletType = wallet?.custody === "external" ? wallet.provider : null;
4501
4532
  const [open, setOpen] = react.useState(false);
4502
4533
  const [copied, setCopied] = react.useState(false);
4503
4534
  const wrapperRef = react.useRef(null);