Skip to content
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

feat(synapse-interface): portfolio gas tokens #2401

Merged
merged 53 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
73a15b1
Construct `GasToken` type, add initial few gas tokens to test portfol…
bigboydiamonds Mar 28, 2024
bc13ced
Fetching for native gas token works when creating new Token constant
bigboydiamonds Mar 28, 2024
5c144ad
Implement GasToken type
bigboydiamonds Mar 28, 2024
f1ef57a
Create GasToken constants
bigboydiamonds Mar 29, 2024
a1c9092
Gas tokens showing with icons
bigboydiamonds Mar 29, 2024
60c60b6
Filter out gas tokens from portfolio tokens
bigboydiamonds Mar 29, 2024
40c9a7d
Account for chains that do not have gas tokens
bigboydiamonds Mar 29, 2024
e06fe7e
Create gas token component that is not clickable
bigboydiamonds Mar 29, 2024
c9cf3e8
Fix undefined filter issue
bigboydiamonds Mar 29, 2024
32bf18d
Account for when tokens or gasTokens do not exist
bigboydiamonds Mar 29, 2024
6a3f653
GasTokenAsset'
bigboydiamonds Mar 29, 2024
678525f
Remove extraneous props from GasTokenAsset
bigboydiamonds Mar 29, 2024
748d688
Add remaining gas tokens
bigboydiamonds Mar 29, 2024
3551516
Add gas token asset descriptor text
bigboydiamonds Apr 1, 2024
d6554ed
Add gas token dtext for bridgeable gas tokens
bigboydiamonds Apr 1, 2024
66e9130
Text color
bigboydiamonds Apr 1, 2024
cedbc82
Fix spelling
bigboydiamonds Apr 1, 2024
0ac45f1
Add Gas Icon
bigboydiamonds Apr 1, 2024
711a8b1
Add hover tooltip for Gas Icon
bigboydiamonds Apr 1, 2024
b7b02b7
Refactor: HoverTooltip
bigboydiamonds Apr 1, 2024
017797a
Clean
bigboydiamonds Apr 1, 2024
f141b5b
Add padding to gas icon top
bigboydiamonds Apr 1, 2024
23a3f33
Update gas icon size
bigboydiamonds Apr 2, 2024
a5f573f
Prevent colliding tooltips
bigboydiamonds Apr 2, 2024
093aaba
Center justify tooltip
bigboydiamonds Apr 2, 2024
375309a
Clean
bigboydiamonds Apr 2, 2024
877fdc0
Catch any errors for single network portfolio fetch so rest return
bigboydiamonds Apr 2, 2024
952d8c5
Apply changes to GasTokenAsset
bigboydiamonds Apr 2, 2024
a37ed97
Replace balance title with tooltip
bigboydiamonds Apr 2, 2024
6a31c29
Use HoverTooltip in portfolio network header
bigboydiamonds Apr 2, 2024
e55c1e5
Merge branch 'master' into fe/portfolio-gas-tokens
abtestingalpha Apr 3, 2024
a1bf4cb
Clean
bigboydiamonds Apr 8, 2024
601ea4d
Merge branch 'fe/portfolio-gas-tokens' of https://github.com/synapsec…
bigboydiamonds Apr 8, 2024
1bee10d
Merge branch 'master' into fe/portfolio-gas-tokens
bigboydiamonds Apr 9, 2024
4ae15d7
Move getParsedBalance to utils
bigboydiamonds Apr 9, 2024
f3a0df1
Use CHAINS constant to consruct GasToken data
bigboydiamonds Apr 9, 2024
04f400e
Fix Canto gas token error
bigboydiamonds Apr 10, 2024
354d36a
Update nativeCurrency fields to include gas token properties
bigboydiamonds Apr 10, 2024
77e6d38
Update getGasTokens() util function for updated type
bigboydiamonds Apr 10, 2024
93f6ec7
Allow nativeCurrency fields to be undefined if not bridgeable
bigboydiamonds Apr 10, 2024
3117294
Successfully filter for gas tokens in new approach
bigboydiamonds Apr 10, 2024
fe08d75
Clean
bigboydiamonds Apr 10, 2024
711216e
Optimize mapping for gas tokens
bigboydiamonds Apr 10, 2024
094ca55
Update fetchPortfolioBalances to account for new shape in nativeCurrency
bigboydiamonds Apr 10, 2024
ea57c76
Implement new NON_BRIDGEABLE_GAS_TOKEN constant
bigboydiamonds Apr 10, 2024
be13154
Update fetch functions for type
bigboydiamonds Apr 10, 2024
592fd72
Remove undefined prop types
bigboydiamonds Apr 10, 2024
e5ba641
Clean
bigboydiamonds Apr 10, 2024
d39cb85
Merge pull request #2480 from synapsecns/fe/chain-native-currency
bigboydiamonds Apr 17, 2024
b3a272c
Merge branch 'master' into fe/portfolio-gas-tokens
abtestingalpha Apr 17, 2024
20e2152
Merge branch 'master' into fe/portfolio-gas-tokens
bigboydiamonds Apr 17, 2024
605551e
Merge branch 'fe/portfolio-gas-tokens' of https://github.com/synapsec…
bigboydiamonds Apr 17, 2024
cbfcb6c
GasTokensByChain naming convention
bigboydiamonds Apr 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react'
import { Token } from '@/utils/types'
import Image from 'next/image'
import { getParsedBalance } from './PortfolioTokenAsset'

