@pollar/react 0.10.1-rc.9 → 0.11.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/README.md CHANGED
@@ -1,22 +1,15 @@
1
1
  # @pollar/react
2
2
 
3
3
  React bindings for [Pollar](https://pollar.xyz) — drop-in authentication UI, transaction modals, and hooks for
4
- Stellar-based applications.
4
+ Stellar and Solana applications.
5
5
 
6
6
  > **0.10.0** requires `@pollar/core@^0.10.0`. Headline features: on-chain swaps
7
7
  > via `<SwapModal>` + `usePollar().swap` / `getSwapQuote` / `openSwapModal`;
8
8
  > live SEP-24 on/off-ramps through `<RampWidget>` (now wired to
9
9
  > `client.createOnRamp` / `client.createOffRamp`); and a self-driving Privy
10
10
  > adapter (registered interactive adapters are auto-driven to completion before
11
- > `login({ provider })`). Read the [CHANGELOG](../../CHANGELOG.md) before
12
- > upgrading.
13
- >
14
- > **0.8.0 reshapes `<PollarProvider>` props (breaking).** `config` > `client`
15
- > (now accepts a `PollarClient` instance or a `PollarClientConfig`); `styles`
16
- > moves under `appConfig.styles`; new `appConfig` prop is the opt-out switch
17
- > for the remote `/applications/config` fetch (pass it - even `{}` - to skip
18
- > the fetch). Read the [CHANGELOG](../../CHANGELOG.md) and
19
- > [UPGRADE.md](../../UPGRADE.md) before upgrading.
11
+ > `login({ provider })`). See the [CHANGELOG](../../CHANGELOG.md) and
12
+ > [UPGRADE.md](../../UPGRADE.md) for the full version history before upgrading.
20
13
 
21
14
  ## Installation
22
15
 
@@ -107,12 +100,6 @@ Context provider that initialises the Pollar client and makes it available to ch
107
100
  | `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 |
108
101
  | `adapters` | `PollarAdapters` | No | Named set of `PollarAdapter` objects (e.g. Trustless Work). See below |
109
102
 
110
- > **Renamed in 0.8.0** — `config` → `client`, `styles` → `appConfig.styles`.
111
- > If you were passing `styles={{ ... }}` directly, move it to
112
- > `appConfig={{ styles: { ... } }}` (which also opts you out of the remote
113
- > `/applications/config` fetch). See [UPGRADE.md](../../UPGRADE.md) for the
114
- > full migration matrix.
115
-
116
103
  ---
117
104
 
118
105
  ### `usePollar()`
@@ -169,6 +156,14 @@ const {
169
156
  swap, // (quote: SwapQuote, opts?) => Promise<SubmitOutcome>
170
157
  openSwapModal, // () => void
171
158
 
159
+ // Earn (yield vaults + lending — DeFindex + Blend)
160
+ getEarnProviders, // () => Promise<EarnProviderId[]> ([] means Earn is disabled)
161
+ getEarnOpportunities, // (provider: EarnProviderId) => Promise<EarnOpportunity[]>
162
+ getEarnPosition, // (params: EarnPositionParams) => Promise<EarnPosition>
163
+ earnDeposit, // (params: EarnTxParams) => Promise<SubmitOutcome>
164
+ earnWithdraw, // (params: EarnTxParams) => Promise<SubmitOutcome>
165
+ openEarnModal, // () => void
166
+
172
167
  // Distribution rules
173
168
  openDistributionRulesModal, // () => void
174
169
 
@@ -198,9 +193,6 @@ const {
198
193
  Custody is derived from `wallet`, not a separate field - e.g.
199
194
  `wallet?.custody === 'external' ? wallet.provider : null`.
200
195
 
201
- > **0.6.0 renames** - `transaction` > `tx`, `openTransactionModal` > `openTxModal`, `config` > `appConfig`,
202
- > `openRampWidget` > `openRampModal`, `refreshBalance` > `refreshWalletBalance`. Existing code on 0.5.x must update.
203
-
204
196
  #### Login options
205
197
 
206
198
  ```ts
@@ -246,15 +238,16 @@ already wired inside `<PollarProvider>` — but they're exported in case you wan
246
238
 
247
239
  | Component | Purpose |
248
240
  | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
