mirror of
https://github.com/luxfi/bridge.git
synced 2026-09-24 00:26:46 +00:00
Mobx state mgmt for swap controls (#314)
impl mobx managed state for swap cards
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
],
|
||||
"exclude": [ "/node_modules" ],
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"baseUrl": "src",
|
||||
"paths": {
|
||||
"@/*": ["*"],
|
||||
|
||||
@@ -1,30 +1,23 @@
|
||||
import { useState } from 'react'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
|
||||
import type { Asset } from '@luxfi/core'
|
||||
import { cn } from '@hanzo/ui/util'
|
||||
|
||||
import CurrencyInput, { type CurrencyInputOnChangeValues } from './currency-input'
|
||||
import { useSwapState } from '@/contexts/swap-state'
|
||||
|
||||
import AssetCombobox from './asset-combobox'
|
||||
|
||||
const AssetCard: React.FC<{
|
||||
assets: Asset[]
|
||||
asset: Asset | null
|
||||
setAsset: (asset: Asset | null) => void
|
||||
amountChanged: (a: number) => void
|
||||
usdValue?: number
|
||||
assetsAvailable: number | null
|
||||
availableOfAsset?: number
|
||||
className?: string
|
||||
}> = ({
|
||||
assets,
|
||||
asset,
|
||||
setAsset,
|
||||
amountChanged,
|
||||
}> = observer(({
|
||||
usdValue,
|
||||
assetsAvailable,
|
||||
availableOfAsset,
|
||||
className=''
|
||||
}) => {
|
||||
|
||||
const [_amount, _setAmount] = useState<number>(0)
|
||||
const swapState = useSwapState()
|
||||
|
||||
// component ensures a valid number string
|
||||
const onAmountChange = (
|
||||
@@ -33,8 +26,7 @@ const AssetCard: React.FC<{
|
||||
values?: CurrencyInputOnChangeValues | undefined
|
||||
) => {
|
||||
const a = value ? Number(value) : 0
|
||||
_setAmount(a)
|
||||
amountChanged(a)
|
||||
swapState.setAmount(a)
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -50,15 +42,15 @@ const AssetCard: React.FC<{
|
||||
}
|
||||
/>
|
||||
<AssetCombobox
|
||||
assets={assets}
|
||||
asset={asset}
|
||||
setAsset={setAsset}
|
||||
assets={swapState.assetsAvailable}
|
||||
asset={swapState.asset}
|
||||
setAsset={swapState.setAsset}
|
||||
buttonClx='shrink-0 border-none'
|
||||
popoverAlign='end'
|
||||
/>
|
||||
</div>
|
||||
<div className='flex justify-between items-center text-muted text-sm gap-1.5'>
|
||||
{ (_amount > 0 && usdValue) ? (
|
||||
{ (swapState.amount > 0 && usdValue) ? (
|
||||
<CurrencyInput
|
||||
readOnly
|
||||
prefix='$'
|
||||
@@ -69,13 +61,18 @@ const AssetCard: React.FC<{
|
||||
) : (
|
||||
<div/>
|
||||
)}
|
||||
<span className={cn('block shrink-0', (assetsAvailable === null || asset === null) ? 'invisible w-[1px] h-[1px] overflow-x-hidden' : '')}>
|
||||
{`${assetsAvailable} ${asset?.name} avail`}
|
||||
<span className={cn(
|
||||
'block shrink-0',
|
||||
(availableOfAsset === undefined || !swapState.asset) ?
|
||||
'invisible w-[1px] h-[1px] overflow-x-hidden'
|
||||
:
|
||||
''
|
||||
)}>
|
||||
{`${availableOfAsset} ${swapState.asset?.name} avail`}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
export default AssetCard
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { cn } from '@hanzo/ui/util'
|
||||
|
||||
import { Bridge } from '@/domain/types'
|
||||
import { type Bridge } from '@/domain/types'
|
||||
|
||||
const BridgeLabel: React.FC<{
|
||||
bridge: Bridge
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import React from 'react'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
|
||||
import { cn } from '@hanzo/ui/util'
|
||||
|
||||
import type { Network, Asset } from '@luxfi/core'
|
||||
|
||||
import type { Bridge, } from '@/domain/types'
|
||||
import { useSwapState } from '@/contexts/swap-state'
|
||||
|
||||
import BridgeLabel from './bridge-label'
|
||||
|
||||
const ReceiveCard: React.FC<{
|
||||
from: Network
|
||||
to: Network
|
||||
asset: Asset
|
||||
usdValue: number
|
||||
usdFee: number
|
||||
assetGas: number
|
||||
@@ -20,10 +17,7 @@ const ReceiveCard: React.FC<{
|
||||
bridge?: Bridge
|
||||
onSelect?: (bridge: Bridge) => void
|
||||
className?: string
|
||||
}> = ({
|
||||
from,
|
||||
to,
|
||||
asset,
|
||||
}> = observer(({
|
||||
usdValue,
|
||||
usdFee,
|
||||
assetGas,
|
||||
@@ -32,7 +26,10 @@ const ReceiveCard: React.FC<{
|
||||
onSelect,
|
||||
className=''
|
||||
}) => {
|
||||
return (
|
||||
|
||||
const swapState = useSwapState()
|
||||
|
||||
return swapState.amount > 0 ? (
|
||||
<div
|
||||
className={cn(
|
||||
'border border-muted-4 py-2 px-2',
|
||||
@@ -42,15 +39,19 @@ const ReceiveCard: React.FC<{
|
||||
onClick={(!!bridge && !!onSelect) ? () => {onSelect(bridge)} : undefined}
|
||||
>
|
||||
<div className='flex flex-col justify-between items-center text-sm'>
|
||||
<span className='block'>Receive on {to.display_name}</span>
|
||||
{bridge ? (
|
||||
<BridgeLabel bridge={bridge} />
|
||||
) : (
|
||||
null
|
||||
)}
|
||||
{swapState.to ? (
|
||||
<span className='block'>Receive on {swapState.to.display_name }</span>
|
||||
) : (
|
||||
<span className='block'/>
|
||||
)}
|
||||
{bridge ? (
|
||||
<BridgeLabel bridge={bridge} />
|
||||
) : (
|
||||
<div />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
) : null
|
||||
})
|
||||
|
||||
export default ReceiveCard
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { Network } from '@luxfi/core'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
|
||||
import NetworkCombobox from '../network-combobox'
|
||||
import ReverseButton from './reverse-button'
|
||||
import { useSwapState } from '@/contexts/swap-state'
|
||||
|
||||
const ABS_CENTERED = {
|
||||
position: 'absolute',
|
||||
@@ -11,42 +12,39 @@ const ABS_CENTERED = {
|
||||
} satisfies React.CSSProperties
|
||||
|
||||
const FromToCard: React.FC<{
|
||||
from: Network | null
|
||||
to: Network | null
|
||||
fromNetworks: Network[]
|
||||
toNetworks: Network[]
|
||||
setFrom: (v: Network | null) => void
|
||||
setTo: (v: Network | null) => void
|
||||
swapFromAndTo: () => void
|
||||
className?: string
|
||||
}> = ({
|
||||
from,
|
||||
to,
|
||||
fromNetworks,
|
||||
toNetworks,
|
||||
setFrom,
|
||||
setTo,
|
||||
swapFromAndTo,
|
||||
}> = observer(({
|
||||
className=''
|
||||
}) => {
|
||||
|
||||
const swapState = useSwapState()
|
||||
|
||||
const swapFromAndTo = () => {
|
||||
const tmp = swapState.from
|
||||
swapState.setFrom(swapState.to)
|
||||
swapState.setTo(tmp)
|
||||
|
||||
const tmpNetworks = swapState.fromNetworks
|
||||
swapState.setFromNetworks(swapState.toNetworks)
|
||||
swapState.setToNetworks(tmpNetworks)
|
||||
}
|
||||
|
||||
// 'flex w-full gap-2 relative'
|
||||
return (
|
||||
<div className={className}>
|
||||
<NetworkCombobox
|
||||
networks={fromNetworks}
|
||||
setNetwork={setFrom}
|
||||
network={from}
|
||||
networks={swapState.fromNetworks}
|
||||
setNetwork={swapState.setFrom}
|
||||
network={swapState.from}
|
||||
buttonClx='grow pr-4'
|
||||
popoverClx='w-[350px]'
|
||||
popoverAlign='start'
|
||||
label='from'
|
||||
/>
|
||||
<NetworkCombobox
|
||||
networks={toNetworks}
|
||||
setNetwork={setTo}
|
||||
network={to}
|
||||
networks={swapState.toNetworks}
|
||||
setNetwork={swapState.setTo}
|
||||
network={swapState.to}
|
||||
buttonClx='grow pl-4'
|
||||
popoverClx='w-[350px]'
|
||||
popoverAlign='end'
|
||||
@@ -60,6 +58,6 @@ const FromToCard: React.FC<{
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default FromToCard
|
||||
|
||||
@@ -2,7 +2,6 @@ import React, { useRef, useState } from 'react'
|
||||
|
||||
import { cn } from '@hanzo/ui/util'
|
||||
|
||||
import type { Network, Asset } from '@luxfi/core'
|
||||
import type { Bridge } from '@/domain/types'
|
||||
|
||||
import AssetCard from '../asset-card'
|
||||
@@ -24,94 +23,29 @@ const FIXTURE = {
|
||||
|
||||
const SwapCard: React.FC<{
|
||||
className?: string
|
||||
fromNetworks: Network[]
|
||||
fromInitial?: Network | null
|
||||
toNetworks: Network[]
|
||||
toInitial?: Network | null
|
||||
}> = ({
|
||||
className='',
|
||||
fromNetworks,
|
||||
fromInitial,
|
||||
toNetworks,
|
||||
toInitial,
|
||||
}) => {
|
||||
|
||||
const _from = useRef<Network | null>(fromInitial ?? null)
|
||||
const _to = useRef<Network | null>(toInitial ?? null)
|
||||
const _fromNetworks = useRef<Network[]>(fromNetworks)
|
||||
const _toNetworks = useRef<Network[]>(toNetworks)
|
||||
const _asset = useRef<Asset | null>(fromInitial?.currencies![0] ?? null)
|
||||
const _amount = useRef<number>(0)
|
||||
const [triggerUpdate, setTriggerUpdate] = useState<boolean>(false)
|
||||
|
||||
const update = () => {setTriggerUpdate((c) => (!c))}
|
||||
|
||||
const setFrom = (v: Network | null) => {
|
||||
_from.current = v
|
||||
update()
|
||||
}
|
||||
|
||||
const setTo = (v: Network | null) => {
|
||||
_to.current = v
|
||||
update()
|
||||
}
|
||||
|
||||
const setAmount = (n: number) => {
|
||||
_amount.current = n
|
||||
}
|
||||
|
||||
const setAsset = (t: Asset | null) => {
|
||||
_asset.current = t
|
||||
update()
|
||||
}
|
||||
|
||||
const swapFromAndTo = () => {
|
||||
const tmp = _from.current
|
||||
_from.current = _to.current
|
||||
_to.current = tmp
|
||||
const tmpNetworks = _fromNetworks.current
|
||||
_fromNetworks.current = _toNetworks.current
|
||||
_toNetworks.current = tmpNetworks
|
||||
setTriggerUpdate((c) => (!c))
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn(
|
||||
'flex flex-col justify-start items-center p-6 rounded border border-muted-4',
|
||||
className
|
||||
)}>
|
||||
<FromToCard
|
||||
swapFromAndTo={swapFromAndTo}
|
||||
from={_from.current}
|
||||
to={_to.current}
|
||||
fromNetworks={_fromNetworks.current}
|
||||
toNetworks={_toNetworks.current}
|
||||
setFrom={setFrom}
|
||||
setTo={setTo}
|
||||
className='flex w-full gap-2 relative'
|
||||
/>
|
||||
<FromToCard className='flex w-full gap-2 relative' />
|
||||
<AssetCard
|
||||
assets={_from.current?.currencies!}
|
||||
asset={_asset.current}
|
||||
setAsset={setAsset}
|
||||
usdValue={FIXTURE.usdValue}
|
||||
amountChanged={setAmount}
|
||||
assetsAvailable={FIXTURE.assetsAvailable}
|
||||
availableOfAsset={FIXTURE.assetsAvailable}
|
||||
className='w-full rounded-lg mt-2'
|
||||
/>
|
||||
{_amount.current > 0 && (
|
||||
<ReceiveCard
|
||||
from={_from.current!}
|
||||
to={_to.current!}
|
||||
asset={_asset.current!}
|
||||
usdValue={FIXTURE.usdValue}
|
||||
usdFee={FIXTURE.usdFee}
|
||||
assetGas={FIXTURE.assetGas}
|
||||
bridge={FIXTURE.bridge}
|
||||
txnTime={FIXTURE.txnTime}
|
||||
className=''
|
||||
/>
|
||||
)}
|
||||
<ReceiveCard
|
||||
usdValue={FIXTURE.usdValue}
|
||||
usdFee={FIXTURE.usdFee}
|
||||
assetGas={FIXTURE.assetGas}
|
||||
bridge={FIXTURE.bridge}
|
||||
txnTime={FIXTURE.txnTime}
|
||||
className=''
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
import type { PropsWithChildren } from 'react'
|
||||
|
||||
import { SettingsProvider } from '@/contexts/settings'
|
||||
import type BridgeSettings from '@/domain/types/app-settings'
|
||||
import SettingsProvider from '@/contexts/settings'
|
||||
import SwapStateProvider from '@/contexts/swap-state'
|
||||
|
||||
const Contexts: React.FC<{
|
||||
settings?: BridgeSettings
|
||||
} & PropsWithChildren> = ({
|
||||
settings,
|
||||
const Contexts: React.FC<PropsWithChildren> = ({
|
||||
children
|
||||
}) => {
|
||||
|
||||
return (
|
||||
<SettingsProvider settings={settings}>
|
||||
<SettingsProvider >
|
||||
<SwapStateProvider>
|
||||
{children}
|
||||
</SwapStateProvider>
|
||||
</SettingsProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,9 +6,7 @@ interface AppSettingsRef {
|
||||
settings: AppSettings | undefined
|
||||
}
|
||||
|
||||
const SettingsContext = createContext<AppSettingsRef | null>({
|
||||
settings: undefined
|
||||
} satisfies AppSettingsRef)
|
||||
const SettingsContext = createContext<AppSettingsRef | null>(null)
|
||||
|
||||
const SettingsProvider: React.FC<{
|
||||
settings?: AppSettings
|
||||
@@ -23,17 +21,6 @@ const SettingsProvider: React.FC<{
|
||||
)
|
||||
}
|
||||
|
||||
const useSettingsRef = (): AppSettingsRef => {
|
||||
const ref = useContext(SettingsContext)
|
||||
|
||||
if (!ref ) {
|
||||
throw new Error('useSettingsRef must be used withing a SettingsProvider!')
|
||||
}
|
||||
|
||||
return ref
|
||||
}
|
||||
|
||||
|
||||
const useSettings = (): AppSettings => {
|
||||
const ref = useContext(SettingsContext)
|
||||
|
||||
@@ -42,11 +29,10 @@ const useSettings = (): AppSettings => {
|
||||
}
|
||||
|
||||
return ref.settings
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
SettingsProvider,
|
||||
useSettingsRef,
|
||||
SettingsProvider as default,
|
||||
SettingsContext,
|
||||
useSettings,
|
||||
type AppSettingsRef
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { createContext, useContext, type PropsWithChildren } from 'react'
|
||||
|
||||
import type { Network } from '@luxfi/core'
|
||||
|
||||
import type { SwapState } from '@/domain/types'
|
||||
import getInstance from '@/domain/swap-store/get-instance'
|
||||
|
||||
interface SwapStateRef {
|
||||
swapState: SwapState | null
|
||||
}
|
||||
|
||||
const SwapStateContext = createContext<SwapStateRef | null>(null)
|
||||
|
||||
const SwapStateProvider: React.FC<PropsWithChildren> = ({
|
||||
children,
|
||||
}) => (
|
||||
<SwapStateContext.Provider value={{ swapState: null }}>
|
||||
{children}
|
||||
</SwapStateContext.Provider>
|
||||
)
|
||||
|
||||
const useInitializeSwapState = (
|
||||
networks: Network[],
|
||||
initialTo?: Network,
|
||||
initialFrom?: Network
|
||||
): void => {
|
||||
|
||||
const ref = useContext(SwapStateContext)
|
||||
|
||||
if (!ref ) {
|
||||
throw new Error('useInitializeSwapState() must be used within the scope of a SwapStateProvider!')
|
||||
}
|
||||
|
||||
if (ref.swapState) {
|
||||
ref.swapState.setNetworks(
|
||||
networks,
|
||||
initialTo,
|
||||
initialFrom
|
||||
)
|
||||
}
|
||||
else {
|
||||
ref.swapState = getInstance(
|
||||
networks,
|
||||
initialTo,
|
||||
initialFrom
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const useSwapState = (): SwapState => {
|
||||
|
||||
const ref = useContext(SwapStateContext)
|
||||
|
||||
if (!ref || !ref.swapState) {
|
||||
throw new Error('SwapStateProvider or SwapState not ititialized!')
|
||||
}
|
||||
|
||||
return ref.swapState
|
||||
};
|
||||
|
||||
export {
|
||||
SwapStateProvider as default,
|
||||
SwapStateContext,
|
||||
useInitializeSwapState,
|
||||
useSwapState,
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { useContext } from 'react'
|
||||
|
||||
import type AppSettings from '@/domain/types/app-settings'
|
||||
import { SettingsContext } from './settings'
|
||||
import { useInitializeSwapState } from './swap-state'
|
||||
import type { Network } from '@luxfi/core'
|
||||
|
||||
const useSetSettings = (
|
||||
settings: AppSettings,
|
||||
fromInitial?: Network,
|
||||
toInitial?: Network
|
||||
): void => {
|
||||
|
||||
|
||||
useInitializeSwapState(
|
||||
settings.networks,
|
||||
fromInitial,
|
||||
toInitial
|
||||
)
|
||||
const settingsRef = useContext(SettingsContext)
|
||||
if (!settingsRef) {
|
||||
throw new Error('useSetSettings() must be within SettingsProvider and SwapStateProvider!')
|
||||
}
|
||||
settingsRef.settings = settings
|
||||
}
|
||||
|
||||
export {
|
||||
useSetSettings as default
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BackendService } from '../types'
|
||||
import { type BackendService } from '../types'
|
||||
import { default as getSettings } from './get-settings'
|
||||
|
||||
export default {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { enableStaticRendering } from 'mobx-react-lite'
|
||||
|
||||
import type { Network } from '@luxfi/core'
|
||||
|
||||
import type { SwapState } from '@/domain/types'
|
||||
import SwapStore from './index'
|
||||
|
||||
// https://dev.to/ivandotv/mobx-server-side-rendering-with-next-js-4m18
|
||||
enableStaticRendering(typeof window === "undefined")
|
||||
|
||||
let instance: SwapState | undefined = undefined
|
||||
|
||||
const getInstance = (
|
||||
networks: Network[],
|
||||
initialFrom?: Network,
|
||||
initialTo?: Network
|
||||
): SwapState => {
|
||||
|
||||
// Server side: create a new copy of the store each time
|
||||
if (typeof window === "undefined") {
|
||||
return new SwapStore(
|
||||
networks,
|
||||
initialTo,
|
||||
initialFrom
|
||||
)
|
||||
}
|
||||
|
||||
// Client side: create the store only once
|
||||
if (!instance) {
|
||||
instance = new SwapStore(
|
||||
networks,
|
||||
initialTo,
|
||||
initialFrom
|
||||
)
|
||||
}
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
export default getInstance
|
||||
@@ -0,0 +1,149 @@
|
||||
import {
|
||||
computed,
|
||||
makeObservable,
|
||||
observable,
|
||||
action,
|
||||
} from 'mobx'
|
||||
|
||||
import type { Asset, Network } from '@luxfi/core'
|
||||
import type SwapState from '../types/swap-state'
|
||||
|
||||
class SwapStore implements SwapState {
|
||||
|
||||
private _from: Network | null
|
||||
private _to: Network | null
|
||||
private _fromNetworks: Network[]
|
||||
private _toNetworks: Network[]
|
||||
private _assetsAvailable: Asset[]
|
||||
private _asset: Asset | null
|
||||
|
||||
private _amount: number
|
||||
|
||||
private _networks: Network[]
|
||||
|
||||
constructor(
|
||||
networks: Network[],
|
||||
initialTo?: Network,
|
||||
initialFrom?: Network
|
||||
) {
|
||||
|
||||
this._networks = networks
|
||||
this._fromNetworks = networks
|
||||
this._toNetworks = networks
|
||||
|
||||
this._from = initialFrom ?? networks[0]
|
||||
this._to = initialTo ?? networks[1]
|
||||
|
||||
// TODO
|
||||
this._assetsAvailable = this._from.currencies
|
||||
this._asset = this._from.currencies[0]
|
||||
|
||||
this._amount = 0
|
||||
|
||||
makeObservable<
|
||||
SwapStore,
|
||||
'_from' |
|
||||
'_to' |
|
||||
'_fromNetworks' |
|
||||
'_toNetworks' |
|
||||
'_asset' |
|
||||
'_assetsAvailable' |
|
||||
'_amount'
|
||||
|
||||
>(this, {
|
||||
_from: observable.shallow,
|
||||
_to : observable.shallow,
|
||||
_fromNetworks: observable.shallow,
|
||||
_toNetworks : observable.shallow,
|
||||
_asset: observable.shallow,
|
||||
_assetsAvailable: observable.shallow,
|
||||
_amount: observable
|
||||
})
|
||||
|
||||
makeObservable(this, {
|
||||
from: computed,
|
||||
to: computed,
|
||||
fromNetworks: computed,
|
||||
toNetworks: computed,
|
||||
assetsAvailable: computed,
|
||||
asset: computed,
|
||||
amount: computed,
|
||||
setFromNetworks: action.bound,
|
||||
setToNetworks: action.bound,
|
||||
setFrom: action.bound,
|
||||
setTo: action.bound,
|
||||
setAsset: action.bound,
|
||||
setNetworks: action.bound,
|
||||
setAmount: action.bound
|
||||
})
|
||||
}
|
||||
|
||||
get from() : Network | null {
|
||||
return this._from
|
||||
}
|
||||
|
||||
get to() : Network| null {
|
||||
return this._to
|
||||
}
|
||||
|
||||
get fromNetworks() : Network[] {
|
||||
return this._fromNetworks
|
||||
}
|
||||
|
||||
get toNetworks() : Network[] {
|
||||
return this._toNetworks
|
||||
}
|
||||
|
||||
get assetsAvailable() : Asset[] {
|
||||
return this._assetsAvailable
|
||||
}
|
||||
|
||||
get asset() : Asset | null {
|
||||
return this._asset
|
||||
}
|
||||
|
||||
get amount() : number {
|
||||
return this._amount
|
||||
}
|
||||
|
||||
setAmount = (a: number): void => {
|
||||
this._amount = a
|
||||
}
|
||||
|
||||
setFrom = (n: Network | null) => {
|
||||
this._from = n
|
||||
}
|
||||
|
||||
setTo = (n: Network | null) => {
|
||||
this._to = n
|
||||
}
|
||||
|
||||
setFromNetworks = (n: Network[]) => {
|
||||
this._fromNetworks = n
|
||||
}
|
||||
|
||||
setToNetworks = (n: Network[]) => {
|
||||
this._toNetworks = n
|
||||
}
|
||||
|
||||
setAsset = (a: Asset | null) => {
|
||||
this._asset = a
|
||||
}
|
||||
|
||||
setNetworks = (
|
||||
networks: Network[],
|
||||
initialTo?: Network,
|
||||
initialFrom?: Network
|
||||
) => {
|
||||
this._networks = networks
|
||||
this._fromNetworks = networks
|
||||
this._toNetworks = networks
|
||||
|
||||
this._from = initialFrom ?? networks[0]
|
||||
this._to = initialTo ?? networks[1]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default SwapStore
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AppSettings from './app-settings'
|
||||
import type AppSettings from './app-settings'
|
||||
|
||||
interface BackendService {
|
||||
getSettings: () => Promise<AppSettings | undefined>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export type { default as Bridge } from './bridge'
|
||||
export type { default as AppSettings } from './app-settings'
|
||||
export type { default as BackendService } from './backend-service'
|
||||
export type { default as SwapState } from './swap-state'
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import type { Network, Asset } from '@luxfi/core'
|
||||
|
||||
interface SwapState {
|
||||
get fromNetworks(): Network[]
|
||||
get toNetworks(): Network[]
|
||||
get to() : Network | null
|
||||
get from() : Network | null
|
||||
get assetsAvailable() : Asset[]
|
||||
get asset() : Asset | null
|
||||
setFrom(n: Network | null) : void
|
||||
setTo(n: Network | null): void
|
||||
setFromNetworks(n: Network[]): void
|
||||
setToNetworks(n: Network[]): void
|
||||
setAsset(a: Asset | null): void
|
||||
|
||||
get amount() : number
|
||||
setAmount(a: number): void
|
||||
|
||||
setNetworks(
|
||||
networks: Network[],
|
||||
initialTo?: Network,
|
||||
initialFrom?: Network
|
||||
): void
|
||||
|
||||
}
|
||||
|
||||
export {
|
||||
type SwapState as default
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { PropsWithChildren } from 'react'
|
||||
import React, { type PropsWithChildren } from 'react'
|
||||
|
||||
import {
|
||||
Links,
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { Network } from '@luxfi/core'
|
||||
|
||||
import SwapCard from '@/components/swap-card'
|
||||
import backend from '@/domain/backend'
|
||||
import { useSettingsRef } from '@/contexts/settings'
|
||||
import useSetSettings from '@/contexts/use-set-settings'
|
||||
|
||||
export const loader = async () => {
|
||||
|
||||
@@ -36,17 +36,12 @@ export const shouldRevalidate = () => false;
|
||||
const Index: React.FC = () => {
|
||||
|
||||
const { settings, fromInitial, toInitial } = useLoaderData<typeof loader>()
|
||||
const settingsRef = useSettingsRef()
|
||||
settingsRef.settings = settings
|
||||
useSetSettings(
|
||||
settings,
|
||||
fromInitial,
|
||||
toInitial
|
||||
)
|
||||
|
||||
return (
|
||||
<SwapCard
|
||||
className='w-[500px] h-[530px]'
|
||||
fromNetworks={settingsRef.settings!.networks!}
|
||||
fromInitial={fromInitial}
|
||||
toNetworks={settingsRef.settings!.networks!}
|
||||
toInitial={toInitial}
|
||||
/>
|
||||
)
|
||||
return ( <SwapCard className='w-[500px] h-[530px]' /> )
|
||||
}
|
||||
export default Index
|
||||
|
||||
@@ -1,28 +1,20 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"isolatedModules": true,
|
||||
// All settings are as per remix rec's
|
||||
// https://remix.run/docs/hi/main/guides/typescript
|
||||
"target": "ES2022",
|
||||
"jsx": "react-jsx",
|
||||
"lib": [
|
||||
"DOM",
|
||||
"DOM.Iterable",
|
||||
"ES2022"
|
||||
],
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"noEmit": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./app/*"
|
||||
]
|
||||
"@/*": [ "./app/*" ]
|
||||
},
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"target": "ES2022",
|
||||
"types": [
|
||||
"@vercel/remix",
|
||||
"vite/client",
|
||||
|
||||
+1
-3
@@ -15,7 +15,5 @@
|
||||
"verbatimModuleSyntax": true,
|
||||
"jsx": "preserve",
|
||||
"declaration": false,
|
||||
"noEmit": true
|
||||
},
|
||||
"plugins": [ { "name": "next" } ]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user