export const GasTokenAsset = ({
token,
balance,
}: {
token: Token
balance: bigint
}) => {
const { icon, symbol, decimals } = token
const parsedBalance = getParsedBalance(balance, decimals as number, 3)

return (
<div
id="gas-token-asset"
className={`
p-2 flex items-center border-y text-white
justify-between last:rounded-b-md border-transparent
`}
>
<div className="flex items-center gap-2 py-2 pl-2 pr-4 rounded">
<Image
loading="lazy"
alt={`${symbol} img`}
className="w-6 h-6 rounded-md"
src={icon}
/>
{parsedBalance} {symbol}
<div className="text-sm text-secondary">gas token</div>
</div>

<div className="p-1 text-sm text-secondary">Not bridgable</div>
bigboydiamonds marked this conversation as resolved.
Show resolved Hide resolved
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useBridgeState } from '@/slices/bridge/hooks'
import { hasOnlyZeroes } from '@/utils/hasOnlyZeroes'
import { PortfolioAssetActionButton } from './PortfolioAssetActionButton'
import { trimTrailingZeroesAfterDecimal } from '@/utils/trimTrailingZeroesAfterDecimal'
import { zeroAddress } from 'viem'

const handleFocusOnBridgeInput = () => {
inputRef.current.focus()
Expand All @@ -34,7 +35,7 @@ export const PortfolioTokenAsset = ({
}: PortfolioTokenAssetProps) => {
const dispatch = useAppDispatch()
const { fromChainId, fromToken } = useBridgeState()
const { icon, symbol, decimals } = token
const { icon, symbol, decimals, addresses } = token

const tokenDecimals = _.isNumber(decimals)
? decimals
Expand All @@ -58,6 +59,8 @@ export const PortfolioTokenAsset = ({
)
}, [token, balance, portfolioChainId])

const isBridgeableGasToken = addresses[portfolioChainId] === zeroAddress

return (
<div
id="portfolio-token-asset"
Expand All @@ -82,6 +85,9 @@ export const PortfolioTokenAsset = ({
src={icon}
/>
{parsedBalance} {symbol}
{isBridgeableGasToken ? (
<div className="text-sm text-secondary">gas token</div>
) : null}
</div>
<PortfolioAssetActionButton
selectCallback={handleFromSelectionCallback}
Expand All @@ -92,7 +98,7 @@ export const PortfolioTokenAsset = ({
)
}

const getParsedBalance = (
export const getParsedBalance = (
abtestingalpha marked this conversation as resolved.
Show resolved Hide resolved
balance: bigint,
decimals: number,
places?: number
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react'
import { Address } from 'viem'
import { useDispatch } from 'react-redux'
import _ from 'lodash'
import _, { isArray } from 'lodash'
import { CHAINS_BY_ID } from '@/constants/chains'
import {
TokenAndBalance,
Expand All @@ -19,6 +19,9 @@ import { TWITTER_URL, DISCORD_URL } from '@/constants/urls'
import { setFromToken, setToToken } from '@/slices/bridge/reducer'
import { PortfolioTokenVisualizer } from './PortfolioTokenVisualizer'
import { PortfolioNetwork } from './PortfolioNetwork'
import { GAS_TOKENS } from '@/constants/tokens'
import { GasTokenAsset } from './GasTokenAsset'
import { GasToken } from '@/constants/tokens/gasTokens'

type SingleNetworkPortfolioProps = {
connectedAddress: Address
Expand All @@ -30,6 +33,37 @@ type SingleNetworkPortfolioProps = {
fetchState: FetchState
}

const filterOutGasTokens = (
tokens: TokenAndBalance[],
chainId: number
): [TokenAndBalance[], TokenAndBalance[]] => {
const gasTokens = GAS_TOKENS[chainId]

let filteredGasTokens: TokenAndBalance[] = []
let remainingTokens: TokenAndBalance[] = []

if (!gasTokens && !isArray(tokens)) {
return [filteredGasTokens, remainingTokens]
}

if (!gasTokens && isArray(tokens)) {
remainingTokens = [...tokens]
} else {
const gasTokenAddresses = gasTokens?.flatMap((token) =>
Object.values(token.addresses)
)
tokens?.forEach((token) => {
if (gasTokenAddresses?.includes(token.tokenAddress)) {
filteredGasTokens.push(token)
} else {
remainingTokens.push(token)
}
})
}

return [filteredGasTokens, remainingTokens]
}

export const SingleNetworkPortfolio = ({
connectedAddress,
portfolioChainId,
Expand All @@ -47,6 +81,12 @@ export const SingleNetworkPortfolio = ({
const isUnsupportedChain: boolean = !chain

const sortedTokens = sortTokensByBalanceDescending(portfolioTokens)

const [gasTokens, bridgeableTokens] = filterOutGasTokens(
sortedTokens,
portfolioChainId
)

const hasNoTokenBalance: boolean =
_.isNull(portfolioTokens) || _.isEmpty(portfolioTokens)

Expand Down Expand Up @@ -110,9 +150,14 @@ export const SingleNetworkPortfolio = ({
connectedChain={chain}
/>
)}
{sortedTokens &&
sortedTokens.length > 0 &&
sortedTokens.map(({ token, balance }: TokenAndBalance) => (
{gasTokens &&
gasTokens.length > 0 &&
gasTokens.map(({ token, balance }: TokenAndBalance) => (
<GasTokenAsset key={token.symbol} token={token} balance={balance} />
))}
{bridgeableTokens &&
bridgeableTokens.length > 0 &&
bridgeableTokens.map(({ token, balance }: TokenAndBalance) => (
<PortfolioTokenAsset
key={token.symbol}
token={token}
Expand Down
108 changes: 108 additions & 0 deletions packages/synapse-interface/constants/tokens/gasTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { zeroAddress } from 'viem'
import bscImg from '@assets/chains/bnb.svg'
import metisImg from '@assets/chains/metis.svg'
import moonbeamImg from '@assets/chains/moonbeam.svg'
import moonriverImg from '@assets/chains/moonriver.svg'
import harmonyImg from '@assets/chains/harmony.svg'
import cantoImg from '@assets/chains/canto.svg'
import dogechainImg from '@assets/chains/dogechain.svg'
import cronosImg from '@assets/chains/cronos.svg'

import * as CHAINS from '@/constants/chains/master'

export type GasToken = {
addresses: { [x: number]: string }
chainId: number
decimals: number
symbol: string
name: string
icon: any
}

export const BNB: GasToken = {
addresses: {
[CHAINS.BNB.id]: zeroAddress,
},
chainId: 56,
abtestingalpha marked this conversation as resolved.
Show resolved Hide resolved
decimals: 18,
symbol: 'BNB',
name: 'Binance Coin',
icon: bscImg,
}

export const METIS: GasToken = {
addresses: {
[CHAINS.METIS.id]: zeroAddress,
},
chainId: 1088,
name: 'Metis',
symbol: 'METIS',
decimals: 18,
icon: metisImg,
}

export const NOTE: GasToken = {
addresses: {
[CHAINS.CANTO.id]: zeroAddress,
},
chainId: 7700,
name: 'Canto',
symbol: 'NOTE',
decimals: 18,
icon: cantoImg,
}

export const MOVR: GasToken = {
addresses: {
[CHAINS.MOONRIVER.id]: zeroAddress,
},
chainId: 1285,
name: 'Moonriver',
symbol: 'MOVR',
decimals: 18,
icon: moonriverImg,
}

export const GLMR: GasToken = {
addresses: {
[CHAINS.MOONBEAM.id]: zeroAddress,
},
chainId: 1284,
name: 'Glimmer',
symbol: 'GLMR',
decimals: 18,
icon: moonbeamImg,
}

export const ONE: GasToken = {
addresses: {
[CHAINS.HARMONY.id]: zeroAddress,
},
chainId: 1666600000,
name: 'Harmony One',
symbol: 'ONE',
decimals: 18,
icon: harmonyImg,
}

export const CRO: GasToken = {
addresses: {
[CHAINS.CRONOS.id]: zeroAddress,
},
chainId: 25,
name: 'Cronos',
symbol: 'CRO',
decimals: 18,
icon: cronosImg,
}

export const DOGE: GasToken = {
addresses: {
[CHAINS.DOGE.id]: zeroAddress,
},
chainId: 2000,
name: 'DOGE',
symbol: 'DOGE',
decimals: 18,
icon: dogechainImg,
}
26 changes: 26 additions & 0 deletions packages/synapse-interface/constants/tokens/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import _ from 'lodash'
import * as CHAINS from '@constants/chains/master'
import * as all from '@constants/tokens/bridgeable'
import * as allGasTokens from '@constants/tokens/gasTokens'
import * as allPool from '@constants/tokens/poolMaster'
import { GMX, ETH, USDC, USDT, WETH } from '@constants/tokens/bridgeable'
import { SYN_ETH_SUSHI_TOKEN } from '@constants/tokens/sushiMaster'
import { Token } from '@utils/types'
import { GasToken } from '@constants/tokens/gasTokens'

const allSwap = [WETH, USDC, USDT]

Expand All @@ -13,6 +15,10 @@ interface TokensByChain {
[cID: string]: Token[]
}

interface GasTokensByChain {
[cID: string]: GasToken[]
}

interface TokenByKey {
[cID: string]: Token
}
Expand Down Expand Up @@ -69,6 +75,25 @@ const getBridgeableTokens = (): TokensByChain => {
return bridgeableTokens
}

const getGasTokens = (): GasTokensByChain => {
const gasTokens: GasTokensByChain = {}
Object.entries(allGasTokens).map(([key, token]) => {
for (const cID of Object.keys(token.addresses)) {
// Skip if the token is paused on the current chain
if (PAUSED_TOKENS_BY_CHAIN[cID]?.includes(key)) continue

if (!gasTokens[cID]) {
gasTokens[cID] = [token]
} else {
if (!gasTokens[cID]?.includes(token)) {
gasTokens[cID] = [...gasTokens[cID], token]
}
}
}
})
return gasTokens
}

const getTokenHashMap = () => {
const tokenHashMap = {}

Expand All @@ -93,6 +118,7 @@ export const TOKENS_SORTED_BY_SYMBOL = Array.from(
new Set(sortedTokens.map((token) => token.symbol))
)
export const BRIDGABLE_TOKENS = getBridgeableTokens()
export const GAS_TOKENS = getGasTokens()

export const tokenSymbolToToken = (chainId: number, symbol: string) => {
if (chainId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { sortByTokenBalance } from '../sortTokens'
import { Chain, Token } from '../types'
import { BRIDGABLE_TOKENS, POOLS_BY_CHAIN } from '@/constants/tokens'
import {
BRIDGABLE_TOKENS,
POOLS_BY_CHAIN,
GAS_TOKENS,
} from '@/constants/tokens'
import { FetchState } from '@/slices/portfolio/actions'

export interface TokenAndBalance {
Expand Down Expand Up @@ -50,16 +54,24 @@ export const fetchPortfolioBalances = async (

try {
const balancePromises = filteredChains.map(async (chainId) => {
let currentChainTokens
const currentChainId = Number(chainId)
let currentChainTokens

currentChainTokens = BRIDGABLE_TOKENS[chainId]

if (POOLS_BY_CHAIN[chainId]) {
currentChainTokens = BRIDGABLE_TOKENS[chainId].concat(
POOLS_BY_CHAIN[chainId]
)
} else {
currentChainTokens = BRIDGABLE_TOKENS[chainId]
// currentChainTokens = BRIDGABLE_TOKENS[chainId].concat(
// POOLS_BY_CHAIN[chainId]
// )
currentChainTokens = currentChainTokens.concat(POOLS_BY_CHAIN[chainId])
}

if (GAS_TOKENS[chainId]) {
currentChainTokens = currentChainTokens.concat(GAS_TOKENS[chainId])
}
// else {
// currentChainTokens = BRIDGABLE_TOKENS[chainId]
// }

const [tokenBalances] = await Promise.all([
getTokenBalances(address, currentChainTokens, currentChainId),
Expand Down
Loading