@pollar/react 0.11.1-rc.1 → 0.11.1
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 +92 -28
- package/dist/index.css +173 -124
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +143 -14
- package/dist/index.d.ts +143 -14
- package/dist/index.js +309 -76
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +307 -79
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -3,13 +3,16 @@
|
|
|
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.
|
|
7
|
-
>
|
|
8
|
-
>
|
|
9
|
-
>
|
|
10
|
-
>
|
|
11
|
-
> `
|
|
12
|
-
>
|
|
6
|
+
> **0.11.1** requires `@pollar/core@^0.11.1`. Headline feature: a **network
|
|
7
|
+
> picker** (`<ChainSelect>`) across the wallet-balance, enabled-assets, send and
|
|
8
|
+
> receive modals - each scopes its rows to the selected chain instead of tagging
|
|
9
|
+
> every row, and the filter is local (the backend returns every chain in one
|
|
10
|
+
> payload, so switching networks costs no request). Balances now format against
|
|
11
|
+
> each token's own `decimals`, and a `null` balance renders as a dash rather than
|
|
12
|
+
> as `0`, because `null` means the chain could not be read. The login modal shows
|
|
13
|
+
> loading / error state when the app config fails to load. See the
|
|
14
|
+
> [CHANGELOG](../../CHANGELOG.md) and [UPGRADE.md](../../UPGRADE.md) for the full
|
|
15
|
+
> version history before upgrading.
|
|
13
16
|
|
|
14
17
|
## Installation
|
|
15
18
|
|
|
@@ -69,11 +72,11 @@ Context provider that initialises the Pollar client and makes it available to ch
|
|
|
69
72
|
<PollarProvider
|
|
70
73
|
client={{
|
|
71
74
|
apiKey: 'your-api-key',
|
|
72
|
-
baseUrl: 'https://sdk.api.pollar.xyz', // optional
|
|
75
|
+
baseUrl: 'https://sdk.api.pollar.xyz', // optional, origin only — the SDK appends /v2
|
|
73
76
|
stellarNetwork: 'testnet', // optional, default: 'testnet'
|
|
74
77
|
storage, // optional, RN apps inject this
|
|
75
78
|
keyManager, // optional, autodetects on web
|
|
76
|
-
|
|
79
|
+
walletAdapters, // optional, WalletAdapter[] — external wallet stacks
|
|
77
80
|
deviceLabel: 'iPhone — Safari', // optional, shown in SessionsModal
|
|
78
81
|
onStorageDegrade, // optional, telemetry hook
|
|
79
82
|
}}
|
|
@@ -112,8 +115,15 @@ const {
|
|
|
112
115
|
// Session
|
|
113
116
|
isAuthenticated, // boolean - true when a wallet address is present
|
|
114
117
|
wallet, // WalletInfo | null - read wallet?.address for the on-chain address
|
|
118
|
+
wallets, // WalletInfo[] - every wallet the user holds, one per chain. To drive
|
|
119
|
+
// a network picker, prefer the useChains() hook (below) over reading
|
|
120
|
+
// this directly - it applies the app's configured chain order
|
|
115
121
|
verified, // boolean - true once the server has confirmed the session
|
|
116
122
|
|
|
123
|
+
// App config (the remote /config fetch behind the login modal)
|
|
124
|
+
configStatus, // 'loading' | 'ready' | 'error'
|
|
125
|
+
retryConfig, // () => void - re-runs the fetch after an error
|
|
126
|
+
|
|
117
127
|
// Client escape hatch
|
|
118
128
|
getClient, // () => PollarClient - for getUserProfile(), listSessions(), …
|
|
119
129
|
|
|
@@ -131,6 +141,7 @@ const {
|
|
|
131
141
|
buildTx, // (operation, params, options?) => Promise<BuildOutcome>
|
|
132
142
|
signAndSubmitTx, // (unsignedXdr?: string) => Promise<SubmitOutcome> (custodial; XDR optional)
|
|
133
143
|
signTx, // (unsignedXdr: string) => Promise<SignOutcome> (external-wallet only)
|
|
144
|
+
sendPayment, // (params: SendPaymentParams) => Promise<SubmitOutcome>
|
|
134
145
|
submitTx, // (signedXdr: string) => Promise<SubmitOutcome>
|
|
135
146
|
buildAndSignAndSubmitTx, // (operation, params, options?) => Promise<SubmitOutcome> (one-shot)
|
|
136
147
|
runTx, // alias of buildAndSignAndSubmitTx
|
|
@@ -148,12 +159,14 @@ const {
|
|
|
148
159
|
// Enabled assets / trustlines
|
|
149
160
|
enabledAssets, // EnabledAssetsState
|
|
150
161
|
refreshAssets, // () => Promise<void>
|
|
151
|
-
setTrustline, // (asset, opts?) => Promise<TrustlineOutcome>
|
|
162
|
+
setTrustline, // (asset, opts?: { limit?, skipSponsorship? }) => Promise<TrustlineOutcome> (sponsorship decided server-side)
|
|
152
163
|
openEnabledAssetsModal, // () => void
|
|
153
164
|
|
|
154
165
|
// Swap (DEX/AMM)
|
|
155
166
|
getSwapQuote, // (params: SwapQuoteParams) => Promise<SwapQuote[]>
|
|
156
167
|
swap, // (quote: SwapQuote, opts?) => Promise<SubmitOutcome>
|
|
168
|
+
getSwapConfig, // () => Promise<SwapVenue[]> (which venues this app offers)
|
|
169
|
+
getSwapTokens, // () => Promise<SwapToken[]>
|
|
157
170
|
openSwapModal, // () => void
|
|
158
171
|
|
|
159
172
|
// Earn (yield vaults + lending — DeFindex + Blend)
|
|
@@ -213,6 +226,14 @@ login({ provider: 'xbull' });
|
|
|
213
226
|
login({ provider: 'lobstr' });
|
|
214
227
|
```
|
|
215
228
|
|
|
229
|
+
#### When the app config fails to load
|
|
230
|
+
|
|
231
|
+
The login modal is gated on the remote app-config fetch. While it runs the modal shows a spinner; if it fails, it shows
|
|
232
|
+
"Could not load sign-in options. Check your connection and try again." plus a **Try again** button wired to
|
|
233
|
+
`retryConfig()`. Both states are readable from `usePollar().configStatus` (`'loading' | 'ready' | 'error'`) if you are
|
|
234
|
+
driving `<LoginModalTemplate>` yourself. Passing `appConfig` to `<PollarProvider>` opts out of the fetch entirely, so
|
|
235
|
+
neither state can occur.
|
|
236
|
+
|
|
216
237
|
#### Self-driving interactive adapters (Privy, …)
|
|
217
238
|
|
|
218
239
|
Registered adapters that opt into the interactive-auth contract
|
|
@@ -231,25 +252,57 @@ provider:
|
|
|
231
252
|
|
|
232
253
|
---
|
|
233
254
|
|
|
255
|
+
### `useChains()`
|
|
256
|
+
|
|
257
|
+
The single source of truth for "which chains, in what order, and which address to
|
|
258
|
+
show". Every built-in component (`<WalletButton>`, the network pickers) reads from
|
|
259
|
+
it, so they can never disagree about which chain leads. Use it when you build your
|
|
260
|
+
own wallet button or picker instead of calling `chainsOf(wallets)` yourself —
|
|
261
|
+
`chainsOf` alone cannot know the app's configured order.
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
import { useChains } from '@pollar/react';
|
|
265
|
+
|
|
266
|
+
const { chains, primaryChain, primaryAddress, ready } = useChains();
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
| Field | Type | Description |
|
|
270
|
+
| ---------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
271
|
+
| `chains` | `WalletChain[]` | Chains to offer, in the app's configured order: those the app serves **and** the user holds. `[]` until config resolves |
|
|
272
|
+
| `primaryChain` | `WalletChain \| null` | The app's first configured chain the user holds. `null` until ready |
|
|
273
|
+
| `primaryAddress` | `string` | The address on `primaryChain`. Falls back to the session's first wallet while config is in flight |
|
|
274
|
+
| `ready` | `boolean` | `false` while `/config` is loading or failed — gate any chain UI on it |
|
|
275
|
+
|
|
276
|
+
The order and membership come from the app's `/applications/config`
|
|
277
|
+
(`appConfig.application.chains`), not from the session's `wallets`: a chain the app
|
|
278
|
+
switched off stops appearing on the next page load even for a user whose stored
|
|
279
|
+
session still carries it.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
234
283
|
### Components
|
|
235
284
|
|
|
236
285
|
Every modal mounts itself when its `openXModal()` action is called. You don't need to render these directly — they're
|
|
237
|
-
already wired inside `<PollarProvider>` —
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
|
244
|
-
|
|
|
245
|
-
| `<
|
|
246
|
-
| `<
|
|
247
|
-
| `<
|
|
248
|
-
| `<
|
|
249
|
-
| `<
|
|
250
|
-
| `<
|
|
251
|
-
| `<
|
|
252
|
-
| `<
|
|
286
|
+
already wired inside `<PollarProvider>` — and most are exported in case you want to mount them yourself.
|
|
287
|
+
|
|
288
|
+
> Two wrappers are **not** exported: `<TxHistoryModal>` and `<TransactionModal>`. Only their templates
|
|
289
|
+
> (`TxHistoryModalTemplate` / `TransactionModalTemplate`) are public. Mount those instead if you need to drive them
|
|
290
|
+
> yourself.
|
|
291
|
+
|
|
292
|
+
| Component | Purpose |
|
|
293
|
+
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
294
|
+
| `<WalletButton>` | Drop-in button. Opens login when signed out; signed in, shows the wallet address with a dropdown (Send, Receive, copy address, balance, history, ramp, KYC, distribution rules, sessions, sign out, plus a "Create account" action when the external wallet has no on-chain account yet). Inline arc spinner during in-progress transactions |
|
|
295
|
+
| `<SendModal>` | Full send flow: network picker, asset picker, amount, destination, inline build > sign > success/error. Sending is available on Stellar and Solana; Polygon can be browsed but not sent from |
|
|
296
|
+
| `<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
|
+
| `<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
|
+
| `<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 links |
|
|
300
|
+
| `<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
|
+
| `<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
|
+
| `<DistributionRulesModal>` | Manage the wallet's distribution rules |
|
|
303
|
+
| `<SessionsModal>` | Lists every active refresh-token family for the current user with device metadata, marks the local session, per-row revoke, and a "Sign out everywhere" button |
|
|
304
|
+
| `<KycModal>` | Identity verification flow - provider selection + status polling _(UI preview - backend coming soon)_ |
|
|
305
|
+
| `<RampWidget>` | Buy/sell crypto via SEP-24 - direction tabs, route comparison, payment instructions (wired to `client.createOnRamp` / `client.createOffRamp`) |
|
|
253
306
|
|
|
254
307
|
```tsx
|
|
255
308
|
import { WalletButton } from '@pollar/react';
|
|
@@ -263,8 +316,15 @@ export function Header() {
|
|
|
263
316
|
|
|
264
317
|
### Template components
|
|
265
318
|
|
|
266
|
-
|
|
267
|
-
want to swap the chrome but keep the data wiring from `usePollar()`.
|
|
319
|
+
Almost every modal ships a pure presentational "template" companion — same name with a `Template` suffix. Use these when
|
|
320
|
+
you want to swap the chrome but keep the data wiring from `usePollar()`. (`<EarnModal>` is the exception: it has no
|
|
321
|
+
template yet.)
|
|
322
|
+
|
|
323
|
+
> The wallet-balance, enabled-assets, send and receive templates each require `chains`, `selectedChain` and
|
|
324
|
+
> `onSelectChain`. Get `chains` (in the app's configured order) from `useChains()`, keep `selectedChain` in your own
|
|
325
|
+
> state, and render `<ChainSelect>` for the stock picker. `useChains()` is preferred over `chainsOf(wallets)` on its
|
|
326
|
+
> own, which cannot know the configured order; if you do call `chainsOf` directly, pass the order as its second
|
|
327
|
+
> argument. `addressForChain(wallets, selectedChain)` gives the address for the picked chain.
|
|
268
328
|
|
|
269
329
|
| Wrapper | Template |
|
|
270
330
|
| -------------------------- | ---------------------------------- |
|
|
@@ -385,6 +445,10 @@ import type {
|
|
|
385
445
|
PollarAuthProvider,
|
|
386
446
|
AuthProviderContext,
|
|
387
447
|
|
|
448
|
+
// Network picker
|
|
449
|
+
ChainSelectProps,
|
|
450
|
+
UseChainsResult,
|
|
451
|
+
|
|
388
452
|
// Template props
|
|
389
453
|
WalletButtonTemplateProps,
|
|
390
454
|
SendModalTemplateProps,
|
package/dist/index.css
CHANGED
|
@@ -343,6 +343,111 @@
|
|
|
343
343
|
background: transparent;
|
|
344
344
|
border: none;
|
|
345
345
|
}
|
|
346
|
+
.pollar-chain-tag {
|
|
347
|
+
font-size: 0.625rem;
|
|
348
|
+
font-weight: 600;
|
|
349
|
+
line-height: 1;
|
|
350
|
+
letter-spacing: 0.02em;
|
|
351
|
+
text-transform: uppercase;
|
|
352
|
+
padding: 0.1875rem 0.375rem;
|
|
353
|
+
border-radius: 4px;
|
|
354
|
+
color: var(--pollar-chain-color, var(--pollar-muted));
|
|
355
|
+
background: color-mix(in srgb, var(--pollar-chain-color, #6b7280) 14%, transparent);
|
|
356
|
+
border: 1px solid color-mix(in srgb, var(--pollar-chain-color, #6b7280) 34%, transparent);
|
|
357
|
+
}
|
|
358
|
+
.pollar-issuer {
|
|
359
|
+
display: inline-flex;
|
|
360
|
+
align-items: center;
|
|
361
|
+
gap: 0.25rem;
|
|
362
|
+
}
|
|
363
|
+
.pollar-issuer-addr {
|
|
364
|
+
font-size: 0.6875rem;
|
|
365
|
+
font-family: monospace;
|
|
366
|
+
color: var(--pollar-muted);
|
|
367
|
+
}
|
|
368
|
+
.pollar-busy-overlay {
|
|
369
|
+
position: absolute;
|
|
370
|
+
inset: 0;
|
|
371
|
+
z-index: 2;
|
|
372
|
+
border-radius: inherit;
|
|
373
|
+
cursor: wait;
|
|
374
|
+
background: color-mix(in srgb, var(--pollar-bg) 62%, transparent);
|
|
375
|
+
backdrop-filter: blur(1.5px);
|
|
376
|
+
-webkit-backdrop-filter: blur(1.5px);
|
|
377
|
+
}
|
|
378
|
+
.pollar-busy-overlay-inner {
|
|
379
|
+
position: sticky;
|
|
380
|
+
top: 45%;
|
|
381
|
+
display: flex;
|
|
382
|
+
flex-direction: column;
|
|
383
|
+
align-items: center;
|
|
384
|
+
gap: 0.625rem;
|
|
385
|
+
color: var(--pollar-muted);
|
|
386
|
+
font-size: 0.8125rem;
|
|
387
|
+
}
|
|
388
|
+
.pollar-switch {
|
|
389
|
+
flex: none;
|
|
390
|
+
width: 38px;
|
|
391
|
+
height: 22px;
|
|
392
|
+
padding: 2px;
|
|
393
|
+
border-radius: 999px;
|
|
394
|
+
border: 1px solid var(--pollar-border);
|
|
395
|
+
background: var(--pollar-input-bg);
|
|
396
|
+
cursor: pointer;
|
|
397
|
+
display: flex;
|
|
398
|
+
align-items: center;
|
|
399
|
+
justify-content: flex-start;
|
|
400
|
+
transition: background 0.15s, border-color 0.15s;
|
|
401
|
+
}
|
|
402
|
+
.pollar-switch-on {
|
|
403
|
+
justify-content: flex-end;
|
|
404
|
+
background: var(--pollar-accent);
|
|
405
|
+
border-color: var(--pollar-accent);
|
|
406
|
+
}
|
|
407
|
+
.pollar-switch-knob {
|
|
408
|
+
width: 16px;
|
|
409
|
+
height: 16px;
|
|
410
|
+
border-radius: 50%;
|
|
411
|
+
background: var(--pollar-bg);
|
|
412
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
|
|
413
|
+
display: flex;
|
|
414
|
+
align-items: center;
|
|
415
|
+
justify-content: center;
|
|
416
|
+
transition: transform 0.15s;
|
|
417
|
+
}
|
|
418
|
+
.pollar-switch:disabled {
|
|
419
|
+
opacity: 0.5;
|
|
420
|
+
cursor: not-allowed;
|
|
421
|
+
}
|
|
422
|
+
.pollar-switch-busy {
|
|
423
|
+
cursor: wait;
|
|
424
|
+
}
|
|
425
|
+
.pollar-switch-busy .pollar-switch-knob {
|
|
426
|
+
color: var(--pollar-muted);
|
|
427
|
+
}
|
|
428
|
+
.pollar-chain-field {
|
|
429
|
+
margin-bottom: 0.75rem;
|
|
430
|
+
}
|
|
431
|
+
.pollar-address-row {
|
|
432
|
+
display: flex;
|
|
433
|
+
align-items: center;
|
|
434
|
+
gap: 0.5rem;
|
|
435
|
+
margin-bottom: 1rem;
|
|
436
|
+
}
|
|
437
|
+
.pollar-address {
|
|
438
|
+
flex: 1;
|
|
439
|
+
min-width: 0;
|
|
440
|
+
font-size: 0.75rem;
|
|
441
|
+
font-family: monospace;
|
|
442
|
+
color: var(--pollar-muted);
|
|
443
|
+
background: var(--pollar-input-bg);
|
|
444
|
+
border: 1px solid var(--pollar-border);
|
|
445
|
+
border-radius: var(--pollar-card-border-radius, 10px);
|
|
446
|
+
padding: 0.375rem 0.75rem;
|
|
447
|
+
overflow: hidden;
|
|
448
|
+
text-overflow: ellipsis;
|
|
449
|
+
white-space: nowrap;
|
|
450
|
+
}
|
|
346
451
|
|
|
347
452
|
/* src/components/distribution-rules-modal/DistributionRulesModal.css */
|
|
348
453
|
.pollar-dist-modal {
|
|
@@ -435,22 +540,60 @@
|
|
|
435
540
|
color: var(--pollar-error-text, #dc2626);
|
|
436
541
|
}
|
|
437
542
|
|
|
438
|
-
/* src/components/
|
|
439
|
-
.pollar-
|
|
440
|
-
max-width:
|
|
543
|
+
/* src/components/send-modal/SendModal.css */
|
|
544
|
+
.pollar-send-modal {
|
|
545
|
+
max-width: 420px;
|
|
546
|
+
}
|
|
547
|
+
.pollar-send-header-left {
|
|
548
|
+
display: flex;
|
|
549
|
+
align-items: center;
|
|
550
|
+
gap: 0.5rem;
|
|
551
|
+
}
|
|
552
|
+
.pollar-send-field {
|
|
553
|
+
display: flex;
|
|
554
|
+
flex-direction: column;
|
|
555
|
+
gap: 0.375rem;
|
|
556
|
+
margin-bottom: 1rem;
|
|
557
|
+
}
|
|
558
|
+
.pollar-send-label {
|
|
559
|
+
font-size: 0.8125rem;
|
|
560
|
+
font-weight: 600;
|
|
561
|
+
color: var(--pollar-muted);
|
|
441
562
|
}
|
|
442
|
-
.pollar-
|
|
563
|
+
.pollar-send-label-row {
|
|
564
|
+
display: flex;
|
|
565
|
+
align-items: baseline;
|
|
566
|
+
justify-content: space-between;
|
|
567
|
+
}
|
|
568
|
+
.pollar-send-hint {
|
|
443
569
|
font-size: 0.75rem;
|
|
444
|
-
font-family: monospace;
|
|
445
570
|
color: var(--pollar-muted);
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
571
|
+
}
|
|
572
|
+
.pollar-send-select {
|
|
573
|
+
appearance: none;
|
|
574
|
+
-webkit-appearance: none;
|
|
575
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M2 4l4 4 4-4' stroke='%236b7280' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
576
|
+
background-repeat: no-repeat;
|
|
577
|
+
background-position: right 0.875rem center;
|
|
578
|
+
padding-right: 2.25rem;
|
|
579
|
+
cursor: pointer;
|
|
580
|
+
}
|
|
581
|
+
.pollar-send-skeleton {
|
|
582
|
+
height: var(--pollar-input-height, 44px);
|
|
583
|
+
border-radius: var(--pollar-input-border-radius, 0.5rem);
|
|
584
|
+
background:
|
|
585
|
+
linear-gradient(
|
|
586
|
+
90deg,
|
|
587
|
+
var(--pollar-input-bg) 25%,
|
|
588
|
+
var(--pollar-border) 50%,
|
|
589
|
+
var(--pollar-input-bg) 75%);
|
|
590
|
+
background-size: 200% 100%;
|
|
591
|
+
animation: pollar-pulse 1.4s ease-in-out infinite;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/* src/components/enabled-assets-modal/EnabledAssetsModal.css */
|
|
595
|
+
.pollar-asset-modal {
|
|
596
|
+
max-width: 380px;
|
|
454
597
|
}
|
|
455
598
|
.pollar-asset-list {
|
|
456
599
|
display: flex;
|
|
@@ -498,20 +641,12 @@
|
|
|
498
641
|
font-size: 0.6875rem;
|
|
499
642
|
color: var(--pollar-muted);
|
|
500
643
|
}
|
|
501
|
-
.pollar-asset-trustline {
|
|
644
|
+
.pollar-asset-trustline-label {
|
|
502
645
|
font-size: 0.6875rem;
|
|
503
646
|
font-weight: 600;
|
|
504
647
|
color: var(--pollar-muted);
|
|
505
|
-
background: var(--pollar-bg);
|
|
506
|
-
border: 1px solid var(--pollar-border);
|
|
507
|
-
border-radius: 999px;
|
|
508
|
-
padding: 0.1875rem 0.5rem;
|
|
509
648
|
white-space: nowrap;
|
|
510
649
|
}
|
|
511
|
-
.pollar-asset-trustline.pollar-established {
|
|
512
|
-
color: var(--pollar-success-text);
|
|
513
|
-
border-color: var(--pollar-success-text);
|
|
514
|
-
}
|
|
515
650
|
.pollar-asset-sponsor {
|
|
516
651
|
font-size: 0.625rem;
|
|
517
652
|
color: var(--pollar-muted);
|
|
@@ -521,37 +656,6 @@
|
|
|
521
656
|
align-items: center;
|
|
522
657
|
gap: 0.5rem;
|
|
523
658
|
}
|
|
524
|
-
.pollar-asset-btn {
|
|
525
|
-
font-size: 0.6875rem;
|
|
526
|
-
font-weight: 600;
|
|
527
|
-
color: var(--pollar-accent);
|
|
528
|
-
background: var(--pollar-bg);
|
|
529
|
-
border: 1px solid var(--pollar-accent);
|
|
530
|
-
border-radius: 999px;
|
|
531
|
-
padding: 0.25rem 0.625rem;
|
|
532
|
-
cursor: pointer;
|
|
533
|
-
white-space: nowrap;
|
|
534
|
-
transition:
|
|
535
|
-
opacity 0.15s,
|
|
536
|
-
background 0.15s,
|
|
537
|
-
color 0.15s;
|
|
538
|
-
}
|
|
539
|
-
.pollar-asset-btn:hover:not(:disabled) {
|
|
540
|
-
background: var(--pollar-accent);
|
|
541
|
-
color: #fff;
|
|
542
|
-
}
|
|
543
|
-
.pollar-asset-btn.pollar-danger {
|
|
544
|
-
color: var(--pollar-error-text);
|
|
545
|
-
border-color: var(--pollar-error-border);
|
|
546
|
-
}
|
|
547
|
-
.pollar-asset-btn.pollar-danger:hover:not(:disabled) {
|
|
548
|
-
background: var(--pollar-error-text);
|
|
549
|
-
color: #fff;
|
|
550
|
-
}
|
|
551
|
-
.pollar-asset-btn:disabled {
|
|
552
|
-
opacity: 0.5;
|
|
553
|
-
cursor: not-allowed;
|
|
554
|
-
}
|
|
555
659
|
.pollar-asset-add-custom {
|
|
556
660
|
width: 100%;
|
|
557
661
|
background: none;
|
|
@@ -1689,57 +1793,6 @@
|
|
|
1689
1793
|
overflow-y: auto;
|
|
1690
1794
|
}
|
|
1691
1795
|
|
|
1692
|
-
/* src/components/send-modal/SendModal.css */
|
|
1693
|
-
.pollar-send-modal {
|
|
1694
|
-
max-width: 420px;
|
|
1695
|
-
}
|
|
1696
|
-
.pollar-send-header-left {
|
|
1697
|
-
display: flex;
|
|
1698
|
-
align-items: center;
|
|
1699
|
-
gap: 0.5rem;
|
|
1700
|
-
}
|
|
1701
|
-
.pollar-send-field {
|
|
1702
|
-
display: flex;
|
|
1703
|
-
flex-direction: column;
|
|
1704
|
-
gap: 0.375rem;
|
|
1705
|
-
margin-bottom: 1rem;
|
|
1706
|
-
}
|
|
1707
|
-
.pollar-send-label {
|
|
1708
|
-
font-size: 0.8125rem;
|
|
1709
|
-
font-weight: 600;
|
|
1710
|
-
color: var(--pollar-muted);
|
|
1711
|
-
}
|
|
1712
|
-
.pollar-send-label-row {
|
|
1713
|
-
display: flex;
|
|
1714
|
-
align-items: baseline;
|
|
1715
|
-
justify-content: space-between;
|
|
1716
|
-
}
|
|
1717
|
-
.pollar-send-hint {
|
|
1718
|
-
font-size: 0.75rem;
|
|
1719
|
-
color: var(--pollar-muted);
|
|
1720
|
-
}
|
|
1721
|
-
.pollar-send-select {
|
|
1722
|
-
appearance: none;
|
|
1723
|
-
-webkit-appearance: none;
|
|
1724
|
-
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M2 4l4 4 4-4' stroke='%236b7280' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
1725
|
-
background-repeat: no-repeat;
|
|
1726
|
-
background-position: right 0.875rem center;
|
|
1727
|
-
padding-right: 2.25rem;
|
|
1728
|
-
cursor: pointer;
|
|
1729
|
-
}
|
|
1730
|
-
.pollar-send-skeleton {
|
|
1731
|
-
height: var(--pollar-input-height, 44px);
|
|
1732
|
-
border-radius: var(--pollar-input-border-radius, 0.5rem);
|
|
1733
|
-
background:
|
|
1734
|
-
linear-gradient(
|
|
1735
|
-
90deg,
|
|
1736
|
-
var(--pollar-input-bg) 25%,
|
|
1737
|
-
var(--pollar-border) 50%,
|
|
1738
|
-
var(--pollar-input-bg) 75%);
|
|
1739
|
-
background-size: 200% 100%;
|
|
1740
|
-
animation: pollar-pulse 1.4s ease-in-out infinite;
|
|
1741
|
-
}
|
|
1742
|
-
|
|
1743
1796
|
/* src/components/swap-modal/SwapModal.css */
|
|
1744
1797
|
.pollar-swap-quote {
|
|
1745
1798
|
display: flex;
|
|
@@ -2083,26 +2136,6 @@
|
|
|
2083
2136
|
.pollar-bal-modal {
|
|
2084
2137
|
max-width: 380px;
|
|
2085
2138
|
}
|
|
2086
|
-
.pollar-bal-address-row {
|
|
2087
|
-
display: flex;
|
|
2088
|
-
align-items: center;
|
|
2089
|
-
gap: 0.5rem;
|
|
2090
|
-
margin-bottom: 1rem;
|
|
2091
|
-
}
|
|
2092
|
-
.pollar-bal-address {
|
|
2093
|
-
flex: 1;
|
|
2094
|
-
min-width: 0;
|
|
2095
|
-
font-size: 0.75rem;
|
|
2096
|
-
font-family: monospace;
|
|
2097
|
-
color: var(--pollar-muted);
|
|
2098
|
-
background: var(--pollar-input-bg);
|
|
2099
|
-
border: 1px solid var(--pollar-border);
|
|
2100
|
-
border-radius: var(--pollar-card-border-radius, 10px);
|
|
2101
|
-
padding: 0.375rem 0.75rem;
|
|
2102
|
-
overflow: hidden;
|
|
2103
|
-
text-overflow: ellipsis;
|
|
2104
|
-
white-space: nowrap;
|
|
2105
|
-
}
|
|
2106
2139
|
.pollar-bal-list {
|
|
2107
2140
|
display: flex;
|
|
2108
2141
|
flex-direction: column;
|
|
@@ -2134,6 +2167,22 @@
|
|
|
2134
2167
|
font-weight: 600;
|
|
2135
2168
|
color: var(--pollar-text);
|
|
2136
2169
|
}
|
|
2170
|
+
.pollar-bal-faucet-hint {
|
|
2171
|
+
font-size: 0.6875rem;
|
|
2172
|
+
color: var(--pollar-muted);
|
|
2173
|
+
}
|
|
2174
|
+
.pollar-bal-faucet-hint a {
|
|
2175
|
+
color: var(--pollar-accent);
|
|
2176
|
+
text-decoration: none;
|
|
2177
|
+
font-weight: 600;
|
|
2178
|
+
}
|
|
2179
|
+
.pollar-bal-faucet-hint a:hover {
|
|
2180
|
+
text-decoration: underline;
|
|
2181
|
+
}
|
|
2182
|
+
.pollar-bal-faucet-net {
|
|
2183
|
+
font-size: 0.625rem;
|
|
2184
|
+
opacity: 0.8;
|
|
2185
|
+
}
|
|
2137
2186
|
.pollar-bal-chain-tag {
|
|
2138
2187
|
font-size: 0.625rem;
|
|
2139
2188
|
font-weight: 600;
|