diff --git a/codegen.ts b/codegen.ts new file mode 100644 index 000000000..2af3e5fe1 --- /dev/null +++ b/codegen.ts @@ -0,0 +1,23 @@ +import { CodegenConfig } from '@graphql-codegen/cli'; + +const schemaUrl = 'https://index.bostrom.cybernode.ai/v1/graphql'; //process.env.NEXT_PUBLIC_GRAPHQL_HOST; + +const config: CodegenConfig = { + overwrite: true, + schema: schemaUrl, + documents: ['src/**/*.graphql'], + config: { + withHooks: true, + }, + generates: { + 'src/generated/graphql.ts': { + plugins: [ + 'typescript', + 'typescript-operations', + 'typescript-react-apollo', + ], + }, + }, +}; + +export default config; diff --git a/docker-compose.yml b/docker-compose.yml index d0ff2ef2e..8b0768b85 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,10 +9,14 @@ services: environment: - NODE_OPTIONS=--max-old-space-size=8192 - CHAIN_ID=bostrom - - CYBER_NODE_URL_API=https://rpc.bostrom.cybernode.ai - - CYBER_NODE_URL_WS=wss://rpc.bostrom.cybernode.ai/websocket - - CYBER_NODE_URL_LCD=https://lcd.bostrom.cybernode.ai - - CYBER_INDEX_HTTPS=https://index.bostrom.cybernode.ai/v1/graphql - - CYBER_INDEX_WEBSOCKET=wss://index.bostrom.cybernode.ai/v1/graphql + - RPC_URL=https://rpc.bostrom.cybernode.ai + - LCD_URL=https://lcd.bostrom.cybernode.ai + - WEBSOCKET_URL=wss://rpc.bostrom.cybernode.ai/websocket + - INDEX_HTTPS=https://index.bostrom.cybernode.ai/v1/graphql + - INDEX_WEBSOCKET=wss://index.bostrom.cybernode.ai/v1/graphql - CYBER_GATEWAY=https://gateway.bostrom.cybernode.ai + - BASE_DENOM=boot + - DENOM_LIQUID=hydrogen + - BECH32_PREFIX=bostrom + command: npx serve -s build diff --git a/package.json b/package.json index 077a9bb23..983e2bf01 100644 --- a/package.json +++ b/package.json @@ -21,12 +21,14 @@ "stylelint:lint": "stylelint \"**/*.*css\"", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build", - "test": "jest --transformIgnorePatterns --verbose" + "test": "jest --transformIgnorePatterns --verbose", + "generate-graphql-types": "yarn graphql-codegen --config ./codegen.ts", + "generate-lcd-types": "npx swagger-typescript-api -p https://lcd.bostrom.cybernode.ai/swagger/swagger.yaml -o ./src/generated -n lcd.ts --axios --modular " }, "browserslist": "> 0.5%, last 2 versions, not dead", "license": "ISC", "devDependencies": { - "@babel/core": "7.21.0", + "@babel/core": "^7.24.3", "@babel/eslint-parser": "^7.16.5", "@babel/helper-compilation-targets": "^7.21.4", "@babel/plugin-proposal-class-properties": "7.18.6", @@ -36,6 +38,10 @@ "@babel/preset-typescript": "^7.21.0", "@commitlint/cli": "^11.0.0", "@commitlint/config-conventional": "^11.0.0", + "@graphql-codegen/cli": "^5.0.2", + "@graphql-codegen/typescript": "^4.0.6", + "@graphql-codegen/typescript-operations": "^4.2.0", + "@graphql-codegen/typescript-react-apollo": "^4.3.0", "@keplr-wallet/types": "^0.11.52", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.10", "@rjsf/core": "^3.2.1", @@ -82,6 +88,7 @@ "eslint-plugin-react": "^7.32.2", "eslint-plugin-typescript": "^0.14.0", "file-loader": "^6.2.0", + "graphql-tag": "^2.12.6", "history": "^4.9.0", "html-webpack-plugin": "^5.5.0", "https-browserify": "^1.0.0", @@ -122,6 +129,7 @@ "stylelint-config-standard": "^33.0.0", "stylelint-config-standard-scss": "^9.0.0", "stylelint-order": "^6.0.3", + "swagger-typescript-api": "^13.0.3", "swr": "^1.0.1", "terser-webpack-plugin": "4.2.3", "ts-migrate": "^0.1.35", @@ -176,6 +184,7 @@ "bignumber.js": "^9.0.0", "blockstore-core": "^4.3.4", "blockstore-idb": "^1.1.4", + "buffer": "^6.0.3", "cjs-to-es6": "^2.0.1", "classnames": "^2.3.1", "comlink": "^4.4.1", diff --git a/src/components/BandwidthBar/index.tsx b/src/components/BandwidthBar/index.tsx index 045878520..84954b397 100644 --- a/src/components/BandwidthBar/index.tsx +++ b/src/components/BandwidthBar/index.tsx @@ -3,8 +3,10 @@ import { Battery, Pane, Text } from '@cybercongress/gravity'; import { Link } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; import { useQueryClient } from 'src/contexts/queryClient'; +import { Networks } from 'src/types/networks'; +import { routes } from 'src/routes'; +import { CHAIN_ID, BASE_DENOM } from 'src/constants/config'; import Tooltip from '../tooltip/tooltip'; -import { CYBER } from '../../utils/config'; import { coinDecimals, convertResources, @@ -12,9 +14,6 @@ import { reduceBalances, } from '../../utils/utils'; import { setBandwidth } from '../../redux/actions/bandwidth'; -import { useSigningClient } from 'src/contexts/signerClient'; -import { Networks } from 'src/types/networks'; -import { routes } from 'src/routes'; const PREFIXES = [ { @@ -55,12 +54,12 @@ function ContentTooltip({ bwRemained, bwMaxValue, amounPower, countLink }) { {text} - Get {CYBER.DENOM_CYBER.toUpperCase()} + Get {BASE_DENOM.toUpperCase()} @@ -68,13 +67,13 @@ function ContentTooltip({ bwRemained, bwMaxValue, amounPower, countLink }) { ); } -function BandwidthBar({ tooltipPlacement }) // bwRemained = 0, -// bwMaxValue = 0, -// countLink = 0, -// amounPower, -// ...props +function BandwidthBar({ tooltipPlacement }) { + // bwRemained = 0, + // bwMaxValue = 0, + // countLink = 0, + // amounPower, + // ...props -{ const [linkPrice] = useState(4); const queryClient = useQueryClient(); diff --git a/src/components/MusicalAddress/utils.js b/src/components/MusicalAddress/utils.js index 871dfa964..9a5a6cc26 100644 --- a/src/components/MusicalAddress/utils.js +++ b/src/components/MusicalAddress/utils.js @@ -1,13 +1,13 @@ /* eslint-disable no-restricted-syntax */ import * as Tone from 'tone'; import { + PATTERN_CYBER, PATTERN_ETH, PATTERN_COSMOS, PATTERN_OSMOS, PATTERN_TERRA, PATTERN_CYBER_VALOPER, -} from '../../utils/config'; -import { PATTERN_CYBER } from 'src/constants/app'; +} from 'src/constants/patterns'; const DICTIONARY_ABC = { a: { note: 'E3', height: 16, gain: 1, color: '#36D6AE' }, diff --git a/src/components/TableTxs/ActionTx.tsx b/src/components/TableTxs/ActionTx.tsx new file mode 100644 index 000000000..1a7ed9d78 --- /dev/null +++ b/src/components/TableTxs/ActionTx.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +function ActionTx() { + return ( +
+ +
+ ) +} + +export default ActionTx diff --git a/src/components/TableTxs/TableTxs.tsx b/src/components/TableTxs/TableTxs.tsx new file mode 100644 index 000000000..e663b69c3 --- /dev/null +++ b/src/components/TableTxs/TableTxs.tsx @@ -0,0 +1,99 @@ +import InfiniteScroll from 'react-infinite-scroll-component'; +import { MessagesByAddressQuery } from 'src/generated/graphql'; +import { useMemo } from 'react'; +import statusTrueImg from 'src/image/ionicons_svg_ios-checkmark-circle.svg'; +import statusFalseImg from 'src/image/ionicons_svg_ios-close-circle.svg'; +import { getNowUtcTime, timeSince, trimString } from 'src/utils/utils'; +import { Link } from 'react-router-dom'; +import { routes } from 'src/routes'; +import Display from '../containerGradient/Display/Display'; +import Table from '../Table/Table'; +import { Dots } from '../ui/Dots'; +import TextTable from '../text/textTable'; +import MsgType from '../msgType/msgType'; + +type Props = { + hasMore: boolean; + fetchMoreData: () => void; + data: MessagesByAddressQuery | undefined; + accountUser: string; +}; + +enum ColumnsTable { + status = 'status', + type = 'type', + timestamp = 'timestamp', + tx = 'tx', + action = 'action', +} + +function TableTxs({ hasMore, fetchMoreData, data, accountUser }: Props) { + const tableData = useMemo(() => { + return data?.messages_by_address.map((item) => { + let typeTx = item.type; + if ( + typeTx.includes('MsgSend') && + item?.value?.to_address === accountUser + ) { + typeTx = 'Receive'; + } + const timeAgoInMS = + getNowUtcTime() - Date.parse(item.transaction.block.timestamp); + + return { + [ColumnsTable.status]: ( + + status + + ), + [ColumnsTable.type]: ( +
+ +
+ ), + [ColumnsTable.timestamp]: ( + {timeSince(timeAgoInMS)} ago + ), + [ColumnsTable.tx]: ( + + + {trimString(item.transaction_hash, 6, 6)} + + + ), + // [ColumnsTable.action]: (), + }; + }); + }, []); + + return ( + + + Loading +

+ } + style={{ display: 'grid', gap: '15px' }} + > + ({ + header: item, + accessorKey: item, + cell: (info) => info.getValue(), + }))} + /> + + + ); +} + +export default TableTxs; diff --git a/src/components/TokenChange/TokenChange.tsx b/src/components/TokenChange/TokenChange.tsx index b986c0ebc..8a1b30ee0 100644 --- a/src/components/TokenChange/TokenChange.tsx +++ b/src/components/TokenChange/TokenChange.tsx @@ -1,8 +1,8 @@ -import { CYBER } from 'src/utils/config'; import { formatNumber } from 'src/utils/utils'; import cx from 'classnames'; import styles from './TokenChange.module.scss'; import FormatNumberTokens from '../FormatNumberTokens/FormatNumberTokens'; +import { DENOM_LIQUID } from 'src/constants/config'; export type Props = { total: number; @@ -25,7 +25,7 @@ function TokenChange({ total, change = 0, className }: Props) { )} - + ); } diff --git a/src/components/account/account.tsx b/src/components/account/account.tsx index 7397851a7..985c9e78d 100644 --- a/src/components/account/account.tsx +++ b/src/components/account/account.tsx @@ -5,8 +5,8 @@ import { useQueryClient } from 'src/contexts/queryClient'; import { routes } from 'src/routes'; import usePassportByAddress from 'src/features/passport/hooks/usePassportByAddress'; import cx from 'classnames'; +import { BECH32_PREFIX_VALOPER } from 'src/constants/config'; import { trimString } from '../../utils/utils'; -import { CYBER } from '../../utils/config'; import { AvataImgIpfs } from '../../containers/portal/components/avataIpfs'; import styles from './account.module.scss'; @@ -25,9 +25,7 @@ function useGetValidatorInfo(address: string) { }, { enabled: Boolean( - queryClient && - address && - address.includes(CYBER.BECH32_PREFIX_ACC_ADDR_CYBERVALOPER) + queryClient && address && address.includes(BECH32_PREFIX_VALOPER) ), } ); @@ -77,7 +75,7 @@ function Account({ }, [address, trimAddressParam]); const linkAddress = useMemo(() => { - if (address?.includes(CYBER.BECH32_PREFIX_ACC_ADDR_CYBERVALOPER)) { + if (address?.includes(BECH32_PREFIX_VALOPER)) { return `/network/bostrom/hero/${address}`; } diff --git a/src/components/actionBar/index.tsx b/src/components/actionBar/index.tsx index c71b22152..78b7f9567 100644 --- a/src/components/actionBar/index.tsx +++ b/src/components/actionBar/index.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { $TsFixMeFunc } from 'src/types/tsfix'; import { routes } from 'src/routes'; -import { CYBER } from 'src/utils/config'; import { useLocation } from 'react-router-dom'; import { Networks } from 'src/types/networks'; import usePassportByAddress from 'src/features/passport/hooks/usePassportByAddress'; @@ -13,6 +12,7 @@ import styles from './styles.module.scss'; import Button from '../btnGrd'; import { useSigningClient } from 'src/contexts/signerClient'; import { trimString } from 'src/utils/utils'; +import { CHAIN_ID } from 'src/constants/config'; const back = require('../../image/arrow-left-img.svg'); @@ -59,7 +59,7 @@ function ActionBar({ children, text, onClickBack, button }: Props) { const { passport } = usePassportByAddress(address); const noAccount = !defaultAccount.account; - const noPassport = CYBER.CHAIN_ID === Networks.BOSTROM && !passport; + const noPassport = CHAIN_ID === Networks.BOSTROM && !passport; const exception = (location.pathname !== routes.keys.path && diff --git a/src/components/contentIpfs/contentIpfs.tsx b/src/components/contentIpfs/contentIpfs.tsx index c74274e83..ba762538e 100644 --- a/src/components/contentIpfs/contentIpfs.tsx +++ b/src/components/contentIpfs/contentIpfs.tsx @@ -1,5 +1,5 @@ import { IPFSContentDetails, IPFSContentMaybe } from 'src/services/ipfs/ipfs'; -import { CYBER } from 'src/utils/config'; +import { CYBER_GATEWAY } from 'src/constants/config'; import VideoPlayerGatewayOnly from '../VideoPlayer/VideoPlayerGatewayOnly'; import GatewayContent from './component/gateway'; import TextMarkdown from '../TextMarkdown'; @@ -22,14 +22,14 @@ function OtherItem({ {content || `${cid} (n/a)`} ); } - return ; + return ; } function DownloadableItem({ cid, search }: { cid: string; search?: boolean }) { if (search) { return
{`${cid} (gateway)`}
; } - return ; + return ; } type ContentTabProps = { diff --git a/src/components/governance/governance.jsx b/src/components/governance/governance.jsx index 17e115d93..4ebe5c3dd 100644 --- a/src/components/governance/governance.jsx +++ b/src/components/governance/governance.jsx @@ -1,6 +1,7 @@ import { Pane, Text } from '@cybercongress/gravity'; +import { ProposalStatus } from 'cosmjs-types/cosmos/gov/v1beta1/gov'; +import { BASE_DENOM } from 'src/constants/config'; import { formatNumber } from '../../utils/search/utils'; -import { CYBER, PROPOSAL_STATUS } from '../../utils/config'; import Tooltip from '../tooltip/tooltip'; const submitted = require('../../image/ionicons_svg_ios-battery-full.svg'); @@ -161,27 +162,27 @@ export function IconStatus({ status, size, text, ...props }) { let statusText = ''; switch (status) { - case PROPOSAL_STATUS.PROPOSAL_STATUS_DEPOSIT_PERIOD: { + case ProposalStatus.PROPOSAL_STATUS_DEPOSIT_PERIOD: { imgIcon = submitted; statusText = 'deposit period'; break; } - case PROPOSAL_STATUS.PROPOSAL_STATUS_VOTING_PERIOD: { + case ProposalStatus.PROPOSAL_STATUS_VOTING_PERIOD: { imgIcon = voting; statusText = 'voting period'; break; } - case PROPOSAL_STATUS.PROPOSAL_STATUS_PASSED: { + case ProposalStatus.PROPOSAL_STATUS_PASSED: { imgIcon = passed; statusText = 'passed'; break; } - case PROPOSAL_STATUS.PROPOSAL_STATUS_REJECTED: { + case ProposalStatus.PROPOSAL_STATUS_REJECTED: { imgIcon = rejected; statusText = 'rejected'; break; } - case PROPOSAL_STATUS.PROPOSAL_STATUS_FAILED: { + case ProposalStatus.PROPOSAL_STATUS_FAILED: { imgIcon = failed; statusText = 'failed'; break; @@ -241,7 +242,7 @@ export function Deposit({ totalDeposit, minDeposit }) { className="tooltip-text-deposit" > Total Deposit {formatNumber(totalDeposit)}{' '} - {CYBER.DENOM_CYBER.toUpperCase()} + {BASE_DENOM.toUpperCase()} diff --git a/src/components/ledger/stageActionBar.jsx b/src/components/ledger/stageActionBar.jsx index e8e7c6730..e815a14f1 100644 --- a/src/components/ledger/stageActionBar.jsx +++ b/src/components/ledger/stageActionBar.jsx @@ -1,4 +1,3 @@ -import { useState, useEffect, useRef } from 'react'; import LocalizedStrings from 'react-localization'; import { Link } from 'react-router-dom'; import { @@ -9,6 +8,8 @@ import { IconButton, } from '@cybercongress/gravity'; +import { BondStatus } from 'cosmjs-types/cosmos/staking/v1beta1/staking'; +import { useBackend } from 'src/contexts/backend/backend'; import { ContainetLedger } from './container'; import { Dots } from '../ui/Dots'; import Account from '../account/account'; @@ -17,17 +18,13 @@ import { formatNumber, trimString, selectNetworkImg } from '../../utils/utils'; import { i18n } from '../../i18n/en'; -import { CYBER, BOND_STATUS } from '../../utils/config'; import Button from '../btnGrd'; import { InputNumber, Input } from '../Input'; import ActionBarContainer from '../actionBar'; import ButtonIcon from '../buttons/ButtonIcon'; import { Color } from '../LinearGradientContainer/LinearGradientContainer'; import AddFileButton from '../buttons/AddFile/AddFile'; -import { useBackend } from 'src/contexts/backend/backend'; -import useDelegation from 'src/features/staking/delegation/useDelegation'; - -const { DENOM_CYBER } = CYBER; +import { CHAIN_ID, BASE_DENOM } from 'src/constants/config'; const param = { slashing: [ @@ -161,10 +158,12 @@ export function Confirmed({ txHash, txHeight, cosmos, onClickBtnClose }) { {trimString(txHash, 6, 6)} )}{' '} - - was included in the block
at height{' '} - {formatNumber(parseFloat(txHeight))} -
+ {txHeight && ( + + was included in the block
at height{' '} + {formatNumber(parseFloat(txHeight))} +
+ )}
- - - hash - - - height - - - tx - - - proposer address - - - timestamp, UTC - - - - - Loading - - - } - pullDownToRefresh - pullDownToRefreshContent={ -

- ↓ Pull down to refresh -

- } - releaseToRefreshContent={ -

- ↑ Release to refresh -

- } - > - {items.map((item, index) => ( - - - {trimString(item.hash, 5, 5)} - - - - - {formatNumber(item.height)} - - - - - - {formatNumber(item.transactions_aggregate.aggregate.count)} - - - - - {trimString(item.proposer_address, 5, 5)} - - - - - {' '} - {dateFormat(item.timestamp, 'dd/mm/yyyy, HH:MM:ss')} - - - - ))} -
-
-
- - ); -} - -export default Block; diff --git a/src/containers/blok/index.tsx b/src/containers/blok/index.tsx new file mode 100644 index 000000000..6f71c014c --- /dev/null +++ b/src/containers/blok/index.tsx @@ -0,0 +1,119 @@ +import { useMemo, useState } from 'react'; +import { Link } from 'react-router-dom'; +import InfiniteScroll from 'react-infinite-scroll-component'; +import { Dots, TextTable } from '../../components'; +import Table from 'src/components/Table/Table'; +import { trimString, formatNumber } from '../../utils/utils'; +import { useBlocksQuery } from 'src/generated/graphql'; +import { routes } from 'src/routes'; + +const dateFormat = require('dateformat'); + +const limit = 20; + +const TableKeyMap = { + hash: 'hash', + height: 'height', + tx: 'tx', + proposerAddress: 'proposer address', + timestampUTC: 'timestamp, UTC', +}; + +function Block() { + const [hasMore, setHasMore] = useState(true); + const { data, loading, error, fetchMore } = useBlocksQuery({ + variables: { + limit, + offset: 0, + }, + }); + + const lastBlockQuery = data?.block[data.block.length - 1].height; + + const fetchMoreData = async () => { + setTimeout(() => { + fetchMore({ + variables: { + offset: data?.block.length, + where: { height: { _lte: lastBlockQuery } }, + }, + updateQuery: (prev, { fetchMoreResult }) => { + if (!fetchMoreResult) { + return prev; + } + setHasMore(fetchMoreResult.block.length > 0); + + return { + ...prev, + block: [...prev.block, ...fetchMoreResult.block], + }; + }, + }); + }, 2000); + }; + + const tableData = useMemo(() => { + return (data?.block || []).map((item) => { + return { + hash: {trimString(item.hash, 5, 5)}, + height: ( + + + {formatNumber(item.height)} + + + ), + tx: ( + + {formatNumber(item.transactions_aggregate.aggregate?.count || 0)} + + ), + proposerAddress: ( + {trimString(item.proposer_address, 5, 5)} + ), + timestampUTC: ( + + {dateFormat(item.timestamp, 'dd/mm/yyyy, HH:MM:ss')} + + ), + }; + }); + }, [data]); + + if (loading) { + return ; + } + + if (error) { + return {error.message}; + } + + return ( +
+ + Loading + + + } + > + ({ + header: TableKeyMap[key], + accessorKey: key, + cell: (info) => info.getValue(), + }))} + /> + + + ); +} + +export default Block; diff --git a/src/containers/brain/accountCount.jsx b/src/containers/brain/accountCount.jsx deleted file mode 100644 index 435437ec7..000000000 --- a/src/containers/brain/accountCount.jsx +++ /dev/null @@ -1,30 +0,0 @@ -import { useQuery, gql } from '@apollo/client'; - -import { Dots } from '../../components'; -import { formatNumber } from '../../utils/utils'; - -const GET_CHARACTERS = gql` - query MyQuery { - account_aggregate { - aggregate { - count(columns: address) - } - } - } -`; - -function AccountCount() { - try { - // eslint-disable-next-line react-hooks/rules-of-hooks - const { loading, data } = useQuery(GET_CHARACTERS); - if (loading) { - return ; - } - - return {formatNumber(data.account_aggregate.aggregate.count)}; - } catch (error) { - return ; - } -} - -export default AccountCount; diff --git a/src/containers/brain/accountCount.tsx b/src/containers/brain/accountCount.tsx new file mode 100644 index 000000000..c8df4d3f7 --- /dev/null +++ b/src/containers/brain/accountCount.tsx @@ -0,0 +1,19 @@ +import { useAccountCountQuery } from 'src/generated/graphql'; +import { Dots } from '../../components'; +import { formatNumber } from '../../utils/utils'; + +function AccountCount() { + const { loading, data, error } = useAccountCountQuery(); + if (loading) { + return ; + } + if (error) { + return ; + } + + return ( + {formatNumber(data?.account_aggregate.aggregate?.count || 0)} + ); +} + +export default AccountCount; diff --git a/src/containers/brain/hooks/getStatisticsCyber.js b/src/containers/brain/hooks/getStatisticsCyber.js index f88a6050c..dacb2034b 100644 --- a/src/containers/brain/hooks/getStatisticsCyber.js +++ b/src/containers/brain/hooks/getStatisticsCyber.js @@ -1,10 +1,10 @@ import { useEffect, useState } from 'react'; import BigNumber from 'bignumber.js'; import { useQueryClient } from 'src/contexts/queryClient'; +import { BASE_DENOM, DENOM_LIQUID } from 'src/constants/config'; import { getInlfation } from '../../../utils/search/utils'; import { getProposals } from '../../../utils/governance'; import { coinDecimals } from '../../../utils/utils'; -import { CYBER } from '../../../utils/config'; function useGetStatisticsCyber() { const queryClient = useQueryClient(); @@ -75,9 +75,9 @@ function useGetStatisticsCyber() { }); } - if (totalCyb[CYBER.DENOM_CYBER] && totalCyb[CYBER.DENOM_LIQUID_TOKEN]) { - staked = new BigNumber(totalCyb[CYBER.DENOM_LIQUID_TOKEN]) - .dividedBy(totalCyb[CYBER.DENOM_CYBER]) + if (totalCyb[BASE_DENOM] && totalCyb[DENOM_LIQUID]) { + staked = new BigNumber(totalCyb[DENOM_LIQUID]) + .dividedBy(totalCyb[BASE_DENOM]) .toString(10); } setKnowledge((item) => ({ diff --git a/src/containers/brain/tx.jsx b/src/containers/brain/tx.jsx index c17726509..141147861 100644 --- a/src/containers/brain/tx.jsx +++ b/src/containers/brain/tx.jsx @@ -1,32 +1,21 @@ -import { useQuery, gql } from '@apollo/client'; - +import { useTransactionCountQuery } from 'src/generated/graphql'; import { Dots } from '../../components'; import { formatNumber } from '../../utils/utils'; -const GET_CHARACTERS = gql` - query MyQuery { - transaction_aggregate { - aggregate { - count(columns: hash) - } - } - } -`; - function Txs() { - try { - // eslint-disable-next-line react-hooks/rules-of-hooks - const { loading, data } = useQuery(GET_CHARACTERS); - if (loading) { - return ; - } + const { loading, data, error } = useTransactionCountQuery(); - return ( - {formatNumber(data.transaction_aggregate.aggregate.count)} - ); - } catch (error) { + if (loading) { + return ; + } + + if (error) { return ; } + + return ( + {formatNumber(data.transaction_aggregate.aggregate.count)} + ); } export default Txs; diff --git a/src/containers/energy/component/actionBar.tsx b/src/containers/energy/component/actionBar.tsx index ba3a28663..a00f34164 100644 --- a/src/containers/energy/component/actionBar.tsx +++ b/src/containers/energy/component/actionBar.tsx @@ -3,6 +3,8 @@ import { ActionBar as ActionBarContainer, Tab } from '@cybercongress/gravity'; import { coin } from '@cosmjs/launchpad'; import { Link, useNavigate } from 'react-router-dom'; import { useSigningClient } from 'src/contexts/signerClient'; +import { PATTERN_CYBER, PATTERN_CYBER_CONTRACT } from 'src/constants/patterns'; +import { DEFAULT_GAS_LIMITS } from 'src/constants/config'; import { Dots, ActionBarContentText, @@ -15,12 +17,7 @@ import { ActionBar as ActionBarCenter, Input, } from '../../../components'; -import { - LEDGER, - PATTERN_CYBER_CONTRACT, - DEFAULT_GAS_LIMITS, -} from '../../../utils/config'; -import { PATTERN_CYBER } from 'src/constants/app'; +import { LEDGER } from '../../../utils/config'; import { getTxs } from '../../../utils/search/utils'; import { ValueImg } from '../ui'; import { routes } from '../../../routes'; diff --git a/src/containers/energy/ui/tableSlots.tsx b/src/containers/energy/ui/tableSlots.tsx index de0b135c8..5b13da088 100644 --- a/src/containers/energy/ui/tableSlots.tsx +++ b/src/containers/energy/ui/tableSlots.tsx @@ -1,11 +1,11 @@ import { useIbcDenom } from 'src/contexts/ibcDenom'; import { formatNumber, getDisplayAmount } from '../../../utils/utils'; import { DenomArr, TextTable, ValueImg } from '../../../components'; -import { CYBER } from '../../../utils/config'; import Table from 'src/components/Table/Table'; import { CssVariables } from 'src/style/variables'; import { createColumnHelper } from '@tanstack/react-table'; import { useMemo } from 'react'; +import { DENOM_LIQUID } from 'src/constants/config'; const columnHelper = createColumnHelper(); @@ -54,10 +54,10 @@ function TableSlots({ data }: Props) { ), unfreezing: item.time ? {item.time} : '', - supplied: item.amount[CYBER.DENOM_LIQUID_TOKEN] ? ( + supplied: item.amount[DENOM_LIQUID] ? ( - {formatNumber(item.amount[CYBER.DENOM_LIQUID_TOKEN])}  - + {formatNumber(item.amount[DENOM_LIQUID])}  + ) : ( '' diff --git a/src/containers/forceGraph/hooks.js b/src/containers/forceGraph/hooks.ts similarity index 67% rename from src/containers/forceGraph/hooks.js rename to src/containers/forceGraph/hooks.ts index 918866879..650a1ebac 100644 --- a/src/containers/forceGraph/hooks.js +++ b/src/containers/forceGraph/hooks.ts @@ -1,22 +1,28 @@ import { useEffect, useState } from 'react'; -import { useQuery } from '@apollo/client'; import useQueueIpfsContent from 'src/hooks/useQueueIpfsContent'; -import { PATTERN_CYBER } from 'src/constants/app'; -import QUERY_GET_FOLLOWERS from './query'; +import { PATTERN_CYBER } from 'src/constants/patterns'; +import { useCyberlinksByParticleQuery } from 'src/generated/graphql'; +import { QUERY_GET_FOLLOWERS } from './query'; const useGetDataGql = () => { const { fetchWithDetails } = useQueueIpfsContent(); - const { data: dataGql, loading: loadingGql } = useQuery(QUERY_GET_FOLLOWERS); + const { data: dataGql, loading: loadingGql } = useCyberlinksByParticleQuery({ + variables: { + limit: 1000, + where: QUERY_GET_FOLLOWERS , + offset: 0, + }, + }); const [data, setData] = useState([]); useEffect(() => { if (!loadingGql && fetchWithDetails) { - if (dataGql !== null && dataGql.cyberlinks) { + if (dataGql) { const { cyberlinks } = dataGql; cyberlinks.forEach(async (item) => { const addressResolve = fetchWithDetails - ? (await fetchWithDetails(item.particle_to)).content + ? (await fetchWithDetails(item.to)).content : null; if (addressResolve && addressResolve.match(PATTERN_CYBER)) { setData((itemData) => [ diff --git a/src/containers/forceGraph/query.js b/src/containers/forceGraph/query.js index bb92dcb55..e9aa278f6 100644 --- a/src/containers/forceGraph/query.js +++ b/src/containers/forceGraph/query.js @@ -1,18 +1,3 @@ -import { gql } from '@apollo/client'; - -const QUERY_GET_FOLLOWERS = gql` - query Cyberlinks { - cyberlinks( - limit: 1000 - where: { - particle_from: { _eq: "QmPLSA5oPqYxgc8F7EwrM8WS9vKrr1zPoDniSRFh8HSrxx" } - } - ) { - particle_to - neuron - transaction_hash - } - } -`; - -export default QUERY_GET_FOLLOWERS; +export const QUERY_GET_FOLLOWERS = { + particle_from: { _eq: 'QmPLSA5oPqYxgc8F7EwrM8WS9vKrr1zPoDniSRFh8HSrxx' }, +}; diff --git a/src/containers/governance/actionBar.tsx b/src/containers/governance/actionBar.tsx index d314cc0ac..4388a4550 100644 --- a/src/containers/governance/actionBar.tsx +++ b/src/containers/governance/actionBar.tsx @@ -1,5 +1,8 @@ import { Component } from 'react'; import { coins } from '@cosmjs/launchpad'; +import withIpfsAndKeplr from 'src/hocs/withIpfsAndKeplr'; +import { DefaultAccount } from 'src/types/defaultAccount'; +import { DEFAULT_GAS_LIMITS, BASE_DENOM } from 'src/constants/config'; import { TransactionSubmitted, Confirmed, @@ -11,11 +14,9 @@ import { GovernanceSoftwareUpgrade, } from '../../components'; -import { LEDGER, CYBER, DEFAULT_GAS_LIMITS } from '../../utils/config'; +import { LEDGER } from '../../utils/config'; import { getTxs } from '../../utils/search/utils'; -import withIpfsAndKeplr from 'src/hocs/withIpfsAndKeplr'; import withAccount from '../../hocs/withAccount'; -import { DefaultAccount } from 'src/types/defaultAccount'; const STAGE_TYPE_GOV = 9; @@ -80,7 +81,7 @@ class ActionBar extends Component { const [{ address }] = await signer.getAccounts(); try { - const deposit = coins(parseFloat(valueDeposit), CYBER.DENOM_CYBER); + const deposit = coins(parseFloat(valueDeposit), BASE_DENOM); if (valueSelect === 'textProposal') { response = await signingClient.submitProposal( address, @@ -97,7 +98,7 @@ class ActionBar extends Component { } if (valueSelect === 'communityPool') { - const amount = coins(10, CYBER.DENOM_CYBER); + const amount = coins(10, BASE_DENOM); response = await signingClient.submitProposal( address, { @@ -259,7 +260,7 @@ class ActionBar extends Component { }; onFilePickerChange = (files) => { - //TODO: create utils method for that + // TODO: create utils method for that const reader = new FileReader(); reader.readAsText(files[0], 'UTF-8'); diff --git a/src/containers/governance/actionBarDatail.tsx b/src/containers/governance/actionBarDatail.tsx index f412522c6..48931d31a 100644 --- a/src/containers/governance/actionBarDatail.tsx +++ b/src/containers/governance/actionBarDatail.tsx @@ -5,6 +5,11 @@ import { ActionBar, Pane } from '@cybercongress/gravity'; import { coins } from '@cosmjs/launchpad'; import { useQueryClient } from 'src/contexts/queryClient'; import { useSigningClient } from 'src/contexts/signerClient'; +import { + VoteOption, + ProposalStatus, +} from 'cosmjs-types/cosmos/gov/v1beta1/gov'; +import { DEFAULT_GAS_LIMITS, BASE_DENOM, MEMO_KEPLR } from 'src/constants/config'; import { TransactionSubmitted, Confirmed, @@ -20,13 +25,7 @@ import { import { getTxs } from '../../utils/search/utils'; -import { - LEDGER, - CYBER, - PROPOSAL_STATUS, - DEFAULT_GAS_LIMITS, - VOTE_OPTION, -} from '../../utils/config'; +import { LEDGER } from '../../utils/config'; const imgKeplr = require('../../image/keplr-icon.svg'); const imgCyber = require('../../image/blue-circle.png'); @@ -106,27 +105,27 @@ function ActionBarDetail({ proposals, id, addressActive, update }) { setStage(STAGE_SUBMITTED); if ( - proposals.status === PROPOSAL_STATUS.PROPOSAL_STATUS_VOTING_PERIOD + proposals.status === ProposalStatus.PROPOSAL_STATUS_VOTING_PERIOD ) { response = await signingClient.voteProposal( address, id, valueSelect, fee, - CYBER.MEMO_KEPLR + MEMO_KEPLR ); } if ( - proposals.status === PROPOSAL_STATUS.PROPOSAL_STATUS_DEPOSIT_PERIOD + proposals.status === ProposalStatus.PROPOSAL_STATUS_DEPOSIT_PERIOD ) { - const amount = coins(parseFloat(valueDeposit), CYBER.DENOM_CYBER); + const amount = coins(parseFloat(valueDeposit), BASE_DENOM); response = await signingClient.depositProposal( address, id, amount, fee, - CYBER.MEMO_KEPLR + MEMO_KEPLR ); } @@ -172,7 +171,7 @@ function ActionBarDetail({ proposals, id, addressActive, update }) { if ( stage === STAGE_INIT && - proposals.status === PROPOSAL_STATUS.PROPOSAL_STATUS_DEPOSIT_PERIOD + proposals.status === ProposalStatus.PROPOSAL_STATUS_DEPOSIT_PERIOD ) { return ( @@ -190,7 +189,7 @@ function ActionBarDetail({ proposals, id, addressActive, update }) { allowLeadingZeros /> - {CYBER.DENOM_CYBER.toUpperCase()} + {BASE_DENOM.toUpperCase()} @@ -214,10 +213,10 @@ function ActionBarDetail({ proposals, id, addressActive, update }) { value={valueSelect} onChange={(e) => setValueSelect(e.target.value)} > - - - - + + + diff --git a/src/containers/governance/components/card.jsx b/src/containers/governance/components/card.jsx index f46b8b909..27eca8725 100644 --- a/src/containers/governance/components/card.jsx +++ b/src/containers/governance/components/card.jsx @@ -5,8 +5,8 @@ import { Tooltip, ContainerGradientText, } from '../../../components'; -import { PROPOSAL_STATUS } from '../../../utils/config'; import Display from 'src/components/containerGradient/Display/Display'; +import { ProposalStatus } from 'cosmjs-types/cosmos/gov/v1beta1/gov'; const textPropsImg = require('../../../image/reader-outline.svg'); const paramChangePropsImg = require('../../../image/cog-outline.svg'); @@ -166,13 +166,13 @@ function ActiveCard({ - {state === PROPOSAL_STATUS.PROPOSAL_STATUS_DEPOSIT_PERIOD && ( + {state === ProposalStatus.PROPOSAL_STATUS_DEPOSIT_PERIOD && ( Deposit End Time: {timeEndDeposit} )} - {state === PROPOSAL_STATUS.PROPOSAL_STATUS_VOTING_PERIOD && ( + {state === ProposalStatus.PROPOSAL_STATUS_VOTING_PERIOD && ( Voting End Time: {timeEndVoting} diff --git a/src/containers/governance/governance.tsx b/src/containers/governance/governance.tsx index 642fb818a..79303f4b2 100644 --- a/src/containers/governance/governance.tsx +++ b/src/containers/governance/governance.tsx @@ -2,14 +2,15 @@ import { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; import { Pane } from '@cybercongress/gravity'; import { useQueryClient } from 'src/contexts/queryClient'; +import { useAdviser } from 'src/features/adviser/context'; +import { ProposalStatus } from 'cosmjs-types/cosmos/gov/v1beta1/gov'; +import { BASE_DENOM, DENOM_LIQUID } from 'src/constants/config'; import ActionBar from './actionBar'; import { getProposals, getMinDeposit } from '../../utils/governance'; import Columns from './components/columns'; import { AcceptedCard, ActiveCard, RejectedCard } from './components/card'; import { CardStatisics } from '../../components'; -import { CYBER, PROPOSAL_STATUS } from '../../utils/config'; import { formatNumber, coinDecimals } from '../../utils/utils'; -import { useAdviser } from 'src/features/adviser/context'; const dateFormat = require('dateformat'); @@ -23,7 +24,7 @@ function Statistics({ communityPoolCyber, staked }) { gridGap="20px" > @@ -81,9 +82,8 @@ function Governance() { totalCyb[item.denom] = parseFloat(item.amount); }); } - if (totalCyb[CYBER.DENOM_CYBER] && totalCyb[CYBER.DENOM_LIQUID_TOKEN]) { - stakedBoot = - totalCyb[CYBER.DENOM_LIQUID_TOKEN] / totalCyb[CYBER.DENOM_CYBER]; + if (totalCyb[BASE_DENOM] && totalCyb[DENOM_LIQUID]) { + stakedBoot = totalCyb[DENOM_LIQUID] / totalCyb[BASE_DENOM]; } setStaked(stakedBoot); } @@ -99,7 +99,7 @@ function Governance() { // if (queryClient !== null) { const responseProposals = await getProposals(); // const responseProposals = await queryClient.proposals( - // PROPOSAL_STATUS.PROPOSAL_STATUS_PASSED, + // ProposalStatus.PROPOSAL_STATUS_PASSED, // '', // '' // ); @@ -122,7 +122,7 @@ function Governance() { .reverse() .filter( (item) => - PROPOSAL_STATUS[item.status] < PROPOSAL_STATUS.PROPOSAL_STATUS_PASSED + ProposalStatus[item.status] < ProposalStatus.PROPOSAL_STATUS_PASSED ) .map((item) => ( - PROPOSAL_STATUS[item.status] === PROPOSAL_STATUS.PROPOSAL_STATUS_PASSED + ProposalStatus[item.status] === ProposalStatus.PROPOSAL_STATUS_PASSED ) .map((item) => ( - PROPOSAL_STATUS[item.status] > PROPOSAL_STATUS.PROPOSAL_STATUS_PASSED + ProposalStatus[item.status] > ProposalStatus.PROPOSAL_STATUS_PASSED ) .map((item) => ( { const finalVotes = { @@ -89,8 +89,7 @@ function ProposalsDetail({ defaultAccount }) { proposalsInfo.title = title; proposalsInfo.type = responseProposalsDetail.content['@type']; proposalsInfo.description = description; - proposalsInfo.status = - PROPOSAL_STATUS[responseProposalsDetail.status]; + proposalsInfo.status = ProposalStatus[responseProposalsDetail.status]; if (plan) { proposalsInfo.plan = plan; @@ -292,7 +291,7 @@ function ProposalsDetail({ defaultAccount }) { tally={tally} /> - {proposals.status > PROPOSAL_STATUS.PROPOSAL_STATUS_DEPOSIT_PERIOD && ( + {proposals.status > ProposalStatus.PROPOSAL_STATUS_DEPOSIT_PERIOD && ( - {formatNumber(minDeposit)} {CYBER.DENOM_CYBER.toUpperCase()}{' '} - MinDeposit + {formatNumber(minDeposit)} {BASE_DENOM.toUpperCase()} MinDeposit diff --git a/src/containers/governance/proposalsIdDetail.jsx b/src/containers/governance/proposalsIdDetail.jsx index 755b797ac..8064d8a4e 100644 --- a/src/containers/governance/proposalsIdDetail.jsx +++ b/src/containers/governance/proposalsIdDetail.jsx @@ -1,7 +1,7 @@ import { Pane } from '@cybercongress/gravity'; import { IconStatus, Item, ContainerGradientText } from '../../components'; import { formatNumber } from '../../utils/search/utils'; -import { CYBER } from '../../utils/config'; +import { BASE_DENOM } from 'src/constants/config'; const dateFormat = require('dateformat'); @@ -48,7 +48,7 @@ function ProposalsIdDetail({ )} {proposals.voting_start_time && ( diff --git a/src/containers/home/home.jsx b/src/containers/home/home.tsx similarity index 90% rename from src/containers/home/home.jsx rename to src/containers/home/home.tsx index 0a718e2e0..f6fd04b59 100644 --- a/src/containers/home/home.jsx +++ b/src/containers/home/home.tsx @@ -2,18 +2,17 @@ import { useEffect, useState, useMemo } from 'react'; import { Link } from 'react-router-dom'; import { Pane } from '@cybercongress/gravity'; import axios from 'axios'; -import { useQuery, gql } from '@apollo/client'; - import BigNumber from 'bignumber.js'; import { useQueryClient } from 'src/contexts/queryClient'; import { useAppData } from 'src/contexts/appData'; import { CardStatisics, Dots } from '../../components'; -import { CYBER } from '../../utils/config'; import Txs from '../brain/tx'; import { formatCurrency, formatNumber } from '../../utils/utils'; import useGetStatisticsCyber from '../brain/hooks/getStatisticsCyber'; import KnowledgeTab from '../brain/tabs/knowledge'; import { getNumTokens, getStateGift } from '../portal/utils'; +import { BASE_DENOM, LCD_URL } from 'src/constants/config'; +import { useContractsCountQuery } from 'src/generated/graphql'; const PREFIXES = [ { @@ -48,16 +47,6 @@ function ContainerGrid({ children }) { ); } -const GET_CHARACTERS = gql` - query MyQuery { - contracts_aggregate { - aggregate { - count - } - } - } -`; - function Home() { const { block } = useAppData(); const queryClient = useQueryClient(); @@ -67,7 +56,7 @@ function Home() { const [memoryLoader, setMemoryLoader] = useState(true); const [counCitizenshipst, setCounCitizenshipst] = useState(0); const [citizensClaim, setCitizensClaim] = useState(0); - const { loading, data } = useQuery(GET_CHARACTERS); + const { loading, data } = useContractsCountQuery(); const { linksCount, cidsCount, @@ -114,7 +103,7 @@ function Home() { setEntropyLoader(true); const response = await axios({ method: 'get', - url: `${CYBER.CYBER_NODE_URL_LCD}/rank/negentropy`, + url: `${LCD_URL}/rank/negentropy`, }); if (response.data.result.negentropy) { setEntropy(response.data.result.negentropy); @@ -147,13 +136,6 @@ function Home() { } }, [queryClient]); - const useCountContracts = useMemo(() => { - if (data && data !== null && data.contracts_aggregate.aggregate) { - return data.contracts_aggregate.aggregate.count; - } - return 0; - }, [data]); - const useGetBeta = useMemo(() => { const link = new BigNumber(linksCount); const particles = new BigNumber(cidsCount); @@ -212,7 +194,7 @@ function Home() { : formatNumber(useCountContracts)} + value={ + loading ? ( + + ) : ( + formatNumber(data?.contracts_aggregate.aggregate?.count || 0) + ) + } /> div { + display: inline-block !important; + } +} \ No newline at end of file diff --git a/src/containers/mint/InfoText/InfoText.tsx b/src/containers/mint/InfoText/InfoText.tsx new file mode 100644 index 000000000..40d67066b --- /dev/null +++ b/src/containers/mint/InfoText/InfoText.tsx @@ -0,0 +1,31 @@ +import { formatNumber } from 'src/utils/utils'; +import { DenomArr } from 'src/components'; +import { SLOTS_MAX } from '../utils'; +import styles from './InfoText.module.scss'; +import { SelectedState } from '../types'; + +type Props = { + value: { + amount: number; + days: number; + }; + selected: SelectedState; + resourceToken: number; +}; + +function InfoText({ value: { amount, days }, selected, resourceToken }: Props) { + return ( +

+ You’re freezing {formatNumber(amount)}{' '} + for{' '} + {days} days. It will release{' '} + {resourceToken}{' '} + for you. At the end of the + period, {selected} becomes liquid automatically, but you can use it to + boost ranking during the freeze. You can have only{' '} + {SLOTS_MAX} slots for investmint at a time. +

+ ); +} + +export default InfoText; diff --git a/src/containers/mint/LiquidBalances/LiquidBalances.module.scss b/src/containers/mint/LiquidBalances/LiquidBalances.module.scss new file mode 100644 index 000000000..c3b351fcc --- /dev/null +++ b/src/containers/mint/LiquidBalances/LiquidBalances.module.scss @@ -0,0 +1,5 @@ +.wrapper { + display: grid; + align-content: space-evenly; + height: 100%; +} \ No newline at end of file diff --git a/src/containers/mint/LiquidBalances/LiquidBalances.tsx b/src/containers/mint/LiquidBalances/LiquidBalances.tsx new file mode 100644 index 000000000..f42021da1 --- /dev/null +++ b/src/containers/mint/LiquidBalances/LiquidBalances.tsx @@ -0,0 +1,21 @@ +import { DENOM_LIQUID } from 'src/constants/config'; +import ItemBalance from '../components/ItemBalance/ItemBalance'; +import styles from './LiquidBalances.module.scss'; + +type Props = { + amount: { + liquidH: number; + frozenH: number; + }; +}; + +function LiquidBalances({ amount: { liquidH, frozenH } }: Props) { + return ( +
+ + +
+ ); +} + +export default LiquidBalances; diff --git a/src/containers/mint/Mint.module.scss b/src/containers/mint/Mint.module.scss index 8b81b0d06..6cbf2f652 100644 --- a/src/containers/mint/Mint.module.scss +++ b/src/containers/mint/Mint.module.scss @@ -3,22 +3,22 @@ margin: 0 auto; } -.text { - text-align: center; - grid-area: 2/2/2/2; - font-size: 16px; - position: absolute; - bottom: 30px; - - color: var(--grayscale-dark); - - strong { - color: white; - font-weight: 400; - white-space: nowrap; - } - - > div { - display: inline-block !important; - } +.containerRcSlider { + display: grid; + grid-template-rows: repeat(3, 1fr); + justify-items: center; + padding: 0px 10px; + height: 100%; + width: 100%; } + +.containerControl { + display: grid; + grid-template-columns: 250px 1fr 250px; + grid-template-rows: auto; + align-items: center; + margin: 64px 8px 0 8px; + grid-gap: 16px; + padding-bottom: 150px; + position: relative; +} \ No newline at end of file diff --git a/src/containers/mint/Statistics/Statistics.module.scss b/src/containers/mint/Statistics/Statistics.module.scss new file mode 100644 index 000000000..b946f24aa --- /dev/null +++ b/src/containers/mint/Statistics/Statistics.module.scss @@ -0,0 +1,9 @@ + +.container { + margin-top: 10px; + margin-bottom: 50px; + display: grid; + grid-template-columns: repeat(3, 300px); + grid-gap: 20px; + justify-content: center; +} \ No newline at end of file diff --git a/src/containers/mint/Statistics/Statistics.tsx b/src/containers/mint/Statistics/Statistics.tsx new file mode 100644 index 000000000..63e228a1e --- /dev/null +++ b/src/containers/mint/Statistics/Statistics.tsx @@ -0,0 +1,30 @@ +import { CardStatisics, ValueImg } from 'src/components'; +import { formatNumber } from 'src/utils/utils'; +import styles from './Statistics.module.scss'; + +function Statistics({ + amount, +}: { + amount: { vestedA: number; vestedV: number }; +}) { + const { vestedA, vestedV } = amount; + + return ( +
+ } + value={formatNumber(vestedA)} + /> + } + value={formatNumber(vestedV)} + /> + +
+ ); +} + +export default Statistics; diff --git a/src/containers/mint/actionBar.jsx b/src/containers/mint/actionBar.jsx deleted file mode 100644 index fa5c4ec1a..000000000 --- a/src/containers/mint/actionBar.jsx +++ /dev/null @@ -1,179 +0,0 @@ -import { useEffect, useState } from 'react'; -import { coin } from '@cosmjs/launchpad'; -import { Link } from 'react-router-dom'; -import { useSigningClient } from 'src/contexts/signerClient'; -import { useQueryClient } from 'src/contexts/queryClient'; -import { - Dots, - ActionBarContentText, - TransactionSubmitted, - Confirmed, - TransactionError, - Account, - ActionBar as ActionBarContainer, - BtnGrd, -} from '../../components'; -import { CYBER, LEDGER, DEFAULT_GAS_LIMITS } from '../../utils/config'; -import { getTxs } from '../../utils/search/utils'; - -const { - STAGE_INIT, - STAGE_ERROR, - STAGE_SUBMITTED, - STAGE_CONFIRMING, - STAGE_CONFIRMED, -} = LEDGER; - -const BASE_VESTING_TIME = 86401; - -function ActionBar({ - value, - selected, - valueDays, - resourceToken, - updateFnc, - addressActive, -}) { - const queryClient = useQueryClient(); - const { signer, signingClient } = useSigningClient(); - const [stage, setStage] = useState(STAGE_INIT); - const [txHash, setTxHash] = useState(null); - const [txHeight, setTxHeight] = useState(null); - const [errorMessage, setErrorMessage] = useState(null); - - useEffect(() => { - const confirmTx = async () => { - if (queryClient && txHash) { - setStage(STAGE_CONFIRMING); - const response = await getTxs(txHash); - - if (response && response !== null) { - if (response.logs) { - setStage(STAGE_CONFIRMED); - setTxHeight(response.height); - if (updateFnc) { - updateFnc(); - } - return; - } - if (response.code) { - setStage(STAGE_ERROR); - setTxHeight(response.height); - setErrorMessage(response.raw_log); - return; - } - } - setTimeout(confirmTx, 1500); - } - }; - confirmTx(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [signingClient, txHash]); - - const investmint = async () => { - if (signer && signingClient) { - setStage(STAGE_SUBMITTED); - const [{ address }] = await signer.getAccounts(); - const gas = DEFAULT_GAS_LIMITS * 2; - const fee = { - amount: [], - gas: gas.toString(), - }; - if (addressActive === address) { - try { - const response = await signingClient.investmint( - address, - coin(parseFloat(value), CYBER.DENOM_LIQUID_TOKEN), - selected, - parseFloat(BASE_VESTING_TIME * valueDays), - fee - ); - - if (response.code === 0) { - setTxHash(response.transactionHash); - } else if (response.code === 4) { - setTxHash(null); - setErrorMessage( - 'Cyberlinking and investmint is not working. Wait for updates.' - ); - setStage(STAGE_ERROR); - } else { - setTxHash(null); - setErrorMessage(response.rawLog.toString()); - setStage(STAGE_ERROR); - } - } catch (error) { - setTxHash(null); - setErrorMessage(error.toString()); - setStage(STAGE_ERROR); - } - } else { - setErrorMessage( - - Add address to your - pocket or make active{' '} - - ); - setStage(STAGE_ERROR); - } - } - }; - - const clearState = () => { - setStage(STAGE_INIT); - setTxHash(null); - setTxHeight(null); - setErrorMessage(null); - }; - - if (stage === STAGE_INIT) { - return ( - - ); - } - - if (stage === STAGE_SUBMITTED) { - return ( - - check the transaction - - } - /> - ); - } - - if (stage === STAGE_CONFIRMING) { - return ; - } - - if (stage === STAGE_CONFIRMED) { - return ( - clearState()} - /> - ); - } - - if (stage === STAGE_ERROR && errorMessage !== null) { - return ( - clearState()} - /> - ); - } - - return ; -} - -export default ActionBar; diff --git a/src/containers/mint/actionBar.tsx b/src/containers/mint/actionBar.tsx new file mode 100644 index 000000000..e2485fedc --- /dev/null +++ b/src/containers/mint/actionBar.tsx @@ -0,0 +1,134 @@ +import { useState } from 'react'; +import { coin } from '@cosmjs/launchpad'; +import { useSigningClient } from 'src/contexts/signerClient'; +import { investmint } from 'src/services/neuron/neuronApi'; +import useWaitForTransaction, { + Props as PropsTx, +} from 'src/hooks/useWaitForTransaction'; +import { + Dots, + TransactionSubmitted, + Confirmed, + TransactionError, + ActionBar as ActionBarContainer, +} from '../../components'; +import { LEDGER } from '../../utils/config'; +import { SelectedState } from './types'; +import { DENOM_LIQUID } from 'src/constants/config'; + +const { + STAGE_INIT, + STAGE_ERROR, + STAGE_SUBMITTED, + STAGE_CONFIRMING, + STAGE_CONFIRMED, +} = LEDGER; + +const BASE_VESTING_TIME = 86401; + +type Props = { + amountH: number; + resource: SelectedState; + valueDays: number; + resourceAmount: number; + updateFnc?: () => void; +}; + +function ActionBar({ + amountH, + resource, + valueDays, + resourceAmount, + updateFnc, +}: Props) { + const { signer, signingClient } = useSigningClient(); + const [stage, setStage] = useState(STAGE_INIT); + const [tx, setTx] = useState(); + const [errorMessage, setErrorMessage] = useState(null); + + useWaitForTransaction({ hash: tx?.hash, onSuccess: tx?.onSuccess }); + + const investmintFunc = async () => { + if (!signer || !signingClient) { + return; + } + + setStage(STAGE_SUBMITTED); + const [{ address }] = await signer.getAccounts(); + + await investmint( + address, + coin(amountH, DENOM_LIQUID), + resource, + BASE_VESTING_TIME * valueDays, + signingClient + ) + .then((txHash) => { + setStage(STAGE_CONFIRMING); + + setTx({ + hash: txHash, + onSuccess: () => { + updateFnc && updateFnc(); + setStage(STAGE_CONFIRMED); + }, + }); + }) + .catch((e) => { + setTx(undefined); + setErrorMessage(e.toString()); + setStage(STAGE_ERROR); + }); + }; + + const clearState = () => { + setStage(STAGE_INIT); + setTx(undefined); + setErrorMessage(null); + }; + + if (stage === STAGE_INIT) { + return ( + + ); + } + + if (stage === STAGE_SUBMITTED) { + return ( + + check the transaction + + } + /> + ); + } + + if (stage === STAGE_CONFIRMING) { + return ; + } + + if (stage === STAGE_CONFIRMED) { + return clearState()} />; + } + + if (stage === STAGE_ERROR && errorMessage !== null) { + return ( + clearState()} + /> + ); + } + + return ; +} + +export default ActionBar; diff --git a/src/containers/mint/components/ERatio/ERatio.module.scss b/src/containers/mint/components/ERatio/ERatio.module.scss new file mode 100644 index 000000000..35b224eae --- /dev/null +++ b/src/containers/mint/components/ERatio/ERatio.module.scss @@ -0,0 +1,12 @@ +.containerText { + font-size: 20px; + margin-bottom: 20px; + display: flex; + justify-content: center; + align-items: center; + + .icon { + margin-left: 5px; + margin-top: 5px; + } +} \ No newline at end of file diff --git a/src/containers/mint/eRatio.jsx b/src/containers/mint/components/ERatio/ERatio.tsx similarity index 67% rename from src/containers/mint/eRatio.jsx rename to src/containers/mint/components/ERatio/ERatio.tsx index 390a83ad3..1184ffa8c 100644 --- a/src/containers/mint/eRatio.jsx +++ b/src/containers/mint/components/ERatio/ERatio.tsx @@ -1,25 +1,13 @@ import QuestionBtn from 'src/components/Rank/QuestionBtn/QuestionBtn'; -import { Tooltip } from '../../components'; +import { Tooltip } from 'src/components'; +import styles from './ERatio.module.scss'; -function ERatio({ eRatio }) { +function ERatio({ eRatio }: { eRatio: number }) { return ( - <> -
+
+
E-Ratio -
+
{eRatio}
- +
); } diff --git a/src/containers/mint/components/ItemBalance/ItemBalance.module.scss b/src/containers/mint/components/ItemBalance/ItemBalance.module.scss new file mode 100644 index 000000000..c45190398 --- /dev/null +++ b/src/containers/mint/components/ItemBalance/ItemBalance.module.scss @@ -0,0 +1,11 @@ +.wrapper { +display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + font-size: 16px; + + .text { + color: var(--grayscale-dark); + } +} \ No newline at end of file diff --git a/src/containers/mint/components/ItemBalance/ItemBalance.tsx b/src/containers/mint/components/ItemBalance/ItemBalance.tsx new file mode 100644 index 000000000..220814cd4 --- /dev/null +++ b/src/containers/mint/components/ItemBalance/ItemBalance.tsx @@ -0,0 +1,23 @@ +import { FormatNumberTokens } from 'src/components'; +import styles from './ItemBalance.module.scss'; + +type Props = { + text: string; + amount: number; + demon: string; +}; + +function ItemBalance({ text, amount, demon }: Props) { + return ( +
+ {text} + +
+ ); +} + +export default ItemBalance; diff --git a/src/containers/mint/components/Slider/Slider.tsx b/src/containers/mint/components/Slider/Slider.tsx new file mode 100644 index 000000000..5bdf95c0a --- /dev/null +++ b/src/containers/mint/components/Slider/Slider.tsx @@ -0,0 +1,43 @@ +import Slider from 'rc-slider'; +import 'rc-slider/assets/index.css'; +import { GenericSliderProps } from 'rc-slider/lib/interface'; + +type Props = { + minMax: { + min: number; + max: number; + }; + value: { + amount: number; + onChange: (amount: number) => void; + }; + marks: GenericSliderProps['marks']; +}; + +function RcSlider({ minMax, value, marks }: Props) { + return ( + + ); +} + +export default RcSlider; diff --git a/src/containers/mint/index.tsx b/src/containers/mint/index.tsx index 3d241e77f..2ad35b716 100644 --- a/src/containers/mint/index.tsx +++ b/src/containers/mint/index.tsx @@ -1,44 +1,38 @@ import { useEffect, useState, useMemo } from 'react'; -import { Tablist, Pane } from '@cybercongress/gravity'; -import Slider from 'rc-slider'; import BigNumber from 'bignumber.js'; import { useIbcDenom } from 'src/contexts/ibcDenom'; import { useQueryClient } from 'src/contexts/queryClient'; -import { Btn, ItemBalance } from './ui'; -import 'rc-slider/assets/index.css'; -import { formatNumber, getDisplayAmount } from '../../utils/utils'; -import { CYBER } from '../../utils/config'; -import ERatio from './eRatio'; +import { useAdviser } from 'src/features/adviser/context'; +import Display from 'src/components/containerGradient/Display/Display'; +import { useAppSelector } from 'src/redux/hooks'; +import { selectCurrentAddress } from 'src/redux/features/pocket'; +import { QueryParamsResponse as QueryParamsResponseResources } from '@cybercongress/cyber-js/build/codec/cyber/resources/v1beta1/query'; import { Dots, - CardStatisics, ValueImg, DenomArr, Tabs, -} from '../../components'; + MainContainer, + FormatNumberTokens, +} from 'src/components'; +import { formatNumber, getDisplayAmount } from 'src/utils/utils'; import useGetSlots from './useGetSlots'; import { TableSlots } from '../energy/ui'; import ActionBar from './actionBar'; -import { useAdviser } from 'src/features/adviser/context'; -import Display from 'src/components/containerGradient/Display/Display'; -import ImgDenom from 'src/components/valueImg/imgDenom'; -import { useAppSelector } from 'src/redux/hooks'; -import { selectCurrentAddress } from 'src/redux/features/pocket'; import styles from './Mint.module.scss'; - -const BASE_VESTING_TIME = 86401; -const BASE_MAX_MINT_TIME = 41; - -const grid = { - display: 'grid', - gridTemplateColumns: '250px 1fr 250px', - gridTemplateRows: 'auto', - alignItems: 'center', - margin: '64px 8px 0 8px', - gridGap: '16px 16px', - position: 'relative', - paddingBottom: '150px', -}; +import { + SLOTS_MAX, + getAmountResource, + getERatio, + getMaxTimeMint, +} from './utils'; +import { SelectedState } from './types'; +import Statistics from './Statistics/Statistics'; +import RcSlider from './components/Slider/Slider'; +import InfoText from './InfoText/InfoText'; +import LiquidBalances from './LiquidBalances/LiquidBalances'; +import ERatio from './components/ERatio/ERatio'; +import { DENOM_LIQUID } from 'src/constants/config'; const returnColorDot = (marks) => { return { @@ -50,37 +44,46 @@ const returnColorDot = (marks) => { }; }; -const SLOTS_MAX = 16; - -enum SelectedState { - millivolt = 'millivolt', - milliampere = 'milliampere', -} - function Mint() { const queryClient = useQueryClient(); const { traseDenom } = useIbcDenom(); const [updateAddress, setUpdateAddress] = useState(0); - // const { balance } = useGetBalance(addressActive, updateAddress); const [selected, setSelected] = useState( SelectedState.milliampere ); const [value, setValue] = useState(0); const [valueDays, setValueDays] = useState(1); - const [max, setMax] = useState(0); - const [maxMintTime, setMaxMintTime] = useState(BASE_MAX_MINT_TIME); - const [eRatio, setERatio] = useState(0); - const [resourceToken, setResourceToken] = useState(0); const [height, setHeight] = useState(0); - const [resourcesParams, setResourcesParams] = useState(null); + const [resourcesParams, setResourcesParams] = + useState(undefined); const [balanceHydrogen, SetBalanceHydrogen] = useState(0); const addressActive = useAppSelector(selectCurrentAddress); - const { slotsData, vested, loadingAuthAccounts, originalVesting } = - useGetSlots(addressActive, updateAddress); + const { slotsData, vested, loadingAuthAccounts, originalVesting, update } = + useGetSlots(addressActive); const { setAdviser } = useAdviser(); + const frozenH = + originalVesting[DENOM_LIQUID] > 0 + ? new BigNumber(originalVesting[DENOM_LIQUID]) + .minus(vested[DENOM_LIQUID]) + .toNumber() + : 0; + + const eRatio = getERatio(frozenH, balanceHydrogen); + + const liquidH = new BigNumber(balanceHydrogen) + .minus(frozenH) + .dp(0, BigNumber.ROUND_FLOOR) + .toNumber(); + + const maxMintTime = getMaxTimeMint(resourcesParams, selected, height); + const resourceToken = getAmountResource(resourcesParams, selected, height, { + valueH: value, + valueDays, + }); + useEffect(() => { const availableSlots = SLOTS_MAX - @@ -102,186 +105,73 @@ function Mint() { }, [setAdviser, slotsData]); useEffect(() => { - const getBalanceH = async () => { - let amountHydrogen = 0; - if (queryClient && addressActive !== null) { - const responseBalance = await queryClient.getBalance( - addressActive, - CYBER.DENOM_LIQUID_TOKEN - ); - if (responseBalance.amount) { - amountHydrogen = parseFloat(responseBalance.amount); - } - } - SetBalanceHydrogen(amountHydrogen); - }; - getBalanceH(); - }, [queryClient, addressActive]); - - useEffect(() => { - const getParam = async () => { - const responseResourcesParams = await queryClient.resourcesParams(); - if ( - responseResourcesParams.params && - Object.keys(responseResourcesParams.params).length > 0 - ) { - const { params } = responseResourcesParams; - setResourcesParams((item) => ({ ...item, ...params })); - } - - const responseGetHeight = await queryClient.getHeight(); - if (responseGetHeight > 0) { - setHeight(responseGetHeight); - } - }; - getParam(); - }, [queryClient]); - - useEffect(() => { - let vestedTokens = 0; - let maxValue = 0; - if (originalVesting[CYBER.DENOM_LIQUID_TOKEN] > 0) { - vestedTokens = - parseFloat(originalVesting[CYBER.DENOM_LIQUID_TOKEN]) - - parseFloat(vested[CYBER.DENOM_LIQUID_TOKEN]); - } - if (balanceHydrogen > 0) { - maxValue = Math.floor(balanceHydrogen) - vestedTokens; - } else { - maxValue = 0; + if (!queryClient || !addressActive) { + return; } - setMax(maxValue); - }, [balanceHydrogen, vested, originalVesting]); + queryClient + .getBalance(addressActive, DENOM_LIQUID) + .then((response) => { + SetBalanceHydrogen(parseFloat(response.amount)); + }); + }, [queryClient, addressActive, updateAddress]); useEffect(() => { - let vestedTokens = 0; - if (originalVesting[CYBER.DENOM_LIQUID_TOKEN] > 0) { - vestedTokens = - parseFloat(originalVesting[CYBER.DENOM_LIQUID_TOKEN]) - - parseFloat(vested[CYBER.DENOM_LIQUID_TOKEN]); - } - if (vestedTokens > 0 && balanceHydrogen > 0) { - const procent = (vestedTokens / balanceHydrogen) * 100; - const eRatioTemp = Math.floor(procent * 100) / 100; - setERatio(eRatioTemp); - } else { - setERatio(0); + if (!queryClient) { + return; } - }, [balanceHydrogen, vested, originalVesting]); - useEffect(() => { - let maxValueTaime = BASE_MAX_MINT_TIME; - if (resourcesParams !== null) { - const { - halvingPeriodAmpereBlocks: halvingPeriodBlocksAmpere, - halvingPeriodVoltBlocks: halvingPeriodBlocksVolt, - } = resourcesParams; - let halvingPeriod = 0; - if (selected === 'millivolt') { - halvingPeriod = halvingPeriodBlocksVolt; - } else { - halvingPeriod = halvingPeriodBlocksAmpere; - } - - const halving = 2 ** Math.floor(height / halvingPeriod); - maxValueTaime = Math.floor( - (halvingPeriod * 5 * halving) / BASE_VESTING_TIME - ); - } - setMaxMintTime(maxValueTaime); - }, [resourcesParams, height, selected]); + queryClient + .resourcesParams() + .then((response: QueryParamsResponseResources) => { + setResourcesParams(response.params); + }); - useEffect(() => { - let token = 0; - if (resourcesParams !== null && value > 0 && valueDays > 0) { - const hydrogen = value; - const { - baseInvestmintAmountVolt, - baseInvestmintAmountAmpere, - baseInvestmintPeriodVolt, - baseInvestmintPeriodAmpere, - halvingPeriodAmpereBlocks: halvingPeriodBlocksAmpere, - halvingPeriodVoltBlocks: halvingPeriodBlocksVolt, - } = resourcesParams; - let baseLength = 0; - let baseAmount = 0; - let halvingPeriod = 0; - if (selected === 'millivolt') { - baseLength = baseInvestmintPeriodVolt; - baseAmount = parseFloat(baseInvestmintAmountVolt.amount); - halvingPeriod = halvingPeriodBlocksVolt; - } else { - baseLength = baseInvestmintPeriodAmpere; - baseAmount = parseFloat(baseInvestmintAmountAmpere.amount); - halvingPeriod = halvingPeriodBlocksAmpere; - } - const vestingTime = valueDays * BASE_VESTING_TIME; - const cycles = vestingTime / baseLength; - const base = hydrogen / baseAmount; - const halving = 0.5 ** Math.floor(height / halvingPeriod); - - token = Math.floor(cycles * base * halving); - } - setResourceToken(token); - }, [value, valueDays, selected, resourcesParams, height]); + queryClient.getHeight().then((response) => { + setHeight(response); + }); + }, [queryClient]); const updateFunc = () => { setValue(0); setValueDays(1); - setUpdateAddress(updateAddress + 1); + setUpdateAddress((item) => item + 1); + update(); }; const vestedA = useMemo(() => { - let amountA = 0; - if (originalVesting.milliampere > 0) { - const [{ coinDecimals }] = traseDenom('milliampere'); - const vestedTokensA = new BigNumber(originalVesting.milliampere) - .minus(vested.milliampere) - .toNumber(); - amountA = getDisplayAmount(vestedTokensA, coinDecimals); + if (originalVesting.milliampere <= 0) { + return 0; } - return amountA; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [vested, originalVesting]); + + const [{ coinDecimals }] = traseDenom(SelectedState.milliampere); + const amount = new BigNumber(originalVesting.milliampere) + .minus(vested.milliampere) + .toNumber(); + + return getDisplayAmount(amount, coinDecimals); + }, [vested, originalVesting, traseDenom]); const vestedV = useMemo(() => { - let amountV = 0; - if (originalVesting.millivolt > 0) { - const [{ coinDecimals }] = traseDenom('millivolt'); - const vestedTokensA = new BigNumber(originalVesting.millivolt) - .minus(vested.millivolt) - .toNumber(); - amountV = getDisplayAmount(vestedTokensA, coinDecimals); + if (originalVesting.millivolt <= 0) { + return 0; } - return amountV; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [vested, originalVesting]); + + const [{ coinDecimals }] = traseDenom(SelectedState.millivolt); + const amount = new BigNumber(originalVesting.millivolt) + .minus(vested.millivolt) + .toNumber(); + return getDisplayAmount(amount, coinDecimals); + }, [vested, originalVesting, traseDenom]); + + const onChangeValue = (amountH: number) => setValue(amountH); + + const onChangeValueDays = (days: number) => setValueDays(days); return ( <> -
- - } - value={formatNumber(vestedA)} - /> - } - value={formatNumber(vestedV)} - /> - - + +
-
-
- {/* */} - } - /> - } +
+ + +
+ -
-
- {resourceToken} - setValue(eValue)} - trackStyle={{ backgroundColor: '#3ab793' }} - railStyle={{ backgroundColor: '#97979775' }} - dotStyle={{ - backgroundColor: '#97979775', - borderColor: '#97979775', - }} - activeDotStyle={{ - borderColor: '#3ab793', - backgroundColor: '#3ab793', - }} - handleStyle={{ - border: 'none', - backgroundColor: '#3ab793', + [liquidH]: returnColorDot(`${formatNumber(liquidH)} H`), }} /> - setValueDays(eValue)} - trackStyle={{ backgroundColor: '#3ab793' }} - railStyle={{ backgroundColor: '#97979775' }} - dotStyle={{ - backgroundColor: '#97979775', - borderColor: '#97979775', - }} - activeDotStyle={{ - borderColor: '#3ab793', - backgroundColor: '#3ab793', - }} - handleStyle={{ - border: 'none', - backgroundColor: '#3ab793', - }} />
-
- -
+ + + {value > 0 && ( -

- You’re freezing {formatNumber(value)}{' '} - for{' '} - {valueDays} days. It will release{' '} - {resourceToken}{' '} - for you. At the end of - the period, {selected} becomes liquid automatically, but you can - use it to boost ranking during the freeze. You can have only{' '} - {SLOTS_MAX} slots for investmint at a time. -

+ )}
@@ -405,14 +232,13 @@ function Mint() { )} -
+ ); diff --git a/src/containers/mint/types.d.ts b/src/containers/mint/types.ts similarity index 66% rename from src/containers/mint/types.d.ts rename to src/containers/mint/types.ts index 360a23de3..590219689 100644 --- a/src/containers/mint/types.d.ts +++ b/src/containers/mint/types.ts @@ -8,3 +8,9 @@ export type Slot = { milliampere: number; }; }; + +export enum SelectedState { + millivolt = 'millivolt', + milliampere = 'milliampere', +} + diff --git a/src/containers/mint/ui.jsx b/src/containers/mint/ui.jsx deleted file mode 100644 index c39a749f4..000000000 --- a/src/containers/mint/ui.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import { Tab, Pane } from '@cybercongress/gravity'; -import { formatNumber } from '../../utils/utils'; -import { Dots } from '../../components'; - -function Btn({ onSelect, checkedSwitch, text, disabledBtn, ...props }) { - return ( - - {text} - - ); -} - -function ItemBalance({ text, amount, currency }) { - return ( - - - {text} - - {amount === null ? ( - - ) : ( - - {formatNumber(amount)} {currency} - - )} - - ); -} - -export { Btn, ItemBalance }; diff --git a/src/containers/mint/useGetSlots.tsx b/src/containers/mint/useGetSlots.tsx index 6d46be4c2..1bc105f14 100644 --- a/src/containers/mint/useGetSlots.tsx +++ b/src/containers/mint/useGetSlots.tsx @@ -3,13 +3,13 @@ import { useQuery } from '@tanstack/react-query'; import { useQueryClient } from 'src/contexts/queryClient'; import { authAccounts } from '../../utils/search/utils'; import { convertResources } from '../../utils/utils'; -import { CYBER } from '../../utils/config'; import { Slot } from './types'; +import { DENOM_LIQUID } from 'src/constants/config'; const MILLISECONDS_IN_SECOND = 1000; const initStateVested = { - [CYBER.DENOM_LIQUID_TOKEN]: 0, + [DENOM_LIQUID]: 0, millivolt: 0, milliampere: 0, }; @@ -105,7 +105,7 @@ function useGetSlots(addressActive) { setVested(initStateVested); const originalVestingInitAmount = { - [CYBER.DENOM_LIQUID_TOKEN]: 0, + [DENOM_LIQUID]: 0, millivolt: 0, milliampere: 0, }; @@ -118,9 +118,9 @@ function useGetSlots(addressActive) { const { start_time: startTime } = dataAuthAccounts.result.value; const balances = getCalculationBalance(originalVestingAmount); - if (balances[CYBER.DENOM_LIQUID_TOKEN]) { - originalVestingInitAmount[CYBER.DENOM_LIQUID_TOKEN] = - balances[CYBER.DENOM_LIQUID_TOKEN]; + if (balances[DENOM_LIQUID]) { + originalVestingInitAmount[DENOM_LIQUID] = + balances[DENOM_LIQUID]; } if (balances.millivolt) { originalVestingInitAmount.millivolt = balances.millivolt; @@ -225,9 +225,9 @@ function useGetSlots(addressActive) { } }); if (obj.status !== 'Unfreezing') { - if (obj.amount[CYBER.DENOM_LIQUID_TOKEN]) { - vestedAmount[CYBER.DENOM_LIQUID_TOKEN] += - obj.amount[CYBER.DENOM_LIQUID_TOKEN]; + if (obj.amount[DENOM_LIQUID]) { + vestedAmount[DENOM_LIQUID] += + obj.amount[DENOM_LIQUID]; } if (obj.amount.milliampere) { vestedAmount.milliampere += obj.amount.milliampere; diff --git a/src/containers/mint/utils.ts b/src/containers/mint/utils.ts new file mode 100644 index 000000000..c5bd5203e --- /dev/null +++ b/src/containers/mint/utils.ts @@ -0,0 +1,87 @@ +import BigNumber from 'bignumber.js'; +import { QueryParamsResponse as QueryParamsResponseResources } from '@cybercongress/cyber-js/build/codec/cyber/resources/v1beta1/query'; +import { SelectedState } from './types'; + +const BASE_VESTING_TIME = 86401; +const BASE_MAX_MINT_TIME = 41; +export const SLOTS_MAX = 16; + +export const getERatio = (liquidH: number, balanceHydrogen: number) => { + if (liquidH <= 0 || balanceHydrogen <= 0) { + return 0; + } + + return new BigNumber(liquidH) + .dividedBy(balanceHydrogen) + .shiftedBy(2) + .dp(2, BigNumber.ROUND_FLOOR) + .toNumber(); +}; + +export const getMaxTimeMint = ( + resourcesParams: QueryParamsResponseResources['params'], + selected: SelectedState, + height: number +) => { + if (!resourcesParams || height <= 0) { + return BASE_MAX_MINT_TIME; + } + + const { halvingPeriodAmpereBlocks, halvingPeriodVoltBlocks } = + resourcesParams; + + const halvingPeriod = + selected === SelectedState.millivolt + ? halvingPeriodVoltBlocks + : halvingPeriodAmpereBlocks; + + const halving = new BigNumber(2).pow( + new BigNumber(height).dividedBy(halvingPeriod).dp(0, BigNumber.ROUND_FLOOR) + ); + + return new BigNumber( + new BigNumber(halvingPeriod).multipliedBy(5).multipliedBy(halving) + ) + .dividedBy(BASE_VESTING_TIME) + .dp(0, BigNumber.ROUND_FLOOR) + .toNumber(); +}; + +export const getAmountResource = ( + params: QueryParamsResponseResources['params'], + selected: SelectedState, + height: number, + value: { valueH: number; valueDays: number } +) => { + const { valueH, valueDays } = value; + if (!params || valueDays <= 0 || valueH <= 0) { + return 0; + } + + const baseLength = + selected === SelectedState.millivolt + ? params.baseInvestmintPeriodVolt + : params.baseInvestmintPeriodAmpere; + const baseAmount = + selected === SelectedState.millivolt + ? params.baseInvestmintAmountVolt?.amount || 0 + : params.baseInvestmintAmountAmpere?.amount || 0; + const halvingPeriod = + selected === SelectedState.millivolt + ? params.halvingPeriodVoltBlocks + : params.halvingPeriodAmpereBlocks; + + const cycles = new BigNumber( + new BigNumber(valueDays).multipliedBy(BASE_VESTING_TIME) + ).dividedBy(baseLength); + const base = new BigNumber(valueH).dividedBy(baseAmount); + const halving = new BigNumber(0.5).pow( + new BigNumber(height).dividedBy(halvingPeriod).dp(0, BigNumber.ROUND_FLOOR) + ); + + return new BigNumber(cycles) + .multipliedBy(base) + .multipliedBy(halving) + .dp(0, BigNumber.ROUND_FLOOR) + .toNumber(); +}; diff --git a/src/containers/nebula/index.tsx b/src/containers/nebula/index.tsx index 34f8d6d77..bdb3e5662 100644 --- a/src/containers/nebula/index.tsx +++ b/src/containers/nebula/index.tsx @@ -15,8 +15,8 @@ import { import { replaceSlash, getDisplayAmount } from '../../utils/utils'; // import { getMarketData } from './getMarketData'; import { ColItem, RowItem, NebulaImg } from './components'; -import { CYBER } from '../../utils/config'; import { useAdviser } from 'src/features/adviser/context'; +import { DENOM_LIQUID } from 'src/constants/config'; function Title({ capData, @@ -168,7 +168,7 @@ function Nebula() { @@ -176,7 +176,7 @@ function Nebula() { diff --git a/src/containers/network/customNetwork.tsx b/src/containers/network/customNetwork.tsx index 659960c62..187e18208 100644 --- a/src/containers/network/customNetwork.tsx +++ b/src/containers/network/customNetwork.tsx @@ -27,9 +27,8 @@ function ValueItem({ text, value, onChange }) { const initValue = { CHAIN_ID: 'bostrom', - DENOM_CYBER: 'boot', - DENOM_LIQUID_TOKEN: 'hydrogen', - DENOM_CYBER_G: 'GBOOT', + BASE_DENOM: 'boot', + DENOM_LIQUID: 'hydrogen', CYBER_NODE_URL_API: 'https://rpc.bostrom.cybernode.ai', CYBER_WEBSOCKET_URL: 'wss://rpc.bostrom.cybernode.ai/websocket', CYBER_NODE_URL_LCD: 'https://lcd.bostrom.cybernode.ai', @@ -69,7 +68,7 @@ function CustomNetwork() { })); break; - case 'DENOM_CYBER': + case 'BASE_DENOM': setCustomConfig((item) => ({ ...item, [key]: value, @@ -116,13 +115,13 @@ function CustomNetwork() { /> onChangeValue(e, 'DENOM_CYBER')} + value={customConfig.BASE_DENOM} + onChange={(e) => onChangeValue(e, 'BASE_DENOM')} /> onChangeValue(e, 'DENOM_LIQUID_TOKEN')} + value={customConfig.DENOM_LIQUID} + onChange={(e) => onChangeValue(e, 'DENOM_LIQUID')} /> ({ ...item, [key]: value, - BECH32_PREFIX_ACC_ADDR_CYBERVALOPER: `${value}valoper`, + BECH32_PREFIX_VALOPER: `${value}valoper`, })); break; - case 'DENOM_CYBER': + case 'BASE_DENOM': setCustomConfig((item) => ({ ...item, [key]: value, - DENOM_CYBER_G: `G${value.toUpperCase()}`, + DENOM_G: `G${value.toUpperCase()}`, })); break; @@ -106,13 +106,13 @@ function DetailsNetwork() { /> onChangeValue(e, 'DENOM_CYBER')} + value={customConfig.BASE_DENOM} + onChange={(e) => onChangeValue(e, 'BASE_DENOM')} /> onChangeValue(e, 'DENOM_LIQUID_TOKEN')} + value={customConfig.DENOM_LIQUID} + onChange={(e) => onChangeValue(e, 'DENOM_LIQUID')} /> {key !== 'bostrom' && key !== 'space-pussy' && - key !== CYBER.CHAIN_ID && ( + key !== CHAIN_ID && ( onClickDeleteAddress(key)} typeBtn="red" @@ -79,11 +79,11 @@ function ListNetwork() {
denom
-
{item.DENOM_CYBER}
+
{item.BASE_DENOM}
liquid denom
-
{item.DENOM_LIQUID_TOKEN}
+
{item.DENOM_LIQUID}
rpc
diff --git a/src/containers/portal/ActionBarAddAvatar.tsx b/src/containers/portal/ActionBarAddAvatar.tsx index 184d284d1..131f847ef 100644 --- a/src/containers/portal/ActionBarAddAvatar.tsx +++ b/src/containers/portal/ActionBarAddAvatar.tsx @@ -3,8 +3,7 @@ import { GasPrice } from '@cosmjs/launchpad'; import { useSigningClient } from 'src/contexts/signerClient'; import { Nullable } from 'src/types'; import { useBackend } from 'src/contexts/backend/backend'; -import Soft3MessageFactory from 'src/soft.js/api/msgs'; -import { DEFAULT_GAS_LIMITS } from 'src/utils/config'; +import Soft3MessageFactory from 'src/services/soft.js/api/msgs'; import { ActionBarSteps, ActionBarContainer } from './components'; import { Dots, BtnGrd } from '../../components'; import { CONTRACT_ADDRESS_PASSPORT } from './utils'; diff --git a/src/containers/portal/citizenship/ActionBar.tsx b/src/containers/portal/citizenship/ActionBar.tsx index 34989ad74..711ecf29a 100644 --- a/src/containers/portal/citizenship/ActionBar.tsx +++ b/src/containers/portal/citizenship/ActionBar.tsx @@ -5,11 +5,12 @@ import { connect } from 'react-redux'; import { useSigningClient } from 'src/contexts/signerClient'; import { setDefaultAccount, setAccounts } from '../../../redux/features/pocket'; import { Dots, BtnGrd } from '../../../components'; -import { CYBER, LEDGER } from '../../../utils/config'; +import { LEDGER } from '../../../utils/config'; import { steps } from './utils'; import { ActionBarSteps } from '../components'; import { useBackend } from 'src/contexts/backend/backend'; import NodeIsLoadingButton from 'src/components/btnGrd/NodeIsLoadingButton/NodeIsLoadingButton'; +import { CHAIN_ID } from 'src/constants/config'; const { STEP_INIT, @@ -68,7 +69,7 @@ function ActionBar({ let pocketAccount = {}; let defaultAccounts = null; let defaultAccountsKeys = null; - const chainId = CYBER.CHAIN_ID; + const chainId = CHAIN_ID; let count = 1; if (signer) { diff --git a/src/containers/portal/citizenship/index.tsx b/src/containers/portal/citizenship/index.tsx index ab2acf52c..a0ba424be 100644 --- a/src/containers/portal/citizenship/index.tsx +++ b/src/containers/portal/citizenship/index.tsx @@ -8,8 +8,13 @@ import { useSigningClient } from 'src/contexts/signerClient'; import { getKeplr } from 'src/utils/keplrUtils'; import { useDevice } from 'src/contexts/device'; import { Nullable } from 'src/types'; -import txs from '../../../utils/txs'; +import { useAdviser } from 'src/features/adviser/context'; +import { useBackend } from 'src/contexts/backend/backend'; +import { getPassport } from 'src/features/passport/passports.redux'; +import { useAppDispatch } from 'src/redux/hooks'; +import Soft3MessageFactory from 'src/services/soft.js/api/msgs'; +import { CHAIN_ID } from 'src/constants/config'; import { MainContainer, MoonAnimation, Stars } from '../components'; import { Rules, @@ -28,16 +33,10 @@ import { getPassportByNickname, getNumTokens, } from '../utils'; -import { CYBER } from '../../../utils/config'; import useSetActiveAddress from '../../../hooks/useSetActiveAddress'; import { steps } from './utils'; import Info from './Info'; import Carousel from '../../../components/Tabs/Carousel/CarouselOld/CarouselOld'; -import { useAdviser } from 'src/features/adviser/context'; -import { useBackend } from 'src/contexts/backend/backend'; -import { getPassport } from 'src/features/passport/passports.redux'; -import { useAppDispatch } from 'src/redux/hooks'; -import Soft3MessageFactory from 'src/soft.js/api/msgs'; const portalConfirmed = require('../../../sounds/portalConfirmed112.mp3'); const portalAmbient = require('../../../sounds/portalAmbient112.mp3'); @@ -131,7 +130,7 @@ const calculatePriceNicname = (valueNickname) => { const exponent = 8 - valueNickname.length; const base = new BigNumber(10).pow(exponent); const priceName = new BigNumber(1000000).multipliedBy(base).toNumber(); - funds = coins(priceName, CYBER.DENOM_CYBER); + funds = coins(priceName, BASE_DENOM); } return funds; @@ -216,7 +215,7 @@ function GetCitizenship({ defaultAccount }) { if (window.keplr === undefined) { setStep(STEP_KEPLR_INIT_CHECK_FNC); } else { - const offlineSigner = window.getOfflineSigner(CYBER.CHAIN_ID); + const offlineSigner = window.getOfflineSigner(CHAIN_ID); try { const [{ address }] = await offlineSigner.getAccounts(); if (addressActive !== null) { @@ -328,10 +327,7 @@ function GetCitizenship({ defaultAccount }) { if (usePriceNickname !== null) { const { amountPrice } = usePriceNickname; if (queryClient) { - const getBalance = await queryClient.getBalance( - bech32, - CYBER.DENOM_CYBER - ); + const getBalance = await queryClient.getBalance(bech32, BASE_DENOM); const { amount } = getBalance; if (parseFloat(amount) === 0) { setRegisterDisabled(false); @@ -371,16 +367,12 @@ function GetCitizenship({ defaultAccount }) { const keplrWindow = await getKeplr(); if (keplrWindow) { - await keplrWindow.enable(CYBER.CHAIN_ID); - const signer = await keplrWindow.getOfflineSignerAuto(CYBER.CHAIN_ID); + await keplrWindow.enable(CHAIN_ID); + const signer = await keplrWindow.getOfflineSignerAuto(CHAIN_ID); const [{ address }] = await signer.getAccounts(); const data = `${address}:${CONSTITUTION_HASH}`; - const res = await keplrWindow.signArbitrary( - CYBER.CHAIN_ID, - address, - data - ); + const res = await keplrWindow.signArbitrary(CHAIN_ID, address, data); const proveData = { pub_key: res.pub_key.value, signature: res.signature, diff --git a/src/containers/portal/components/ReleaseStatus/index.tsx b/src/containers/portal/components/ReleaseStatus/index.tsx index dbcb80c3a..98d51fcdf 100644 --- a/src/containers/portal/components/ReleaseStatus/index.tsx +++ b/src/containers/portal/components/ReleaseStatus/index.tsx @@ -1,11 +1,11 @@ import { useMemo } from 'react'; import { FormatNumberTokens } from 'src/components'; -import { CYBER } from '../../../../utils/config'; import DonutChart from '../../../../components/DonutChart'; import ContainerGradient from '../../../../components/containerGradient/ContainerGradient'; import { GIFT_ICON } from '../../utils'; import { ProgressBar } from '../progressCard'; import styles from './ReleaseStatus.module.scss'; +import { BASE_DENOM } from 'src/constants/config'; type DataReleaseStatus = { availableRelease: number; @@ -64,7 +64,7 @@ function RowItem({ item }: { item: Item }) {
{item.title}
- +
); @@ -81,7 +81,7 @@ function ReleaseStatus({
release status {GIFT_ICON}
- +
); diff --git a/src/containers/portal/components/currentGift/index.jsx b/src/containers/portal/components/currentGift/index.jsx index c426137ce..a0f21a89b 100644 --- a/src/containers/portal/components/currentGift/index.jsx +++ b/src/containers/portal/components/currentGift/index.jsx @@ -4,7 +4,7 @@ import BigNumber from 'bignumber.js'; import { formatNumber } from '../../../../utils/utils'; import ContainerGradient from '../../../../components/containerGradient/ContainerGradient'; import styles from './CurrentGift.module.scss'; -import { PATTERN_CYBER } from 'src/constants/app'; +import { PATTERN_CYBER } from 'src/constants/patterns'; const GIFT_ICON = '🎁'; const BOOT_ICON = '🟢'; diff --git a/src/containers/portal/components/imgNetwork/index.jsx b/src/containers/portal/components/imgNetwork/index.jsx index 516a2216a..3fc40f862 100644 --- a/src/containers/portal/components/imgNetwork/index.jsx +++ b/src/containers/portal/components/imgNetwork/index.jsx @@ -1,5 +1,8 @@ -import { PATTERN_COSMOS, PATTERN_ETH } from '../../../../utils/config'; -import { PATTERN_CYBER } from 'src/constants/app'; +import { + PATTERN_CYBER, + PATTERN_COSMOS, + PATTERN_ETH, +} from 'src/constants/patterns'; import styles from './styles.scss'; diff --git a/src/containers/portal/gift/ActionBarPortalGift.tsx b/src/containers/portal/gift/ActionBarPortalGift.tsx index 4555bd811..3ed5f6a1f 100644 --- a/src/containers/portal/gift/ActionBarPortalGift.tsx +++ b/src/containers/portal/gift/ActionBarPortalGift.tsx @@ -4,7 +4,7 @@ /* eslint-disable jsx-a11y/control-has-associated-label */ import { useEffect, useState, useCallback, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { GasPrice, coins } from '@cosmjs/launchpad'; +import { GasPrice } from '@cosmjs/launchpad'; import { toAscii, toBase64 } from '@cosmjs/encoding'; import { useSigningClient } from 'src/contexts/signerClient'; import { getKeplr } from 'src/utils/keplrUtils'; @@ -13,15 +13,16 @@ import { useDispatch, useSelector } from 'react-redux'; import { Citizenship } from 'src/types/citizenship'; import { RootState } from 'src/redux/store'; import { useBackend } from 'src/contexts/backend/backend'; -import txs from '../../../utils/txs'; +import { PATTERN_CYBER } from 'src/constants/patterns'; +import Soft3MessageFactory from 'src/services/soft.js/api/msgs'; +import BigNumber from 'bignumber.js'; +import { Nullable } from 'src/types'; import { Dots, ButtonIcon, ActionBar as ActionBarSteps, BtnGrd, } from '../../../components'; -import { CYBER, DEFAULT_GAS_LIMITS } from '../../../utils/config'; -import { PATTERN_CYBER } from 'src/constants/app'; import { trimString, groupMsg } from '../../../utils/utils'; import { CONSTITUTION_HASH, @@ -42,12 +43,9 @@ import { addAddress, deleteAddress, } from '../../../features/passport/passports.redux'; -import mssgsClaim from '../utilsMsgs'; import { ClaimMsg } from './type'; -import Soft3MessageFactory from 'src/soft.js/api/msgs'; -import BigNumber from 'bignumber.js'; -import { Nullable } from 'src/types'; import { TxHash } from '../hook/usePingTxs'; +import { CHAIN_ID } from 'src/constants/config'; const gasPrice = GasPrice.fromString('0.001boot'); @@ -357,7 +355,7 @@ function ActionBarPortalGift({ msgs.push(msgObject); }); const { bech32Address, isNanoLedger } = await signer.keplr.getKey( - CYBER.CHAIN_ID + CHAIN_ID ); if (!msgs.length) { diff --git a/src/containers/portal/gift/index.tsx b/src/containers/portal/gift/index.tsx index 16da2b652..6f02ab87d 100644 --- a/src/containers/portal/gift/index.tsx +++ b/src/containers/portal/gift/index.tsx @@ -17,7 +17,7 @@ import { MoonAnimation, } from '../components'; import useCheckGift from '../hook/useCheckGift'; -import { PATTERN_CYBER } from 'src/constants/app'; +import { PATTERN_CYBER } from 'src/constants/patterns'; import Carousel from '../../../components/Tabs/Carousel/CarouselOld/CarouselOld'; import STEP_INFO from './utils'; import Info from './Info'; diff --git a/src/containers/portal/pasport/index.tsx b/src/containers/portal/pasport/index.tsx index 0c1152ade..fd8273846 100644 --- a/src/containers/portal/pasport/index.tsx +++ b/src/containers/portal/pasport/index.tsx @@ -6,7 +6,7 @@ import { MusicalAddress, ParseAddressesImg } from '../components'; import { AvataImgIpfs } from '../components/avataIpfs'; import ContainerAvatar from '../components/avataIpfs/containerAvatar'; import { formatNumber, trimString } from '../../../utils/utils'; -import { PATTERN_CYBER } from 'src/constants/app'; +import { PATTERN_CYBER } from 'src/constants/patterns'; import BtnPasport from './btnPasport'; import plus from '../../../image/plus.svg'; import { ContainerGradient } from '../../../components'; diff --git a/src/containers/portal/release/ActionBarRelease.tsx b/src/containers/portal/release/ActionBarRelease.tsx index ecf49077f..6f4248fed 100644 --- a/src/containers/portal/release/ActionBarRelease.tsx +++ b/src/containers/portal/release/ActionBarRelease.tsx @@ -6,16 +6,16 @@ import { Nullable } from 'src/types'; import { AccountValue } from 'src/types/defaultAccount'; import { useQueryClient } from 'src/contexts/queryClient'; import BigNumber from 'bignumber.js'; -import Soft3MessageFactory from 'src/soft.js/api/msgs'; +import Soft3MessageFactory from 'src/services/soft.js/api/msgs'; import { GIFT_ICON } from '../utils'; import { Dots, BtnGrd, ActionBar, Account } from '../../../components'; -import { CYBER } from '../../../utils/config'; -import { PATTERN_CYBER } from 'src/constants/app'; +import { PATTERN_CYBER } from 'src/constants/patterns'; import { trimString } from '../../../utils/utils'; import { TxHash } from '../hook/usePingTxs'; import { CurrentRelease } from './type'; import mssgsClaim from '../utilsMsgs'; import { useAdviser } from 'src/features/adviser/context'; +import { CHAIN_ID } from 'src/constants/config'; const releaseMsg = (giftAddress: string) => { return { @@ -67,7 +67,7 @@ function ActionBarRelease({ try { if (signer && signingClient && currentRelease) { const { isNanoLedger, bech32Address: addressKeplr } = - await signer.keplr.getKey(CYBER.CHAIN_ID); + await signer.keplr.getKey(CHAIN_ID); const msgs = []; diff --git a/src/containers/portal/release/index.tsx b/src/containers/portal/release/index.tsx index 8e3c0f503..5170341f2 100644 --- a/src/containers/portal/release/index.tsx +++ b/src/containers/portal/release/index.tsx @@ -17,7 +17,7 @@ import PasportCitizenship from '../pasport'; import ActionBarRelease from './ActionBarRelease'; import useCheckRelease, { TotalRelease } from '../hook/useCheckRelease'; import useCheckGift from '../hook/useCheckGift'; -import { PATTERN_CYBER } from 'src/constants/app'; +import { PATTERN_CYBER } from 'src/constants/patterns'; import STEP_INFO from './utils'; import Info from './Info'; diff --git a/src/containers/portal/utilsMsgs.ts b/src/containers/portal/utilsMsgs.ts index 110f2e7e2..6e4e400a2 100644 --- a/src/containers/portal/utilsMsgs.ts +++ b/src/containers/portal/utilsMsgs.ts @@ -1,4 +1,4 @@ -import Soft3MessageFactory from 'src/soft.js/api/msgs'; +import Soft3MessageFactory from 'src/services/soft.js/api/msgs'; import BigNumber from 'bignumber.js'; import { coin } from '@cosmjs/launchpad'; import { CyberClient } from '@cybercongress/cyber-js'; diff --git a/src/containers/sigma/components/cardUi/DetailsBalance/index.jsx b/src/containers/sigma/components/cardUi/DetailsBalance/index.jsx index f86b5f420..c915fe276 100644 --- a/src/containers/sigma/components/cardUi/DetailsBalance/index.jsx +++ b/src/containers/sigma/components/cardUi/DetailsBalance/index.jsx @@ -1,6 +1,6 @@ import BigNumber from 'bignumber.js'; import { useIbcDenom } from 'src/contexts/ibcDenom'; -import { CYBER } from '../../../../../utils/config'; +import { DENOM_LIQUID } from 'src/constants/config'; import { convertAmount } from '../../../../../utils/utils'; import RowItem from './RowItem'; import styles from './styles.module.scss'; @@ -31,7 +31,7 @@ function DetailsBalance({ data }) { key={key} value={value} text={key} - cap={{ amount: cap, denom: CYBER.DENOM_LIQUID_TOKEN }} + cap={{ amount: cap, denom: DENOM_LIQUID }} /> ); })} diff --git a/src/containers/sigma/hooks/useBalanceToken.js b/src/containers/sigma/hooks/useBalanceToken.js index 5273967af..b81a80bb8 100644 --- a/src/containers/sigma/hooks/useBalanceToken.js +++ b/src/containers/sigma/hooks/useBalanceToken.js @@ -1,11 +1,9 @@ import { useEffect, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { useQueryClient } from 'src/contexts/queryClient'; -import { CYBER } from '../../../utils/config'; +import { BASE_DENOM, DENOM_LIQUID } from 'src/constants/config'; import useGetSlots from '../../mint/useGetSlots'; -const { DENOM_CYBER, DENOM_LIQUID_TOKEN } = CYBER; - const initValueResponseFunc = (denom = '', amount = 0) => { return { denom, amount }; }; @@ -19,7 +17,7 @@ const initValueTokens = (denom = '', amount = 0) => { }; const initValueToken = { - [DENOM_LIQUID_TOKEN]: { ...initValueTokens(DENOM_LIQUID_TOKEN, 0) }, + [DENOM_LIQUID]: { ...initValueTokens(DENOM_LIQUID, 0) }, milliampere: { ...initValueTokens('milliampere', 0) }, millivolt: { ...initValueTokens('millivolt', 0) }, }; @@ -76,8 +74,8 @@ function useBalanceToken(address, updateAddress) { const getBalance = async () => { setLoading(true); const initValueTokenAmount = { - [DENOM_LIQUID_TOKEN]: { - ...initValueTokens(DENOM_LIQUID_TOKEN, 0), + [DENOM_LIQUID]: { + ...initValueTokens(DENOM_LIQUID, 0), }, milliampere: { ...initValueTokens('milliampere', 0), @@ -94,7 +92,7 @@ function useBalanceToken(address, updateAddress) { if (getAllBalancesPromise.length > 0) { getAllBalancesPromise.forEach((item) => { const { amount, denom } = item; - if (denom !== DENOM_CYBER) { + if (denom !== BASE_DENOM) { const elementBalancesToken = amount; if ( diff --git a/src/containers/sigma/hooks/useGetBalanceBostrom.ts b/src/containers/sigma/hooks/useGetBalanceBostrom.ts index 0457a9c84..664344e3d 100644 --- a/src/containers/sigma/hooks/useGetBalanceBostrom.ts +++ b/src/containers/sigma/hooks/useGetBalanceBostrom.ts @@ -4,10 +4,10 @@ import _ from 'lodash'; import { useIbcDenom } from 'src/contexts/ibcDenom'; import { useAppData } from 'src/contexts/appData'; import { Nullable } from 'src/types'; +import { BASE_DENOM, DENOM_LIQUID } from 'src/constants/config'; import useGetBalanceMainToken from './useGetBalanceMainToken'; import useBalanceToken from './useBalanceToken'; import { convertAmount } from '../../../utils/utils'; -import { CYBER } from '../../../utils/config'; const usePrevious = (value: any) => { const ref = useRef(); @@ -63,10 +63,10 @@ function useGetBalanceBostrom(address: Nullable) { [key]: { ...data[key], price: { - denom: CYBER.DENOM_LIQUID_TOKEN, + denom: DENOM_LIQUID, amount: price.toNumber(), }, - cap: { denom: CYBER.DENOM_LIQUID_TOKEN, amount: tempCap }, + cap: { denom: DENOM_LIQUID, amount: tempCap }, }, }; }, {}); @@ -90,7 +90,7 @@ function useGetBalanceBostrom(address: Nullable) { if (!loadingMalin && !loadingToken) { let dataResult = {}; const mainToken = { - [CYBER.DENOM_CYBER]: { ...balanceMainToken }, + [BASE_DENOM]: { ...balanceMainToken }, }; const dataResultTemp = { ...mainToken, ...balanceToken }; const tempData = getBalanceMarket(dataResultTemp); diff --git a/src/containers/sigma/hooks/useGetPassportByAddress.ts b/src/containers/sigma/hooks/useGetPassportByAddress.ts index c404b2c71..2a528fa3a 100644 --- a/src/containers/sigma/hooks/useGetPassportByAddress.ts +++ b/src/containers/sigma/hooks/useGetPassportByAddress.ts @@ -1,6 +1,6 @@ import { Citizenship } from 'src/types/citizenship'; import usePassportContract from 'src/features/passport/usePassportContract'; -import { PATTERN_CYBER } from 'src/constants/app'; +import { PATTERN_CYBER } from 'src/constants/patterns'; function useGetPassportByAddress(accounts: any) { let address = diff --git a/src/containers/sigma/hooks/utils.js b/src/containers/sigma/hooks/utils.js index 0c105fd4e..ba17cd30e 100644 --- a/src/containers/sigma/hooks/utils.js +++ b/src/containers/sigma/hooks/utils.js @@ -3,13 +3,11 @@ import { Decimal } from '@cosmjs/math'; import BigNumber from 'bignumber.js'; import { useQuery } from '@tanstack/react-query'; import { getDelegatorDelegations } from 'src/utils/search/utils'; -import { CYBER } from '../../../utils/config'; +import { BECH32_PREFIX_VALOPER, BASE_DENOM } from 'src/constants/config'; import { fromBech32 } from '../../../utils/utils'; -const { DENOM_CYBER } = CYBER; - const initValue = { - denom: DENOM_CYBER, + denom: BASE_DENOM, amount: '0', }; @@ -32,7 +30,7 @@ const getDelegationsAmount = (data) => { delegationsAmount = delegationsAmount.plus(itemDelegation.balance.amount); }); } - return initValueResponseFunc(DENOM_CYBER, delegationsAmount.toString()); + return initValueResponseFunc(BASE_DENOM, delegationsAmount.toString()); }; const getUnbondingAmount = (data) => { @@ -45,7 +43,7 @@ const getUnbondingAmount = (data) => { }); }); } - return initValueResponseFunc(DENOM_CYBER, unbondingAmount.toString()); + return initValueResponseFunc(BASE_DENOM, unbondingAmount.toString()); }; const getRewardsAmount = (data) => { @@ -57,7 +55,7 @@ const getRewardsAmount = (data) => { Decimal.fromAtomics(amount, 18).floor().toString() ); } - return initValueResponseFunc(DENOM_CYBER, rewardsAmount.toString()); + return initValueResponseFunc(BASE_DENOM, rewardsAmount.toString()); }; const getCommissionAmount = (data) => { @@ -70,7 +68,7 @@ const getCommissionAmount = (data) => { Decimal.fromAtomics(amount, 18).floor().toString() ); } - return initValueResponseFunc(DENOM_CYBER, commissionAmount.toString()); + return initValueResponseFunc(BASE_DENOM, commissionAmount.toString()); }; export const useGetBalance = (client, addressBech32) => { @@ -81,7 +79,7 @@ export const useGetBalance = (client, addressBech32) => { async () => { const responsegetBalance = await client.getBalance( addressBech32, - DENOM_CYBER + BASE_DENOM ); const responsedelegatorDelegations = await getDelegatorDelegations( @@ -107,7 +105,7 @@ export const useGetBalance = (client, addressBech32) => { const dataValidatorAddress = fromBech32( addressBech32, - CYBER.BECH32_PREFIX_ACC_ADDR_CYBERVALOPER + BECH32_PREFIX_VALOPER ); const responsevalidatorCommission = await client.validatorCommission( @@ -136,7 +134,7 @@ export const useGetBalance = (client, addressBech32) => { return { ...resultBalance, total: { - denom: DENOM_CYBER, + denom: BASE_DENOM, amount: total, }, }; diff --git a/src/containers/taverna/useGetTweets.ts b/src/containers/taverna/useGetTweets.ts index d771a6f75..b73bae35f 100644 --- a/src/containers/taverna/useGetTweets.ts +++ b/src/containers/taverna/useGetTweets.ts @@ -2,9 +2,10 @@ import { useCallback, useEffect, useState } from 'react'; import useQueueIpfsContent from 'src/hooks/useQueueIpfsContent'; import { Option } from 'src/types'; import { getFollows, getTweet } from '../../utils/search/utils'; -import { CYBER } from '../../utils/config'; -import { PATTERN_CYBER } from 'src/constants/app'; +import { PATTERN_CYBER } from 'src/constants/patterns'; import { fromBech32 } from '../../utils/utils'; +import { CYBER_CONGRESS_ADDRESS } from 'src/constants/app'; +import { BECH32_PREFIX } from 'src/constants/config'; interface Tweet { status: string; @@ -67,8 +68,8 @@ const useGetTweets = (addressActive: Option) => { Number(responseFollows.total_count) === 0 ) { const cyberCongressAddress = fromBech32( - CYBER.CYBER_CONGRESS_ADDRESS, - CYBER.BECH32_PREFIX_ACC_ADDR_CYBER + CYBER_CONGRESS_ADDRESS, + BECH32_PREFIX ); const responseTwit = await getTweet(cyberCongressAddress); diff --git a/src/containers/temple/hooks/getTotalCap.ts b/src/containers/temple/hooks/getTotalCap.ts index d290e11b0..0cf28b0cc 100644 --- a/src/containers/temple/hooks/getTotalCap.ts +++ b/src/containers/temple/hooks/getTotalCap.ts @@ -2,12 +2,12 @@ import BigNumber from 'bignumber.js'; import { useEffect, useState } from 'react'; import { useIbcDenom } from 'src/contexts/ibcDenom'; import { useAppData } from 'src/contexts/appData'; -import { CYBER } from '../../../utils/config'; import { findDenomInTokenList, getDenomHash, getDisplayAmount, } from '../../../utils/utils'; +import { BASE_DENOM } from 'src/constants/config'; function useGetTotalCap() { const { marketData, dataTotalSupply } = useAppData(); @@ -90,9 +90,9 @@ function useGetTotalCap() { const ibcDenomAtom = getDenomHash(path, denomInfo.coinMinimalDenom); if ( Object.prototype.hasOwnProperty.call(marketData, ibcDenomAtom) && - Object.prototype.hasOwnProperty.call(marketData, CYBER.DENOM_CYBER) + Object.prototype.hasOwnProperty.call(marketData, BASE_DENOM) ) { - const priceBoot = new BigNumber(marketData[CYBER.DENOM_CYBER]); + const priceBoot = new BigNumber(marketData[BASE_DENOM]); const priceAtom = new BigNumber(marketData[ibcDenomAtom]); const priceBootForAtom = priceAtom .dividedBy(priceBoot) diff --git a/src/containers/temple/hooks/useAccountCount.js b/src/containers/temple/hooks/useAccountCount.js deleted file mode 100644 index 95a45a19b..000000000 --- a/src/containers/temple/hooks/useAccountCount.js +++ /dev/null @@ -1,66 +0,0 @@ -import { useQuery } from '@tanstack/react-query'; -import BigNumber from 'bignumber.js'; -import request from 'graphql-request'; -import { gql } from '@apollo/client'; - -import { useEffect, useState } from 'react'; -import { CYBER } from '../../../utils/config'; - -const GET_CHARACTERS = gql` - query MyQuery { - account_aggregate { - aggregate { - count(columns: address) - } - } - } -`; - -function useAccountCount() { - const keyQuery = 'accountCount'; - const [changeTimeAmount, setChangeTimeAmount] = useState({ - amount: 0, - time: 0, - }); - const { data, status } = useQuery({ - queryKey: [keyQuery], - queryFn: async () => { - let response = { accountCount: 0, timestamp: '' }; - const res = await request(CYBER.CYBER_INDEX_HTTPS, GET_CHARACTERS); - const d = new Date(); - - response = { - accountCount: res.account_aggregate.aggregate.count, - timestamp: d, - }; - - return response; - }, - refetchInterval: 1000 * 60 * 3, - }); - - useEffect(() => { - if (data && data !== null) { - const lastgraphStatsLs = localStorage.getItem(keyQuery); - if (lastgraphStatsLs !== null) { - const oldData = JSON.parse(lastgraphStatsLs); - const timeChange = - Date.parse(data.timestamp) - Date.parse(oldData.timestamp); - const amountChange = new BigNumber(data.accountCount) - .minus(oldData.accountCount) - .toNumber(); - if (timeChange > 0 && amountChange > 0) { - setChangeTimeAmount({ - time: timeChange, - amount: amountChange, - }); - } - } - localStorage.setItem(keyQuery, JSON.stringify(data)); - } - }, [data]); - - return { data, changeTimeAmount, status }; -} - -export default useAccountCount; diff --git a/src/containers/temple/hooks/useAccountCount.ts b/src/containers/temple/hooks/useAccountCount.ts new file mode 100644 index 000000000..75f1ab4ff --- /dev/null +++ b/src/containers/temple/hooks/useAccountCount.ts @@ -0,0 +1,45 @@ +import BigNumber from 'bignumber.js'; +import { useEffect, useState } from 'react'; +import { useAccountCountQuery } from 'src/generated/graphql'; + +function useAccountCount() { + const keyQuery = 'accountCount'; + const [changeTimeAmount, setChangeTimeAmount] = useState({ + amount: 0, + time: 0, + }); + const { data } = useAccountCountQuery({ pollInterval: 1000 * 60 * 3 }); + + useEffect(() => { + if (data) { + const timestamp = new Date(); + const lastgraphStatsLs = localStorage.getItem(keyQuery); + if (lastgraphStatsLs !== null) { + const oldData = JSON.parse(lastgraphStatsLs); + const timeChange = + Date.parse(timestamp) - Date.parse(oldData.timestamp); + const amountChange = new BigNumber( + data.account_aggregate.aggregate?.count || 0 + ) + .minus(oldData.accountCount) + .toNumber(); + if (timeChange > 0 && amountChange > 0) { + setChangeTimeAmount({ + time: timeChange, + amount: amountChange, + }); + } + } + localStorage.setItem(keyQuery, JSON.stringify(data)); + } + }, [data]); + + return { + data: { + accountCount: data?.account_aggregate.aggregate?.count || 0, + }, + changeTimeAmount, + }; +} + +export default useAccountCount; diff --git a/src/containers/temple/hooks/useGetContract.js b/src/containers/temple/hooks/useGetContract.js deleted file mode 100644 index db8bcefab..000000000 --- a/src/containers/temple/hooks/useGetContract.js +++ /dev/null @@ -1,66 +0,0 @@ -import { useQuery } from '@tanstack/react-query'; -import BigNumber from 'bignumber.js'; -import request from 'graphql-request'; -import { gql } from '@apollo/client'; - -import { useEffect, useState } from 'react'; -import { CYBER } from '../../../utils/config'; - -const GET_CHARACTERS = gql` - query MyQuery { - contracts_aggregate { - aggregate { - count - } - } - } -`; - -function useContractsCount() { - const keyQuery = 'contractsCount'; - const [changeTimeAmount, setChangeTimeAmount] = useState({ - amount: 0, - time: 0, - }); - const { data, status } = useQuery({ - queryKey: [keyQuery], - queryFn: async () => { - let response = { contractsCount: 0, timestamp: '' }; - const res = await request(CYBER.CYBER_INDEX_HTTPS, GET_CHARACTERS); - const d = new Date(); - - response = { - contractsCount: res.contracts_aggregate.aggregate.count, - timestamp: d, - }; - - return response; - }, - refetchInterval: 1000 * 60 * 3, - }); - - useEffect(() => { - if (data && data !== null) { - const lastgraphStatsLs = localStorage.getItem(keyQuery); - if (lastgraphStatsLs !== null) { - const oldData = JSON.parse(lastgraphStatsLs); - const timeChange = - Date.parse(data.timestamp) - Date.parse(oldData.timestamp); - const amountChange = new BigNumber(data.contractsCount) - .minus(oldData.contractsCount) - .toNumber(); - if (timeChange > 0 && amountChange > 0) { - setChangeTimeAmount({ - time: timeChange, - amount: amountChange, - }); - } - } - localStorage.setItem(keyQuery, JSON.stringify(data)); - } - }, [data]); - - return { data, changeTimeAmount, status }; -} - -export default useContractsCount; diff --git a/src/containers/temple/hooks/useGetContract.ts b/src/containers/temple/hooks/useGetContract.ts new file mode 100644 index 000000000..2c21262b4 --- /dev/null +++ b/src/containers/temple/hooks/useGetContract.ts @@ -0,0 +1,46 @@ +import BigNumber from 'bignumber.js'; +import { useEffect, useState } from 'react'; +import { useContractsCountQuery } from 'src/generated/graphql'; + + +function useContractsCount() { + const keyQuery = 'contractsCount'; + const [changeTimeAmount, setChangeTimeAmount] = useState({ + amount: 0, + time: 0, + }); + const { data } = useContractsCountQuery({ pollInterval: 1000 * 60 * 3 }); + + useEffect(() => { + if (data) { + const timestamp = new Date(); + const lastgraphStatsLs = localStorage.getItem(keyQuery); + if (lastgraphStatsLs !== null) { + const oldData = JSON.parse(lastgraphStatsLs); + const timeChange = + Date.parse(timestamp) - Date.parse(oldData.timestamp); + const amountChange = new BigNumber( + data.contracts_aggregate.aggregate?.count || 0 + ) + .minus(oldData.contractsCount) + .toNumber(); + if (timeChange > 0 && amountChange > 0) { + setChangeTimeAmount({ + time: timeChange, + amount: amountChange, + }); + } + } + localStorage.setItem(keyQuery, JSON.stringify(data)); + } + }, [data]); + + return { + data: { + contractsCount: data?.contracts_aggregate.aggregate?.count || 0, + }, + changeTimeAmount, + }; +} + +export default useContractsCount; diff --git a/src/containers/temple/hooks/useGetNegentropy.ts b/src/containers/temple/hooks/useGetNegentropy.ts index b28a671f7..2254a8987 100644 --- a/src/containers/temple/hooks/useGetNegentropy.ts +++ b/src/containers/temple/hooks/useGetNegentropy.ts @@ -1,20 +1,16 @@ import { useEffect, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import BigNumber from 'bignumber.js'; -import axios from 'axios'; -import { CYBER } from '../../../utils/config'; +import { LCD_URL } from 'src/constants/config'; -const getNegentropy = async () => { - try { - const response = await axios({ - method: 'get', - url: `${CYBER.CYBER_NODE_URL_LCD}/rank/negentropy`, - }); +import { Cyber as CyberLcdApi } from 'src/generated/Cyber'; +import { dataOrNull } from 'src/utils/axios'; + +const lcdCyberApi = new CyberLcdApi({ baseURL: LCD_URL }); - return response.data; - } catch (e) { - return null; - } +const getNegentropy = async () => { + const response = await lcdCyberApi.negentropy(); + return dataOrNull(response); }; const keyQuery = 'negentropy'; @@ -28,32 +24,19 @@ function useGetNegentropy(refetchInterval: number | undefined) { const { data, status } = useQuery({ queryKey: [keyQuery], queryFn: async () => { - let response = { - negentropy: 0, - timestamp: '', - }; - - const responseNegentropy = await getNegentropy(); - - if (responseNegentropy && responseNegentropy !== null) { - const { result } = responseNegentropy; - const d = new Date(); - response = { negentropy: result.negentropy, timestamp: d }; - } - - return response; + const result = await getNegentropy(); + return { negentropy: result?.negentropy || 0, timestamp: Date.now() }; }, refetchInterval, }); useEffect(() => { - if (data && data !== null) { + if (data) { const lastgraphStatsLs = localStorage.getItem(keyQuery); if (lastgraphStatsLs !== null) { const oldData = JSON.parse(lastgraphStatsLs); - const timeChange = - Date.parse(data.timestamp) - Date.parse(oldData.timestamp); - const amountChange = new BigNumber(data.negentropy) + const timeChange = data!.timestamp - oldData.timestamp; + const amountChange = new BigNumber(data!.negentropy) .minus(oldData.negentropy) .toNumber(); if (timeChange > 0 && amountChange > 0) { diff --git a/src/containers/temple/pages/play/PlayBanerContent.jsx b/src/containers/temple/pages/play/PlayBanerContent.jsx index 22a00903d..1a8485296 100644 --- a/src/containers/temple/pages/play/PlayBanerContent.jsx +++ b/src/containers/temple/pages/play/PlayBanerContent.jsx @@ -144,7 +144,7 @@ function PlayBanerContent() { }, [dataGetNegentropy]); useEffect(() => { - if (dataAccountCount.status === 'success' && dataAccountCount.data) { + if (dataAccountCount.data) { slideDataRef.current = { ...slideDataRef.current, everGrowing: { @@ -160,7 +160,7 @@ function PlayBanerContent() { }, [dataAccountCount]); useEffect(() => { - if (dataContractsCount.status === 'success' && dataContractsCount.data) { + if (dataContractsCount.data) { slideDataRef.current = { ...slideDataRef.current, autonomousSemantic: { diff --git a/src/containers/txs/Activites.jsx b/src/containers/txs/Activites.jsx index 2033a5120..4b7037f14 100644 --- a/src/containers/txs/Activites.jsx +++ b/src/containers/txs/Activites.jsx @@ -4,8 +4,8 @@ import { fromBase64, fromUtf8 } from '@cosmjs/encoding'; import ReactJson from 'react-json-view'; import { Account, MsgType, DenomArr, AmountDenom, Cid } from 'src/components'; import { formatNumber } from '../../utils/search/utils'; -import { CYBER } from '../../utils/config'; import { timeSince } from '../../utils/utils'; +import { BASE_DENOM } from 'src/constants/config'; const S_TO_MS = 1 * 10 ** 3; @@ -256,7 +256,7 @@ function Activites({ msg }) { /> ); }) - : `0 ${CYBER.DENOM_CYBER.toUpperCase()}` + : `0 ${BASE_DENOM.toUpperCase()}` } /> @@ -283,7 +283,7 @@ function Activites({ msg }) { @@ -514,7 +514,7 @@ function Activites({ msg }) { amount.amount )} ${amount.denom.toUpperCase()}`; }) - : `0 ${CYBER.DENOM_CYBER.toUpperCase()}` + : `0 ${BASE_DENOM.toUpperCase()}` } /> @@ -603,7 +603,7 @@ function Activites({ msg }) { amount.amount )} ${amount.denom.toUpperCase()}`; }) - : `0 ${CYBER.DENOM_CYBER.toUpperCase()}` + : `0 ${BASE_DENOM.toUpperCase()}` } /> @@ -649,7 +649,7 @@ function Activites({ msg }) { amount.amount )} ${amount.denom.toUpperCase()}`; }) - : `0 ${CYBER.DENOM_CYBER.toUpperCase()}` + : `0 ${BASE_DENOM.toUpperCase()}` } /> diff --git a/src/containers/txs/graphql/transactions.graphql b/src/containers/txs/graphql/transactions.graphql new file mode 100644 index 000000000..443df543e --- /dev/null +++ b/src/containers/txs/graphql/transactions.graphql @@ -0,0 +1,8 @@ +subscription Transactions { + transaction(offset: 0, limit: 200, order_by: { height: desc }) { + success + messages + height + hash + } +} diff --git a/src/containers/txs/index.tsx b/src/containers/txs/index.tsx index 94e1850e8..9df1d348e 100644 --- a/src/containers/txs/index.tsx +++ b/src/containers/txs/index.tsx @@ -1,31 +1,19 @@ -import { gql } from '@apollo/client'; - import { v4 as uuidv4 } from 'uuid'; -import { useSubscription } from '@apollo/client'; import { Pane, TableEv as Table } from '@cybercongress/gravity'; import { Link } from 'react-router-dom'; +import { useTransactionsSubscription } from 'src/generated/graphql'; + import { trimString, formatNumber } from '../../utils/utils'; import { Loading, MsgType, TextTable } from '../../components'; -const statusTrueImg = require('../../image/ionicons_svg_ios-checkmark-circle.svg'); -const statusFalseImg = require('../../image/ionicons_svg_ios-close-circle.svg'); - -const GET_CHARACTERS = gql` - subscription Query { - transaction(offset: 0, limit: 200, order_by: { height: desc }) { - success - messages - height - hash - } - } -`; +import statusTrueImg from '../../image/ionicons_svg_ios-checkmark-circle.svg'; +import statusFalseImg from '../../image/ionicons_svg_ios-close-circle.svg'; function Txs() { - const { loading, error, data } = useSubscription(GET_CHARACTERS); + const { loading, error, data } = useTransactionsSubscription(); function renderRows() { - return data.transaction.map((item, index) => ( + return (data?.transaction || []).map((item, index) => ( - ) : data?.transaction.length > 0 ? ( + ) : data?.transaction.length ? ( { try { const response = await axios({ method: 'get', - url: `${CYBER.CYBER_NODE_URL_LCD}/cosmos/tx/v1beta1/txs/${txs}`, + url: `${LCD_URL}/cosmos/tx/v1beta1/txs/${txs}`, }); return response.data; } catch (e) { diff --git a/src/containers/validator/UptimeHook.jsx b/src/containers/validator/UptimeHook.jsx index 96ea42a72..a75d7901d 100644 --- a/src/containers/validator/UptimeHook.jsx +++ b/src/containers/validator/UptimeHook.jsx @@ -1,53 +1,29 @@ -import { useQuery, gql } from '@apollo/client'; +import { useUptimeByAddressQuery } from 'src/generated/graphql'; +import { INFINITY } from 'src/constants/app'; +import { BECH32_PREFIX_VAL_CONS } from 'src/constants/config'; +import BigNumber from 'bignumber.js'; import { Dots } from '../../components'; -import { formatNumber, fromBech32 } from '../../utils/utils'; +import { fromBech32 } from '../../utils/utils'; function useUptime({ accountUser }) { - try { - const GET_CHARACTERS = gql` - query uptime { - uptime(where: {consensus_address: {_eq: "${fromBech32( - accountUser, - 'bostromvalcons' - )}"}}) { - uptime - } - - } - `; - - // eslint-disable-next-line react-hooks/rules-of-hooks - const { loading, data } = useQuery(GET_CHARACTERS); - - if (loading) { - return ; - } - - let uptime = 0; - - if (data) { - const { pre_commit, pre_commit_aggregate, block_aggregate } = data; - - if ( - pre_commit && - pre_commit_aggregate && - block_aggregate && - Object.keys(pre_commit).length !== 0 && - Object.keys(pre_commit_aggregate).length !== 0 && - Object.keys(block_aggregate).length !== 0 - ) { - const thisBlock = block_aggregate.nodes[0].height; - const firstPreCommit = pre_commit[0].validator.blocks[0].height; - const countPreCommit = pre_commit_aggregate.aggregate.count; - uptime = countPreCommit / (thisBlock - firstPreCommit); - } - } + const { loading, data, error } = useUptimeByAddressQuery({ + variables: { + address: `${fromBech32(accountUser, BECH32_PREFIX_VAL_CONS)}`, + }, + }); + + if (loading) { + return ; + } - return `${formatNumber(uptime * 100, 2)} %`; - } catch (error) { - console.warn(error); - return '∞'; + if (error) { + return INFINITY; } + + return `${new BigNumber(data.uptime) + .shiftedBy(2) + .dp(2, BigNumber.ROUND_FLOOR) + .toString()} %`; } export default useUptime; diff --git a/src/containers/validator/delegated.jsx b/src/containers/validator/delegated.jsx index 1dadce4a9..969515669 100644 --- a/src/containers/validator/delegated.jsx +++ b/src/containers/validator/delegated.jsx @@ -1,10 +1,10 @@ import { Pane, Text } from '@cybercongress/gravity'; import { Link } from 'react-router-dom'; -import { CardTemplate, FormatNumber } from '../../components'; +import Display from 'src/components/containerGradient/Display/Display'; +import { BASE_DENOM, DIVISOR_CYBER_G } from 'src/constants/config'; +import { FormatNumber } from '../../components'; import { formatNumber } from '../../utils/utils'; -import { CYBER } from '../../utils/config'; import KeybaseCheck from './keybaseCheck'; -import Display from 'src/components/containerGradient/Display/Display'; const dateFormat = require('dateformat'); @@ -89,13 +89,11 @@ function Delegated({ data, marginBottom }) { title="Delegator Shares" value={`${formatNumber( Math.floor(delegatorShares) - )} ${CYBER.DENOM_CYBER.toUpperCase()}`} + )} ${BASE_DENOM.toUpperCase()}`} /> {formatNumber(selfPercent, 2)}% ( ) diff --git a/src/containers/validator/leadership.jsx b/src/containers/validator/leadership.jsx deleted file mode 100644 index 0dd5ea074..000000000 --- a/src/containers/validator/leadership.jsx +++ /dev/null @@ -1,66 +0,0 @@ -import { gql } from '@apollo/client'; - -import { useSubscription } from '@apollo/client'; -import TableTxs from '../../pages/robot/_refactor/account/component/tableTxs'; -import { Dots } from '../../components'; -import Loader2 from 'src/components/ui/Loader2'; - -const typeTx = `["cosmos.gov.v1beta1.MsgDeposit", "cosmos.gov.v1beta1.MsgVote", "cosmos.gov.v1beta1.MsgSubmitProposal" ]`; - -function Leadership({ accountUser }) { - const GET_CHARACTERS = gql` - subscription MyQuery { - _transaction( - where: { - _and: [ - { - type: { - _in: ${typeTx} - } - } - { - _or: [ - { - subject1: { - _eq: "${accountUser}" - } - } - { - subject2: { - _eq: "${accountUser}" - } - } - ] - } - ] - } - order_by: { height: desc } - ) { - hash - type - success - height - messages - } - } - `; - const { loading, error, data } = useSubscription(GET_CHARACTERS); - - const { _transaction: transaction } = data || {}; - - return ( -
- {loading ? ( - - ) : transaction ? ( - - ) : error ? ( -

{error.message}

- ) : ( - 'No data' - )} -
- ); -} - -export default Leadership; diff --git a/src/containers/validator/leadership.tsx b/src/containers/validator/leadership.tsx new file mode 100644 index 000000000..ad4bf448d --- /dev/null +++ b/src/containers/validator/leadership.tsx @@ -0,0 +1,60 @@ + +import TableTxs from '../../pages/robot/_refactor/account/component/tableTxs'; +import Loader2 from 'src/components/ui/Loader2'; +import { useLeadershipQuery } from 'src/generated/graphql'; +import { useState } from 'react'; + +const LIMIT = 10; + +function Leadership({ accountUser }: { accountUser: string }) { + const [hasMore, setHasMore] = useState(true); + const { loading, error, data, fetchMore } = useLeadershipQuery({ + variables: { + limit: LIMIT, + offset: 0, + valAddress: accountUser, + }, + }); + + const { _transaction: transaction } = data || {}; + + const fetchNextData = () => { + fetchMore({ + variables: { + offset: data?._transaction.length, + }, + updateQuery: (prev, { fetchMoreResult }) => { + if (!fetchMoreResult) { + return prev; + } + setHasMore(fetchMoreResult._transaction.length > 0); + + return { + ...prev, + _transaction: [...prev._transaction, ...fetchMoreResult._transaction], + }; + }, + }); + }; + + return ( +
+ {loading ? ( + + ) : transaction ? ( + + ) : error ? ( +

{error.message}

+ ) : ( + 'No data' + )} +
+ ); +} + +export default Leadership; diff --git a/src/containers/validator/rumors.jsx b/src/containers/validator/rumors.jsx deleted file mode 100644 index f11bec9e8..000000000 --- a/src/containers/validator/rumors.jsx +++ /dev/null @@ -1,61 +0,0 @@ -import { gql } from '@apollo/client'; - -import { useSubscription } from '@apollo/client'; -import TableTxs from '../../pages/robot/_refactor/account/component/tableTxs'; -import { Loading, NoItems } from '../../components'; - -function Rumors({ accountUser }) { - const GET_CHARACTERS = gql` - subscription getRumors { - transaction( - order_by: { height: desc } - where: { - _and: [ - { - messagesByTransactionHash: { - type: { - _in: [ - "cosmos.staking.v1beta1.MsgDelegate" - "cosmos.staking.v1beta1.MsgUndelegate" - ] - } - } - } - { - messagesByTransactionHash: { - value: { - _contains: { - validator_address: "${accountUser}" - } - } - } - } - ] - } - ) { - messages - success - hash - height - } - } - `; - - const { loading, error, data: dataTxs } = useSubscription(GET_CHARACTERS); - - return ( -
- {loading ? ( - - ) : dataTxs ? ( - - ) : error ? ( - <>{JSON.stringify(error)} - ) : ( - - )} -
- ); -} - -export default Rumors; diff --git a/src/containers/validator/rumors.tsx b/src/containers/validator/rumors.tsx new file mode 100644 index 000000000..63a95181b --- /dev/null +++ b/src/containers/validator/rumors.tsx @@ -0,0 +1,63 @@ +import { useGetRumorsQuery } from 'src/generated/graphql'; +import { useState } from 'react'; +import TableTxs from '../../pages/robot/_refactor/account/component/tableTxs'; +import { Loading, NoItems } from '../../components'; + +const LIMIT = 10; + +function Rumors({ accountUser }: { accountUser: string }) { + const [hasMore, setHasMore] = useState(true); + const { + loading, + error, + data: dataTxs, + fetchMore, + } = useGetRumorsQuery({ + variables: { + limit: LIMIT, + offset: 0, + valAddress: accountUser, + }, + }); + + const fetchNextData = () => { + fetchMore({ + variables: { + offset: dataTxs?.transaction.length, + }, + updateQuery: (prev, { fetchMoreResult }) => { + if (!fetchMoreResult) { + return prev; + } + setHasMore(fetchMoreResult.transaction.length > 0); + + return { + ...prev, + transaction: [...prev.transaction, ...fetchMoreResult.transaction], + }; + }, + }); + }; + + return ( +
+ {loading ? ( + + ) : dataTxs ? ( + + ) : error ? ( + <>{JSON.stringify(error)} + ) : ( + + )} +
+ ); +} + +export default Rumors; diff --git a/src/containers/warp/ActionBar.tsx b/src/containers/warp/ActionBar.tsx index 5851370f2..7fbe800c0 100644 --- a/src/containers/warp/ActionBar.tsx +++ b/src/containers/warp/ActionBar.tsx @@ -9,8 +9,9 @@ import { useSelector } from 'react-redux'; import { Coin } from '@cosmjs/launchpad'; import { useIbcDenom } from 'src/contexts/ibcDenom'; import { RootState } from 'src/redux/store'; +import { CHAIN_ID, DEFAULT_GAS_LIMITS } from 'src/constants/config'; import { Account, ActionBar as ActionBarCenter } from '../../components'; -import { CYBER, DEFAULT_GAS_LIMITS, LEDGER } from '../../utils/config'; +import { LEDGER } from '../../utils/config'; import { convertAmountReverce, selectNetworkImg } from '../../utils/utils'; import ActionBarStaps from './actionBarSteps'; @@ -301,8 +302,8 @@ function ActionBar({ stateActionBar }: Props) { price 1 000 000 000 {CYBER.CHAIN_ID}
), diff --git a/src/containers/warp/Warp.tsx b/src/containers/warp/Warp.tsx index 31b0b3a42..bf20bd761 100644 --- a/src/containers/warp/Warp.tsx +++ b/src/containers/warp/Warp.tsx @@ -16,7 +16,6 @@ import usePoolListInterval from 'src/hooks/usePoolListInterval'; import { useIbcDenom } from 'src/contexts/ibcDenom'; import { RootState } from 'src/redux/store'; import useGetBalances from 'src/hooks/getBalances'; -import { CYBER } from '../../utils/config'; import useSetActiveAddress from '../../hooks/useSetActiveAddress'; import { reduceBalances, getDisplayAmountReverce } from '../../utils/utils'; import TabList from './components/tabList'; @@ -32,9 +31,10 @@ import { calculateCounterPairAmount, } from './utils'; import { useAdviser } from 'src/features/adviser/context'; +import { BASE_DENOM, DENOM_LIQUID } from 'src/constants/config'; -const tokenADefaultValue = CYBER.DENOM_CYBER; -const tokenBDefaultValue = CYBER.DENOM_LIQUID_TOKEN; +const tokenADefaultValue = BASE_DENOM; +const tokenBDefaultValue = DENOM_LIQUID; function Warp() { const queryClient = useQueryClient(); @@ -216,7 +216,7 @@ function Warp() { exceeded = false; } - //valid add-liquidity in empty pool + // valid add-liquidity in empty pool if ( tab === 'add-liquidity' && isEmptyPool && diff --git a/src/containers/warp/pool/InfoPool.tsx b/src/containers/warp/pool/InfoPool.tsx index 1cef08fb6..e25f7208b 100644 --- a/src/containers/warp/pool/InfoPool.tsx +++ b/src/containers/warp/pool/InfoPool.tsx @@ -1,6 +1,6 @@ import { Coin } from '@cosmjs/launchpad'; import { ContainerGradientText, FormatNumberTokens } from 'src/components'; -import { CYBER } from '../../../utils/config'; +import { DENOM_LIQUID } from 'src/constants/config'; import styles from './styles.module.scss'; type Props = { @@ -17,7 +17,7 @@ function PoolsInfo({ totalCap, myCap, useMyProcent, vol24 }: Props) {
@@ -29,7 +29,7 @@ function PoolsInfo({ totalCap, myCap, useMyProcent, vol24 }: Props) {
@@ -44,7 +44,7 @@ function PoolsInfo({ totalCap, myCap, useMyProcent, vol24 }: Props) {
Volume 24h
diff --git a/src/containers/warp/pool/TitlePoolCard.tsx b/src/containers/warp/pool/TitlePoolCard.tsx index 375e96cca..ac1be9b67 100644 --- a/src/containers/warp/pool/TitlePoolCard.tsx +++ b/src/containers/warp/pool/TitlePoolCard.tsx @@ -1,6 +1,6 @@ import { Pool } from '@cybercongress/cyber-js/build/codec/tendermint/liquidity/v1beta1/liquidity'; import { DenomArr, FormatNumberTokens } from 'src/components'; -import { CYBER } from '../../../utils/config'; +import { DENOM_LIQUID } from 'src/constants/config'; import styles from './styles.module.scss'; type TitlePoolPool = { @@ -28,7 +28,7 @@ function TitlePool({ pool, totalCap, useInactive }: TitlePoolPool) { {totalCap !== undefined && ( )} diff --git a/src/containers/warp/pool/pollItems.tsx b/src/containers/warp/pool/pollItems.tsx index 685359b48..032283db9 100644 --- a/src/containers/warp/pool/pollItems.tsx +++ b/src/containers/warp/pool/pollItems.tsx @@ -4,7 +4,7 @@ import { Link } from 'react-router-dom'; import { useIbcDenom } from 'src/contexts/ibcDenom'; import { useAppData } from 'src/contexts/appData'; import { DenomArr, FormatNumberTokens } from 'src/components'; -import { CYBER } from '../../../utils/config'; +import { DENOM_LIQUID } from 'src/constants/config'; import { replaceSlash } from '../../../utils/utils'; function PoolItemsList({ assets, token }) { @@ -75,12 +75,12 @@ function PoolItemsList({ assets, token }) { ); diff --git a/src/containers/wasm/codes/actionBar.jsx b/src/containers/wasm/codes/actionBar.jsx index a2e376543..2589466f0 100644 --- a/src/containers/wasm/codes/actionBar.jsx +++ b/src/containers/wasm/codes/actionBar.jsx @@ -1,10 +1,12 @@ /* eslint-disable jsx-a11y/control-has-associated-label */ import { useEffect, useState, useRef } from 'react'; import { ActionBar as ActionBarContainer, Pane } from '@cybercongress/gravity'; -import { GasPrice } from '@cosmjs/launchpad'; import { useSigningClient } from 'src/contexts/signerClient'; -import txs from '../../../utils/txs'; -import { CYBER, LEDGER } from '../../../utils/config'; +import Button from 'src/components/btnGrd'; +import AddFileButton from 'src/components/buttons/AddFile/AddFile'; +import Soft3MessageFactory from 'src/services/soft.js/api/msgs'; +import { MEMO_KEPLR } from 'src/constants/config'; +import { getTxs } from '../../../utils/search/utils'; import { ActionBarContentText, Dots, @@ -13,12 +15,7 @@ import { TransactionError, Account, } from '../../../components'; -import { getTxs } from '../../../utils/search/utils'; -import Button from 'src/components/btnGrd'; -import AddFileButton from 'src/components/buttons/AddFile/AddFile'; -import Soft3MessageFactory from 'src/soft.js/api/msgs'; - -const gasPrice = GasPrice.fromString('0.001boot'); +import { LEDGER } from '../../../utils/config'; const { STAGE_INIT, @@ -78,7 +75,7 @@ function ActionBar({ updateFnc, addressActive }) { address, wasmBytes, Soft3MessageFactory.fee(2), - CYBER.MEMO_KEPLR + MEMO_KEPLR ); if (response.code === 0) { setTxHash(response.transactionHash); diff --git a/src/containers/wasm/contract/DashboardPage.jsx b/src/containers/wasm/contract/DashboardPage.tsx similarity index 85% rename from src/containers/wasm/contract/DashboardPage.jsx rename to src/containers/wasm/contract/DashboardPage.tsx index 231d07d6c..f08789950 100644 --- a/src/containers/wasm/contract/DashboardPage.jsx +++ b/src/containers/wasm/contract/DashboardPage.tsx @@ -1,47 +1,23 @@ import { useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; -import { useQuery, gql } from '@apollo/client'; import { useQueryClient } from 'src/contexts/queryClient'; +import { BASE_DENOM } from 'src/constants/config'; +import { useWasmDashboardPageQuery } from 'src/generated/graphql'; import { formatNumber } from '../../../utils/utils'; import { CardStatisics, Dots } from '../../../components'; import { ContainerCardStatisics, ContainerCol } from '../ui/ui'; import ContractTable from './ContractTable'; -import { CYBER } from '../../../utils/config'; const PAGE_SIZE = 50; -const GET_CHARACTERS = gql` - query MyQuery($offset: Int) { - contracts(limit: 50, offset: $offset, order_by: { tx: desc }) { - address - admin - code_id - creator - fees - gas - label - tx - } - contracts_aggregate { - aggregate { - sum { - gas - fees - tx - } - count(columns: address) - } - } - } -`; - const useGetContracts = (offset) => { const [dataContracts, setDataContracts] = useState([]); const [dataAggregate, setDataAggregate] = useState(null); - const { loading, data } = useQuery(GET_CHARACTERS, { + const { loading, data } = useWasmDashboardPageQuery({ variables: { offset: offset * PAGE_SIZE, + limit: PAGE_SIZE, }, }); @@ -104,7 +80,7 @@ function DashboardPage() { } /> { const getBalance = async (client, contractAddress, setBalance) => { try { - const response = await client.getBalance( - contractAddress, - CYBER.DENOM_CYBER - ); + const response = await client.getBalance(contractAddress, BASE_DENOM); if (response !== null) { setBalance(response); } diff --git a/src/containers/wasm/contract/renderAbi/RenderAbiExecute.jsx b/src/containers/wasm/contract/renderAbi/RenderAbiExecute.jsx index 8dd76ff8f..69632dcdc 100644 --- a/src/containers/wasm/contract/renderAbi/RenderAbiExecute.jsx +++ b/src/containers/wasm/contract/renderAbi/RenderAbiExecute.jsx @@ -1,15 +1,11 @@ import { useState, useEffect } from 'react'; -import { GasPrice } from '@cosmjs/launchpad'; import { useQueryClient } from 'src/contexts/queryClient'; import { useSigningClient } from 'src/contexts/signerClient'; -import txs from '../../../../utils/txs'; -import { CYBER } from '../../../../utils/config'; import JsonSchemaParse from './JsonSchemaParse'; -import Soft3MessageFactory from 'src/soft.js/api/msgs'; +import Soft3MessageFactory from 'src/services/soft.js/api/msgs'; +import { MEMO_KEPLR } from 'src/constants/config'; -const gasPrice = GasPrice.fromString('0.001boot'); - -// const coinsPlaceholder = [{ denom: CYBER.DENOM_CYBER, amount: '1' }]; +// const coinsPlaceholder = [{ denom: BASE_DENOM, amount: '1' }]; function RenderAbiExecute({ contractAddress, schema, updateFnc }) { const queryClient = useQueryClient(); @@ -80,7 +76,7 @@ function RenderAbiExecute({ contractAddress, schema, updateFnc }) { contractAddress, formData, Soft3MessageFactory.fee(2), - CYBER.MEMO_KEPLR + MEMO_KEPLR // coinsPlaceholder ); console.log(`executeResponseResult`, executeResponseResult); diff --git a/src/contexts/backend/backend.tsx b/src/contexts/backend/backend.tsx index 2e1034cf5..c2e2e9473 100644 --- a/src/contexts/backend/backend.tsx +++ b/src/contexts/backend/backend.tsx @@ -1,4 +1,10 @@ -import React, { useContext, useEffect, useMemo, useState } from 'react'; +import React, { + useCallback, + useContext, + useEffect, + useMemo, + useState, +} from 'react'; import { useAppDispatch, useAppSelector } from 'src/redux/hooks'; import { proxy, Remote } from 'comlink'; import { backgroundWorkerInstance } from 'src/services/backend/workers/background/service'; @@ -8,14 +14,17 @@ import RxBroadcastChannelListener from 'src/services/backend/channels/RxBroadcas import { CybIpfsNode } from 'src/services/ipfs/ipfs'; import { getIpfsOpts } from 'src/services/ipfs/config'; import { selectCurrentAddress } from 'src/redux/features/pocket'; -import DbApiWrapper from 'src/services/backend/services/dataSource/indexedDb/dbApiWrapper'; +import DbApiWrapper from 'src/services/backend/services/DbApi/DbApi'; import { CozoDbWorker } from 'src/services/backend/workers/db/worker'; import { BackgroundWorker } from 'src/services/backend/workers/background/worker'; -import { SenseApi, createSenseApi } from './services/senseApi'; + import { SyncEntryName } from 'src/services/backend/types/services'; -// import BroadcastChannelListener from 'src/services/backend/channels/BroadcastChannelListener'; import { DB_NAME } from 'src/services/CozoDb/cozoDb'; import { RESET_SYNC_STATE_ACTION_NAME } from 'src/redux/reducers/backend'; +import BroadcastChannelSender from 'src/services/backend/channels/BroadcastChannelSender'; +// import BroadcastChannelListener from 'src/services/backend/channels/BroadcastChannelListener'; + +import { SenseApi, createSenseApi } from './services/senseApi'; const setupStoragePersistence = async () => { let isPersistedStorage = await navigator.storage.persisted(); @@ -72,6 +81,7 @@ window.cyb.db = { }; // const dbApi = new DbApiWrapper(); +const bcSender = new BroadcastChannelSender(); function BackendProvider({ children }: { children: React.ReactNode }) { const dispatch = useAppDispatch(); @@ -120,6 +130,31 @@ function BackendProvider({ children }: { children: React.ReactNode }) { return null; }, [isDbInitialized, dbApi, myAddress, followings]); + const createDbApi = useCallback(() => { + const dbApi = new DbApiWrapper(); + + dbApi.init(proxy(cozoDbWorkerInstance)); + setDbApi(dbApi); + return dbApi; + }, []); + + const loadIpfs = async () => { + const ipfsOpts = getIpfsOpts(); + await backgroundWorkerInstance.ipfsApi.stop(); + console.time('🔋 Ipfs started.'); + + await backgroundWorkerInstance.ipfsApi + .start(ipfsOpts) + .then(() => { + setIpfsError(null); + console.timeEnd('🔋 Ipfs started.'); + }) + .catch((err) => { + setIpfsError(err); + console.log(`☠️ Ipfs error: ${err}`); + }); + }; + useEffect(() => { // eslint-disable-next-line @typescript-eslint/no-unused-vars // const channel = new BroadcastChannelListener((msg) => { @@ -128,6 +163,18 @@ function BackendProvider({ children }: { children: React.ReactNode }) { // }); const channel = new RxBroadcastChannelListener(dispatch); + const loadCozoDb = async () => { + console.time('🔋 CozoDb worker started.'); + await cozoDbWorkerInstance + .init() + .then(async () => { + const dbApi = createDbApi(); + // pass dbApi into background worker + await backgroundWorkerInstance.init(proxy(dbApi)); + }) + .then(() => console.timeEnd('🔋 CozoDb worker started.')); + }; + (async () => { console.log( process.env.IS_DEV @@ -140,6 +187,8 @@ function BackendProvider({ children }: { children: React.ReactNode }) { const isInitialized = await backgroundWorkerInstance.isInitialized(); if (isInitialized) { console.log('🔋 Background worker already active.'); + bcSender.postServiceStatus('ipfs', 'started'); + bcSender.postServiceStatus('sync', 'started'); return Promise.resolve(); } return loadIpfs(); @@ -149,6 +198,8 @@ function BackendProvider({ children }: { children: React.ReactNode }) { const isInitialized = await cozoDbWorkerInstance.isInitialized(); if (isInitialized) { console.log('🔋 CozoDb worker already active.'); + bcSender.postServiceStatus('db', 'started'); + createDbApi(); return Promise.resolve(); } return loadCozoDb(); @@ -160,41 +211,7 @@ function BackendProvider({ children }: { children: React.ReactNode }) { window.q = backgroundWorkerInstance.ipfsQueue; return () => channel.close(); - }, [dispatch]); - - const loadCozoDb = async () => { - console.time('🔋 CozoDb worker started.'); - await cozoDbWorkerInstance - .init() - .then(async () => { - // init dbApi - // TODO: refactor to use simple object instead of global instance - const dbApi = new DbApiWrapper(); - dbApi.init(proxy(cozoDbWorkerInstance)); - setDbApi(dbApi); - - // pass dbApi into background worker - await backgroundWorkerInstance.init(proxy(dbApi)); - }) - .then(() => console.timeEnd('🔋 CozoDb worker started.')); - }; - - const loadIpfs = async () => { - const ipfsOpts = getIpfsOpts(); - await backgroundWorkerInstance.ipfsApi.stop(); - console.time('🔋 Ipfs started.'); - - await backgroundWorkerInstance.ipfsApi - .start(ipfsOpts) - .then(() => { - setIpfsError(null); - console.timeEnd('🔋 Ipfs started.'); - }) - .catch((err) => { - setIpfsError(err); - console.log(`☠️ Ipfs error: ${err}`); - }); - }; + }, [dispatch, createDbApi]); const valueMemo = useMemo( () => diff --git a/src/contexts/backend/services/senseApi.ts b/src/contexts/backend/services/senseApi.ts index b771f4903..056f09ba3 100644 --- a/src/contexts/backend/services/senseApi.ts +++ b/src/contexts/backend/services/senseApi.ts @@ -8,7 +8,7 @@ import { } from 'src/services/CozoDb/types/dto'; import { EntryType } from 'src/services/CozoDb/types/entities'; import BroadcastChannelSender from 'src/services/backend/channels/BroadcastChannelSender'; -import DbApiWrapper from 'src/services/backend/services/dataSource/indexedDb/dbApiWrapper'; +import DbApiWrapper from 'src/services/backend/services/DbApi/DbApi'; import { CYBER_LINK_TRANSACTION_TYPE, CyberLinkValue, diff --git a/src/contexts/networks.tsx b/src/contexts/networks.tsx index e22193b34..c79bd58e9 100644 --- a/src/contexts/networks.tsx +++ b/src/contexts/networks.tsx @@ -1,7 +1,7 @@ import React, { useContext, useEffect, useMemo, useState } from 'react'; +import defaultNetworks from 'src/constants/defaultNetworks'; import { Option } from 'src/types'; import { NetworksList } from 'src/types/networks'; -import defaultNetworks from 'src/utils/defaultNetworks'; type NetworksContext = { networks: Option; diff --git a/src/contexts/queryClient.tsx b/src/contexts/queryClient.tsx index 5d45e8a04..33d846dd4 100644 --- a/src/contexts/queryClient.tsx +++ b/src/contexts/queryClient.tsx @@ -1,8 +1,8 @@ import React, { useContext } from 'react'; import { CyberClient } from '@cybercongress/cyber-js'; -import { CYBER } from 'src/utils/config'; import { Option } from 'src/types'; import { useQuery } from '@tanstack/react-query'; +import { RPC_URL } from 'src/constants/config'; const QueryClientContext = React.createContext>(undefined); @@ -14,7 +14,7 @@ function QueryClientProvider({ children }: { children: React.ReactNode }) { const { data, error, isFetching } = useQuery({ queryKey: ['cyberClient', 'connect'], queryFn: async () => { - return CyberClient.connect(CYBER.CYBER_NODE_URL_API); + return CyberClient.connect(RPC_URL); }, }); diff --git a/src/contexts/signerClient.tsx b/src/contexts/signerClient.tsx index b4c7fe4e6..f0410d4a8 100644 --- a/src/contexts/signerClient.tsx +++ b/src/contexts/signerClient.tsx @@ -7,7 +7,6 @@ import React, { } from 'react'; import _ from 'lodash'; import { SigningCyberClient } from '@cybercongress/cyber-js'; -import { CYBER } from 'src/utils/config'; import configKeplr, { getKeplr } from 'src/utils/keplrUtils'; import { OfflineSigner } from '@cybercongress/cyber-js/build/signingcyberclient'; import { Option } from 'src/types'; @@ -16,6 +15,7 @@ import { Keplr } from '@keplr-wallet/types'; import { addAddressPocket, setDefaultAccount } from 'src/redux/features/pocket'; import { accountsKeplr } from 'src/utils/utils'; import usePrevious from 'src/hooks/usePrevious'; +import { RPC_URL, BECH32_PREFIX, CHAIN_ID } from 'src/constants/config'; // TODO: interface for keplr and OfflineSigner // type SignerType = OfflineSigner & { @@ -32,9 +32,9 @@ type SignerClientContextType = { async function createClient( signer: OfflineSigner ): Promise { - const options = { prefix: CYBER.BECH32_PREFIX_ACC_ADDR_CYBER }; + const options = { prefix: BECH32_PREFIX }; const client = await SigningCyberClient.connectWithSigner( - CYBER.CYBER_NODE_URL_API, + RPC_URL, signer, options ); @@ -69,7 +69,7 @@ function SigningClientProvider({ children }: { children: React.ReactNode }) { if (!accounts || _.isEqual(prevAccounts, accounts)) { return; } - const keyInfo = await keplr.getKey(CYBER.CHAIN_ID); + const keyInfo = await keplr.getKey(CHAIN_ID); const findAccount = Object.keys(accounts).find((key) => { if (accounts[key].cyber.bech32 === keyInfo.bech32Address) { @@ -112,13 +112,9 @@ function SigningClientProvider({ children }: { children: React.ReactNode }) { preferNoSetFee: true, }, }; - await windowKeplr.experimentalSuggestChain( - configKeplr(CYBER.BECH32_PREFIX_ACC_ADDR_CYBER) - ); - await windowKeplr.enable(CYBER.CHAIN_ID); - const offlineSigner = await windowKeplr.getOfflineSignerAuto( - CYBER.CHAIN_ID - ); + await windowKeplr.experimentalSuggestChain(configKeplr(BECH32_PREFIX)); + await windowKeplr.enable(CHAIN_ID); + const offlineSigner = await windowKeplr.getOfflineSignerAuto(CHAIN_ID); const clientJs = await createClient(offlineSigner); @@ -154,4 +150,5 @@ function SigningClientProvider({ children }: { children: React.ReactNode }) { ); } +export { createClient as createSignerClient }; export default SigningClientProvider; diff --git a/src/features/cyberlinks/CyberlinksGraph/CyberlinksGraphContainer.tsx b/src/features/cyberlinks/CyberlinksGraph/CyberlinksGraphContainer.tsx index 87720e7f6..4c92bc5ab 100644 --- a/src/features/cyberlinks/CyberlinksGraph/CyberlinksGraphContainer.tsx +++ b/src/features/cyberlinks/CyberlinksGraph/CyberlinksGraphContainer.tsx @@ -66,37 +66,3 @@ function CyberlinksGraphContainer({ } export default CyberlinksGraphContainer; - -// old code - -// const handleNewLink = useCallback(subscription => { -// let link = subscription["subscriptionData"].data["cyberlink"][0] -// let { nodes, links } = data; -// let l = { -// source: link["object_from"], -// target: link["object_to"], -// name: link["txhash"] -// } - -// if (!nodes.some(node => node["id"] == l["source"])) { -// nodes.push({id: l["source"]}) -// } - -// if (!nodes.some(node => node["id"] == l["target"])) { -// nodes.push({id: l["target"]}) -// } - -// setItems({ -// nodes: [...nodes], -// links: [...links, { -// source: l["source"], -// target: l["target"], -// name: l["name"], -// curvative: getRandomInt(20,500)/1000 -// }] -// }) -// }, [data]) - -// const { loading: loadingLinks, data: dataNew } = useSubscription(CYBERLINK_SUBSCRIPTION, { -// onSubscriptionData: handleNewLink -// }); diff --git a/src/features/cyberlinks/CyberlinksGraph/useCyberlinks.ts b/src/features/cyberlinks/CyberlinksGraph/useCyberlinks.ts index 47057e6e2..d46a11012 100644 --- a/src/features/cyberlinks/CyberlinksGraph/useCyberlinks.ts +++ b/src/features/cyberlinks/CyberlinksGraph/useCyberlinks.ts @@ -1,10 +1,10 @@ // import gql from 'graphql-tag'; import { useEffect, useMemo, useState } from 'react'; -import { useQuery, gql } from '@apollo/client'; - -import { useBackend } from 'src/contexts/backend/backend'; -import { useEffect, useState } from 'react'; import { useBackend } from 'src/contexts/backend/backend'; +import { + Order_By as OrderBy, + useCyberlinksByParticleQuery, +} from 'src/generated/graphql'; const valueByKeyOrSelf = (key: string, obj: Record) => obj[key] || key; @@ -52,32 +52,23 @@ function useCyberlinks( ) { let where; if (address) { - where = `{neuron: {_eq: "${address}"}}`; + where = { neuron: { _eq: address } }; } else { - where = '{}'; + where = {}; } const { loading, error, data: gqlData, - } = useQuery( - gql` - query Cyberlinks { - cyberlinks(limit: ${String( - limit - )}, order_by: {height: desc}, where: ${where}) { - particle_from - particle_to - neuron - transaction_hash - } - } - `, - { - skip, - } - ); + } = useCyberlinksByParticleQuery({ + variables: { + where, + orderBy: { height: OrderBy.Desc }, + limit, + }, + skip, + }); const cyberlinks = gqlData?.cyberlinks; const { isLoading, particlesPreview } = useParticlesPreview(); @@ -91,8 +82,8 @@ function useCyberlinks( } // TODO: a lot of loops, try to refactor - const from = cyberlinks.map((a) => a.particle_from); - const to = cyberlinks.map((a) => a.particle_to); + const from = cyberlinks.map((a) => a.from); + const to = cyberlinks.map((a) => a.to); const object = Array.from(new Set(from.concat(to))).map((value) => ({ id: valueByKeyOrSelf(value, particlesPreview), @@ -107,10 +98,10 @@ function useCyberlinks( for (let i = 0; i < cyberlinks.length; i++) { links[i] = { - source: valueByKeyOrSelf(cyberlinks[i].particle_from, particlesPreview), - target: valueByKeyOrSelf(cyberlinks[i].particle_to, particlesPreview), + source: valueByKeyOrSelf(cyberlinks[i].from, particlesPreview), + target: valueByKeyOrSelf(cyberlinks[i].to, particlesPreview), name: cyberlinks[i].transaction_hash, - subject: cyberlinks[i].subject, + subject: cyberlinks[i].neuron, // curvative: getRandomInt(20, 500) / 1000, }; } diff --git a/src/features/cyberlinks/hooks/useCyberlinksCount.ts b/src/features/cyberlinks/hooks/useCyberlinksCount.ts index 128b97cdc..83989a4d2 100644 --- a/src/features/cyberlinks/hooks/useCyberlinksCount.ts +++ b/src/features/cyberlinks/hooks/useCyberlinksCount.ts @@ -1,20 +1,16 @@ -import { useQuery, gql } from '@apollo/client'; +import { useCyberlinksCountByParticleQuery } from 'src/generated/graphql'; -function generateQuery(cid: string, type: 'to' | 'from') { - return gql` - query Query { - cyberlinks_aggregate(where: {particle_${type}: {_eq: "${cid}"}}) { - aggregate { - count - } - } - } - `; -} +const getVar = (type: 'from' | 'to', cid: string) => { + return { [`particle_${type}`]: { _eq: cid } }; +}; function useCyberlinksCount(cid: string) { - const toCountQuery = useQuery(generateQuery(cid, 'to')); - const fromCountQuery = useQuery(generateQuery(cid, 'from')); + const toCountQuery = useCyberlinksCountByParticleQuery({ + variables: { where: getVar('to', cid) }, + }); + const fromCountQuery = useCyberlinksCountByParticleQuery({ + variables: { where: getVar('to', cid) }, + }); return { data: { diff --git a/src/features/ipfs/Drive/AutzKeys.tsx b/src/features/ipfs/Drive/AutzKeys.tsx new file mode 100644 index 000000000..1b8de70b4 --- /dev/null +++ b/src/features/ipfs/Drive/AutzKeys.tsx @@ -0,0 +1,263 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { useAppSelector } from 'src/redux/hooks'; +import { Colors } from 'src/components/containerGradient/types'; + +import Display from 'src/components/containerGradient/Display/Display'; + +import styles from './drive.scss'; +import { Button, Input } from 'src/components'; +import { generateWalletFromMnemonic } from 'src/services/wallet/walletGenerator'; +import { + createSignerClient, + useSigningClient, +} from 'src/contexts/signerClient'; + +import { LCD_URL } from 'src/constants/config'; +import { NeuronAddress } from 'src/types/base'; +import { selectCurrentAddress } from 'src/redux/features/pocket'; +import { GenericAuthorization } from 'cosmjs-types/cosmos/authz/v1beta1/authz'; +import { SendAuthorization } from 'cosmjs-types/cosmos/bank/v1beta1/authz'; + +import { defaultFee } from 'src/services/neuron/neuronApi'; +import { coins } from '@cosmjs/launchpad'; +import axios from 'axios'; +import { useBackend } from 'src/contexts/backend/backend'; +import { SigningCyberClient } from '@cybercongress/cyber-js'; +import { MsgCyberlink } from '@cybercongress/cyber-js/build/codec/cyber/graph/v1beta1/tx'; +import { CID_TWEET } from 'src/constants/app'; +// import { MsgExec } from 'cosmjs-types/cosmos/authz/v1beta1/tx'; + +/* +https://lcd.bostrom.cybernode.ai/cosmos/authz/v1beta1/grants/grantee/bostrom1a3zu6emqfzkc6rz9a44mq2ks88dmgvjrfcq6jl + +https://lcd.bostrom.cybernode.ai/cosmos/authz/v1beta1/grants/granter/bostrom1p0r7uxstcw8ehrwuj4kn8qzzs0yypsjwxgd445 + +https://lcd.bostrom.cybernode.ai/cosmos/authz/v1beta1/grants?granter=bostrom1p0r7uxstcw8ehrwuj4kn8qzzs0yypsjwxgd445&grantee=bostrom1a3zu6emqfzkc6rz9a44mq2ks88dmgvjrfcq6jl +*/ +const getGranters = async (address: NeuronAddress) => { + return axios({ + method: 'get', + url: `${LCD_URL}/cosmos/authz/v1beta1/grants/grantee/${address}`, + }); +}; + +const getGrantees = async (address: NeuronAddress) => { + return axios({ + method: 'get', + url: `${LCD_URL}/cosmos/authz/v1beta1/grants/granter/${address}`, + }); +}; + +const getGrants = async (granter: NeuronAddress, grantee: NeuronAddress) => { + return axios({ + method: 'get', + url: `${LCD_URL}/cosmos/authz/v1beta1/grants?granter=${granter}&grantee=${grantee}`, + }); +}; + +const mnemonic = + 'picture check person they response slam post cement moon sorry nuclear price knock figure sugar distance remember lunar powder balance bleak weasel cherry review'; +function AutzKeys() { + const { ipfsApi, senseApi } = useBackend(); + const [address, setAddress] = React.useState(null); + const [grantees, setGrantees] = React.useState([]); + const [testLink, setTestLink] = React.useState( + new Date().toISOString() + ); + const [autzSigner, setAutzSigner] = useState< + SigningCyberClient | undefined + >(); + + // const [grants, setGrants] = React.useState([]); + const { signingClient, signer, signerReady } = useSigningClient(); + const myAddress = useAppSelector(selectCurrentAddress); + const loadGrantees = useCallback(async () => { + const grantees = await getGrantees(myAddress); + setGrantees(grantees.data.grants); + console.log('----grantees', grantees.data.grants); + }, [myAddress]); + + useEffect(() => { + (async () => { + if (myAddress) { + const { wallet, address } = await generateWalletFromMnemonic(mnemonic); + const autzSigner = await createSignerClient(wallet); + setAutzSigner(autzSigner); + + setAddress(address); + await loadGrantees(); + } + })(); + }, [myAddress]); + + const onGrantClick = async () => { + if (myAddress && address) { + const sendMsg = { + typeUrl: '/cosmos.bank.v1beta1.MsgSend', + value: { + fromAddress: myAddress, + toAddress: address, + amount: coins(1, 'boot'), + }, + }; + + const expirationTimestamp = Math.floor( + Date.parse('2024-05-01T18:52:56.449Z') / 1000 + ); + + const grantCyberlink = { + authorization: { + typeUrl: '/cosmos.authz.v1beta1.GenericAuthorization', + value: GenericAuthorization.encode( + GenericAuthorization.fromPartial({ + msg: '/cyber.graph.v1beta1.MsgCyberlink', + }) + ).finish(), + }, + expiration: { seconds: expirationTimestamp, nano: 0 }, + }; + + // const grantCyberlinkMsg = { + // typeUrl: '/cosmos.authz.v1beta1.MsgGrant', + // value: { + // granter: myAddress, + // grantee: address, + // grant: grantCyberlink, + // }, + // }; + + const createGrantMsg = (grant: any) => ({ + typeUrl: '/cosmos.authz.v1beta1.MsgGrant', + value: { + granter: myAddress, + grantee: address, + grant, + }, + }); + + const grantSend = { + authorization: { + typeUrl: '/cosmos.bank.v1beta1.SendAuthorization', + value: SendAuthorization.encode( + SendAuthorization.fromPartial({ + spendLimit: coins(1, 'boot'), + }) + ).finish(), + }, + expiration: { seconds: expirationTimestamp, nano: 0 }, + }; + + const result = await signingClient?.signAndBroadcast( + myAddress, + [sendMsg, createGrantMsg(grantCyberlink), createGrantMsg(grantSend)], + defaultFee + ); + await loadGrantees(); + console.log('----onGrantClick', result); + } + }; + + const onRevokeClick = async () => { + console.log('-----revoke', grantees); + const result = await Promise.all( + grantees.map( + async (grant) => + grant.grantee === address && + signingClient!.revoke( + myAddress, + address, + grant.authorization.msg, + defaultFee + ) + ) + ); + console.log('----onRevokeClick', result); + + await loadGrantees(); + }; + + const onTestLink = async () => { + if (myAddress && address) { + const fromCid = CID_TWEET; // await ipfsApi?.addContent('test-autz'); + + const toCid = await ipfsApi?.addContent(testLink); + console.log('----test link', fromCid, toCid); + + const actionMsg = { + typeUrl: '/cyber.graph.v1beta1.MsgCyberlink', // For example, sending tokens + value: MsgCyberlink.encode( + MsgCyberlink.fromPartial({ + neuron: myAddress, + links: [ + { + from: fromCid, + to: toCid, + }, + ], + }) + ).finish(), + }; + + // Step 3: Wrap the action message in a MsgExec message + const execMsg = { + typeUrl: '/cosmos.authz.v1beta1.MsgExec', + value: { + grantee: address, // The grantee's address + msgs: [actionMsg], // The message to be executed on behalf of the granter + }, + }; + + // Step 4: Sign and broadcast the MsgExec transaction + const execResult = await autzSigner!.signAndBroadcast( + address, // The grantee signs the transaction + [execMsg], // The MsgExec message + defaultFee, // Fee for the transaction + 'Executing action on behalf of granter 2w2' // Memo + ); + console.log('----test link result', execResult, execMsg); + // await sendCyberlink(myAddress, fromCid, toCid, deps); + } + }; + + return ( + +
+

Autz keys

+
Mnemonic: {mnemonic}
+
Address: {address}
+ +
Grantees:
+
    + {grantees.map((data, index) => ( +
  • + {data.granter} to {data.grantee} - {data.authorization.msg}: ( + {data.expiration}) +
  • + ))} +
+ +
+ + + {' '} +
+
+ setTestLink(v.target.value)} + placeholder="any text" + /> + +
+
+
+ ); +} + +export default AutzKeys; diff --git a/src/features/ipfs/Drive/index.tsx b/src/features/ipfs/Drive/index.tsx index eb0e3238b..553994f00 100644 --- a/src/features/ipfs/Drive/index.tsx +++ b/src/features/ipfs/Drive/index.tsx @@ -20,6 +20,7 @@ import BackendStatus from './BackendStatus'; import cozoPresets from './cozo_presets.json'; import styles from './drive.scss'; +import AutzKeys from './AutzKeys'; const DEFAULT_PRESET_NAME = '💡 defaul commands...'; @@ -186,7 +187,7 @@ function Drive() {

- +