From 1e8c8cd5441412f992326ec1110effae02ffe6bd Mon Sep 17 00:00:00 2001 From: Tom Beynon Date: Sat, 5 Mar 2022 23:11:01 +0000 Subject: [PATCH 1/2] Bug fixes and stability --- Dockerfile | 2 ++ src/components/Delegations.js | 8 ++++++-- src/components/Wallet.js | 10 ++++++++-- src/index.js | 3 ++- src/utils/SigningClient.mjs | 1 - 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index bb98489c..ef79d7ab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,5 +6,7 @@ COPY package*.json ./ RUN npm install COPY . ./ +ENV NODE_ENV=development + EXPOSE 3000 CMD npm run start diff --git a/src/components/Delegations.js b/src/components/Delegations.js index 632e3a31..54fc731d 100644 --- a/src/components/Delegations.js +++ b/src/components/Delegations.js @@ -39,6 +39,10 @@ class Delegations extends React.Component { } async componentDidUpdate(prevProps){ + if(this.props.network !== prevProps.network){ + clearInterval(this.state.refreshInterval); + } + if(!this.props.address) return if(this.props.address !== prevProps.address){ @@ -77,7 +81,7 @@ class Delegations extends React.Component { this.setState({ rewards: rewards }); }, (error) => { - if([404, 500].includes(error.response.status)){ + if([404, 500].includes(error.response && error.response.status)){ this.setState({ rewards: {} }); }else{ this.setState({ error: 'Failed to get rewards. Please refresh' }); @@ -107,7 +111,7 @@ class Delegations extends React.Component { operatorGrants: _.set(state.operatorGrants, botAddress, operatorGrant) })) }, (error) => { - if (error.response.status === 501) { + if (error.response && error.response.status === 501) { this.setState({ authzMissing: true }); }else{ this.setState({ error: 'Failed to get grants. Please refresh' }); diff --git a/src/components/Wallet.js b/src/components/Wallet.js index 253e9f65..912c2cd0 100644 --- a/src/components/Wallet.js +++ b/src/components/Wallet.js @@ -23,7 +23,14 @@ class Wallet extends React.Component { } componentDidUpdate(prevProps) { + if(this.props.network !== prevProps.network){ + clearInterval(this.state.refreshInterval); + } + + if(!this.props.address) return + if(this.props.address !== prevProps.address){ + clearInterval(this.state.refreshInterval); this.getDelegations() this.refreshInterval() } @@ -34,7 +41,6 @@ class Wallet extends React.Component { } refreshInterval(){ - clearInterval(this.state.refreshInterval); const interval = setInterval(() => { this.getDelegations() }, 30_000) @@ -55,7 +61,7 @@ class Wallet extends React.Component { }); }, (error) => { - if(error.response && [404, 500].includes(error.response.status)){ + if([404, 500].includes(error.response && error.response.status)){ this.setState({ isLoaded: true, delegations: {}, diff --git a/src/index.js b/src/index.js index 8bd7d67a..1a0650e9 100644 --- a/src/index.js +++ b/src/index.js @@ -16,7 +16,8 @@ import reportWebVitals from './utils/reportWebVitals'; Bugsnag.start({ apiKey: '5cda10bb1c98f351cd0b722a1535d8c2', plugins: [new BugsnagPluginReact()], - enabledReleaseStages: [ 'production', 'staging' ] + enabledReleaseStages: [ 'production', 'staging' ], + releaseStage: process.env.NODE_ENV }) const ErrorBoundary = Bugsnag.getPlugin('react') diff --git a/src/utils/SigningClient.mjs b/src/utils/SigningClient.mjs index 75d415aa..6a5bdcee 100644 --- a/src/utils/SigningClient.mjs +++ b/src/utils/SigningClient.mjs @@ -32,7 +32,6 @@ const SigningClient = async (rpcUrl, chainId, defaultGasPrice, signer, key) => { const getFee = (gas, gasPrice) => { if(!gas) gas = 200_000 if(!gasPrice) gasPrice = GasPrice.fromString(defaultGasPrice); - console.log(gas, gasPrice, defaultGasPrice) return calculateFee(gas, gasPrice); } From 890c44c0243132a4cac10e8d080edae506fb1d14 Mon Sep 17 00:00:00 2001 From: Tom Beynon Date: Sat, 5 Mar 2022 23:11:17 +0000 Subject: [PATCH 2/2] Get validators in batches if required --- scripts/autostake.mjs | 4 +-- src/utils/Network.mjs | 2 +- src/utils/RestClient.mjs | 66 +++++++++++++++++++++++++--------------- 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/scripts/autostake.mjs b/scripts/autostake.mjs index c0e8487f..144ec9b0 100644 --- a/scripts/autostake.mjs +++ b/scripts/autostake.mjs @@ -120,8 +120,8 @@ class Autostake { } getDelegations(client) { - return client.restClient.getAllValidatorDelegations(client.operator.address, 250, (batches, total) => { - console.log("...batch", batches.length) + return client.restClient.getAllValidatorDelegations(client.operator.address, 250, (pages) => { + console.log("...batch", pages.length) }).catch(error => { console.log("ERROR:", error) process.exit() diff --git a/src/utils/Network.mjs b/src/utils/Network.mjs index f8804805..207980de 100644 --- a/src/utils/Network.mjs +++ b/src/utils/Network.mjs @@ -31,7 +31,7 @@ const Network = async (data) => { } const getValidators = () => { - return restClient.getValidators() + return restClient.getAllValidators(150) } return { diff --git a/src/utils/RestClient.mjs b/src/utils/RestClient.mjs index 5d7a6d51..660d5bbd 100644 --- a/src/utils/RestClient.mjs +++ b/src/utils/RestClient.mjs @@ -6,15 +6,22 @@ const RestClient = async (chainId, restUrls) => { const restUrl = await findAvailableUrl(Array.isArray(restUrls) ? restUrls : [restUrls]) - const getValidators = () => { - return axios.get(restUrl + "/cosmos/staking/v1beta1/validators?status=BOND_STATUS_BONDED&pagination.limit=500") + const getAllValidators = (pageSize, pageCallback) => { + return getAllPages((nextKey) => { + return getValidators(pageSize, nextKey) + }, pageCallback).then(pages => { + const validators = _.shuffle(pages.map(el => el.validators).flat()) + return validators.reduce((a, v) => ({ ...a, [v.operator_address]: v}), {}) + }) + } + + const getValidators = (pageSize, nextKey) => { + const searchParams = new URLSearchParams() + searchParams.append('status', 'BOND_STATUS_BONDED') + if(pageSize) searchParams.append('pagination.limit', pageSize) + if(nextKey) searchParams.append('pagination.key', nextKey) + return axios.get(restUrl + "/cosmos/staking/v1beta1/validators?" + searchParams.toString()) .then(res => res.data) - .then( - (result) => { - const validators = _.shuffle(result.validators).reduce((a, v) => ({ ...a, [v.operator_address]: v}), {}) - return validators - } - ) } const getBalance = (address, denom) => { @@ -82,20 +89,12 @@ const RestClient = async (chainId, restUrls) => { ) } - const getAllValidatorDelegations = async (validatorAddress, pageSize, pageCallback) => { - let batches = [] - let nextKey, error - do { - try { - const result = await getValidatorDelegations(validatorAddress, pageSize, nextKey) - batches.push(result.delegation_responses) - nextKey = result.pagination.next_key - if(pageCallback) pageCallback(batches, result.pagination.total) - } catch (err) { - error = err - } - } while (nextKey && !error) - return batches.flat() + const getAllValidatorDelegations = (validatorAddress, pageSize, pageCallback) => { + return getAllPages((nextKey) => { + return getValidatorDelegations(validatorAddress, pageSize, nextKey) + }, pageCallback).then(pages => { + return pages.map(el => el.delegation_responses).flat() + }) } const getValidatorDelegations = (validatorAddress, pageSize, nextKey) => { @@ -107,6 +106,22 @@ const RestClient = async (chainId, restUrls) => { .then(res => res.data) } + const getAllPages = async (getPage, pageCallback) => { + let pages = [] + let nextKey, error + do { + try { + const result = await getPage(nextKey) + pages.push(result) + nextKey = result.pagination.next_key + if(pageCallback) pageCallback(pages) + } catch (err) { + error = err + } + } while (nextKey && !error) + return pages + } + function findAvailableUrl(urls){ return findAsync(urls, (url) => { return axios.get(url + '/node_info', {timeout: 2000}) @@ -122,13 +137,14 @@ const RestClient = async (chainId, restUrls) => { return { connected: !!restUrl, restUrl, + getAllValidators, getValidators, + getAllValidatorDelegations, + getValidatorDelegations, getBalance, getDelegations, getRewards, - getGrants, - getAllValidatorDelegations, - getValidatorDelegations + getGrants } }