-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add settings, onlyTestnet, routeConfig, filter props #386
Merged
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
8860377
Add default route prop
toddkao c66a262
Merge branch 'main' into add-default-route
toddkao d874e0d
Refactor/fix useEffect being called multiple times
toddkao dd89b75
Remove blue brandColor
toddkao ed06878
Move useInitDefaultRoute into a hook
toddkao ea2c87f
Add more props
toddkao dcdc9b6
Add filter prop
toddkao ce78c0c
Add custom slippage input
toddkao e4523cb
Merge branch 'main' into add-more-props
toddkao 36a38db
Add onlyTestnet prop
toddkao ca82689
Remove unused import
toddkao 2ca11a4
Add customGasAmount prop
toddkao 24d272f
Refactor hook naming
toddkao 6f0c8c9
Refactor/simplify list logic
toddkao add7f22
Update useFilteredChains.ts
toddkao 72943f1
use filteredChains to calculate how many networks
toddkao ee762d7
use empty array fallback
toddkao 78ba634
revert "fix duplicate chains" logic
toddkao 0b4ac7e
update usesEvmInOperation logic
toddkao 635e042
Add EvmDisclaimer to SwapExecutionPageRouteDetailed
toddkao 075ccc6
Remove unused styled component
toddkao f87b397
Update logic to search for chainIds in route?.requiredChainAddresses
toddkao File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { skipChainsAtom } from "@/state/skipClient"; | ||
import { useAtomValue } from "jotai"; | ||
import { useMemo } from "react"; | ||
import styled, { useTheme } from "styled-components"; | ||
import { SmallText } from "./Typography"; | ||
import { RouteResponse } from "@skip-go/client"; | ||
|
||
export const EvmDisclaimer = ({ route }: { route?: RouteResponse } = {}) => { | ||
const theme = useTheme(); | ||
const { data: chains } = useAtomValue(skipChainsAtom); | ||
|
||
const usesEvmInOperations = useMemo(() => { | ||
return route?.requiredChainAddresses?.find( | ||
(chainId) => { | ||
const chainType = chains?.find(chain => chain.chainID === chainId)?.chainType; | ||
return chainType === "evm"; | ||
} | ||
); | ||
}, [chains, route?.requiredChainAddresses]); | ||
|
||
if (usesEvmInOperations) { | ||
return ( | ||
<StyledEvmWarningMessage> | ||
<SmallText color={theme.warning.text}> | ||
This swap contains at least one EVM chain, so it might take longer. | ||
<br /> Read more about common finality times. | ||
</SmallText> | ||
</StyledEvmWarningMessage> | ||
); | ||
} | ||
}; | ||
|
||
const StyledEvmWarningMessage = styled.div` | ||
padding: 12px; | ||
border-radius: 5px; | ||
background-color: ${({ theme }) => theme.warning.background}; | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,10 +15,10 @@ import { | |
isGroupedAsset, | ||
} from "./TokenAndChainSelectorModalRowItem"; | ||
import { TokenAndChainSelectorModalSearchInput } from "./TokenAndChainSelectorModalSearchInput"; | ||
import { matchSorter } from "match-sorter"; | ||
import { useGetBalance } from "@/hooks/useGetBalance"; | ||
import { Chain } from "@skip-go/client"; | ||
import { convertTokenAmountToHumanReadableAmount } from "@/utils/crypto"; | ||
import { useFilteredChains } from "./useFilteredChains"; | ||
import { useFilteredAssets } from "./useFilteredAssets"; | ||
import { useGroupedAssetByRecommendedSymbol } from "./useGroupedAssetsByRecommendedSymbol"; | ||
|
||
export type GroupedAsset = { | ||
id: string; | ||
|
@@ -41,20 +41,18 @@ export type SelectorContext = "source" | "destination"; | |
export type TokenAndChainSelectorModalProps = ModalProps & { | ||
onSelect: (token: ClientAsset | null) => void; | ||
selectedAsset?: ClientAsset; | ||
networkSelection?: boolean; | ||
context: SelectorContext | ||
selectChain?: boolean; | ||
context: SelectorContext; | ||
}; | ||
|
||
export const TokenAndChainSelectorModal = createModal( | ||
(modalProps: TokenAndChainSelectorModalProps) => { | ||
const modal = useModal(); | ||
const { onSelect: _onSelect, selectedAsset, networkSelection } = modalProps; | ||
const { onSelect: _onSelect, selectedAsset, selectChain, context } = modalProps; | ||
const { data: assets, isLoading: isAssetsLoading } = | ||
useAtomValue(skipAssetsAtom); | ||
const { data: chains } = useAtomValue(skipChainsAtom); | ||
const { isLoading: isChainsLoading } = useAtomValue(skipChainsAtom); | ||
const isLoading = isAssetsLoading || isChainsLoading; | ||
const getBalance = useGetBalance(); | ||
|
||
const [showSkeleton, setShowSkeleton] = useState(true); | ||
const [searchQuery, setSearchQuery] = useState<string>(""); | ||
|
@@ -83,67 +81,7 @@ export const TokenAndChainSelectorModal = createModal( | |
[_onSelect] | ||
); | ||
|
||
const groupedAssetsByRecommendedSymbol = useMemo(() => { | ||
if (!assets) return; | ||
const groupedAssets: GroupedAsset[] = []; | ||
|
||
const calculateBalanceSummary = (assets: ClientAsset[]) => { | ||
return assets.reduce( | ||
(accumulator, asset) => { | ||
const balance = getBalance(asset.chainID, asset.denom); | ||
if (balance) { | ||
accumulator.totalAmount += Number( | ||
convertTokenAmountToHumanReadableAmount( | ||
balance.amount, | ||
balance.decimals | ||
) | ||
); | ||
if (Number(balance.valueUSD)) { | ||
accumulator.totalUsd += Number(balance.valueUSD); | ||
} | ||
} | ||
return accumulator; | ||
}, | ||
{ totalAmount: 0, totalUsd: 0 } | ||
); | ||
}; | ||
|
||
assets.forEach((asset) => { | ||
const foundGroup = groupedAssets.find( | ||
(group) => group.id === asset.recommendedSymbol | ||
); | ||
if (foundGroup) { | ||
foundGroup.assets.push(asset); | ||
foundGroup.chains.push({ | ||
chainID: asset.chainID, | ||
chainName: asset.chainName, | ||
originChainID: asset.originChainID, | ||
}); | ||
} else { | ||
groupedAssets.push({ | ||
id: asset.recommendedSymbol || asset.symbol || asset.denom, | ||
chains: [ | ||
{ | ||
chainID: asset.chainID, | ||
chainName: asset.chainName, | ||
originChainID: asset.originChainID, | ||
}, | ||
], | ||
assets: [asset], | ||
totalAmount: 0, | ||
totalUsd: 0, | ||
}); | ||
} | ||
}); | ||
|
||
groupedAssets.forEach((group) => { | ||
const balanceSummary = calculateBalanceSummary(group.assets); | ||
group.totalAmount = balanceSummary.totalAmount; | ||
group.totalUsd = balanceSummary.totalUsd; | ||
}); | ||
|
||
return groupedAssets; | ||
}, [assets, getBalance]); | ||
const groupedAssetsByRecommendedSymbol = useGroupedAssetByRecommendedSymbol({ context }); | ||
|
||
const selectedGroup = useMemo(() => { | ||
const asset = groupedAssetSelected?.assets[0] || selectedAsset; | ||
|
@@ -157,76 +95,8 @@ export const TokenAndChainSelectorModal = createModal( | |
groupedAssetsByRecommendedSymbol, | ||
]); | ||
|
||
const filteredAssets = useMemo(() => { | ||
if (!groupedAssetsByRecommendedSymbol) return; | ||
return matchSorter(groupedAssetsByRecommendedSymbol, searchQuery, { | ||
keys: ["id"], | ||
}).sort((itemA, itemB) => { | ||
const PRIVILEGED_ASSETS = ["ATOM", "USDC", "USDT", "ETH", "TIA", "OSMO", "NTRN", "INJ"]; | ||
if (itemA.totalUsd === 0 && itemB.totalUsd === 0) { | ||
const indexA = PRIVILEGED_ASSETS.indexOf(itemA.id); | ||
const indexB = PRIVILEGED_ASSETS.indexOf(itemB.id); | ||
|
||
if (indexA !== -1 && indexB !== -1) { | ||
return indexA - indexB; | ||
} | ||
|
||
if (indexA !== -1) return -1; | ||
if (indexB !== -1) return 1; | ||
} | ||
|
||
if (itemA.totalUsd < itemB.totalUsd) { | ||
return 1; | ||
} | ||
if (itemA.totalUsd > itemB.totalUsd) { | ||
return -1; | ||
} | ||
return 0; | ||
}); | ||
}, [groupedAssetsByRecommendedSymbol, searchQuery]); | ||
|
||
const filteredChains = useMemo(() => { | ||
if (!selectedGroup || !chains) return; | ||
const resChains = selectedGroup.assets | ||
.map((asset) => { | ||
const c = chains.find((c) => c.chainID === asset.chainID); | ||
return { | ||
...c, | ||
asset, | ||
}; | ||
}) | ||
.filter((c) => c) as ChainWithAsset[]; | ||
return matchSorter(resChains, searchQuery, { | ||
keys: ["prettyName", "chainName", "chainID"], | ||
}).sort((assetA, assetB) => { | ||
const balanceA = getBalance( | ||
assetA.chainID, | ||
assetA.asset.denom | ||
); | ||
const balanceB = getBalance( | ||
assetB.chainID, | ||
assetB.asset.denom | ||
); | ||
|
||
if (Number(balanceA?.valueUSD ?? 0) < Number(balanceB?.valueUSD ?? 0)) { | ||
return 1; | ||
} | ||
|
||
if (Number(balanceA?.valueUSD ?? 0) > Number(balanceB?.valueUSD ?? 0)) { | ||
return -1; | ||
} | ||
|
||
if (assetB.asset.originChainID === assetB.chainID) { | ||
return 1; | ||
} | ||
|
||
if (assetA.asset.originChainID === assetA.chainID) { | ||
return -1; | ||
} | ||
|
||
return 0; | ||
}); | ||
}, [chains, getBalance, searchQuery, selectedGroup]); | ||
const filteredAssets = useFilteredAssets({ groupedAssetsByRecommendedSymbol, searchQuery }); | ||
const filteredChains = useFilteredChains({ selectedGroup, searchQuery, context }); | ||
|
||
useEffect(() => { | ||
if (!isLoading && assets) { | ||
|
@@ -254,28 +124,19 @@ export const TokenAndChainSelectorModal = createModal( | |
index={index} | ||
onSelect={onSelect} | ||
skeleton={<Skeleton />} | ||
context={modalProps.context} | ||
context={context} | ||
/> | ||
); | ||
}, | ||
[modalProps.context, onSelect] | ||
[context, onSelect] | ||
); | ||
const list = useMemo(() => { | ||
if (!networkSelection) { | ||
if (groupedAssetSelected) { | ||
if (modalProps.context === "source") { | ||
return filteredChains?.filter(c => !c.chainID.includes("penumbra")); | ||
} | ||
return filteredChains; | ||
} | ||
return filteredAssets; | ||
} | ||
if (modalProps.context === "source") { | ||
return filteredChains?.filter(c => !c.chainID.includes("penumbra")); | ||
} | ||
return filteredChains; | ||
}, [filteredAssets, filteredChains, groupedAssetSelected, modalProps.context, networkSelection]); | ||
|
||
const listOfAssetsOrChains = useMemo(() => { | ||
if (selectChain || groupedAssetSelected) { | ||
return filteredChains; | ||
} | ||
return filteredAssets; | ||
}, [filteredAssets, filteredChains, groupedAssetSelected, selectChain]); | ||
Comment on lines
+134
to
+139
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. simplify logic, moved penumbra filtering to |
||
|
||
const onClickBack = () => { | ||
if (groupedAssetSelected === null) { | ||
|
@@ -308,7 +169,7 @@ export const TokenAndChainSelectorModal = createModal( | |
</Column> | ||
) : ( | ||
<VirtualList | ||
listItems={list ?? []} | ||
listItems={listOfAssetsOrChains ?? []} | ||
height={530} | ||
itemHeight={70} | ||
itemKey={(item) => { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename prop to
selectChain
, I think it's best to be consistent and always use the same word when referring tochains
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to refactor/change the name of this Modal to
AssetsAndChainSelectorModal
for the same reason, but I will do it in a separate PR to not mess with the diffThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#388