249
- | `<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). Inline arc spinner during in-progress transactions |
241
+ | `<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 |
250
242
  | `<SendModal>` | Full send flow: asset picker, amount, destination, inline build > sign > success/error |
251
- | `<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) |
243
+ | `<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) |
244
+ | `<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 |
252
245
  | `<ReceiveModal>` | Wallet address as QR code with copy-to-clipboard (no external QR dependency required) |
253
246
  | `<TxHistoryModal>` | Paginated transaction history with auto-fetch on open and stellar.expert explorer links |
254
- | `<WalletBalanceModal>` | Stellar account balances with refresh button |
247
+ | `<WalletBalanceModal>` | Multichain wallet balances (Stellar + Solana); each balance carries a per-chain tag on multichain apps, with refresh button |
255
248
  | `<EnabledAssetsModal>` | The application's dashboard-enabled assets with per-asset trustline state; establish/remove trustlines |
256
249
  | `<DistributionRulesModal>` | Manage the wallet's distribution rules |
257
- | `<SessionsModal>` | **New in 0.7.0.** 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 |
250
+ | `<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 |
258
251
  | `<KycModal>` | Identity verification flow - provider selection + status polling _(UI preview - backend coming soon)_ |
259
252
  | `<RampWidget>` | Buy/sell crypto via SEP-24 - direction tabs, route comparison, payment instructions (wired to `client.createOnRamp` / `client.createOffRamp`) |
260
253
 
@@ -292,7 +285,7 @@ want to swap the chrome but keep the data wiring from `usePollar()`.
292
285
  `<TxStatusView>` is the shared status component (build → sign → success/error) reused by `TransactionModal` and
293
286
  `SendModal`; it's exported on its own for consumers that want to embed the lifecycle elsewhere.
294
287
 
295
- > **0.8.1** — `onWalletConnect` is now **optional** on `<LoginModalTemplate>` (defaults to a no-op).
288
+ > `onWalletConnect` is **optional** on `<LoginModalTemplate>` (defaults to a no-op).
296
289
 
297
290
  ---
298
291
 
