@pollar/react 0.11.1 → 0.11.2
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/README.md +20 -14
- package/dist/index.d.mts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +61 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +61 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -3,14 +3,20 @@
|
|
|
3
3
|
React bindings for [Pollar](https://pollar.xyz) — drop-in authentication UI, transaction modals, and hooks for
|
|
4
4
|
Stellar and Solana applications.
|
|
5
5
|
|
|
6
|
-
> **0.11.
|
|
7
|
-
> picker
|
|
8
|
-
>
|
|
9
|
-
>
|
|
10
|
-
>
|
|
11
|
-
>
|
|
12
|
-
>
|
|
13
|
-
>
|
|
6
|
+
> **0.11.2** requires `@pollar/core@^0.11.2`. The **Transaction History modal
|
|
7
|
+
> goes multichain**: the same network picker and address chip as the Balance /
|
|
8
|
+
> Send modals, a server-side chain filter (pagination is server-side, so
|
|
9
|
+
> switching networks refetches and resets to page 1), per-chain explorer links
|
|
10
|
+
> (stellar.expert for Stellar, explorer.solana.com for Solana), and the unified
|
|
11
|
+
> `{ amount, unit }` fee, so a Solana row reads "5000 lamports". The picker
|
|
12
|
+
> hides itself on a single-chain app. Non-breaking.
|
|
13
|
+
>
|
|
14
|
+
> Earlier: **0.11.1** added the network picker (`<ChainSelect>`) across the
|
|
15
|
+
> wallet-balance, enabled-assets, send and receive modals - each scopes its rows
|
|
16
|
+
> to the selected chain instead of tagging every row, with a local filter (the
|
|
17
|
+
> backend returns every chain in one payload). Balances format against each
|
|
18
|
+
> token's own `decimals`, and a `null` balance renders as a dash rather than as
|
|
19
|
+
> `0`, because `null` means the chain could not be read. See the
|
|
14
20
|
> [CHANGELOG](../../CHANGELOG.md) and [UPGRADE.md](../../UPGRADE.md) for the full
|
|
15
21
|
> version history before upgrading.
|
|
16
22
|
|
|
@@ -97,11 +103,11 @@ Context provider that initialises the Pollar client and makes it available to ch
|
|
|
97
103
|
</PollarProvider>
|
|
98
104
|
```
|
|
99
105
|
|
|
100
|
-
| Prop | Type | Required | Description
|
|
101
|
-
| ----------- | ------------------------------------ | -------- |
|
|
102
|
-
| `client` | `PollarClient \| PollarClientConfig` | Yes | Either a pre-built `PollarClient` (testing, reuse outside React) or a `PollarClientConfig` the provider will construct one from. **Locked at first render** — swapping after mount is ignored
|
|
103
|
-
| `appConfig` | `PollarConfig` | No | Local override of `/applications/config`. **Presence is the opt-out switch**: pass it (even `{}`) and the remote fetch is skipped. Omit it to keep the existing remote-fetch-on-mount behaviour |
|
|
104
|
-
| `adapters` | `PollarAdapters` | No | Named set of `PollarAdapter` objects (e.g. Trustless Work). See below
|
|
106
|
+
| Prop | Type | Required | Description |
|
|
107
|
+
| ----------- | ------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
108
|
+
| `client` | `PollarClient \| PollarClientConfig` | Yes | Either a pre-built `PollarClient` (testing, reuse outside React) or a `PollarClientConfig` the provider will construct one from. **Locked at first render** — swapping after mount is ignored |
|
|
109
|
+
| `appConfig` | `PollarConfig` | No | Local override of `/applications/config`. **Presence is the opt-out switch**: pass it (even `{}`) and the remote fetch is skipped. Omit it to keep the existing remote-fetch-on-mount behaviour. Unlike `client`, it can be added or swapped after mount — the context re-applies it (compared by value, so an inline object literal is fine) |
|
|
110
|
+
| `adapters` | `PollarAdapters` | No | Named set of `PollarAdapter` objects (e.g. Trustless Work). See below |
|
|
105
111
|
|
|
106
112
|
---
|
|
107
113
|
|
|
@@ -296,7 +302,7 @@ already wired inside `<PollarProvider>` — and most are exported in case you wa
|
|
|
296
302
|
| `<SwapModal>` | On-chain asset-to-asset swap: pick from/to assets and amount, quote across venues, execute (auto-trustline on the buy asset when needed); paste a custom buy token (code + issuer) |
|
|
297
303
|
| `<EarnModal>` | Deposit/withdraw across DeFindex vaults and Blend pools: provider + opportunity selection with live APY, wallet balance, over-spend guards, and auto-trustline on deposit |
|
|
298
304
|
| `<ReceiveModal>` | Wallet address as QR code with copy-to-clipboard (no external QR dependency required) |
|
|
299
|
-
| `<TxHistoryModal>` | Paginated transaction history with auto-fetch on open and stellar.expert explorer
|
|
305
|
+
| `<TxHistoryModal>` | Paginated multichain transaction history with auto-fetch on open. A `<ChainSelect>` in the header filters server-side (switching networks refetches and resets to page 1); rows link to their own chain's explorer (stellar.expert for Stellar, explorer.solana.com for Solana) and show the unified `{ amount, unit }` fee |
|
|
300
306
|
| `<WalletBalanceModal>` | Multichain wallet balances (Stellar, Polygon, Solana). A `<ChainSelect>` in the header picks the network and the rows are filtered to it; shows that chain's address plus a refresh button. An unreadable chain's balance renders as a dash, never as `0`. On Solana testnet each row offers a faucet hint — a devnet SOL faucet on the native row, Circle's USDC faucet on the USDC row |
|
|
301
307
|
| `<EnabledAssetsModal>` | The application's dashboard-enabled assets for the network picked in the header, with per-asset trustline state; establish/remove trustlines (Stellar only - other chains are informational) |
|
|
302
308
|
| `<DistributionRulesModal>` | Manage the wallet's distribution rules |
|
package/dist/index.d.mts
CHANGED
|
@@ -535,12 +535,18 @@ interface TxHistoryModalTemplateProps {
|
|
|
535
535
|
accentColor: string;
|
|
536
536
|
txHistory: TxHistoryState;
|
|
537
537
|
offset: number;
|
|
538
|
+
/** Networks the user holds a wallet on; the first one is the default. */
|
|
539
|
+
chains: WalletChain[];
|
|
540
|
+
selectedChain: WalletChain | null;
|
|
541
|
+
/** Address of the wallet on {@link selectedChain}. */
|
|
542
|
+
walletAddress: string;
|
|
543
|
+
onSelectChain: (chain: WalletChain) => void;
|
|
538
544
|
onRefresh: () => void;
|
|
539
545
|
onPrev: () => void;
|
|
540
546
|
onNext: () => void;
|
|
541
547
|
onClose: () => void;
|
|
542
548
|
}
|
|
543
|
-
declare function TxHistoryModalTemplate({ theme, accentColor, txHistory, offset, onRefresh, onPrev, onNext, onClose, }: TxHistoryModalTemplateProps): react_jsx_runtime.JSX.Element;
|
|
549
|
+
declare function TxHistoryModalTemplate({ theme, accentColor, txHistory, offset, chains, selectedChain, walletAddress, onSelectChain, onRefresh, onPrev, onNext, onClose, }: TxHistoryModalTemplateProps): react_jsx_runtime.JSX.Element;
|
|
544
550
|
|
|
545
551
|
interface WalletBalanceModalTemplateProps {
|
|
546
552
|
theme: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -535,12 +535,18 @@ interface TxHistoryModalTemplateProps {
|
|
|
535
535
|
accentColor: string;
|
|
536
536
|
txHistory: TxHistoryState;
|
|
537
537
|
offset: number;
|
|
538
|
+
/** Networks the user holds a wallet on; the first one is the default. */
|
|
539
|
+
chains: WalletChain[];
|
|
540
|
+
selectedChain: WalletChain | null;
|
|
541
|
+
/** Address of the wallet on {@link selectedChain}. */
|
|
542
|
+
walletAddress: string;
|
|
543
|
+
onSelectChain: (chain: WalletChain) => void;
|
|
538
544
|
onRefresh: () => void;
|
|
539
545
|
onPrev: () => void;
|
|
540
546
|
onNext: () => void;
|
|
541
547
|
onClose: () => void;
|
|
542
548
|
}
|
|
543
|
-
declare function TxHistoryModalTemplate({ theme, accentColor, txHistory, offset, onRefresh, onPrev, onNext, onClose, }: TxHistoryModalTemplateProps): react_jsx_runtime.JSX.Element;
|
|
549
|
+
declare function TxHistoryModalTemplate({ theme, accentColor, txHistory, offset, chains, selectedChain, walletAddress, onSelectChain, onRefresh, onPrev, onNext, onClose, }: TxHistoryModalTemplateProps): react_jsx_runtime.JSX.Element;
|
|
544
550
|
|
|
545
551
|
interface WalletBalanceModalTemplateProps {
|
|
546
552
|
theme: string;
|
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.11.
|
|
1038
|
+
"0.11.2"
|
|
1039
1039
|
] })
|
|
1040
1040
|
] })
|
|
1041
1041
|
] });
|
|
@@ -4151,6 +4151,11 @@ function SendModal({ onClose }) {
|
|
|
4151
4151
|
setFormError("Enter a destination address");
|
|
4152
4152
|
return;
|
|
4153
4153
|
}
|
|
4154
|
+
const isNativeAsset = selectedAsset.type === "native";
|
|
4155
|
+
if (isBaseUnitChain && !isNativeAsset && (!selectedAsset.issuer || selectedAsset.decimals === void 0)) {
|
|
4156
|
+
setFormError("This token is missing its mint or decimals and cannot be sent.");
|
|
4157
|
+
return;
|
|
4158
|
+
}
|
|
4154
4159
|
let sendAmount = amount;
|
|
4155
4160
|
if (isBaseUnitChain) {
|
|
4156
4161
|
try {
|
|
@@ -4166,8 +4171,9 @@ function SendModal({ onClose }) {
|
|
|
4166
4171
|
chain: "SOLANA",
|
|
4167
4172
|
destination: destination.trim(),
|
|
4168
4173
|
amount: sendAmount,
|
|
4169
|
-
// Native SOL carries no mint; an SPL token's mint rides in `issuer
|
|
4170
|
-
|
|
4174
|
+
// Native SOL carries no mint; an SPL token's mint rides in `issuer`,
|
|
4175
|
+
// which the guard above proved is present.
|
|
4176
|
+
...isNativeAsset ? {} : { mint: selectedAsset.issuer }
|
|
4171
4177
|
});
|
|
4172
4178
|
return;
|
|
4173
4179
|
}
|
|
@@ -4639,7 +4645,7 @@ function SwapModal({ onClose }) {
|
|
|
4639
4645
|
const assetRecords = enabledAssets.step === "loaded" ? enabledAssets.data.assets : [];
|
|
4640
4646
|
const isLoadingData = walletBalance.step === "loading" || enabledAssets.step === "loading";
|
|
4641
4647
|
const sellOptions = balances.filter(
|
|
4642
|
-
(b) => b.
|
|
4648
|
+
(b) => (b.chain === void 0 || b.chain === "STELLAR") && (b.type === "native" || (b.type === "credit_alphanum4" || b.type === "credit_alphanum12") && !b.trustlineRemoved)
|
|
4643
4649
|
).map((b) => ({
|
|
4644
4650
|
ref: toRef(b),
|
|
4645
4651
|
code: b.code,
|
|
@@ -4952,9 +4958,7 @@ function EarnModal({ onClose }) {
|
|
|
4952
4958
|
if (!selectedOpportunity) return null;
|
|
4953
4959
|
const balances = walletBalance.step === "loaded" ? walletBalance.data.balances : [];
|
|
4954
4960
|
const issuer = selectedOpportunity.asset.issuer;
|
|
4955
|
-
const rec = balances.find(
|
|
4956
|
-
(b) => issuer === null ? b.type === "native" : b.code === assetCode && b.issuer === issuer
|
|
4957
|
-
);
|
|
4961
|
+
const rec = balances.find((b) => issuer === null ? b.type === "native" : b.code === assetCode && b.issuer === issuer);
|
|
4958
4962
|
return rec ? rec.available : null;
|
|
4959
4963
|
})();
|
|
4960
4964
|
const depositAssetRecord = (() => {
|
|
@@ -5631,6 +5635,12 @@ function TransactionModal({ onClose }) {
|
|
|
5631
5635
|
) });
|
|
5632
5636
|
}
|
|
5633
5637
|
var PAGE_SIZE = 10;
|
|
5638
|
+
function explorerUrlFor(chain, hash, network) {
|
|
5639
|
+
if (chain === "SOLANA") {
|
|
5640
|
+
return `https://explorer.solana.com/tx/${hash}${network === "testnet" ? "?cluster=devnet" : ""}`;
|
|
5641
|
+
}
|
|
5642
|
+
return `https://stellar.expert/explorer/${network === "testnet" ? "testnet" : "public"}/tx/${hash}`;
|
|
5643
|
+
}
|
|
5634
5644
|
function StatusBadge({ status }) {
|
|
5635
5645
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-hist-item-badge", "data-status": status, children: status });
|
|
5636
5646
|
}
|
|
@@ -5669,6 +5679,10 @@ function TxHistoryModalTemplate({
|
|
|
5669
5679
|
accentColor,
|
|
5670
5680
|
txHistory,
|
|
5671
5681
|
offset,
|
|
5682
|
+
chains,
|
|
5683
|
+
selectedChain,
|
|
5684
|
+
walletAddress,
|
|
5685
|
+
onSelectChain,
|
|
5672
5686
|
onRefresh,
|
|
5673
5687
|
onPrev,
|
|
5674
5688
|
onNext,
|
|
@@ -5744,6 +5758,11 @@ function TxHistoryModalTemplate({
|
|
|
5744
5758
|
/* @__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" }) }) })
|
|
5745
5759
|
] })
|
|
5746
5760
|
] }),
|
|
5761
|
+
/* @__PURE__ */ jsxRuntime.jsx(ChainSelect, { value: selectedChain, options: chains, onChange: onSelectChain, disabled: isLoading }),
|
|
5762
|
+
walletAddress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-address-row", children: [
|
|
5763
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-address", children: cropAddress(walletAddress) }),
|
|
5764
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value: walletAddress, label: "Copy wallet address" })
|
|
5765
|
+
] }),
|
|
5747
5766
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-hist-list", children: [
|
|
5748
5767
|
txHistory.step === "idle" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "Click Refresh to load transactions." }),
|
|
5749
5768
|
isLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-loading-block", children: [
|
|
@@ -5754,7 +5773,7 @@ function TxHistoryModalTemplate({
|
|
|
5754
5773
|
txHistory.step === "loaded" && records.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "No transactions yet." }),
|
|
5755
5774
|
records.map((record) => {
|
|
5756
5775
|
const hash = typeof record.hash === "string" && record.hash.length > 0 ? record.hash : void 0;
|
|
5757
|
-
const explorerUrl = hash ?
|
|
5776
|
+
const explorerUrl = hash ? explorerUrlFor(record.chain, hash, record.network) : void 0;
|
|
5758
5777
|
const asset = typeof record.details?.asset === "string" ? record.details.asset : void 0;
|
|
5759
5778
|
const colon = asset ? asset.indexOf(":") : -1;
|
|
5760
5779
|
const trustline = record.operation === "change_trust" && asset && colon > 0 ? {
|
|
@@ -5788,10 +5807,11 @@ function TxHistoryModalTemplate({
|
|
|
5788
5807
|
"\xB7 ",
|
|
5789
5808
|
record.details.sponsored ? "Sponsored" : "Self-paid"
|
|
5790
5809
|
] }),
|
|
5791
|
-
record.
|
|
5810
|
+
record.fee && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
5792
5811
|
"\xB7 ",
|
|
5793
|
-
record.
|
|
5794
|
-
"
|
|
5812
|
+
record.fee.amount,
|
|
5813
|
+
" ",
|
|
5814
|
+
record.fee.unit
|
|
5795
5815
|
] })
|
|
5796
5816
|
] }),
|
|
5797
5817
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-hist-item-footer", children: [
|
|
@@ -5807,7 +5827,7 @@ function TxHistoryModalTemplate({
|
|
|
5807
5827
|
href: explorerUrl,
|
|
5808
5828
|
target: "_blank",
|
|
5809
5829
|
rel: "noopener noreferrer",
|
|
5810
|
-
"aria-label": "View on
|
|
5830
|
+
"aria-label": "View on block explorer",
|
|
5811
5831
|
children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "12", height: "12", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
|
|
5812
5832
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5813
5833
|
"path",
|
|
@@ -5856,19 +5876,29 @@ function TxHistoryModalTemplate({
|
|
|
5856
5876
|
}
|
|
5857
5877
|
var PAGE_SIZE2 = 10;
|
|
5858
5878
|
function TxHistoryModal({ onClose }) {
|
|
5859
|
-
const { getClient, styles, txHistory } = usePollar();
|
|
5879
|
+
const { getClient, styles, txHistory, wallets } = usePollar();
|
|
5860
5880
|
const { theme = "light", accentColor = "#005DB4" } = styles;
|
|
5861
5881
|
const [offset, setOffset] = react.useState(0);
|
|
5882
|
+
const { chains } = useChains();
|
|
5883
|
+
const [selectedChain, setSelectedChain] = react.useState(null);
|
|
5884
|
+
react.useEffect(() => {
|
|
5885
|
+
if (selectedChain === null && chains.length > 0) setSelectedChain(chains[0]);
|
|
5886
|
+
}, [chains, selectedChain]);
|
|
5887
|
+
const walletAddress = addressForChain(wallets, selectedChain);
|
|
5862
5888
|
const load = react.useCallback(
|
|
5863
|
-
(nextOffset) => {
|
|
5889
|
+
(nextOffset, chain) => {
|
|
5864
5890
|
setOffset(nextOffset);
|
|
5865
|
-
void getClient().fetchTxHistory({ limit: PAGE_SIZE2, offset: nextOffset });
|
|
5891
|
+
void getClient().fetchTxHistory({ limit: PAGE_SIZE2, offset: nextOffset, chain });
|
|
5866
5892
|
},
|
|
5867
5893
|
[getClient]
|
|
5868
5894
|
);
|
|
5869
5895
|
react.useEffect(() => {
|
|
5870
|
-
load(0);
|
|
5871
|
-
}, [load]);
|
|
5896
|
+
if (selectedChain) load(0, selectedChain);
|
|
5897
|
+
}, [selectedChain, load]);
|
|
5898
|
+
const onSelectChain = (chain) => setSelectedChain(chain);
|
|
5899
|
+
const paged = (nextOffset) => {
|
|
5900
|
+
if (selectedChain) load(nextOffset, selectedChain);
|
|
5901
|
+
};
|
|
5872
5902
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5873
5903
|
TxHistoryModalTemplate,
|
|
5874
5904
|
{
|
|
@@ -5876,9 +5906,13 @@ function TxHistoryModal({ onClose }) {
|
|
|
5876
5906
|
accentColor,
|
|
5877
5907
|
txHistory,
|
|
5878
5908
|
offset,
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5909
|
+
chains,
|
|
5910
|
+
selectedChain,
|
|
5911
|
+
walletAddress,
|
|
5912
|
+
onSelectChain,
|
|
5913
|
+
onRefresh: () => paged(offset),
|
|
5914
|
+
onPrev: () => paged(Math.max(0, offset - PAGE_SIZE2)),
|
|
5915
|
+
onNext: () => paged(offset + PAGE_SIZE2),
|
|
5882
5916
|
onClose
|
|
5883
5917
|
}
|
|
5884
5918
|
) });
|
|
@@ -6147,6 +6181,9 @@ function PollarProvider({
|
|
|
6147
6181
|
);
|
|
6148
6182
|
const [configRetry, setConfigRetry] = react.useState(0);
|
|
6149
6183
|
const retryConfig = react.useCallback(() => setConfigRetry((n) => n + 1), []);
|
|
6184
|
+
const appConfigKey = appConfigProp === void 0 ? "" : JSON.stringify(appConfigProp);
|
|
6185
|
+
const appConfigPropRef = react.useRef(appConfigProp);
|
|
6186
|
+
appConfigPropRef.current = appConfigProp;
|
|
6150
6187
|
react.useEffect(() => {
|
|
6151
6188
|
return pollarClient.onTransactionStateChange(setTransaction);
|
|
6152
6189
|
}, [pollarClient]);
|
|
@@ -6210,7 +6247,9 @@ function PollarProvider({
|
|
|
6210
6247
|
setModalErrorLogger(pollarClient.getLogger());
|
|
6211
6248
|
}, [pollarClient]);
|
|
6212
6249
|
react.useEffect(() => {
|
|
6213
|
-
|
|
6250
|
+
const localConfig = appConfigPropRef.current;
|
|
6251
|
+
if (localConfig !== void 0) {
|
|
6252
|
+
setResolvedConfig(localConfig ?? DEFAULT_APP_CONFIG);
|
|
6214
6253
|
setConfigStatus("ready");
|
|
6215
6254
|
return;
|
|
6216
6255
|
}
|
|
@@ -6232,7 +6271,7 @@ function PollarProvider({
|
|
|
6232
6271
|
return () => {
|
|
6233
6272
|
cancelled = true;
|
|
6234
6273
|
};
|
|
6235
|
-
}, [pollarClient,
|
|
6274
|
+
}, [pollarClient, appConfigKey, configRetry]);
|
|
6236
6275
|
const [loginModalOpen, setLoginModalOpen] = react.useState(false);
|
|
6237
6276
|
const [transactionModalOpen, setTransactionModalOpen] = react.useState(false);
|
|
6238
6277
|
const [kycModalOpen, setKycModalOpen] = react.useState(false);
|