diff --git a/package.json b/package.json index 13ab7d619..8bb838ebc 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "devDependencies": { "@commitlint/cli": "^19.8.1", "@commitlint/config-conventional": "^19.8.1", - "@swc/core": "^1.11.24", + "@swc/core": "^1.11.29", "concurrently": "^9.1.2", "husky": "^9.1.7", "node-notifier": "^10.0.1", diff --git a/packages/extension-bridge/package.json b/packages/extension-bridge/package.json index 7b3f52712..7366d8c34 100644 --- a/packages/extension-bridge/package.json +++ b/packages/extension-bridge/package.json @@ -44,12 +44,12 @@ "webextension-polyfill": "^0.12.0" }, "devDependencies": { - "@types/node": "^22.15.17", + "@types/node": "^22.15.24", "@types/webextension-polyfill": "^0.12.3", - "@typescript-eslint/eslint-plugin": "^8.32.1", - "@typescript-eslint/parser": "^8.32.1", - "bumpp": "^10.1.0", - "eslint": "^9.26.0", + "@typescript-eslint/eslint-plugin": "^8.33.0", + "@typescript-eslint/parser": "^8.33.0", + "bumpp": "^10.1.1", + "eslint": "^9.27.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-config-prettier": "^10.1.5", "eslint-import-resolver-alias": "^1.1.2", @@ -58,9 +58,9 @@ "prettier": "^3.5.3", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", - "tsup": "^8.4.0", + "tsup": "^8.5.0", "type-fest": "^4.41.0", "typescript": "^5.8.3", - "typescript-eslint": "8.32.1" + "typescript-eslint": "8.33.0" } } diff --git a/packages/extension/package.json b/packages/extension/package.json index b3c53b344..d85d7977c 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -1,6 +1,6 @@ { "name": "@enkryptcom/extension", - "version": "2.7.0", + "version": "2.8.0", "private": true, "type": "module", "scripts": { @@ -23,7 +23,7 @@ "watch:firefox": "yarn prebuild && cross-env BROWSER='firefox' vite" }, "dependencies": { - "@amplitude/analytics-browser": "^2.17.4", + "@amplitude/analytics-browser": "^2.17.6", "@enkryptcom/extension-bridge": "workspace:^", "@enkryptcom/hw-wallets": "workspace:^", "@enkryptcom/keyring": "workspace:^", @@ -38,19 +38,19 @@ "@ethereumjs/wallet": "^2.0.4", "@kadena/client": "^1.17.1", "@kadena/pactjs-cli": "^1.17.1", - "@ledgerhq/hw-transport-webusb": "^6.29.4", + "@ledgerhq/hw-transport-webusb": "^6.29.5", "@metamask/eth-sig-util": "^8.2.0", - "@metaplex-foundation/mpl-bubblegum": "^5.0.0", + "@metaplex-foundation/mpl-bubblegum": "^5.0.1", "@metaplex-foundation/umi": "^1.2.0", "@metaplex-foundation/umi-bundle-defaults": "^1.2.0", - "@polkadot/api": "^15.9.3", - "@polkadot/extension-inject": "^0.58.9", - "@polkadot/keyring": "^13.4.4", - "@polkadot/rpc-provider": "^15.9.3", - "@polkadot/types": "^15.9.3", - "@polkadot/types-known": "^15.9.3", - "@polkadot/ui-shared": "^3.13.1", - "@polkadot/util": "^13.4.4", + "@polkadot/api": "^16.1.1", + "@polkadot/extension-inject": "^0.58.10", + "@polkadot/keyring": "^13.5.1", + "@polkadot/rpc-provider": "^16.1.1", + "@polkadot/types": "^16.1.1", + "@polkadot/types-known": "^16.1.1", + "@polkadot/ui-shared": "^3.14.1", + "@polkadot/util": "^13.5.1", "@polkadot/wasm-crypto": "^7.4.1", "@solana-developers/helpers": "2.8.0", "@solana/spl-token": "^0.4.13", @@ -78,7 +78,7 @@ "switch-ts": "^1.1.1", "url-parse": "^1.5.10", "uuid": "^11.1.0", - "vue": "^3.5.13", + "vue": "^3.5.16", "vue-echarts": "7.0.3", "vue-router": "^4.5.1", "vue3-lottie": "^3.3.1", @@ -99,13 +99,13 @@ "@rollup/plugin-typescript": "^12.1.2", "@tsconfig/node20": "^20.1.5", "@types/bs58": "^5.0.0", - "@types/chrome": "^0.0.322", + "@types/chrome": "^0.0.323", "@types/ethereumjs-abi": "^0.6.5", "@types/events": "^3.0.3", "@types/fs-extra": "^11.0.4", "@types/less": "^3.0.8", - "@types/lodash": "^4.17.16", - "@types/node": "^22.15.17", + "@types/lodash": "^4.17.17", + "@types/node": "^22.15.24", "@types/semver": "^7.7.0", "@types/url-parse": "^1.4.11", "@types/utf-8-validate": "^5.0.2", @@ -116,28 +116,28 @@ "@vue/eslint-config-prettier": "^10.2.0", "@vue/eslint-config-typescript": "^14.5.0", "@vue/tsconfig": "^0.7.0", - "@vueuse/core": "^13.1.0", + "@vueuse/core": "^13.3.0", "cross-env": "^7.0.3", - "eslint": "^9.26.0", + "eslint": "^9.27.0", "eslint-plugin-vue": "^10.1.0", "fs-extra": "^11.3.0", "jsdom": "^26.1.0", "less": "^4.3.0", "less-loader": "^12.3.0", - "npm-run-all2": "^8.0.1", + "npm-run-all2": "^8.0.4", "prettier": "^3.5.3", "rimraf": "^6.0.1", - "rollup": "^4.40.2", - "rollup-plugin-visualizer": "^5.14.0", + "rollup": "^4.41.1", + "rollup-plugin-visualizer": "^6.0.1", "semver": "^7.7.2", - "systeminformation": "^5.25.11", - "tsup": "^8.4.0", + "systeminformation": "^5.27.1", + "tsup": "^8.5.0", "typescript": "~5.8.3", "url": "^0.11.4", "vite": "^6.3.5", "vite-plugin-node-polyfills": "0.23.0", "vite-tsconfig-paths": "^5.1.4", - "vitest": "^3.1.3", + "vitest": "^3.1.4", "vue-tsc": "^2.2.10", "webextension-polyfill": "^0.12.0" }, diff --git a/packages/extension/src/libs/name-resolver/index.ts b/packages/extension/src/libs/name-resolver/index.ts index b19d9684a..fd3656efd 100644 --- a/packages/extension/src/libs/name-resolver/index.ts +++ b/packages/extension/src/libs/name-resolver/index.ts @@ -14,11 +14,11 @@ class GenericNameResolver { }); } - async resolveName(name: string, coins: CoinType[]): Promise { + async resolveName(name: string, coins: CoinType[], providerChain?: string): Promise { let response: string | null = null; for (const coin of coins) { response = await this.nameResolver - .resolveAddress(name, coin) + .resolveAddress(name, coin, providerChain) .catch(() => null); if (response) return response; } diff --git a/packages/extension/src/providers/bitcoin/types/bitcoin-network.ts b/packages/extension/src/providers/bitcoin/types/bitcoin-network.ts index 82425336a..458cda9a6 100644 --- a/packages/extension/src/providers/bitcoin/types/bitcoin-network.ts +++ b/packages/extension/src/providers/bitcoin/types/bitcoin-network.ts @@ -10,7 +10,6 @@ import { BitcoinNetworkInfo } from '.'; import { payments } from 'bitcoinjs-lib'; import { hexToBuffer, fromBase } from '@enkryptcom/utils'; import { - formatFiatValue, formatFloatingPointValue, } from '@/libs/utils/number-formatter'; import MarketData from '@/libs/market-data'; @@ -131,13 +130,12 @@ export class BitcoinNetwork extends BaseNetwork { balance: balance, balancef: formatFloatingPointValue(userBalance).value, balanceUSD: usdBalance.toNumber(), - balanceUSDf: formatFiatValue(usdBalance.toString()).value, + balanceUSDf: usdBalance.toString(), icon: this.icon, name: this.name_long, symbol: this.currencyName, value: marketData[0]?.current_price?.toString() ?? '0', - valuef: formatFiatValue(marketData[0]?.current_price?.toString() ?? '0') - .value, + valuef: marketData[0]?.current_price?.toString() ?? '0', contract: '', decimals: this.decimals, sparkline: marketData.length diff --git a/packages/extension/src/providers/bitcoin/ui/btc-verify-transaction.vue b/packages/extension/src/providers/bitcoin/ui/btc-verify-transaction.vue index 8fed5af06..7020b54a1 100644 --- a/packages/extension/src/providers/bitcoin/ui/btc-verify-transaction.vue +++ b/packages/extension/src/providers/bitcoin/ui/btc-verify-transaction.vue @@ -62,9 +62,9 @@ {{ network.currencyName }}

- ${{ + {{ fiatValue !== '~' - ? $filters.formatFiatValue(fiatValue).value + ? $filters.parseCurrency(fiatValue) : fiatValue }}

diff --git a/packages/extension/src/providers/bitcoin/ui/send-transaction/components/send-alert.vue b/packages/extension/src/providers/bitcoin/ui/send-transaction/components/send-alert.vue index e62d46777..781f8c773 100644 --- a/packages/extension/src/providers/bitcoin/ui/send-transaction/components/send-alert.vue +++ b/packages/extension/src/providers/bitcoin/ui/send-transaction/components/send-alert.vue @@ -7,9 +7,7 @@ Not enough funds. You are
~{{ $filters.formatFloatingPointValue(nativeValue).value }} - {{ nativeSymbol }} (${{ - $filters.formatFiatValue(priceDifference).value - }}) short. + {{ nativeSymbol }} ({{ $filters.parseCurrency(priceDifference) }}) short.

diff --git a/packages/extension/src/providers/common/libs/new-features.ts b/packages/extension/src/providers/common/libs/new-features.ts index f61ce0003..4619503ba 100644 --- a/packages/extension/src/providers/common/libs/new-features.ts +++ b/packages/extension/src/providers/common/libs/new-features.ts @@ -1,10 +1,6 @@ import { NetworkNames } from '@enkryptcom/types'; -const newNetworks: NetworkNames[] = [ - NetworkNames.Derive, - NetworkNames.Conflux, - NetworkNames.UnitZero, -]; +const newNetworks: NetworkNames[] = [NetworkNames.Hemi]; const newSwaps: NetworkNames[] = []; export { newNetworks, newSwaps }; diff --git a/packages/extension/src/providers/common/ui/send-transaction/send-alert.vue b/packages/extension/src/providers/common/ui/send-transaction/send-alert.vue index 6e8284c19..1b5d63585 100644 --- a/packages/extension/src/providers/common/ui/send-transaction/send-alert.vue +++ b/packages/extension/src/providers/common/ui/send-transaction/send-alert.vue @@ -5,9 +5,7 @@ Not enough funds. You are
~{{ $filters.formatFloatingPointValue(nativeValue).value }} - {{ nativeSymbol }} (${{ - $filters.formatFiatValue(priceDifference).value - }}) short. + {{ nativeSymbol }} ({{ $filters.parseCurrency(priceDifference) }}) short.

diff --git a/packages/extension/src/providers/common/ui/send-transaction/send-contacts-list.vue b/packages/extension/src/providers/common/ui/send-transaction/send-contacts-list.vue index 7800a0c69..fd2fae412 100644 --- a/packages/extension/src/providers/common/ui/send-transaction/send-contacts-list.vue +++ b/packages/extension/src/providers/common/ui/send-transaction/send-contacts-list.vue @@ -125,7 +125,9 @@ const isChecked = (address: string) => { props.network.displayAddress(address) ); } catch (err) { - console.error('Error checking if address is checked', err); + console.error( + 'Error checking if address is checked, probably name resolver', + ); return false; } }; diff --git a/packages/extension/src/providers/common/ui/styles/verify-transaction.less b/packages/extension/src/providers/common/ui/styles/verify-transaction.less index 28904b599..d2970606d 100644 --- a/packages/extension/src/providers/common/ui/styles/verify-transaction.less +++ b/packages/extension/src/providers/common/ui/styles/verify-transaction.less @@ -7,6 +7,13 @@ &__logo { margin-bottom: 8px; } + &__label { + font-size: 12px; + line-height: 16px; + letter-spacing: 0.5px; + color: @grayPrimary; + margin: 0 0 4px 44px; + } &__network { display: flex; justify-content: flex-start; @@ -167,11 +174,11 @@ &-to { font-style: normal; - font-weight: 400; - font-size: 14px; - line-height: 20px; - letter-spacing: 0.25px; - color: @primaryLabel; + font-weight: 400 !important; + font-size: 16px !important; + line-height: 20px !important; + letter-spacing: 0.5px; + color: @black !important; word-break: break-all; } } diff --git a/packages/extension/src/providers/common/ui/verify-transaction/verify-transaction-amount.vue b/packages/extension/src/providers/common/ui/verify-transaction/verify-transaction-amount.vue index 3496aa67e..7c4edf68f 100644 --- a/packages/extension/src/providers/common/ui/verify-transaction/verify-transaction-amount.vue +++ b/packages/extension/src/providers/common/ui/verify-transaction/verify-transaction-amount.vue @@ -8,7 +8,7 @@ {{ fromBase(token.amount, token.decimals) }} {{ token.symbol }} -
{{ $filters.formatFiatValue(token.valueUSD).value }}
+
{{ $filters.parseCurrency(token.valueUSD) }}
diff --git a/packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts b/packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts index 8358490d8..09b8f3576 100644 --- a/packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts +++ b/packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts @@ -71,9 +71,11 @@ const NetworkEndpoints: Record = { [NetworkNames.Scroll]: 'https://api.scrollscan.com/', [NetworkNames.Fraxtal]: 'https://api.fraxscan.com/', [NetworkNames.Coti]: 'https://mainnet.cotiscan.io/', - [NetworkNames.CytonicTestnet]: 'https://explorer-api.evm.testnet.cytonic.com/api/', + [NetworkNames.CytonicTestnet]: + 'https://explorer-api.evm.testnet.cytonic.com/api/', [NetworkNames.Derive]: 'https://explorer.derive.xyz/', [NetworkNames.Conflux]: 'https://evmapi.confluxscan.org/', + [NetworkNames.Hemi]: 'https://explorer.hemi.xyz/', }; export { NetworkEndpoints }; diff --git a/packages/extension/src/providers/ethereum/libs/assets-handlers/assetinfo-mew.ts b/packages/extension/src/providers/ethereum/libs/assets-handlers/assetinfo-mew.ts index 2de30d2d8..d14f044d6 100644 --- a/packages/extension/src/providers/ethereum/libs/assets-handlers/assetinfo-mew.ts +++ b/packages/extension/src/providers/ethereum/libs/assets-handlers/assetinfo-mew.ts @@ -10,7 +10,7 @@ import { fromBase } from '@enkryptcom/utils'; import { toBN } from 'web3-utils'; import BigNumber from 'bignumber.js'; import { - formatFiatValue, + formatFloatingPointValue, } from '@/libs/utils/number-formatter'; import API from '@/providers/ethereum/libs/api'; @@ -278,15 +278,15 @@ export default ( const marketInfo = supportedNetworks[networkName].cgPlatform ? await marketData.getMarketInfoByContracts( - Object.keys(balances).filter( - contract => contract !== NATIVE_TOKEN_ADDRESS, - ), - supportedNetworks[networkName].cgPlatform as CoingeckoPlatform, - ) + Object.keys(balances).filter( + contract => contract !== NATIVE_TOKEN_ADDRESS, + ), + supportedNetworks[networkName].cgPlatform as CoingeckoPlatform, + ) : tokens.reduce( - (obj, cur) => ({ ...obj, [cur.contract]: null }), - {} as Record, - ); + (obj, cur) => ({ ...obj, [cur.contract]: null }), + {} as Record, + ); if (network.coingeckoID) { const nativeMarket = await marketData.getMarketData([ network.coingeckoID, @@ -337,12 +337,12 @@ export default ( balance: toBN(balances[address].balance).toString(), balancef: formatFloatingPointValue(userBalance).value, balanceUSD: usdBalance.toNumber(), - balanceUSDf: formatFiatValue(usdBalance.toString()).value, + balanceUSDf: usdBalance.toString(), icon: market.image, name: market.name, symbol: market.symbol, value: currentPrice.toString(), - valuef: formatFiatValue(currentPrice.toString()).value, + valuef: currentPrice.toString(), contract: address, decimals: tokenInfo[address].decimals, sparkline: new Sparkline(market.sparkline_in_24h.price, 25) @@ -377,7 +377,7 @@ export default ( balance: toBN(balances[unknownTokens[idx]].balance).toString(), balancef: formatFloatingPointValue(userBalance).value, balanceUSD: 0, - balanceUSDf: formatFiatValue('0').value, + balanceUSDf: '0', icon: tokenInfo[unknownTokens[idx]]?.logoURI || tInfo.icon || @@ -385,7 +385,7 @@ export default ( name: tInfo.name, symbol: tInfo.symbol, value: '0', - valuef: formatFiatValue('0').value, + valuef: '0', contract: unknownTokens[idx], decimals: tInfo.decimals, sparkline: '', diff --git a/packages/extension/src/providers/ethereum/libs/transaction/gas-utils.ts b/packages/extension/src/providers/ethereum/libs/transaction/gas-utils.ts index 8abbb3228..73860f4f6 100644 --- a/packages/extension/src/providers/ethereum/libs/transaction/gas-utils.ts +++ b/packages/extension/src/providers/ethereum/libs/transaction/gas-utils.ts @@ -1,6 +1,8 @@ import BigNumber from 'bignumber.js'; import { toBN, toWei } from 'web3-utils'; import { BNType, GasPriceTypes } from '@/providers/common/types'; +import rsk from '../../networks/rsk'; +import rskTestnet from '../../networks/rsk-testnet'; import { FeeHistoryResult } from 'web3-eth'; import { FormattedFeeHistory } from './types'; @@ -177,9 +179,78 @@ const FeeDescriptions = { eta: '30 secs', }, }; +const collectiveGasConfig = { + [rsk.chainID]: { + // rsk mainnet + stakingUrl: + 'https://rootstock.blockscout.com/api/v2/tokens/0x5db91e24BD32059584bbDb831A901f1199f3d459/transfers', + txUrl: 'https://rootstock.blockscout.com/api/v2/transactions', + method: 'depositAndDelegate', + methodId: '0xfbde32f8', + }, + [rskTestnet.chainID]: { + // rsk testnet + stakingUrl: + 'https://rootstock-testnet.blockscout.com/api/v2/tokens/0xc4b091D97ad25cEa5922F09fE80711B7acbBB16f/transfers', + txUrl: 'https://rootstock-testnet.blockscout.com/api/v2/transactions', + method: 'depositAndDelegate', + methodId: '0xfbde32f8', + }, +}; + +const safeGasForStaking = async (chainID: string, estimatedGas: number) => { + const gasConfig = collectiveGasConfig[chainID]; + try { + const stakingResponse = await fetch(gasConfig.stakingUrl); + if (!stakingResponse.ok) { + return estimatedGas; + } + const stakingTxHistory = await stakingResponse.json(); + + for (const tx of stakingTxHistory.items) { + // find stake tx + if (tx.method === gasConfig.method) { + const txDetailsResponse = await fetch( + `${gasConfig.txUrl}/${tx.transaction_hash}`, + ); + + if (!txDetailsResponse.ok) { + return estimatedGas; + } + const txDetail = await txDetailsResponse.json(); + // tx must be successfull + if (txDetail.status === 'ok') { + const txGasLimit = Number(txDetail.gas_limit); + const txGasUsed = Number(txDetail.gas_used); + // if web3 estimate gas is less than previous stake tx gas used + // This could cause tx to fail due to less gas + // Bump the gas limit particularly in this case + if (estimatedGas < txGasUsed) { + // Check if need to add buffer + const usedGasPercentage = (txGasUsed / txGasLimit) * 100; + if (usedGasPercentage > 80) { + // add a safe buffer of 30% + return Math.max(txGasUsed + txGasUsed * 0.3, txGasLimit); + } + // safe buffer not required, just use gas limit + return txGasLimit; + } + // safe to use max of estimate or tx gas limit + return Math.max(estimatedGas, txGasLimit); + } + } + } + // No previous stake tx found, just return web3 estimated gas. + return estimatedGas; + } catch { + return estimatedGas; + } +}; export { getBaseFeeBasedOnType, getPriorityFeeBasedOnType, + safeGasForStaking, + collectiveGasConfig, getGasBasedOnType, FeeDescriptions, formatFeeHistory, diff --git a/packages/extension/src/providers/ethereum/libs/transaction/index.ts b/packages/extension/src/providers/ethereum/libs/transaction/index.ts index ea173a58d..2f6cd9e21 100644 --- a/packages/extension/src/providers/ethereum/libs/transaction/index.ts +++ b/packages/extension/src/providers/ethereum/libs/transaction/index.ts @@ -14,8 +14,12 @@ import { formatFeeHistory, getBaseFeeBasedOnType, getGasBasedOnType, + safeGasForStaking, + collectiveGasConfig, getPriorityFeeBasedOnType, } from './gas-utils'; +import rsk from '../../networks/rsk'; +import rskTestnet from '../../networks/rsk-testnet'; import { Hardfork, Common } from '@ethereumjs/common'; import { FeeMarketEIP1559Transaction, LegacyTransaction } from '@ethereumjs/tx'; import { OPTIMISM_PRICE_ORACLE, OPTIMISM_PRICE_ORACLE_ABI } from './op-data'; @@ -105,9 +109,18 @@ class Transaction { if (!isFeeMarketNetwork) { // Legacy transaction const gasPrice = await this.web3.getGasPrice(); - const gasLimit = + let gasLimit = this.tx.gasLimit || (numberToHex(await this.estimateGas()) as `0x${string}`); + if ( + [rsk.chainID, rskTestnet.chainID].includes(this.tx.chainId) && + this.tx.data && + this.tx.data.startsWith(collectiveGasConfig[this.tx.chainId].methodId) + ) { + gasLimit = numberToHex( + await safeGasForStaking(this.tx.chainId, Number(gasLimit)), + ) as `0x${string}`; + } const legacyTx: FinalizedLegacyEthereumTransaction = { to: this.tx.to || undefined, chainId: this.tx.chainId, diff --git a/packages/extension/src/providers/ethereum/networks/hemi.ts b/packages/extension/src/providers/ethereum/networks/hemi.ts new file mode 100644 index 000000000..1f931b8a5 --- /dev/null +++ b/packages/extension/src/providers/ethereum/networks/hemi.ts @@ -0,0 +1,25 @@ +import icon from './icons/hemi.webp'; +import { NetworkNames } from '@enkryptcom/types'; +import { EvmNetwork, EvmNetworkOptions } from '../types/evm-network'; +import { EtherscanActivity } from '../libs/activity-handlers'; +import wrapActivityHandler from '@/libs/activity-state/wrap-activity-handler'; + +const hemiOptions: EvmNetworkOptions = { + name: NetworkNames.Hemi, + name_long: 'Hemi', + homePage: 'https://hemi.xyz/', + blockExplorerTX: 'https://explorer.hemi.xyz/tx/[[txHash]]', + blockExplorerAddr: 'https://explorer.hemi.xyz/address/[[address]]', + chainID: '0xa867', + isTestNetwork: false, + currencyName: 'ETH', + currencyNameLong: 'Ethereum', + node: 'wss://rpc.hemi.network/wsrpc', + coingeckoID: 'ethereum', + icon, + activityHandler: wrapActivityHandler(EtherscanActivity), +}; + +const hemi = new EvmNetwork(hemiOptions); + +export default hemi; diff --git a/packages/extension/src/providers/ethereum/networks/icons/hemi.webp b/packages/extension/src/providers/ethereum/networks/icons/hemi.webp new file mode 100644 index 000000000..14b44ec5e Binary files /dev/null and b/packages/extension/src/providers/ethereum/networks/icons/hemi.webp differ diff --git a/packages/extension/src/providers/ethereum/networks/index.ts b/packages/extension/src/providers/ethereum/networks/index.ts index 975328d52..2a21187e1 100755 --- a/packages/extension/src/providers/ethereum/networks/index.ts +++ b/packages/extension/src/providers/ethereum/networks/index.ts @@ -76,6 +76,7 @@ import cytonicTestnetNode from './cytonic-testnet'; import unitZero from './unitzero'; import unitZeroTestnet from './unitzero-testnet'; import conflux from './conflux'; +import hemi from './hemi'; export default { sepolia: sepoliaNode, @@ -165,4 +166,5 @@ export default { unitZero: unitZero, unitZeroTestnet: unitZeroTestnet, conflux: conflux, + hemi: hemi, }; diff --git a/packages/extension/src/providers/ethereum/networks/skale/skale-base.ts b/packages/extension/src/providers/ethereum/networks/skale/skale-base.ts index 56c756d6d..347d86482 100644 --- a/packages/extension/src/providers/ethereum/networks/skale/skale-base.ts +++ b/packages/extension/src/providers/ethereum/networks/skale/skale-base.ts @@ -8,7 +8,6 @@ import MarketData from '@/libs/market-data'; import { fromBase } from '@enkryptcom/utils'; import BigNumber from 'bignumber.js'; import { - formatFiatValue, formatFloatingPointValue, } from '@/libs/utils/number-formatter'; import API from '@/providers/ethereum/libs/api'; @@ -155,11 +154,11 @@ async function getPreconfiguredTokens( balancef: formatFloatingPointValue(fromBase(balanceAsset, assetDecimals)) .value, balanceUSD: nativeAssetUsdBalance.toNumber(), - balanceUSDf: formatFiatValue(nativeAssetUsdBalance.toString()).value, + balanceUSDf: nativeAssetUsdBalance.toString(), value: nativeAssetMarketData[index]?.current_price?.toString() ?? '0', - valuef: formatFiatValue( + valuef: nativeAssetMarketData[index]?.current_price?.toString() ?? '0', - ).value, + decimals: assetDecimals, sparkline: nativeAssetMarketData[index] ? new Sparkline( diff --git a/packages/extension/src/providers/ethereum/types/evm-network.ts b/packages/extension/src/providers/ethereum/types/evm-network.ts index a584cb701..406e20b3c 100644 --- a/packages/extension/src/providers/ethereum/types/evm-network.ts +++ b/packages/extension/src/providers/ethereum/types/evm-network.ts @@ -3,7 +3,6 @@ import Sparkline from '@/libs/sparkline'; import { TokensState } from '@/libs/tokens-state'; import { CustomErc20Token, TokenType } from '@/libs/tokens-state/types'; import { - formatFiatValue, formatFloatingPointValue, } from '@/libs/utils/number-formatter'; import { fromBase } from '@enkryptcom/utils'; @@ -151,11 +150,10 @@ export class EvmNetwork extends BaseNetwork { balancef: formatFloatingPointValue(fromBase(balance, this.decimals)) .value, balanceUSD: nativeUsdBalance.toNumber(), - balanceUSDf: formatFiatValue(nativeUsdBalance.toString()).value, + balanceUSDf: nativeUsdBalance.toString(), value: nativeMarketData?.current_price?.toString() ?? '0', - valuef: formatFiatValue( + valuef: nativeMarketData?.current_price?.toString() ?? '0', - ).value, decimals: this.decimals, sparkline: nativeMarketData ? new Sparkline(nativeMarketData.sparkline_in_24h.price, 25) @@ -269,11 +267,10 @@ export class EvmNetwork extends BaseNetwork { fromBase(token.balance ?? '0', token.decimals), ).times(marketInfo.current_price ?? 0); asset.balanceUSD = usdBalance.toNumber(); - asset.balanceUSDf = formatFiatValue(usdBalance.toString()).value; + asset.balanceUSDf = usdBalance.toString(); asset.value = marketInfo.current_price?.toString() ?? '0'; - asset.valuef = formatFiatValue( - marketInfo.current_price?.toString() ?? '0', - ).value; + asset.valuef = + marketInfo.current_price?.toString() ?? '0'; asset.sparkline = new Sparkline( marketInfo.sparkline_in_24h.price, 25, diff --git a/packages/extension/src/providers/ethereum/ui/eth-verify-transaction.vue b/packages/extension/src/providers/ethereum/ui/eth-verify-transaction.vue index 6ae31cb65..31aacc8f7 100644 --- a/packages/extension/src/providers/ethereum/ui/eth-verify-transaction.vue +++ b/packages/extension/src/providers/ethereum/ui/eth-verify-transaction.vue @@ -11,7 +11,9 @@ diff --git a/packages/extension/src/providers/polkadot/types/substrate-network.ts b/packages/extension/src/providers/polkadot/types/substrate-network.ts index f161efac3..1bd3c0fe0 100644 --- a/packages/extension/src/providers/polkadot/types/substrate-network.ts +++ b/packages/extension/src/providers/polkadot/types/substrate-network.ts @@ -9,7 +9,6 @@ import createIcon from '../libs/blockies'; import MarketData from '@/libs/market-data'; import BigNumber from 'bignumber.js'; import { - formatFiatValue, formatFloatingPointValue, } from '@/libs/utils/number-formatter'; import Sparkline from '@/libs/sparkline'; @@ -160,7 +159,7 @@ export class SubstrateNetwork extends BaseNetwork { balance: balances[idx].toString(), balancef: formatFloatingPointValue(userBalance).value, balanceUSD: usdBalance.toNumber(), - balanceUSDf: formatFiatValue(usdBalance.toString()).value, + balanceUSDf: usdBalance.toString(), decimals: st.decimals, icon: st.icon, name: st.name, diff --git a/packages/extension/src/providers/polkadot/ui/send-transaction/components/send-token-item.vue b/packages/extension/src/providers/polkadot/ui/send-transaction/components/send-token-item.vue index 446c56525..9de125a4f 100644 --- a/packages/extension/src/providers/polkadot/ui/send-transaction/components/send-token-item.vue +++ b/packages/extension/src/providers/polkadot/ui/send-transaction/components/send-token-item.vue @@ -17,8 +17,8 @@
-

{{ $filters.formatFiatValue(tokenBalance).value }}

-

@{{ $filters.formatFiatValue(tokenPrice).value }}

+

{{ $filters.parseCurrency(tokenBalance) }}

+

@{{ $filters.parseCurrency(tokenPrice) }}

diff --git a/packages/extension/src/providers/solana/types/sol-network.ts b/packages/extension/src/providers/solana/types/sol-network.ts index 0135e6120..9f8c7787b 100644 --- a/packages/extension/src/providers/solana/types/sol-network.ts +++ b/packages/extension/src/providers/solana/types/sol-network.ts @@ -7,7 +7,6 @@ import { CoingeckoPlatform, NetworkNames, SignerType } from '@enkryptcom/types'; import createIcon from '../libs/blockies'; import { Activity } from '@/types/activity'; import { - formatFiatValue, formatFloatingPointValue, } from '@/libs/utils/number-formatter'; import MarketData from '@/libs/market-data'; @@ -125,14 +124,13 @@ export class SolanaNetwork extends BaseNetwork { balance: balance, balancef: formatFloatingPointValue(userBalance).value, balanceUSD: usdBalance.toNumber(), - balanceUSDf: formatFiatValue(usdBalance.toString()).value, + balanceUSDf: usdBalance.toString(), icon: this.icon, name: this.name_long, symbol: this.currencyName, value: marketData.length ? currentPrice.toString() : '0', - valuef: formatFiatValue( + valuef: marketData.length ? currentPrice.toString() : '0', - ).value, contract: '', decimals: this.decimals, sparkline: marketData.length diff --git a/packages/extension/src/providers/solana/ui/send-transaction/components/send-address-input.vue b/packages/extension/src/providers/solana/ui/send-transaction/components/send-address-input.vue index 7aea88d55..da9d4bfa8 100644 --- a/packages/extension/src/providers/solana/ui/send-transaction/components/send-address-input.vue +++ b/packages/extension/src/providers/solana/ui/send-transaction/components/send-address-input.vue @@ -66,11 +66,13 @@ const solAddress = computed(() => { if (props.value) return props.network.displayAddress(props.value); else return props.value; }); + const address = computed({ - get: () => - isFocus.value - ? solAddress.value - : replaceWithEllipsis(solAddress.value, 6, 6), + get: () => { + if (isFocus.value) return solAddress.value; + if (solAddress.value.length < 13) return solAddress.value; + return replaceWithEllipsis(solAddress.value, 6, 6); + }, set: value => emit('update:inputAddress', value), }); diff --git a/packages/extension/src/providers/solana/ui/send-transaction/index.vue b/packages/extension/src/providers/solana/ui/send-transaction/index.vue index 8e44c2b8e..c347d478d 100644 --- a/packages/extension/src/providers/solana/ui/send-transaction/index.vue +++ b/packages/extension/src/providers/solana/ui/send-transaction/index.vue @@ -704,7 +704,11 @@ const inputAddressFrom = (text: string) => { const inputAddressTo = async (text: string) => { const debounceResolve = debounce(() => { nameResolver - .resolveName(text, [props.network.name as CoinType, 'ETH']) + .resolveName( + text, + [props.network.name as CoinType, 'ETH'], + props.network.provider as string, + ) .then(resolved => { if (resolved) { addressTo.value = resolved; diff --git a/packages/extension/src/providers/solana/ui/sol-verify-transaction.vue b/packages/extension/src/providers/solana/ui/sol-verify-transaction.vue index 08d9fcdc8..ee348f08d 100644 --- a/packages/extension/src/providers/solana/ui/sol-verify-transaction.vue +++ b/packages/extension/src/providers/solana/ui/sol-verify-transaction.vue @@ -69,7 +69,7 @@

{{ item.isNegative ? '-' : '' }} - ${{ $filters.formatFiatValue(parseFloat(item.USDval)).value }} + {{ $filters.parseCurrency(parseFloat(item.USDval)) }}

diff --git a/packages/extension/src/ui/action/composables/account-info.ts b/packages/extension/src/ui/action/composables/account-info.ts index 387c63d18..6143536b3 100644 --- a/packages/extension/src/ui/action/composables/account-info.ts +++ b/packages/extension/src/ui/action/composables/account-info.ts @@ -2,7 +2,7 @@ import MarketData from '@/libs/market-data'; import { BaseNetwork } from '@/types/base-network'; import { computed, ref, watch, onMounted, Ref } from 'vue'; import { AccountsHeaderData } from '../types/account'; -import { formatFloatingPointValue, formatFiatValue } from '../utils/filters'; +import { formatFloatingPointValue } from '../utils/filters'; const defaultFiatVal = '0.00'; export default ( network: Ref, @@ -31,14 +31,11 @@ export default ( const updateFiatValues = async () => { fiatAmount.value = defaultFiatVal; if (network.value.coingeckoID && cryptoAmountRaw.value != '~') { - fiatAmount.value = `${formatFiatValue( - await marketData.getTokenValue( - cryptoAmountRaw.value, - network.value.coingeckoID, - 'USD', - ), - ).value - }`; + fiatAmount.value = `${await marketData.getTokenValue( + cryptoAmountRaw.value, + network.value.coingeckoID, + 'USD', + )}`; } }; watch(cryptoAmount, updateFiatValues); diff --git a/packages/extension/src/ui/action/utils/filters.ts b/packages/extension/src/ui/action/utils/filters.ts index f4551b72a..9d1bc2112 100644 --- a/packages/extension/src/ui/action/utils/filters.ts +++ b/packages/extension/src/ui/action/utils/filters.ts @@ -21,21 +21,16 @@ export const replaceWithEllipsis = ( }; export const parseCurrency = (value: string | number): string => { - const bnValue = BigNumber(value); - const parsedValue = bnValue.isNaN() || bnValue.isZero() || value === undefined ? "0" : bnValue.toString().replace(/,/g, ''); + const raw = value.toString().replace(/[,<]/g, ''); const store = useCurrencyStore(); const currency = store.currentSelectedCurrency; - const currencyCode = - LANG_INFO[currency as keyof typeof LANG_INFO].locale || 'en-US'; - const findRate = store.currencyList.find(c => c.fiat_currency === currency); - const rate = findRate || { exchange_rate: 1 }; + const locale = LANG_INFO[currency as keyof typeof LANG_INFO]?.locale || 'en-US'; + const exchangeRate = store.currencyList.find(c => c.fiat_currency === currency)?.exchange_rate || 1; - return new Intl.NumberFormat(currencyCode, { - style: 'currency', - currency: currency, - }).format( - parseFloat(BigNumber(parsedValue).times(rate.exchange_rate).toString()), - ); + const amount = new BigNumber(raw); + const finalValue = amount.isNaN() || amount.isZero() ? 0 : amount.times(exchangeRate).toNumber(); + const notation = BigNumber(finalValue).gt(999999) ? 'compact' : 'standard'; + return `${amount.lt(0.0000001) && amount.gt(0) ? '< ' : ''}${new Intl.NumberFormat(locale, { style: 'currency', currency: currency, notation, }).format(finalValue)}` }; export const truncate = (value: string, length: number): string => { @@ -55,8 +50,8 @@ export const formatDuration = ( isoString.match(/T((\d+)H)?((\d+)M)?(([\d]+)(\.(\d+))?S)?/) ?? []; if (duration.hours() < 0) - return `${h.padStart(2, '0')}:${m.padStart(2, '0')}:${s.padStart(2, '0')}`; + return `${h.padStart(2, '0')}:${m.padStart(2, '0')}:${s.padStart(2, '0')} `; - return `${m.padStart(2, '0')}:${s.padStart(2, '0')}`; + return `${m.padStart(2, '0')}:${s.padStart(2, '0')} `; }; export { formatFiatValue, formatFloatingPointValue }; diff --git a/packages/extension/src/ui/action/views/asset-detail-view/index.vue b/packages/extension/src/ui/action/views/asset-detail-view/index.vue index 3ccd0ca5f..fc0a90d4d 100644 --- a/packages/extension/src/ui/action/views/asset-detail-view/index.vue +++ b/packages/extension/src/ui/action/views/asset-detail-view/index.vue @@ -23,7 +23,7 @@ v-if="token.priceChangePercentage !== 0" class="asset-detail-view__token-sparkline-price" > -

${{ token.valuef }}

+

{{ $filters.parseCurrency(token.valuef) }}

-

{{ $filters.parseCurrency(token.balanceUSDf) }}

+

{{ $filters.parseCurrency(token.balanceUSD) }}

@{{ $filters.parseCurrency(token.value) }}

diff --git a/packages/extension/src/ui/action/views/send-process/components/send-process-amount.vue b/packages/extension/src/ui/action/views/send-process/components/send-process-amount.vue index a75d9a350..088cb9473 100644 --- a/packages/extension/src/ui/action/views/send-process/components/send-process-amount.vue +++ b/packages/extension/src/ui/action/views/send-process/components/send-process-amount.vue @@ -8,7 +8,7 @@ {{ fromBase(token.amount, token.decimals) }} {{ token.symbol }} -
{{ $filters.formatFiatValue(token.valueUSD).value }}
+
{{ $filters.parseCurrency(token.valueUSD) }}
diff --git a/packages/extension/src/ui/action/views/settings/components/settings-select.vue b/packages/extension/src/ui/action/views/settings/components/settings-select.vue index 6fbd6beab..f0c611f6c 100644 --- a/packages/extension/src/ui/action/views/settings/components/settings-select.vue +++ b/packages/extension/src/ui/action/views/settings/components/settings-select.vue @@ -72,7 +72,7 @@ const props = defineProps({ const searchedList = computed(() => { if (!searchInput.value) return props.list; const filtered = props.list.filter(item => - item.includes(searchInput.value.toUpperCase()), + item.fiat_currency.includes(searchInput.value.toUpperCase()), ); return filtered; }); diff --git a/packages/extension/src/ui/action/views/swap/components/send-address-input.vue b/packages/extension/src/ui/action/views/swap/components/send-address-input.vue index de2509de7..a67809aae 100644 --- a/packages/extension/src/ui/action/views/swap/components/send-address-input.vue +++ b/packages/extension/src/ui/action/views/swap/components/send-address-input.vue @@ -80,6 +80,7 @@ const address = computed({ } catch { displayAddress = props.value; } + if (displayAddress.length < 13) return displayAddress; return isFocus.value ? displayAddress : replaceWithEllipsis(displayAddress, 6, 6); diff --git a/packages/extension/src/ui/action/views/swap/index.vue b/packages/extension/src/ui/action/views/swap/index.vue index ad00e35f3..12b8b8df4 100644 --- a/packages/extension/src/ui/action/views/swap/index.vue +++ b/packages/extension/src/ui/action/views/swap/index.vue @@ -404,7 +404,11 @@ const setMax = () => { const inputAddress = (text: string) => { const debounceResolve = debounce(() => { nameResolver - .resolveName(text, [props.network.name as CoinType, 'ETH']) + .resolveName( + text, + [props.network.name as CoinType, 'ETH'], + props.network.provider as string, + ) .then(resolved => { if (resolved) { inputAddress(resolved); @@ -769,11 +773,12 @@ const sendButtonTitle = computed(() => { }); const isDisabled = computed(() => { + if (!fromToken.value!.balance) return true; if (!fromAmount.value || fromAmount.value === '0' || errors.value.inputAmount) return true; if ( BigNumber(fromAmount.value).gt( - fromBase(fromToken.value!.balance.toString(), fromToken.value.decimals), + fromBase(fromToken.value!.balance!.toString(), fromToken.value!.decimals), ) ) return true; diff --git a/packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-error.vue b/packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-error.vue index 1967db5c2..be7473af4 100644 --- a/packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-error.vue +++ b/packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-error.vue @@ -11,14 +11,14 @@ Not enough {{ nativeSymbol }} to pay the network
fee. You are ~{{ $filters.formatFloatingPointValue(nativeValue).value }} - {{ nativeSymbol }} (${{ $filters.formatFiatValue(price).value }}) short. + {{ nativeSymbol }} ({{ $filters.parseCurrency(price) }}) short.

diff --git a/packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/index.vue b/packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/index.vue index 4708a1eb0..7891613de 100644 --- a/packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/index.vue +++ b/packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/index.vue @@ -16,7 +16,7 @@ {{ $filters.formatFloatingPointValue(toReadable).value }} {{ toToken.symbol }} -

≈ {{ $filters.formatFiatValue(toTokenPrice).value }}

+

≈ {{ $filters.parseCurrency(toTokenPrice) }}