@@ -314,9 +307,6 @@ const trustlessWork: PollarAdapter = {
314
307
  </PollarProvider>;
315
308
  ```
316
309
 
317
- > **Renamed in 0.7.0** — `EscrowFn` → `AdapterFn` and `EscrowAdapter` → `PollarAdapter`. Runtime contract is
318
- > unchanged; rename your imports.
319
-
320
310
  #### `createPollarAdapterHook(key)`
321
311
 
322
312
  Factory that generates a fully-typed hook mirroring an adapter's API with automatic XDR signing built in:
package/dist/index.css CHANGED
@@ -113,29 +113,7 @@
113
113
  top: 1rem;
114
114
  left: 1rem;
115
115
  }
116
- .pollar-modal-refresh-btn {
117
- background: none;
118
- border: 1px solid var(--pollar-border);
119
- cursor: pointer;
120
- color: var(--pollar-muted);
121
- padding: 5px 10px;
122
- display: flex;
123
- align-items: center;
124
- gap: 0.375rem;
125
- border-radius: 6px;
126
- font-size: 0.75rem;
127
- font-weight: 500;
128
- transition: color 150ms, background 150ms;
129
- }
130
- .pollar-modal-refresh-btn:hover:not(:disabled) {
131
- color: var(--pollar-text);
132
- background: var(--pollar-border);
133
- }
134
- .pollar-modal-refresh-btn:disabled {
135
- opacity: 0.5;
136
- cursor: not-allowed;
137
- }
138
- .pollar-modal-refresh-icon.spinning {
116
+ .pollar-modal-refresh-icon.pollar-spinning {
139
117
  animation: pollar-spin 0.8s linear infinite;
140
118
  }
141
119
  .pollar-modal-actions {
@@ -186,12 +164,75 @@
186
164
  border-color: var(--pollar-text);
187
165
  }
188
166
  .pollar-spinner {
167
+ display: inline-block;
168
+ vertical-align: middle;
189
169
  width: 2rem;
190
170
  height: 2rem;
191
171
  border: 3px solid color-mix(in srgb, var(--pollar-accent) 20%, transparent);
192
172
  border-top-color: var(--pollar-accent);
193
173
  border-radius: 50%;
194
174
  animation: pollar-spin 0.8s linear infinite;
175
+ flex-shrink: 0;
176
+ }
177
+ .pollar-spinner-sm {
178
+ width: 1rem;
179
+ height: 1rem;
180
+ border-width: 2px;
181
+ }
182
+ .pollar-btn-primary .pollar-spinner {
183
+ border-color: rgba(255, 255, 255, 0.35);
184
+ border-top-color: #fff;
185
+ }
186
+ .pollar-spinner-current {
187
+ border-color: color-mix(in srgb, currentColor 25%, transparent);
188
+ border-top-color: currentColor;
189
+ }
190
+ .pollar-loading-block {
191
+ display: flex;
192
+ flex-direction: column;
193
+ align-items: center;
194
+ gap: 0.75rem;
195
+ padding: 2rem 1rem;
196
+ color: var(--pollar-muted);
197
+ font-size: 0.875rem;
198
+ }
199
+ .pollar-inline-loading {
200
+ display: flex;
201
+ align-items: center;
202
+ justify-content: center;
203
+ gap: 0.5rem;
204
+ }
205
+ .pollar-select-loading {
206
+ display: flex;
207
+ align-items: center;
208
+ gap: 0.5rem;
209
+ color: var(--pollar-muted);
210
+ }
211
+ .pollar-tabs {
212
+ display: flex;
213
+ gap: 4px;
214
+ margin-bottom: 1.25rem;
215
+ padding: 4px;
216
+ border: 1px solid var(--pollar-border);
217
+ border-radius: var(--pollar-card-border-radius, 10px);
218
+ background: var(--pollar-input-bg);
219
+ }
220
+ .pollar-tab {
221
+ flex: 1;
222
+ height: 36px;
223
+ border: none;
224
+ border-radius: 6px;
225
+ background: transparent;
226
+ color: var(--pollar-muted);
227
+ font-size: 14px;
228
+ font-weight: 600;
229
+ cursor: pointer;
230
+ transition: color 0.15s, background-color 0.15s;
231
+ }
232
+ .pollar-tab[data-active=true] {
233
+ background: var(--pollar-bg);
234
+ color: var(--pollar-accent);
235
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
195
236
  }
196
237
  .pollar-modal-empty {
197
238
  text-align: center;
@@ -467,7 +508,7 @@
467
508
  padding: 0.1875rem 0.5rem;
468
509
  white-space: nowrap;
469
510
  }
470
- .pollar-asset-trustline.established {
511
+ .pollar-asset-trustline.pollar-established {
471
512
  color: var(--pollar-success-text);
472
513
  border-color: var(--pollar-success-text);
473
514
  }
@@ -499,11 +540,11 @@
499
540
  background: var(--pollar-accent);
500
541
  color: #fff;
501
542
  }
502
- .pollar-asset-btn.danger {
543
+ .pollar-asset-btn.pollar-danger {
503
544
  color: var(--pollar-error-text);
504
545
  border-color: var(--pollar-error-border);
505
546
  }
506
- .pollar-asset-btn.danger:hover:not(:disabled) {
547
+ .pollar-asset-btn.pollar-danger:hover:not(:disabled) {
507
548
  background: var(--pollar-error-text);
508
549
  color: #fff;
509
550
  }
@@ -541,32 +582,6 @@
541
582
  padding: 0.5rem 0.75rem;
542
583
  margin-bottom: 1rem;
543
584
  }
544
- .pollar-modal-back {
545
- display: flex;
546
- align-items: center;
547
- justify-content: center;
548
- width: 2rem;
549
- height: 2rem;
550
- padding: 0;
551
- border-radius: var(--pollar-buttons-border-radius, 6px);
552
- border: 1px solid var(--pollar-border);
553
- background-color: transparent;
554
- color: var(--pollar-muted);
555
- cursor: pointer;
556
- transition:
557
- background-color 0.15s,
558
- color 0.15s,
559
- border-color 0.15s;
560
- }
561
- .pollar-modal-back:hover:not(:disabled) {
562
- background-color: var(--pollar-input-bg);
563
- color: var(--pollar-text);
564
- border-color: var(--pollar-text);
565
- }
566
- .pollar-modal-back:disabled {
567
- opacity: 0.5;
568
- cursor: not-allowed;
569
- }
570
585
  .pollar-asset-custom-hint {
571
586
  font-size: 0.75rem;
572
587
  color: var(--pollar-muted);
@@ -592,26 +607,6 @@
592
607
  font-size: 0.6875rem;
593
608
  color: var(--pollar-error-text);
594
609
  }
595
- .pollar-asset-submit {
596
- width: 100%;
597
- height: var(--pollar-buttons-height, 44px);
598
- border: none;
599
- border-radius: var(--pollar-buttons-border-radius, 6px);
600
- background-color: var(--pollar-accent);
601
- color: #fff;
602
- font-size: 0.9375rem;
603
- font-weight: 700;
604
- cursor: pointer;
605
- margin-bottom: 1rem;
606
- transition: opacity 0.15s;
607
- }
608
- .pollar-asset-submit:hover:not(:disabled) {
609
- opacity: 0.9;
610
- }
611
- .pollar-asset-submit:disabled {
612
- opacity: 0.5;
613
- cursor: not-allowed;
614
- }
615
610
 
616
611
  /* src/components/kyc-modal/KycModal.css */
617
612
  .pollar-kyc-badge {
@@ -636,15 +631,11 @@
636
631
  .pollar-kyc-modal {
637
632
  max-width: 500px;
638
633
  }
639
- .pollar-kyc-header {
640
- margin-bottom: 1.5rem;
641
- text-align: center;
642
- }
643
- .pollar-kyc-title {
644
- margin: 0 0 0.375rem;
645
- font-size: var(--pollar-modal-heading-size, 1.375rem);
646
- font-weight: 700;
647
- color: var(--pollar-text);
634
+ .pollar-kyc-header-text {
635
+ display: flex;
636
+ flex-direction: column;
637
+ gap: 0.25rem;
638
+ min-width: 0;
648
639
  }
649
640
  .pollar-kyc-subtitle {
650
641
  margin: 0;
@@ -746,7 +737,7 @@
746
737
  }
747
738
 
748
739
  /* src/components/login-modal/GithubButton.css */
749
- .github-button {
740
+ .pollar-github-button {
750
741
  -webkit-appearance: none;
751
742
  appearance: none;
752
743
  background-color: var(--pollar-input-bg);
@@ -778,35 +769,35 @@
778
769
  width: 100%;
779
770
  user-select: none;
780
771
  }
781
- .github-button-icon {
772
+ .pollar-github-button-icon {
782
773
  width: 20px;
783
774
  height: 20px;
784
775
  flex-shrink: 0;
785
776
  }
786
- .github-button-contents {
777
+ .pollar-github-button-contents {
787
778
  flex-grow: 0;
788
779
  overflow: hidden;
789
780
  text-overflow: ellipsis;
790
781
  }
791
- .github-button:not(:disabled):hover {
782
+ .pollar-github-button:not(:disabled):hover {
792
783
  border-color: var(--pollar-accent);
793
784
  color: var(--pollar-accent);
794
785
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
795
786
  }
796
- .github-button:not(:disabled):active {
787
+ .pollar-github-button:not(:disabled):active {
797
788
  transform: scale(0.99);
798
789
  }
799
- .github-button:disabled {
790
+ .pollar-github-button:disabled {
800
791
  cursor: default;
801
792
  opacity: 0.5;
802
793
  }
803
- .github-button:disabled .github-button-icon,
804
- .github-button:disabled .github-button-contents {
794
+ .pollar-github-button:disabled .pollar-github-button-icon,
795
+ .pollar-github-button:disabled .pollar-github-button-contents {
805
796
  opacity: 38%;
806
797
  }
807
798
 
808
799
  /* src/components/login-modal/GoogleButton.css */
809
- .gsi-material-button {
800
+ .pollar-gsi-material-button {
810
801
  -moz-user-select: none;
811
802
  -webkit-user-select: none;
812
803
  -ms-user-select: none;
@@ -840,14 +831,14 @@
840
831
  white-space: nowrap;
841
832
  width: 100%;
842
833
  }
843
- .gsi-material-button .gsi-material-button-icon {
834
+ .pollar-gsi-material-button .pollar-gsi-material-button-icon {
844
835
  height: 20px;
845
836
  margin-right: 0;
846
837
  min-width: 20px;
847
838
  width: 20px;
848
839
  flex-shrink: 0;
849
840
  }
850
- .gsi-material-button .gsi-material-button-content-wrapper {
841
+ .pollar-gsi-material-button .pollar-gsi-material-button-content-wrapper {
851
842
  -webkit-align-items: center;
852
843
  align-items: center;
853
844
  display: flex;
@@ -861,7 +852,7 @@
861
852
  position: relative;
862
853
  width: 100%;
863
854
  }
864
- .gsi-material-button .gsi-material-button-contents {
855
+ .pollar-gsi-material-button .pollar-gsi-material-button-contents {
865
856
  font-family:
866
857
  -apple-system,
867
858
  BlinkMacSystemFont,
@@ -872,7 +863,7 @@
872
863
  text-overflow: ellipsis;
873
864
  flex-grow: 0;
874
865
  }
875
- .gsi-material-button .gsi-material-button-state {
866
+ .pollar-gsi-material-button .pollar-gsi-material-button-state {
876
867
  -webkit-transition: opacity 0.218s;
877
868
  transition: opacity 0.218s;
878
869
  bottom: 0;
@@ -882,31 +873,31 @@
882
873
  right: 0;
883
874
  top: 0;
884
875
  }
885
- .gsi-material-button:disabled {
876
+ .pollar-gsi-material-button:disabled {
886
877
  cursor: default;
887
878
  background-color: #ffffff61;
888
879
  border-color: #1f1f1f1f;
889
880
  }
890
- .gsi-material-button:disabled .gsi-material-button-contents {
881
+ .pollar-gsi-material-button:disabled .pollar-gsi-material-button-contents {
891
882
  opacity: 38%;
892
883
  }
893
- .gsi-material-button:disabled .gsi-material-button-icon {
884
+ .pollar-gsi-material-button:disabled .pollar-gsi-material-button-icon {
894
885
  opacity: 38%;
895
886
  }
896
- .gsi-material-button:not(:disabled):active .gsi-material-button-state,
897
- .gsi-material-button:not(:disabled):focus .gsi-material-button-state {
887
+ .pollar-gsi-material-button:not(:disabled):active .pollar-gsi-material-button-state,
888
+ .pollar-gsi-material-button:not(:disabled):focus .pollar-gsi-material-button-state {
898
889
  background-color: #303030;
899
890
  opacity: 12%;
900
891
  }
901
- .gsi-material-button:not(:disabled):hover {
892
+ .pollar-gsi-material-button:not(:disabled):hover {
902
893
  border-color: var(--pollar-accent);
903
894
  color: var(--pollar-accent);
904
895
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
905
896
  }
906
- .gsi-material-button:not(:disabled):active {
897
+ .pollar-gsi-material-button:not(:disabled):active {
907
898
  transform: scale(0.99);
908
899
  }
909
- .gsi-material-button:not(:disabled):hover .gsi-material-button-state {
900
+ .pollar-gsi-material-button:not(:disabled):hover .pollar-gsi-material-button-state {
910
901
  background-color: transparent;
911
902
  opacity: 0;
912
903
  }
@@ -954,29 +945,6 @@
954
945
  .pollar-email-section {
955
946
  margin-bottom: 1rem;
956
947
  }
957
- .pollar-email-input {
958
- width: 100%;
959
- height: var(--pollar-input-height, 44px);
960
- padding: 0 1rem;
961
- border-radius: var(--pollar-input-border-radius, 0.5rem);
962
- border: 1px solid var(--pollar-border);
963
- background-color: var(--pollar-input-bg);
964
- font-size: 1rem;
965
- color: var(--pollar-text);
966
- outline: none;
967
- box-sizing: border-box;
968
- }
969
- .pollar-email-input::placeholder {
970
- color: var(--pollar-muted);
971
- }
972
- .pollar-email-input:focus {
973
- box-shadow: 0 0 0 2px var(--pollar-accent);
974
- border-color: transparent;
975
- }
976
- .pollar-email-input:disabled {
977
- opacity: 0.5;
978
- cursor: not-allowed;
979
- }
980
948
  .pollar-divider {
981
949
  position: relative;
982
950
  margin: 1.25rem 0;
@@ -1225,34 +1193,6 @@
1225
1193
  font-size: var(--pollar-modal-subtitle-size, 0.9rem);
1226
1194
  color: var(--pollar-muted);
1227
1195
  }
1228
- .pollar-ramp-input-loading {
1229
- display: flex;
1230
- align-items: center;
1231
- color: var(--pollar-muted);
1232
- }
1233
- .pollar-ramp-tabs {
1234
- display: flex;
1235
- gap: 0;
1236
- border: 1px solid var(--pollar-border);
1237
- border-radius: var(--pollar-input-border-radius, 0.5rem);
1238
- overflow: hidden;
1239
- margin-bottom: 1.25rem;
1240
- }
1241
- .pollar-ramp-tab {
1242
- flex: 1;
1243
- height: 40px;
1244
- border: none;
1245
- background: transparent;
1246
- color: var(--pollar-muted);
1247
- font-size: 0.875rem;
1248
- font-weight: 600;
1249
- cursor: pointer;
1250
- transition: all 0.15s;
1251
- }
1252
- .pollar-ramp-tab[data-active=true] {
1253
- background-color: var(--pollar-accent);
1254
- color: #fff;
1255
- }
1256
1196
  .pollar-ramp-field {
1257
1197
  margin-bottom: 1rem;
1258
1198
  }
@@ -1300,6 +1240,10 @@
1300
1240
  gap: 0.625rem;
1301
1241
  padding: 1.5rem 0;
1302
1242
  }
1243
+ .pollar-ramp-loading-spinner {
1244
+ align-self: center;
1245
+ margin-bottom: 0.5rem;
1246
+ }
1303
1247
  .pollar-ramp-loading-row {
1304
1248
  display: flex;
1305
1249
  align-items: center;
@@ -1854,31 +1798,6 @@
1854
1798
  }
1855
1799
 
1856
1800
  /* src/components/earn-modal/EarnModal.css */
1857
- .pollar-earn-tabs {
1858
- display: flex;
1859
- gap: 4px;
1860
- margin-bottom: 12px;
1861
- padding: 4px;
1862
- border: 1px solid var(--pollar-border);
1863
- border-radius: var(--pollar-card-border-radius);
1864
- background: var(--pollar-input-bg);
1865
- }
1866
- .pollar-earn-tab {
1867
- flex: 1;
1868
- height: 36px;
1869
- border: none;
1870
- border-radius: 6px;
1871
- background: transparent;
1872
- color: var(--pollar-muted);
1873
- font-size: 14px;
1874
- font-weight: 600;
1875
- cursor: pointer;
1876
- }
1877
- .pollar-earn-tab-active {
1878
- background: var(--pollar-bg);
1879
- color: var(--pollar-accent);
1880
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
1881
- }
1882
1801
  .pollar-earn-amount {
1883
1802
  position: relative;
1884
1803
  display: flex;
@@ -2205,11 +2124,28 @@
2205
2124
  gap: 0.1875rem;
2206
2125
  min-width: 0;
2207
2126
  }
2127
+ .pollar-bal-asset-code-row {
2128
+ display: inline-flex;
2129
+ align-items: center;
2130
+ gap: 0.4375rem;
2131
+ }
2208
2132
  .pollar-bal-asset {
2209
2133
  font-size: 0.875rem;
2210
2134
  font-weight: 600;
2211
2135
  color: var(--pollar-text);
2212
2136
  }
2137
+ .pollar-bal-chain-tag {
2138
+ font-size: 0.625rem;
2139
+ font-weight: 600;
2140
+ line-height: 1;
2141
+ letter-spacing: 0.02em;
2142
+ text-transform: uppercase;
2143
+ padding: 0.1875rem 0.375rem;
2144
+ border-radius: 4px;
2145
+ color: var(--pollar-chain-color, var(--pollar-muted));
2146
+ background: color-mix(in srgb, var(--pollar-chain-color, #6b7280) 14%, transparent);
2147
+ border: 1px solid color-mix(in srgb, var(--pollar-chain-color, #6b7280) 34%, transparent);
2148
+ }
2213
2149
  .pollar-bal-issuer {
2214
2150
  display: inline-flex;
2215
2151
  align-items: center;
@@ -2241,7 +2177,7 @@
2241
2177
  }
2242
2178
 
2243
2179
  /* src/components/wallet-button/WalletButton.css */
2244
- .wallet-login-btn {
2180
+ .pollar-wallet-login-btn {
2245
2181
  display: flex;
2246
2182
  align-items: center;
2247
2183
  gap: 0.75rem;
@@ -2255,24 +2191,24 @@
2255
2191
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
2256
2192
  transition: all 0.15s;
2257
2193
  }
2258
- .wallet-login-btn:hover {
2194
+ .pollar-wallet-login-btn:hover {
2259
2195
  opacity: 0.9;
2260
2196
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
2261
2197
  }
2262
- .wallet-login-btn:active {
2198
+ .pollar-wallet-login-btn:active {
2263
2199
  transform: scale(0.98);
2264
2200
  }
2265
- .wallet-btn-logo {
2201
+ .pollar-wallet-btn-logo {
2266
2202
  width: 22px;
2267
2203
  height: 22px;
2268
2204
  object-fit: contain;
2269
2205
  filter: brightness(0) invert(1);
2270
2206
  }
2271
- .wallet-wrapper {
2207
+ .pollar-wallet-wrapper {
2272
2208
  position: relative;
2273
2209
  display: inline-block;
2274
2210
  }
2275
- .wallet-btn {
2211
+ .pollar-wallet-btn {
2276
2212
  display: flex;
2277
2213
  align-items: center;
2278
2214
  gap: 8px;
@@ -2285,18 +2221,18 @@
2285
2221
  cursor: pointer;
2286
2222
  transition: background 0.15s;
2287
2223
  }
2288
- .wallet-btn:hover {
2224
+ .pollar-wallet-btn:hover {
2289
2225
  opacity: 0.9;
2290
2226
  }
2291
- .wallet-chevron {
2227
+ .pollar-wallet-chevron {
2292
2228
  width: 12px;
2293
2229
  height: 12px;
2294
2230
  transition: transform 0.15s;
2295
2231
  }
2296
- .wallet-chevron.open {
2232
+ .pollar-wallet-chevron.pollar-open {
2297
2233
  transform: rotate(180deg);
2298
2234
  }
2299
- .wallet-dropdown {
2235
+ .pollar-wallet-dropdown {
2300
2236
  position: absolute;
2301
2237
  top: calc(100% + 6px);
2302
2238
  right: 0;
@@ -2307,7 +2243,7 @@
2307
2243
  overflow: hidden;
2308
2244
  z-index: 50;
2309
2245
  }
2310
- .wallet-dropdown-item {
2246
+ .pollar-wallet-dropdown-item {
2311
2247
  display: flex;
2312
2248
  align-items: center;
2313
2249
  gap: 10px;
@@ -2321,32 +2257,32 @@
2321
2257
  text-align: left;
2322
2258
  transition: background 0.1s;
2323
2259
  }
2324
- .wallet-dropdown-item:hover {
2260
+ .pollar-wallet-dropdown-item:hover {
2325
2261
  background: rgba(0, 0, 0, 0.05);
2326
2262
  }
2327
- .wallet-dropdown-item.danger {
2263
+ .pollar-wallet-dropdown-item.pollar-danger {
2328
2264
  color: #dc2626;
2329
2265
  }
2330
- .wallet-dropdown-item.danger:hover {
2266
+ .pollar-wallet-dropdown-item.pollar-danger:hover {
2331
2267
  background: #fef2f2;
2332
2268
  }
2333
- .wallet-dropdown-divider {
2269
+ .pollar-wallet-dropdown-divider {
2334
2270
  height: 1px;
2335
2271
  background: rgba(0, 0, 0, 0.08);
2336
2272
  margin: 2px 0;
2337
2273
  }
2338
- .wallet-btn-label {
2274
+ .pollar-wallet-btn-label {
2339
2275
  overflow: hidden;
2340
2276
  text-overflow: ellipsis;
2341
2277
  white-space: nowrap;
2342
2278
  flex: 1;
2343
2279
  min-width: 0;
2344
2280
  }
2345
- .wallet-btn:disabled {
2281
+ .pollar-wallet-btn:disabled {
2346
2282
  cursor: not-allowed;
2347
2283
  opacity: 1;
2348
2284
  }
2349
- .wallet-btn-spinner {
2285
+ .pollar-wallet-btn-spinner {
2350
2286
  flex-shrink: 0;
2351
2287
  animation: pollar-wallet-spin 1.1s linear infinite;
2352
2288
  }