@shapeshiftoss/swap-widget 0.9.1 → 0.10.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 +95 -19
- package/dist/index.css +229 -9
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1722 -652
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -12,6 +12,7 @@ An embeddable React widget that enables multi-chain token swaps using ShapeShift
|
|
|
12
12
|
- [Props Reference](#props-reference)
|
|
13
13
|
- [Filtering Chains and Assets](#filtering-chains-and-assets)
|
|
14
14
|
- [Exact Output and Locked Destinations](#exact-output-and-locked-destinations)
|
|
15
|
+
- [External Wallets and Deposit Addresses](#external-wallets-and-deposit-addresses)
|
|
15
16
|
- [Theming](#theming)
|
|
16
17
|
- [Examples](#examples)
|
|
17
18
|
- [Exported Types](#exported-types)
|
|
@@ -122,7 +123,8 @@ Once connected, the widget can sign and broadcast transactions for three wallet
|
|
|
122
123
|
The header shows a **Connect** button by default (toggle with `showConnectButton`) that opens the
|
|
123
124
|
AppKit modal. Swaps whose sell asset is not in an executable namespace (see
|
|
124
125
|
[Supported Chains](#supported-chains)) redirect to [app.shapeshift.com](https://app.shapeshift.com)
|
|
125
|
-
when `allowShapeshiftRedirect` is enabled.
|
|
126
|
+
when `allowShapeshiftRedirect` is enabled. When such a swap is quoted by an externally paid route,
|
|
127
|
+
both are offered: continue without a wallet, or proceed on ShapeShift.
|
|
126
128
|
|
|
127
129
|
## Props Reference
|
|
128
130
|
|
|
@@ -150,7 +152,7 @@ when `allowShapeshiftRedirect` is enabled.
|
|
|
150
152
|
| `showConnectButton` | `boolean` | `true` | Show the built-in Connect button in the widget header. |
|
|
151
153
|
| `ratesRefetchInterval` | `number` | `15000` | How often (ms) to refetch swap rates. |
|
|
152
154
|
| `onSwapSuccess` | `(txHash: string) => void` | – | Called when a swap transaction succeeds. |
|
|
153
|
-
| `onSwapError` | `(error: Error) => void` | – | Called when a swap
|
|
155
|
+
| `onSwapError` | `(error: Error) => void` | – | Called when a swap fails, or when its outcome can no longer be tracked. |
|
|
154
156
|
|
|
155
157
|
## Filtering Chains and Assets
|
|
156
158
|
|
|
@@ -233,14 +235,16 @@ address.
|
|
|
233
235
|
| `defaultReceiveAddress` only | Prefilled, user can still edit it |
|
|
234
236
|
| Both | Locked to the address you supplied |
|
|
235
237
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
238
|
+
The address belongs to the chain of the `defaultBuyAsset` you pair it with. It is usable there, and
|
|
239
|
+
on any other EVM chain if it is an EVM address, since those share an address space; nowhere else,
|
|
240
|
+
even where the format would pass — a Bitcoin address is not a Bitcoin Cash address. A locked address
|
|
241
|
+
the buy chain can't use blocks the swap and says so, rather than falling back to the connected
|
|
242
|
+
wallet — paying the user's own address is never what a locked destination meant. This is reachable
|
|
243
|
+
whenever the buy asset is left unlocked, since the user can switch chains.
|
|
240
244
|
|
|
241
|
-
An **unlocked** prefill
|
|
242
|
-
|
|
243
|
-
|
|
245
|
+
An **unlocked** prefill follows the same rule but fails quietly: switching to a chain that can't use
|
|
246
|
+
it drops it, and the connected wallet's address takes over as if you had passed nothing. Verify a
|
|
247
|
+
prefill against the chain of the buy asset you pair it with.
|
|
244
248
|
|
|
245
249
|
A lock is only accepted alongside the value it locks — `isReceiveAddressLocked` on its own is a type
|
|
246
250
|
error, as is `isBuyAmountLocked` without `defaultBuyAmountCryptoBaseUnit`. Locking with nothing to
|
|
@@ -285,15 +289,14 @@ user's own wallet, or topping up a locked address again, are both things a user
|
|
|
285
289
|
twice.
|
|
286
290
|
`isBuyAssetLocked` never affects this — restricting swaps to a given token is just a configuration.
|
|
287
291
|
|
|
288
|
-
###
|
|
292
|
+
### Locking the buy amount or receive address disables redirects
|
|
289
293
|
|
|
290
294
|
The app.shapeshift.com redirect carries neither the destination nor the buy amount, so following it
|
|
291
295
|
would drop whichever constraint you set. Locking the buy amount **or** the receive address
|
|
292
296
|
therefore disables it outright: `allowShapeshiftRedirect` has no effect, and assets on
|
|
293
297
|
non-executable chains drop out of the asset pickers rather than dead-ending. The pickers share that
|
|
294
298
|
filter, so Cosmos-SDK assets go from the **buy** side too, even though a swap into them works — only
|
|
295
|
-
the sell side needs a signature. The remaining redirect-only chains
|
|
296
|
-
address validator for them, so they were never usable as a destination.
|
|
299
|
+
the sell side needs a signature. The remaining redirect-only chains go with them.
|
|
297
300
|
|
|
298
301
|
Note this is a wider condition than payment mode — locking either one is enough, because a single
|
|
299
302
|
dropped constraint can send funds somewhere you didn't intend.
|
|
@@ -341,8 +344,70 @@ only the swap itself resets.
|
|
|
341
344
|
### Refunds
|
|
342
345
|
|
|
343
346
|
If a swap can't be completed, the provider returns the funds to the **sending** address — the wallet
|
|
344
|
-
the user swapped from
|
|
345
|
-
|
|
347
|
+
the user swapped from, or the address they entered in the [deposit
|
|
348
|
+
flow](#external-wallets-and-deposit-addresses) — not to the receive address. A locked destination
|
|
349
|
+
does not affect where a refund goes.
|
|
350
|
+
|
|
351
|
+
## External Wallets and Deposit Addresses
|
|
352
|
+
|
|
353
|
+
Some protocols execute a swap by issuing a **deposit address**: the user sends the sell asset to it
|
|
354
|
+
from any wallet, and the protocol handles the rest. The widget uses this to let people swap with no
|
|
355
|
+
wallet connected at all, and to serve chains it can't sign for.
|
|
356
|
+
|
|
357
|
+
There is nothing to configure. When the selected route comes from a deposit-address protocol and no
|
|
358
|
+
wallet is connected for the sell chain, the primary button becomes **Continue without a wallet**
|
|
359
|
+
instead of Connect Wallet.
|
|
360
|
+
|
|
361
|
+
### What the user provides
|
|
362
|
+
|
|
363
|
+
Two addresses, both entered in the widget and validated against their chains:
|
|
364
|
+
|
|
365
|
+
- **Receive address** — where the bought asset is sent.
|
|
366
|
+
- **Refund address** — their own address on the sell chain, returned to if the swap can't complete.
|
|
367
|
+
This is also recorded as the swap's send address; the two are always the same value. There is no
|
|
368
|
+
prop for it, because it must belong to the user.
|
|
369
|
+
|
|
370
|
+
### The deposit screen
|
|
371
|
+
|
|
372
|
+
After quoting, the widget shows the exact amount to send, the deposit address with a QR code, a
|
|
373
|
+
countdown to the quote's expiry, and a summary of the receive and refund addresses. The user pays
|
|
374
|
+
from any external wallet.
|
|
375
|
+
|
|
376
|
+
The QR carries the bare deposit address by default, which any wallet that scans addresses can read.
|
|
377
|
+
A **With amount** option switches it to a payment URI (BIP-21, EIP-681, Solana Pay, TON) that also
|
|
378
|
+
prefills the amount, with a note that not every wallet reads it. Chains with no adopted URI scheme
|
|
379
|
+
(Tron, Sui, NEAR, Starknet) only ever show the address.
|
|
380
|
+
|
|
381
|
+
Tracking then proceeds on its own — the widget polls the ShapeShift API, which learns of the deposit
|
|
382
|
+
from the protocol and reports the sell transaction once it lands. From that point the flow is
|
|
383
|
+
identical to a wallet swap. Tracking is bounded: the API abandons a swap still unsettled a day after
|
|
384
|
+
it was registered, and the widget stops with it and says the swap may still be settling, rather than
|
|
385
|
+
spinning indefinitely.
|
|
386
|
+
|
|
387
|
+
### Expiry and recovery
|
|
388
|
+
|
|
389
|
+
A deposit window is finite (NEAR Intents quotes run one hour, or four when a UTXO chain is
|
|
390
|
+
involved; Chainflip channels six hours).
|
|
391
|
+
When the countdown reaches zero the screen warns not to send and offers a fresh quote. The same
|
|
392
|
+
happens if the API stops recognising the quote before any deposit was seen. Treat expiry as a hard
|
|
393
|
+
cutoff: what happens to a late deposit is protocol-specific — NEAR Intents refunds it to the refund
|
|
394
|
+
address, while an expired Chainflip channel stops being watched altogether and recovering funds sent
|
|
395
|
+
to it is not guaranteed. If a late deposit is credited anyway, the expired screen still resolves to
|
|
396
|
+
the final result rather than stranding there.
|
|
397
|
+
|
|
398
|
+
The deposit is persisted to `localStorage` for as long as it is tracked — while funds are owed and
|
|
399
|
+
after they land — and restored if the page reloads, so a reload mid-settlement doesn't lose the
|
|
400
|
+
swap. A reload after the deposit was seen rejoins tracking rather than asking for it again. It is
|
|
401
|
+
dropped when the swap finishes, when tracking gives up, or when the user starts a new swap.
|
|
402
|
+
|
|
403
|
+
### Limitations
|
|
404
|
+
|
|
405
|
+
- **Not every route can be paid this way.** Swappers that sign transactions, and a few routes that
|
|
406
|
+
cannot take a plain transfer (currently TON via NEAR Intents), keep the Connect Wallet or
|
|
407
|
+
redirect path instead.
|
|
408
|
+
- **Wallet QR scanners vary.** Support for payment URIs is uneven: some wallets read only the
|
|
409
|
+
address from one, and some fail to parse or misinterpret it. That is why the QR defaults to the
|
|
410
|
+
bare address. The amount and address are always shown as copyable text alongside it.
|
|
346
411
|
|
|
347
412
|
## Theming
|
|
348
413
|
|
|
@@ -624,7 +689,8 @@ React Query client).
|
|
|
624
689
|
Assets on the following chains appear in the selector. Swaps are **executed in-widget** only for EVM,
|
|
625
690
|
UTXO, and Solana assets (`isWidgetExecutableChainId` returns `true`). Cosmos-SDK and redirect-only
|
|
626
691
|
chains are selectable but route the user to [app.shapeshift.com](https://app.shapeshift.com) to
|
|
627
|
-
complete the swap (when `allowShapeshiftRedirect` is enabled)
|
|
692
|
+
complete the swap (when `allowShapeshiftRedirect` is enabled), unless an
|
|
693
|
+
[externally paid route](#external-wallets-and-deposit-addresses) quotes them, which needs no signer.
|
|
628
694
|
|
|
629
695
|
| Chain | Chain ID | Type | Executable in-widget |
|
|
630
696
|
| ----------------- | ----------------------------------------- | ------ | -------------------- |
|
|
@@ -656,11 +722,15 @@ complete the swap (when `allowShapeshiftRedirect` is enabled).
|
|
|
656
722
|
The widget aggregates quotes across the protocols below and surfaces the best rate. Use
|
|
657
723
|
`allowedSwapperNames` to restrict which are used.
|
|
658
724
|
|
|
659
|
-
- **NEAR Intents** (`SwapperName.NearIntents`)
|
|
725
|
+
- **NEAR Intents** (`SwapperName.NearIntents`) — deposit address
|
|
726
|
+
- **Chainflip** (`SwapperName.Chainflip`) — deposit address
|
|
660
727
|
- **Relay** (`SwapperName.Relay`)
|
|
661
728
|
- **THORChain** (`SwapperName.Thorchain`)
|
|
662
729
|
- **MAYAChain** (`SwapperName.Mayachain`)
|
|
663
730
|
|
|
731
|
+
Protocols marked *deposit address* can be paid from any wallet — see [External Wallets and Deposit
|
|
732
|
+
Addresses](#external-wallets-and-deposit-addresses).
|
|
733
|
+
|
|
664
734
|
> The set of enabled swappers changes over time. Treat this list as current-at-publish; the
|
|
665
735
|
> authoritative source is the `SwapperName` enum exported by this package.
|
|
666
736
|
|
|
@@ -687,10 +757,16 @@ revenue attribution works.
|
|
|
687
757
|
- **Redirects.** Assets on non-executable chains (Cosmos, Zcash, Tron, Sui, TON, NEAR, Starknet)
|
|
688
758
|
send the user to app.shapeshift.com to finish the swap, unless `allowShapeshiftRedirect={false}`
|
|
689
759
|
or the buy amount or receive address is locked (see
|
|
690
|
-
[
|
|
760
|
+
[Locking the buy amount or receive address disables redirects](#locking-the-buy-amount-or-receive-address-disables-redirects)).
|
|
761
|
+
An [externally paid route](#external-wallets-and-deposit-addresses) takes precedence where one is
|
|
762
|
+
available, since it can be paid without any wallet.
|
|
691
763
|
- **Configuration is applied at mount.** `default*` props are read once; locked values keep
|
|
692
764
|
tracking their prop. Remount to change anything else, or to start a fresh swap. See
|
|
693
765
|
[Configuration is applied at mount](#configuration-is-applied-at-mount).
|
|
694
|
-
- **`onSwapSuccess` reports the sell transaction.** The hash it receives is the transaction
|
|
695
|
-
|
|
766
|
+
- **`onSwapSuccess` reports the sell transaction.** The hash it receives is the transaction that
|
|
767
|
+
paid the swap on the sell chain — signed by the user, or their deposit as the protocol reported
|
|
768
|
+
it. On cross-chain routes the destination transfer may still be in flight.
|
|
769
|
+
- **`onSwapError` does not always mean the swap failed.** It also fires when the widget stops
|
|
770
|
+
tracking a swap whose outcome it never learned, which can still settle afterwards. Treat it as
|
|
771
|
+
"not confirmed" rather than "failed" if you act on it.
|
|
696
772
|
- **Mobile responsive.** The widget is designed to work on mobile as well as desktop.
|
package/dist/index.css
CHANGED
|
@@ -325,7 +325,10 @@
|
|
|
325
325
|
.ssw-swap-btn:disabled:active {
|
|
326
326
|
transform: none;
|
|
327
327
|
}
|
|
328
|
-
.ssw-
|
|
328
|
+
.ssw-address-group {
|
|
329
|
+
display: flex;
|
|
330
|
+
flex-direction: column;
|
|
331
|
+
gap: 12px;
|
|
329
332
|
margin-top: 12px;
|
|
330
333
|
background: var(--ssw-bg-tertiary);
|
|
331
334
|
border: 1px solid var(--ssw-border);
|
|
@@ -333,10 +336,14 @@
|
|
|
333
336
|
padding: 12px 16px;
|
|
334
337
|
transition: box-shadow 0.15s ease;
|
|
335
338
|
}
|
|
336
|
-
.ssw-
|
|
339
|
+
.ssw-address-group:focus-within {
|
|
337
340
|
border-color: var(--ssw-accent);
|
|
338
341
|
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
|
339
342
|
}
|
|
343
|
+
.ssw-address-group > * + * {
|
|
344
|
+
border-top: 1px solid var(--ssw-border);
|
|
345
|
+
padding-top: 12px;
|
|
346
|
+
}
|
|
340
347
|
.ssw-receive-row-resolved {
|
|
341
348
|
display: flex;
|
|
342
349
|
align-items: center;
|
|
@@ -459,10 +466,14 @@
|
|
|
459
466
|
font-size: 12px;
|
|
460
467
|
color: var(--ssw-error);
|
|
461
468
|
}
|
|
462
|
-
.ssw-receive-
|
|
469
|
+
.ssw-receive-hint {
|
|
470
|
+
font-size: 12px;
|
|
471
|
+
color: var(--ssw-text-muted);
|
|
472
|
+
}
|
|
473
|
+
.ssw-address-group.ssw-attention {
|
|
463
474
|
box-shadow: 0 0 16px -2px var(--ssw-accent);
|
|
464
475
|
}
|
|
465
|
-
.ssw-
|
|
476
|
+
.ssw-address-group.ssw-address-group-invalid {
|
|
466
477
|
border-color: var(--ssw-error);
|
|
467
478
|
}
|
|
468
479
|
.ssw-quotes {
|
|
@@ -709,19 +720,43 @@
|
|
|
709
720
|
width: 100%;
|
|
710
721
|
max-width: 320px;
|
|
711
722
|
}
|
|
723
|
+
.ssw-or-divider {
|
|
724
|
+
display: flex;
|
|
725
|
+
align-items: center;
|
|
726
|
+
gap: 12px;
|
|
727
|
+
margin: -4px 16px 12px;
|
|
728
|
+
color: var(--ssw-text-muted);
|
|
729
|
+
font-size: 12px;
|
|
730
|
+
text-transform: uppercase;
|
|
731
|
+
letter-spacing: 0.08em;
|
|
732
|
+
}
|
|
733
|
+
.ssw-or-divider::before,
|
|
734
|
+
.ssw-or-divider::after {
|
|
735
|
+
content: "";
|
|
736
|
+
flex: 1;
|
|
737
|
+
height: 1px;
|
|
738
|
+
background: var(--ssw-border);
|
|
739
|
+
}
|
|
712
740
|
.ssw-step-actions .ssw-action-btn {
|
|
713
741
|
flex: 1;
|
|
714
742
|
width: auto;
|
|
715
743
|
margin: 0;
|
|
716
744
|
white-space: nowrap;
|
|
717
745
|
}
|
|
718
|
-
.ssw-step-actions .ssw-secondary
|
|
746
|
+
.ssw-step-actions .ssw-secondary,
|
|
747
|
+
.ssw-deposit > .ssw-secondary,
|
|
748
|
+
.ssw-btn-outline .ssw-step-actions .ssw-action-btn.ssw-secondary,
|
|
749
|
+
.ssw-btn-outline .ssw-deposit > .ssw-action-btn.ssw-secondary {
|
|
719
750
|
background: var(--ssw-bg-tertiary);
|
|
720
|
-
border: 1px solid var(--ssw-border);
|
|
721
|
-
color: var(--ssw-text-
|
|
751
|
+
border: 1px solid var(--ssw-border-hover);
|
|
752
|
+
color: var(--ssw-text-primary);
|
|
722
753
|
}
|
|
723
|
-
.ssw-step-actions .ssw-secondary:hover
|
|
724
|
-
|
|
754
|
+
.ssw-step-actions .ssw-action-btn.ssw-secondary:hover:not(:disabled),
|
|
755
|
+
.ssw-deposit > .ssw-action-btn.ssw-secondary:hover:not(:disabled),
|
|
756
|
+
.ssw-btn-outline .ssw-step-actions .ssw-action-btn.ssw-secondary:hover:not(:disabled),
|
|
757
|
+
.ssw-btn-outline .ssw-deposit > .ssw-action-btn.ssw-secondary:hover:not(:disabled) {
|
|
758
|
+
background: var(--ssw-bg-tertiary);
|
|
759
|
+
border-color: color-mix(in srgb, var(--ssw-accent) 55%, transparent);
|
|
725
760
|
color: var(--ssw-text-primary);
|
|
726
761
|
}
|
|
727
762
|
.ssw-btn-outline .ssw-action-btn {
|
|
@@ -749,6 +784,191 @@
|
|
|
749
784
|
color: var(--ssw-text-primary);
|
|
750
785
|
background: var(--ssw-bg-hover);
|
|
751
786
|
}
|
|
787
|
+
.ssw-deposit {
|
|
788
|
+
display: flex;
|
|
789
|
+
flex-direction: column;
|
|
790
|
+
align-items: center;
|
|
791
|
+
gap: 14px;
|
|
792
|
+
padding: 12px 0 4px;
|
|
793
|
+
}
|
|
794
|
+
.ssw-deposit-title {
|
|
795
|
+
font-size: 16px;
|
|
796
|
+
font-weight: 600;
|
|
797
|
+
color: var(--ssw-text-primary);
|
|
798
|
+
text-align: center;
|
|
799
|
+
}
|
|
800
|
+
.ssw-deposit-field {
|
|
801
|
+
display: flex;
|
|
802
|
+
flex-direction: column;
|
|
803
|
+
gap: 6px;
|
|
804
|
+
width: 100%;
|
|
805
|
+
}
|
|
806
|
+
.ssw-deposit-field-label {
|
|
807
|
+
font-size: 13px;
|
|
808
|
+
font-weight: 500;
|
|
809
|
+
color: var(--ssw-text-secondary);
|
|
810
|
+
}
|
|
811
|
+
.ssw-qr {
|
|
812
|
+
border-radius: var(--ssw-radius-md);
|
|
813
|
+
padding: 8px;
|
|
814
|
+
background: #ffffff;
|
|
815
|
+
}
|
|
816
|
+
.ssw-deposit-qr-mode {
|
|
817
|
+
display: inline-flex;
|
|
818
|
+
border: 1px solid var(--ssw-border);
|
|
819
|
+
border-radius: var(--ssw-radius-md);
|
|
820
|
+
overflow: hidden;
|
|
821
|
+
}
|
|
822
|
+
.ssw-deposit-qr-mode button {
|
|
823
|
+
padding: 6px 12px;
|
|
824
|
+
border: none;
|
|
825
|
+
background: transparent;
|
|
826
|
+
color: var(--ssw-text-secondary);
|
|
827
|
+
font-family: var(--ssw-font-family);
|
|
828
|
+
font-size: 12px;
|
|
829
|
+
font-weight: 600;
|
|
830
|
+
cursor: pointer;
|
|
831
|
+
}
|
|
832
|
+
.ssw-deposit-qr-mode button + button {
|
|
833
|
+
border-left: 1px solid var(--ssw-border);
|
|
834
|
+
}
|
|
835
|
+
.ssw-deposit-qr-mode button[aria-pressed=true] {
|
|
836
|
+
background: var(--ssw-accent-light);
|
|
837
|
+
color: var(--ssw-accent);
|
|
838
|
+
}
|
|
839
|
+
.ssw-deposit-qr-mode button:focus-visible {
|
|
840
|
+
outline: 2px solid var(--ssw-accent);
|
|
841
|
+
outline-offset: -2px;
|
|
842
|
+
}
|
|
843
|
+
.ssw-deposit-qr-controls {
|
|
844
|
+
position: relative;
|
|
845
|
+
display: flex;
|
|
846
|
+
}
|
|
847
|
+
.ssw-deposit-qr-info {
|
|
848
|
+
position: absolute;
|
|
849
|
+
top: 50%;
|
|
850
|
+
left: calc(100% + 6px);
|
|
851
|
+
transform: translateY(-50%);
|
|
852
|
+
display: grid;
|
|
853
|
+
place-items: center;
|
|
854
|
+
width: 24px;
|
|
855
|
+
height: 24px;
|
|
856
|
+
padding: 0;
|
|
857
|
+
border: none;
|
|
858
|
+
border-radius: 50%;
|
|
859
|
+
background: transparent;
|
|
860
|
+
color: var(--ssw-text-muted);
|
|
861
|
+
cursor: help;
|
|
862
|
+
}
|
|
863
|
+
.ssw-deposit-qr-info:hover,
|
|
864
|
+
.ssw-deposit-qr-info:focus-visible {
|
|
865
|
+
color: var(--ssw-text-primary);
|
|
866
|
+
}
|
|
867
|
+
.ssw-deposit-qr-info:focus-visible {
|
|
868
|
+
outline: 2px solid var(--ssw-accent);
|
|
869
|
+
outline-offset: 1px;
|
|
870
|
+
}
|
|
871
|
+
.ssw-deposit-qr-tooltip {
|
|
872
|
+
position: absolute;
|
|
873
|
+
top: calc(100% + 8px);
|
|
874
|
+
left: 50%;
|
|
875
|
+
z-index: 10;
|
|
876
|
+
display: grid;
|
|
877
|
+
gap: 6px;
|
|
878
|
+
width: max-content;
|
|
879
|
+
max-width: 240px;
|
|
880
|
+
padding: 8px 10px;
|
|
881
|
+
border: 1px solid var(--ssw-border);
|
|
882
|
+
border-radius: var(--ssw-radius-sm);
|
|
883
|
+
background: var(--ssw-bg-secondary);
|
|
884
|
+
color: var(--ssw-text-secondary);
|
|
885
|
+
font-size: 12px;
|
|
886
|
+
line-height: 1.4;
|
|
887
|
+
text-align: left;
|
|
888
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
|
|
889
|
+
opacity: 0;
|
|
890
|
+
visibility: hidden;
|
|
891
|
+
pointer-events: none;
|
|
892
|
+
transform: translateX(-50%);
|
|
893
|
+
}
|
|
894
|
+
.ssw-deposit-qr-tooltip strong {
|
|
895
|
+
color: var(--ssw-text-primary);
|
|
896
|
+
font-weight: 600;
|
|
897
|
+
}
|
|
898
|
+
.ssw-deposit-qr-info:hover + .ssw-deposit-qr-tooltip,
|
|
899
|
+
.ssw-deposit-qr-info:focus-visible + .ssw-deposit-qr-tooltip,
|
|
900
|
+
.ssw-deposit-qr-tooltip.ssw-open {
|
|
901
|
+
opacity: 1;
|
|
902
|
+
visibility: visible;
|
|
903
|
+
}
|
|
904
|
+
.ssw-deposit-qr-controls .ssw-deposit-qr-info + .ssw-deposit-qr-tooltip.ssw-dismissed {
|
|
905
|
+
opacity: 0;
|
|
906
|
+
visibility: hidden;
|
|
907
|
+
}
|
|
908
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
909
|
+
.ssw-deposit-qr-tooltip {
|
|
910
|
+
transition: opacity 0.12s ease, visibility 0.12s ease;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
.ssw-deposit-value {
|
|
914
|
+
display: flex;
|
|
915
|
+
align-items: center;
|
|
916
|
+
justify-content: space-between;
|
|
917
|
+
gap: 8px;
|
|
918
|
+
width: 100%;
|
|
919
|
+
padding: 12px;
|
|
920
|
+
border: 1px solid var(--ssw-border);
|
|
921
|
+
border-radius: var(--ssw-radius-md);
|
|
922
|
+
background: var(--ssw-bg-input);
|
|
923
|
+
color: var(--ssw-text-primary);
|
|
924
|
+
font-family: monospace;
|
|
925
|
+
font-size: 13px;
|
|
926
|
+
font-variant-numeric: tabular-nums;
|
|
927
|
+
cursor: pointer;
|
|
928
|
+
}
|
|
929
|
+
.ssw-deposit-value:hover {
|
|
930
|
+
border-color: var(--ssw-border-hover);
|
|
931
|
+
}
|
|
932
|
+
.ssw-deposit-copy {
|
|
933
|
+
color: var(--ssw-accent);
|
|
934
|
+
font-family: var(--ssw-font-family);
|
|
935
|
+
font-size: 12px;
|
|
936
|
+
font-weight: 600;
|
|
937
|
+
}
|
|
938
|
+
.ssw-deposit-countdown {
|
|
939
|
+
font-size: 13px;
|
|
940
|
+
color: var(--ssw-text-muted);
|
|
941
|
+
}
|
|
942
|
+
.ssw-deposit-watching {
|
|
943
|
+
display: flex;
|
|
944
|
+
align-items: center;
|
|
945
|
+
gap: 8px;
|
|
946
|
+
margin-top: 12px;
|
|
947
|
+
max-width: 280px;
|
|
948
|
+
font-size: 13px;
|
|
949
|
+
color: var(--ssw-text-muted);
|
|
950
|
+
line-height: 1.5;
|
|
951
|
+
text-align: left;
|
|
952
|
+
}
|
|
953
|
+
.ssw-deposit-summary {
|
|
954
|
+
display: flex;
|
|
955
|
+
flex-direction: column;
|
|
956
|
+
gap: 8px;
|
|
957
|
+
width: 100%;
|
|
958
|
+
margin-top: 2px;
|
|
959
|
+
padding-top: 14px;
|
|
960
|
+
border-top: 1px solid var(--ssw-border);
|
|
961
|
+
}
|
|
962
|
+
.ssw-deposit .ssw-action-btn {
|
|
963
|
+
margin-top: 6px;
|
|
964
|
+
}
|
|
965
|
+
.ssw-deposit-row {
|
|
966
|
+
display: flex;
|
|
967
|
+
align-items: center;
|
|
968
|
+
justify-content: space-between;
|
|
969
|
+
font-size: 13px;
|
|
970
|
+
color: var(--ssw-text-secondary);
|
|
971
|
+
}
|
|
752
972
|
|
|
753
973
|
/* src/components/QuoteSelector.css */
|
|
754
974
|
.ssw-quote-selector {
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,8 @@ declare enum SwapperName {
|
|
|
8
8
|
NearIntents = "NEAR Intents",
|
|
9
9
|
Relay = "Relay",
|
|
10
10
|
Thorchain = "THORChain",
|
|
11
|
-
Mayachain = "MAYAChain"
|
|
11
|
+
Mayachain = "MAYAChain",
|
|
12
|
+
Chainflip = "Chainflip"
|
|
12
13
|
}
|
|
13
14
|
type Chain = {
|
|
14
15
|
chainId: ChainId;
|
|
@@ -71,6 +72,7 @@ type TradeRate = {
|
|
|
71
72
|
shapeshiftBps: string;
|
|
72
73
|
affiliateBps: string;
|
|
73
74
|
networkFeeCryptoBaseUnit?: string;
|
|
75
|
+
supportsExternalPayment?: boolean;
|
|
74
76
|
error?: {
|
|
75
77
|
code: string;
|
|
76
78
|
message: string;
|