Commit 917189c4 authored by tom goriunov's avatar tom goriunov Committed by GitHub

Numbers over 16(?) digits are rounded in contract method fields (#1761)

* Numbers over 16(?) digits are rounded in contract method fields

Fixes #1750

* Update values.yaml.gotmpl

Changed public rpc to Sepolia

* Set NEXT_PUBLIC_NETWORK_ID

---------
Co-authored-by: default avatarYan Vaskov <72267126+yvaskov@users.noreply.github.com>
parent 36f9de66
...@@ -4,7 +4,7 @@ imagePullSecrets: ...@@ -4,7 +4,7 @@ imagePullSecrets:
- name: regcred - name: regcred
config: config:
network: network:
id: 5 id: 11155111
name: Blockscout name: Blockscout
shortname: Blockscout shortname: Blockscout
currency: currency:
...@@ -67,7 +67,8 @@ frontend: ...@@ -67,7 +67,8 @@ frontend:
NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL: https://gist.githubusercontent.com/maxaleks/ce5c7e3de53e8f5b240b88265daf5839/raw/328383c958a8f7ecccf6d50c953bcdf8ab3faa0a/security_reports_goerli_test.json NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL: https://gist.githubusercontent.com/maxaleks/ce5c7e3de53e8f5b240b88265daf5839/raw/328383c958a8f7ecccf6d50c953bcdf8ab3faa0a/security_reports_goerli_test.json
NEXT_PUBLIC_LOGOUT_URL: https://blockscoutcom.us.auth0.com/v2/logout NEXT_PUBLIC_LOGOUT_URL: https://blockscoutcom.us.auth0.com/v2/logout
NEXT_PUBLIC_HOMEPAGE_CHARTS: "['daily_txs','coin_price','market_cap']" NEXT_PUBLIC_HOMEPAGE_CHARTS: "['daily_txs','coin_price','market_cap']"
NEXT_PUBLIC_NETWORK_RPC_URL: https://rpc.ankr.com/eth_goerli NEXT_PUBLIC_NETWORK_RPC_URL: https://eth-sepolia.public.blastapi.io
NEXT_PUBLIC_NETWORK_ID: '11155111'
NEXT_PUBLIC_NETWORK_EXPLORERS: "[{'title':'Bitquery','baseUrl':'https://explorer.bitquery.io/','paths':{'tx':'/goerli/tx','address':'/goerli/address','token':'/goerli/token','block':'/goerli/block'}},{'title':'Etherscan','logo':'https://github.com/blockscout/frontend-configs/blob/main/configs/explorer-logos/etherscan.png?raw=true','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]" NEXT_PUBLIC_NETWORK_EXPLORERS: "[{'title':'Bitquery','baseUrl':'https://explorer.bitquery.io/','paths':{'tx':'/goerli/tx','address':'/goerli/address','token':'/goerli/token','block':'/goerli/block'}},{'title':'Etherscan','logo':'https://github.com/blockscout/frontend-configs/blob/main/configs/explorer-logos/etherscan.png?raw=true','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]"
NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace-categories/default.json NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace-categories/default.json
NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d
......
...@@ -9,8 +9,8 @@ interface Params { ...@@ -9,8 +9,8 @@ interface Params {
export interface MatchInt { export interface MatchInt {
isUnsigned: boolean; isUnsigned: boolean;
power: string; power: string;
min: number; min: bigint;
max: number; max: bigint;
} }
export default function useArgTypeMatchInt({ argType }: Params): MatchInt | null { export default function useArgTypeMatchInt({ argType }: Params): MatchInt | null {
......
...@@ -17,8 +17,11 @@ export default function useFormatFieldValue({ argType, argTypeMatchInt }: Params ...@@ -17,8 +17,11 @@ export default function useFormatFieldValue({ argType, argTypeMatchInt }: Params
} }
if (argTypeMatchInt) { if (argTypeMatchInt) {
// we have to store all numbers as strings to avoid precision loss
// and we cannot store them as BigInt because the NumberFormat component will not work properly
// so we just remove all white spaces here otherwise the `viem` library will throw an error on attempt to write value to a contract
const formattedString = value.replace(/\s/g, ''); const formattedString = value.replace(/\s/g, '');
return parseInt(formattedString); return formattedString;
} }
if (argType === 'bool') { if (argType === 'bool') {
......
...@@ -20,7 +20,7 @@ export default function useValidateField({ isOptional, argType, argTypeMatchInt ...@@ -20,7 +20,7 @@ export default function useValidateField({ isOptional, argType, argTypeMatchInt
// some values are formatted before they are sent to the validator // some values are formatted before they are sent to the validator
// see ./useFormatFieldValue.tsx hook // see ./useFormatFieldValue.tsx hook
return React.useCallback((value: string | number | boolean | undefined) => { return React.useCallback((value: string | boolean | undefined) => {
if (value === undefined || value === '') { if (value === undefined || value === '') {
return isOptional ? true : 'Field is required'; return isOptional ? true : 'Field is required';
} }
...@@ -41,11 +41,19 @@ export default function useValidateField({ isOptional, argType, argTypeMatchInt ...@@ -41,11 +41,19 @@ export default function useValidateField({ isOptional, argType, argTypeMatchInt
} }
if (argTypeMatchInt) { if (argTypeMatchInt) {
if (typeof value !== 'number' || Object.is(value, NaN)) { const valueBi = (() => {
try {
return BigInt(value);
} catch (error) {
return null;
}
})();
if (typeof value !== 'string' || valueBi === null) {
return 'Invalid integer format'; return 'Invalid integer format';
} }
if (value > argTypeMatchInt.max || value < argTypeMatchInt.min) { if (valueBi > argTypeMatchInt.max || valueBi < argTypeMatchInt.min) {
const lowerBoundary = argTypeMatchInt.isUnsigned ? '0' : `-1 * 2 ^ ${ Number(argTypeMatchInt.power) - 1 }`; const lowerBoundary = argTypeMatchInt.isUnsigned ? '0' : `-1 * 2 ^ ${ Number(argTypeMatchInt.power) - 1 }`;
const upperBoundary = argTypeMatchInt.isUnsigned ? `2 ^ ${ argTypeMatchInt.power } - 1` : `2 ^ ${ Number(argTypeMatchInt.power) - 1 } - 1`; const upperBoundary = argTypeMatchInt.isUnsigned ? `2 ^ ${ argTypeMatchInt.power } - 1` : `2 ^ ${ Number(argTypeMatchInt.power) - 1 } - 1`;
return `Value should be in range from "${ lowerBoundary }" to "${ upperBoundary }" inclusively`; return `Value should be in range from "${ lowerBoundary }" to "${ upperBoundary }" inclusively`;
......
...@@ -2,7 +2,7 @@ import _set from 'lodash/set'; ...@@ -2,7 +2,7 @@ import _set from 'lodash/set';
import type { SmartContractMethodInput } from 'types/api/contract'; import type { SmartContractMethodInput } from 'types/api/contract';
export type ContractMethodFormFields = Record<string, string | boolean | number | undefined>; export type ContractMethodFormFields = Record<string, string | boolean | undefined>;
export const INT_REGEXP = /^(u)?int(\d+)?$/i; export const INT_REGEXP = /^(u)?int(\d+)?$/i;
...@@ -11,9 +11,9 @@ export const BYTES_REGEXP = /^bytes(\d+)?$/i; ...@@ -11,9 +11,9 @@ export const BYTES_REGEXP = /^bytes(\d+)?$/i;
export const ARRAY_REGEXP = /^(.*)\[(\d*)\]$/; export const ARRAY_REGEXP = /^(.*)\[(\d*)\]$/;
export const getIntBoundaries = (power: number, isUnsigned: boolean) => { export const getIntBoundaries = (power: number, isUnsigned: boolean) => {
const maxUnsigned = 2 ** power; const maxUnsigned = BigInt(2 ** power);
const max = isUnsigned ? maxUnsigned - 1 : maxUnsigned / 2 - 1; const max = isUnsigned ? maxUnsigned - BigInt(1) : maxUnsigned / BigInt(2) - BigInt(1);
const min = isUnsigned ? 0 : -maxUnsigned / 2; const min = isUnsigned ? BigInt(0) : -maxUnsigned / BigInt(2);
return [ min, max ]; return [ min, max ];
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment