diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 08e2fbc9..e46a9b9c 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -24,4 +24,5 @@ jobs: NEXT_PUBLIC_TITLE=Astra Explorer Testnet NEXT_PUBLIC_GA_MEASUREMENT_ID=G-VXSKSRXRLJ NEXT_PUBLIC_SENTRY_DSN=https://e5a0c44ff6ed4b9b967c490d4587a1b9@sentry.astranet.live/2 - NEXT_PUBLIC_ENV=testnet \ No newline at end of file + NEXT_PUBLIC_ENV=testnet + NEXT_PUBLIC_WASA_ADDRESS=0xA625BF1c3565775B1859B579DF980Fef324E7315 \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5b1f4828..e7150d96 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,3 +26,4 @@ jobs: NEXT_PUBLIC_GA_MEASUREMENT_ID=G-1KW22EJBY5 NEXT_PUBLIC_SENTRY_DSN=https://e5a0c44ff6ed4b9b967c490d4587a1b9@sentry.astranet.live/2 NEXT_PUBLIC_ENV=mainnet + NEXT_PUBLIC_WASA_ADDRESS=0x6637D8275DC58983Cb3A2fa64b705EC11f6EC670 diff --git a/Dockerfile b/Dockerfile index fa4f9238..3cfeb920 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,6 +22,7 @@ ARG NEXT_PUBLIC_TITLE ARG NEXT_PUBLIC_GA_MEASUREMENT_ID ARG NEXT_PUBLIC_SENTRY_DSN ARG NEXT_PUBLIC_ENV +ARG NEXT_PUBLIC_WASA_ADDRESS COPY --from=deps /app/node_modules ./node_modules COPY --from=deps /app/ ./ @@ -38,6 +39,7 @@ RUN SENTRY_AUTH_TOKEN=${SENTRY_AUTH_TOKEN} \ NEXT_PUBLIC_GA_MEASUREMENT_ID=${NEXT_PUBLIC_GA_MEASUREMENT_ID} \ NEXT_PUBLIC_SENTRY_DSN=${NEXT_PUBLIC_SENTRY_DSN} \ NEXT_PUBLIC_ENV=${NEXT_PUBLIC_ENV} \ + NEXT_PUBLIC_WASA_ADDRESS=${NEXT_PUBLIC_WASA_ADDRESS} \ yarn build # Production image, copy all the files and run next diff --git a/package.json b/package.json index 1abccf3d..8b889481 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@cosmjs/encoding": "^0.29.0", "@reduxjs/toolkit": "^1.8.5", "@sentry/nextjs": "^7.20.0", + "@solarswap/sdk": "^1.0.12", "abi-decoder": "^2.4.0", "axios": "^0.27.2", "bignumber.js": "^9.1.0", diff --git a/pages/token/[token]/instance/[index].tsx b/pages/token/[token]/instance/[index].tsx index eefdcc30..0a8ae816 100644 --- a/pages/token/[token]/instance/[index].tsx +++ b/pages/token/[token]/instance/[index].tsx @@ -5,6 +5,7 @@ import API_LIST from 'api/api_list' import { AxiosError } from 'axios' import Container from 'components/Container' import React from 'react' +import { CHAIN_ID } from 'utils/constants' import { LinkMaker, ellipseBetweenText } from 'utils/helper' import NftDetailTab from 'views/tokens/[instance]/NftDetailTab' import NftOverview from 'views/tokens/[instance]/NftOverview' @@ -50,7 +51,7 @@ export async function getServerSideProps({ params }) { let errorMessage = '' let tokenData - if (Web3.utils.isAddress(token, parseInt(process.env.NEXT_PUBLIC_CHAIN_ID) || 11115)) { + if (Web3.utils.isAddress(token, CHAIN_ID)) { try { const response = await cosmosApi.get( `${API_LIST.TOKEN_METADATA}contractaddress=${token}/tokenid=${index}` diff --git a/slices/reducers.ts b/slices/reducers.ts index 84ddf773..afb4eda5 100644 --- a/slices/reducers.ts +++ b/slices/reducers.ts @@ -1,5 +1,6 @@ import { combineReducers } from '@reduxjs/toolkit' +import { tokenApi } from 'store/token' import commonReducer, { CommonState } from './commonSlice' import themeReducer, { ThemeState } from './themeSlice' @@ -10,7 +11,8 @@ export interface IAppState { const rootReducers = combineReducers({ theme: themeReducer, - common: commonReducer + common: commonReducer, + [tokenApi.reducerPath]: tokenApi.reducer }) export default rootReducers diff --git a/store/index.ts b/store/index.ts index 22cee7fd..9cc9b768 100644 --- a/store/index.ts +++ b/store/index.ts @@ -1,7 +1,9 @@ import { configureStore } from '@reduxjs/toolkit' +import { setupListeners } from '@reduxjs/toolkit/dist/query' import { FLUSH, PAUSE, PERSIST, persistReducer, persistStore, PURGE, REGISTER, REHYDRATE } from 'redux-persist' import storage from 'redux-persist/lib/storage' import rootReducers from '../slices/reducers' +import { tokenApi } from './token' const persistConfig = { key: 'root', @@ -27,10 +29,12 @@ const store = configureStore({ 'crossChainTransfer/updateSwapConfig' ] } - }), + }).concat(tokenApi.middleware), devTools: true }) +setupListeners(store.dispatch) + export const persistor = persistStore(store) // Infer the `RootState` and `AppDispatch` types from the store itself diff --git a/store/token.ts b/store/token.ts new file mode 100644 index 00000000..81a00d5d --- /dev/null +++ b/store/token.ts @@ -0,0 +1,25 @@ +import { createApi } from '@reduxjs/toolkit/query/react' +import { getBaseQuery } from 'utils/basequery' + +export interface TokenPriceResponse { + result: { + price: string + blockTimestampLast: string + } +} + +export const tokenApi = createApi({ + reducerPath: 'token', + baseQuery: getBaseQuery(), + endpoints: builder => ({ + // update + getTokenPrice: builder.query({ + query: ({ pair }) => ({ + url: `/token-price/${pair}`, + method: 'GET' + }) + }) + }) +}) + +export const { useGetTokenPriceQuery } = tokenApi diff --git a/utils/basequery.ts b/utils/basequery.ts new file mode 100644 index 00000000..cc7176e1 --- /dev/null +++ b/utils/basequery.ts @@ -0,0 +1,8 @@ +/* eslint-disable import/no-cycle */ +import { fetchBaseQuery } from '@reduxjs/toolkit/dist/query' + +export const getBaseQuery = (baseUrl?: string): ReturnType => { + return fetchBaseQuery({ + baseUrl: baseUrl || `${process.env.NEXT_PUBLIC_COSMOS_API}/api/v1` + }) +} diff --git a/utils/constants.ts b/utils/constants.ts index e9b9099a..b53f537e 100644 --- a/utils/constants.ts +++ b/utils/constants.ts @@ -1,8 +1,13 @@ +import { Token } from '@solarswap/sdk' + export const CONFIG = { APPROXIMATE_ZERO: 10 ** -6, TXS_MOBILE_SPLIT_LENGTH: 12, TXS_DESKTOP_SPLIT_LENGTH: 16 } +export const LIMIT_PER_PAGE = 10 +export const CHAIN_ID = parseInt(process.env.NEXT_PUBLIC_CHAIN_ID) || 11115 export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' -export const LIMIT_PER_PAGE = 10 \ No newline at end of file +export const WASA_ADDRESS = process.env.NEXT_PUBLIC_WASA_ADDRESS +export const WASA_TOKEN = new Token(CHAIN_ID, WASA_ADDRESS, 18, 'WASA', 'WASA') diff --git a/utils/helper.ts b/utils/helper.ts index 4783be32..ea302a7c 100644 --- a/utils/helper.ts +++ b/utils/helper.ts @@ -5,7 +5,7 @@ import { formatEther, formatUnits } from 'ethers/lib/utils' import { isEmpty, isUndefined } from 'lodash' import numeral from 'numeral' import qs from 'qs' -import { CONFIG } from './constants' +import { CONFIG, WASA_ADDRESS } from './constants' import { ErcTypeEnum } from './enum' BN.config({ ROUNDING_MODE: 2 }) @@ -204,7 +204,8 @@ export const capitalizeFirstLetter = (text: string) => { return text.charAt(0).toUpperCase() + text.slice(1) } -export const isERC721 = (type: string): boolean => type === ErcTypeEnum.ERC721 +export const isERC721 = (type: string): boolean => type.toLowerCase() === ErcTypeEnum.ERC721.toLowerCase() +export const isWASA = (address: string): boolean => address.toLowerCase() === WASA_ADDRESS.toLowerCase() export const getTransactionInOrOut = ( address: string = '', diff --git a/views/accounts/tabs/AddressTokenTab/AddressTokenRow.tsx b/views/accounts/tabs/AddressTokenTab/AddressTokenRow.tsx index 624045c2..ae76310f 100644 --- a/views/accounts/tabs/AddressTokenTab/AddressTokenRow.tsx +++ b/views/accounts/tabs/AddressTokenTab/AddressTokenRow.tsx @@ -1,7 +1,11 @@ +import { Pair, Token } from '@solarswap/sdk' import clsx from 'clsx' import Row from 'components/Grid/Row' import { LinkText } from 'components/Typography/LinkText' -import { convertBalanceToView, ellipseBetweenText, isERC721, LinkMaker } from 'utils/helper' +import { useMemo } from 'react' +import { useGetTokenPriceQuery } from 'store/token' +import { CHAIN_ID, WASA_TOKEN } from 'utils/constants' +import { LinkMaker, convertBalanceToView, ellipseBetweenText, isERC721, isWASA } from 'utils/helper' import styles from './style.module.scss' interface Props { @@ -10,6 +14,19 @@ interface Props { const AddressTokenRow = ({ data }: Props) => { const isNFT = isERC721(data.type) + const isWASAToken = isWASA(data.contractAddress) + + const pairWASA = useMemo(() => { + if (isWASAToken) return '' + + const tokenA = new Token(CHAIN_ID, data.contractAddress, 18, data.symbol, data.name) + const pair = Pair.getAddress(tokenA, WASA_TOKEN) + return pair + }, [data, isWASAToken]) + + const { data: tokenPriceData, isLoading } = useGetTokenPriceQuery({ pair: pairWASA }, { skip: isWASAToken }) + const pairASAPrice = isWASAToken ? 1 : tokenPriceData?.result?.price + return ( {
{data.type}
-
- {isNFT ? data.balance : convertBalanceToView(data.balance)} -
{data.symbol}
-
- +
+ {isNFT ? data.balance : convertBalanceToView(data.balance)}
-
- +
+ {pairASAPrice}
+ {/*
+ +
*/}
{data.name} ({ellipseBetweenText(data.contractAddress)}) diff --git a/views/accounts/tabs/AddressTokenTab/index.tsx b/views/accounts/tabs/AddressTokenTab/index.tsx index 45149acf..01a1dccb 100644 --- a/views/accounts/tabs/AddressTokenTab/index.tsx +++ b/views/accounts/tabs/AddressTokenTab/index.tsx @@ -84,10 +84,10 @@ const AddressTokenTab = ({ address, addressData }: Props) => { >
Assets
Type
-
Amount
Symbol
-
Price
-
Value
+
Amount
+
Price (ASA)
+ {/*
Value
*/}
Contract Address
diff --git a/yarn.lock b/yarn.lock index c27d251f..2e371fdc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2876,6 +2876,18 @@ dependencies: "@sinonjs/commons" "^2.0.0" +"@solarswap/sdk@^1.0.12": + version "1.0.12" + resolved "https://registry.yarnpkg.com/@solarswap/sdk/-/sdk-1.0.12.tgz#3b84dbd6b9e938b363d8c7f4198b7a23f5e29517" + integrity sha512-lyf+rG5tztBWnwJFkwCLwT/wqSL5Fb0MbvqyHRvYiJ+xQHlkzfuiyn9ButyVaGJE+iQr0yamRyLX7/DQ2Y5teg== + dependencies: + big.js "^5.2.2" + decimal.js-light "^2.5.0" + jsbi "^3.1.4" + tiny-invariant "^1.1.0" + tiny-warning "^1.0.3" + toformat "^2.0.0" + "@svgr/babel-plugin-add-jsx-attribute@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz#74a5d648bd0347bda99d82409d87b8ca80b9a1ba" @@ -3983,6 +3995,11 @@ big-integer@1.6.36: resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.36.tgz#78631076265d4ae3555c04f85e7d9d2f3a071a36" integrity sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg== +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + bignumber.js@^9.0.0, bignumber.js@^9.1.0: version "9.1.1" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" @@ -5057,6 +5074,11 @@ decamelize@^1.1.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== +decimal.js-light@^2.5.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" + integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== + decimal.js@^10.4.2: version "10.4.3" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" @@ -7894,6 +7916,11 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jsbi@^3.1.4: + version "3.2.5" + resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-3.2.5.tgz#b37bb90e0e5c2814c1c2a1bcd8c729888a2e37d6" + integrity sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ== + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -11694,11 +11721,21 @@ timed-out@^4.0.1: resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== +tiny-invariant@^1.1.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" + integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== + tiny-relative-date@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07" integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A== +tiny-warning@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + tmp@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" @@ -11723,6 +11760,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +toformat@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/toformat/-/toformat-2.0.0.tgz#7a043fd2dfbe9021a4e36e508835ba32056739d8" + integrity sha512-03SWBVop6nU8bpyZCx7SodpYznbZF5R4ljwNLBcTQzKOD9xuihRo/psX58llS1BMFhhAI08H3luot5GoXJz2pQ== + toggle-selection@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"