From ba0eba874aedb9202acf80cbfea41e9d0424b4dd Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 25 Feb 2020 22:34:25 -0500 Subject: [PATCH] release (#363) * Fabo/fix gas (#250) * fix gas estimate * linted * fixed test * do not keep data sources (#251) * track failing transactions in Sentry (#249) * correctly set the tx schema for a failing tx (#248) * Fabo/remove per block caching as not working (#247) * remove per block caching as not working * fix memoized results Co-authored-by: Ana G. <40721795+Bitcoinera@users.noreply.github.com> * delete perblockcachedatasource (#253) * Ana/fix balances in actionmodal (#255) * fix action modal available balance * include regen * use dictionary for denomlookup * use correct events for received txs (#257) * enable account creation for some networks (#252) * network update time metric added (#256) * network update time metric added * added missing dep Co-authored-by: Fabian * Fix proposal deposit (#261) * Remove denom handling from getDeposit() * Revert undesired change * delete package-lock.json * localtestnet config change (#265) * Ana/handle "address not from this network" error (#263) * add check address function for all queries * apply suggestions * Ana/add fiatvalue to balances query (e-Money) (#262) * preparation * more preparation * add fiatvalue field to balances query * fix get account info * apply suggestions * apply one last suggestion * suggestions+ Co-authored-by: Fabian * Ana/emoney fix expected returns with inflation and totalbacked (#243) * fix expected returns with inflation and supply * minor fixes. dictionary * query exchange rates from emoney api * fix infinite expected returns * convert api url to const * add eur value to totalbackedvalue. totalngm gains * add important comment * finish calculation * lint * catch errors with sentry Co-authored-by: Fabian * readd coin conversion (#268) * delete amount field (#274) * Fabo/increase gas again (#271) * icrease gas again * fixed test * Fabo/load all txs (even if more then first page in response) (#270) * load all txs (even if more then first page in response) * improved handling of txs * missing renaming * fixed paginated load * add pagination fix also to cosmosV0-source Co-authored-by: iambeone Co-authored-by: Ana G. <40721795+Bitcoinera@users.noreply.github.com> * fixing issue with multiple senders in one event (#273) * fixing issue with multiple senders in one event * Update lib/source/cosmosV2-source.js Co-authored-by: Fabian * Fabo/allow signing for terra + emoney (#267) * allow signing for terra * readd coin conversion * enable actions for terra * fix correct terra testnet url * comments and guards * enabled more txs for emoney and fixed broadcasting * added a catch for wrongly formatted broadcast urls * recover default field. change some network titles (#277) * Fabo/add network data to API (#278) * non desctructive introduction of better address prefix wording * added address creator to API * adjusted test * added ledger app to networks config * add icon property to schema (#281) * add icon property to schema * fix network schema validation Co-authored-by: Ana G. <40721795+Bitcoinera@users.noreply.github.com> * filter out validator specific txs (#279) * Ana/balances coinreducer good fix (#269) * balances coinreducer good fix * refactored fiat value logic Co-authored-by: Fabian * Create network_integration.md * Update network_integration.md * Update network_integration.md * Fabo/avoid 500 errors (#288) * avoid using the latest query * cleanup * Ana/filter validator tx cross network and add txvalue reducer (#285) * filter validators cross network * add value reducer. necessary for multi claim txs * add validator txs filter also for cosmosv0 source * filter and make array only claim rewards msg value * filter txs by whitelist * change length in multi claim reward reducer * add withdrawvalidators * replace dictionary for set * refactor transaction snippet. avoid repetition * Ana/emoney upgrade (mergeable) (#282) * update emoney api_url * fix denom. add default fiat currency * fix rpc endpoint * fix value (my bad) (#293) * fix value (my bad) * trigger another ci flow * erase space * set correct new chain id (#294) * restart API * restart API * fix pr alert (#297) * Fabo/298 tendermint reconnect (#300) * reconnect on tendermint disconnect * cleanup * comments * Update cosmos-node-subscription.js * Fabo/299 trigger a chain hangup error (#301) * trigger a chain hangup error * increase chain hangup time * Apply suggestions from code review * Fabo/store validator addresses (#296) * add validator addresses to db * linted * ignore in local dev * revert * fixed fetch * comment * refactored db into constructor * cleanup * add clearTimeout to avoid reconnection hell (#306) * add clearTimeout to avoid reconnection hell * removed console.log * Aleksei/luniedb replaced (#303) * add validator addresses to db * linted * ignore in local dev * revert * fixed fetch * comment * refactored db into constructor * cleanup * replaced luniedb * linted Co-authored-by: Fabian * disable reconnection logic * clear polling interval for tendermint connection * simple api fixes (#310) * Fabo/remove tendermint (#311) * remove tendermint * fixed empty blockHeight issue * small refactoring * catch on fetches to get logging * delay block updates * add retry logic * refactored getBlockByHeight * remove pm2 dep * validator profiles were returned as array (#312) * remove pr github action (#316) * fixing caching issue and more (#315) * fixing caching issue and more * clear chain hangup timeout * timeout fixed * Update lib/block-listeners/cosmos-node-subscription.js Co-authored-by: Jordan Bibla * added terra_mainnet to networks (#309) * added terra_mainnet to networks * errors fix reverted * Ana/add multidenom rewards. necessary for emoney (#308) * add multidenom rewards. necessary for emoney * add rewards to overview. improve code location * lint * add filter rewards for multidenom * important fix * another important fix * fix cannot read propery constructor of undefined (#318) * change terra mainnet title * pushing something to trigger new build and to restart the node * trying out nylira's node * WIP: Ana/More Terra fixes (#323) * fixing my mess * move all rewards logic to terra * clearly signal single denom rewards * Revert "WIP: Ana/More Terra fixes (#323)" (#325) This reverts commit 408186a3ef743ca51d513eb91c937f49960e7492. * catch inside block polling function (#327) * Fabo/disable writing validator addresses for now (#329) * disable writing validator addresses for now * linted * flushing http cache (#332) * Transaction abstraction schema (#333) * tx abstraction proposal using union * Use Coin type * Cleanup, TransactionV2 * Cleanup, not multisend tx * Unsupported tx (like multisend) don't have details * Fabo/switch to docker swarm mode (#330) * swtich to docker swarm mode * typo * Update .github/workflows/development.yml * Ana/more terra fixes (***THE COMEBACK***) (#324) * fixing my mess * move all rewards logic to terra * clearly signal single denom rewards * error structure has changed. need to look into it * also return denom for single denom rewards * manage errors properly * delete comments * Update lib/reducers/terraV3-reducers.js * loop through transaction messages * doing crazy stuff * rewrite the crazy bit Co-authored-by: Fabian * cosmosv0 was missing the retry logic (#334) * add back validator to db logic (#335) * path_prefix added to network data (#338) * path_prefix added to network data * path_prefix replaced to slug * tests fixed * remove regen (#337) Co-authored-by: Jordan Bibla * Fabo+Mario/transaction abstraction (#336) * draft for transaction abstraction * use lunie message types * Add supported tx types * WIP * Draft new reducers * Fix msg types * Need to resolve type for TransactionDetails union * debug resolver * lint * Fix * Cleanup * fix some union issues * Almost done * Small fixes * Add userTransactionAddedV2 * Add userTransactionAddedV2 to resolvers Co-authored-by: Mario Pino * emoney fixes for fiatvalue (#345) * emoney fixes for fiatvalue * refactor with coinreducer * speaking functions are your friends * refactor ugly nested code * lint * add denoms lookups for terra and emoney (#346) * Ana/add only tokens gas prices 2nd attempt (#344) * add terra and emoney gas price. terra reducer * delete fiatvalue from get balances in cosmos * add emoney reducer * hyper important emoney fixes * fix for emoney denoms * change gas price to micro units * add emoney denoms to denomlookup * transform to microunit also for terra tokens * return null for emoney gas prices * add harcoded gas prices * correct emoney hardcoded values * hardcoded terra gas prices. not working * update hardcoded values to working ones * delete unrelated changes to gas prices * apply suggestions except coinreducer * they call me mr coinreducer * change amount for price. add gas price reducer * change naming in gas price reducer * add error message Co-authored-by: Fabian * fix rewards denoms (#351) * updating image on deploy (#352) * fix my mess once more (#353) * Ana/add gas prices to other networks (#350) * add gasprices to cosmos * format gas prices to three decimals * Apply suggestions from code review * Update lib/reducers/cosmosV0-reducers.js Co-authored-by: Fabian Co-authored-by: Jordan Bibla * added a tx success push, fallback (#354) * fix cosmos gas price (#355) * fix terra for new tmbalance (#358) * Fabo/new emoney rewards (#357) * intent to fix the emoney rewards * intent to fix emoney rewards * simplified code * comments * hack to fix reduce function * eligable -> eligible * correct reducer fix Co-authored-by: Ana G. <40721795+Bitcoinera@users.noreply.github.com> Co-authored-by: Jordan Bibla * Aleksei/prevent constant db calls (#304) * add validator addresses to db * linted * ignore in local dev * revert * fixed fetch * comment * refactored db into constructor * cleanup * prevent constant db interaction * stored object structure changed * remove nesting in validators * filter validators list Co-authored-by: Fabian * limit txs pages load by two pages per request (#314) * limit txs pages load by two pages per request * delete block from loadpaginatedtxs * small fixes * Update lib/source/cosmosV2-source.js * linted Co-authored-by: Ana G. <40721795+Bitcoinera@users.noreply.github.com> Co-authored-by: Fabian * linted * linted Co-authored-by: Ana G. <40721795+Bitcoinera@users.noreply.github.com> Co-authored-by: Aleksey Rudometov Co-authored-by: Mario Pino Co-authored-by: Jordan Bibla --- .github/workflows/development.yml | 2 +- .github/workflows/production.yml | 2 +- .../cosmos-node-subscription.js | 26 +++++++- lib/controller/transaction/index.js | 5 ++ lib/reducers/cosmosV0-reducers.js | 47 +++++++++++---- lib/reducers/emoneyV0-reducers.js | 59 +++++++------------ lib/reducers/terraV3-reducers.js | 22 +------ lib/source/cosmosV0-source.js | 23 +++++++- lib/source/cosmosV2-source.js | 38 ++++++++++-- lib/source/emoneyV0-source.js | 10 ++-- lib/source/terraV3-source.js | 10 ++-- 11 files changed, 154 insertions(+), 90 deletions(-) diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml index cea5618389..4eb92d1b84 100644 --- a/.github/workflows/development.yml +++ b/.github/workflows/development.yml @@ -25,6 +25,6 @@ jobs: - name: Installing Docker Compose run: ssh root@157.245.121.175 "sudo curl -L \"https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)\" -o /usr/local/bin/docker-compose; sudo chmod +x /usr/local/bin/docker-compose" - name: Run on Digital Ocean - run: ssh root@157.245.121.175 "docker image prune -a -f; docker load < lunieapi.tgz;export HASURA_URL="https://staging-db.lunie.io/v1/graphql"; export HASURA_ADMIN_KEY="${{ secrets.LUNIE_STAGING_DB_KEY }}"; export SENTRY_DSN="${{ secrets.SENTRY_DSN }}"; docker stack deploy -c docker-compose.yml lunieapi" + run: ssh root@157.245.121.175 "docker image prune -a -f; docker load < lunieapi.tgz;export HASURA_URL="https://staging-db.lunie.io/v1/graphql"; export HASURA_ADMIN_KEY="${{ secrets.LUNIE_STAGING_DB_KEY }}"; export SENTRY_DSN="${{ secrets.SENTRY_DSN }}"; docker stack deploy -c docker-compose.yml lunieapi; docker service update --image lunieapi:latest --force lunieapi_lunieapi" - name: Setting up cron job for pm2 metrics export run: ssh root@157.245.121.175 "mkdir /logs -p; touch /logs/show; line='*/1 * * * * docker exec lunieapi pm2 show 0 > /logs/show; perl /root/pm2metrics.pl'; crontab -l | grep -q 'lunieapi pm2' && true || (crontab -l; echo "$line" ) | crontab -" diff --git a/.github/workflows/production.yml b/.github/workflows/production.yml index b00160d3db..f775579143 100644 --- a/.github/workflows/production.yml +++ b/.github/workflows/production.yml @@ -25,6 +25,6 @@ jobs: - name: Installing Docker Compose run: ssh root@167.71.107.214 "sudo curl -L \"https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)\" -o /usr/local/bin/docker-compose; sudo chmod +x /usr/local/bin/docker-compose" - name: Run on Digital Ocean - run: ssh root@167.71.107.214 "docker image prune -a -f; docker load < lunieapi.tgz;export HASURA_URL="https://production-db.lunie.io/v1/graphql"; export HASURA_ADMIN_KEY="${{ secrets.LUNIE_PRODUCTION_DB_KEY }}"; export SENTRY_DSN="${{ secrets.SENTRY_DSN_PRODUCTION }}"; docker stack deploy -c docker-compose.yml lunieapi" + run: ssh root@167.71.107.214 "docker image prune -a -f; docker load < lunieapi.tgz;export HASURA_URL="https://production-db.lunie.io/v1/graphql"; export HASURA_ADMIN_KEY="${{ secrets.LUNIE_PRODUCTION_DB_KEY }}"; export SENTRY_DSN="${{ secrets.SENTRY_DSN_PRODUCTION }}"; docker stack deploy -c docker-compose.yml lunieapi; docker service update --image lunieapi:latest --force lunieapi_lunieapi" - name: Setting up cron job for pm2 metrics export run: ssh root@167.71.107.214 "mkdir /logs -p; touch /logs/show; line='*/1 * * * * docker exec lunieapi pm2 show 0 > /logs/show; perl /root/pm2metrics.pl'; crontab -l | grep -q 'lunieapi pm2' && true || (crontab -l; echo "$line" ) | crontab -" diff --git a/lib/block-listeners/cosmos-node-subscription.js b/lib/block-listeners/cosmos-node-subscription.js index 3941464be7..434014b633 100644 --- a/lib/block-listeners/cosmos-node-subscription.js +++ b/lib/block-listeners/cosmos-node-subscription.js @@ -21,6 +21,7 @@ class CosmosNodeSubscription { this.network = network this.cosmosAPI = new CosmosApiClass(network) this.store = store + this.validators = [] const networkSchemaName = this.network.id.replace(/-/g, '_') this.db = new database(config)(networkSchemaName) this.chainHangup = undefined @@ -120,7 +121,30 @@ class CosmosNodeSubscription { // this adds all the validator addresses to the database so we can easily check in the database which ones have an image and which ones don't async updateDBValidatorProfiles(validators) { - const validatorRows = validators.map(({ operatorAddress, name }) => ({ + // filter only new validators + let newValidators = validators.filter( + validator => + !this.validators.find( + v => + v.address == validator.operatorAddress && v.name == validator.name // in case if validator name was changed + ) + ) + // save all new validators to an array + this.validators = [ + ...this.validators.filter( + ({ operatorAddress }) => + !newValidators.find( + ({ operatorAddress: newValidatorOperatorAddress }) => + newValidatorOperatorAddress === operatorAddress + ) + ), + ...newValidators.map(v => ({ + address: v.operatorAddress, + name: v.name + })) + ] + // update only new onces + const validatorRows = newValidators.map(({ operatorAddress, name }) => ({ operator_address: operatorAddress, name })) diff --git a/lib/controller/transaction/index.js b/lib/controller/transaction/index.js index b18b8c601f..d35af23f9c 100644 --- a/lib/controller/transaction/index.js +++ b/lib/controller/transaction/index.js @@ -189,6 +189,11 @@ async function pollTransactionSuccess( } assertOk(res) + // publishUserTransactionAdded is also done in the block subscription + // but also here as a fallback + // TODO the client might now update twice as it receives the success twice, could be fine though + const transaction = reducers.transactionReducer(res, reducers) + publishUserTransactionAdded(networkId, senderAddress, transaction) } catch (error) { console.error('TX failed:', hash, error) let transaction diff --git a/lib/reducers/cosmosV0-reducers.js b/lib/reducers/cosmosV0-reducers.js index d3f070aac7..bacb3f0617 100644 --- a/lib/reducers/cosmosV0-reducers.js +++ b/lib/reducers/cosmosV0-reducers.js @@ -283,8 +283,28 @@ function coinReducer(coin) { } } -function balanceReducer(coin) { - return coin +function gasPriceReducer(gasPrice) { + if (!gasPrice) { + throw new Error( + 'The token you are trying to request data for is not supported by Lunie.' + ) + } + + // we want to show only atoms as this is what users know + const denom = denomLookup(gasPrice.denom) + return { + denom: denom, + price: BigNumber(gasPrice.price).div(1000000) // Danger: this might not be the case for all future tokens + } +} + +function balanceReducer(coin, gasPrices) { + return { + ...coin, + gasPrice: gasPriceReducer( + gasPrices.find(gasPrice => denomLookup(gasPrice.denom) === coin.denom) + ).price + } } function delegationReducer(delegation, validator) { @@ -312,7 +332,7 @@ function undelegationReducer(undelegation, validator) { function rewardReducer(reward, validator) { return { amount: atoms(reward.amount), - denom: reward.denom, + denom: denomLookup(reward.denom), validator } } @@ -401,18 +421,18 @@ function formatTransactionsReducer(txs, reducers) { const sortedTxs = sortBy(duplicateFreeTxs, ['timestamp']) const reversedTxs = reverse(sortedTxs) // here we filter out all transactions related to validators - let filteredTxs = [] + let filteredMsgs = [] reversedTxs.forEach(transaction => { - const index = transaction.tx.value.msg.findIndex(msg => - cosmosWhitelistedMessageTypes.has(msg.type.split('/')[1]) - ) - // only push transactions messages supported by Lunie - if (index !== -1) { - transaction.tx.value.msg = [transaction.tx.value.msg[index]] - filteredTxs.push(transaction) - } + transaction.tx.value.msg.forEach(msg => { + // only push transactions messages supported by Lunie + if (cosmosWhitelistedMessageTypes.has(msg.type.split('/')[1])) { + filteredMsgs.push(msg) + } + }) + transaction.tx.value.msg = filteredMsgs + filteredMsgs = [] }) - return filteredTxs.map(tx => transactionReducer(tx, reducers)) + return reversedTxs.map(tx => transactionReducer(tx, reducers)) } function transactionReducerV2(transaction, reducers) { @@ -635,6 +655,7 @@ module.exports = { blockReducer, delegationReducer, coinReducer, + gasPriceReducer, balanceReducer, transactionReducer, undelegationReducer, diff --git a/lib/reducers/emoneyV0-reducers.js b/lib/reducers/emoneyV0-reducers.js index 6ddbc9c545..b3cffc3fc1 100644 --- a/lib/reducers/emoneyV0-reducers.js +++ b/lib/reducers/emoneyV0-reducers.js @@ -67,54 +67,35 @@ async function expectedRewardsPerToken( inflations, totalBackedValues ) { - const percentTotalStakedNGM = BigNumber(validator.votingPower).times(1000) - const totalNGMStakedToValidator = validator.tokens - const division = BigNumber(percentTotalStakedNGM) + const percentOfAllEligibleStake = validator.votingPower + const totalStakeToValidator = validator.tokens // used to answer the question "How many rewards per ONE token invested?" + const percentOfAllRewardsPerToken = BigNumber(percentOfAllEligibleStake) .times(BigNumber(1).minus(BigNumber(commission))) - .div(BigNumber(totalNGMStakedToValidator)) + .div(BigNumber(totalStakeToValidator)) + // Now we need to multiply each total supply of backed tokens with its corresponding // inflation - let accumulator = BigNumber(0) const totalBackedValueDictionary = _.keyBy(totalBackedValues, 'denom') - - inflations.forEach(inflation => { - accumulator = BigNumber(accumulator) - .plus(accumulator) - .plus( - BigNumber(inflation.inflation) - .times(totalBackedValueDictionary[inflation.denom].amount) - .div(1000000) + const rewardsSumInEur = inflations.reduce((sum, inflation) => { + return BigNumber(sum).plus( + BigNumber(inflation.inflation).times( + totalBackedValueDictionary[inflation.denom].eurValue // we use the eur value to be able to sum up the individual token values ) - }) - const totalBackedValuesTimesInflations = accumulator - // First we calculate the total value of rewards we get for staking one single - // NGM in this particular validator - let delegatorSharePerToken = totalBackedValuesTimesInflations.div(division) - // In testnet some validators have commission at 100% and therefore division is - // equal to 0. Dividing by 0 we get infinity, and we want to make sure that - // we don't display such value - const infinity = new BigNumber(Infinity) - // This is just how BigNumber works. Comparing to 0 and if true, bignumber equals the given parameter. - // Documentation on this method can be found here: https://mikemcl.github.io/bignumber.js/#cmp - delegatorSharePerToken = - delegatorSharePerToken.comparedTo(infinity) === 0 - ? BigNumber(0) - : delegatorSharePerToken.div(1000000) - // Now we get the total net value in EUR of all token's total supplies - let eurAccumulator = 0 - totalBackedValues.forEach(totalBackedValue => { - eurAccumulator += totalBackedValue.eurValue - }) - const totalEURGains = eurAccumulator * delegatorSharePerToken.toNumber() + ) + }, 0) + + // now we calculate the total rewards in eur per token delegated to the validator + const totalEURGainsPerTokenInvested = BigNumber(rewardsSumInEur).times( + percentOfAllRewardsPerToken + ) + // How many NGM tokens can we buy with the total gain in EUR we make in a year's time? // 0.50€ is the price the NGM tokens will be first sold. Therefore, this is the official value // until they reach an exchange const pricePerNGM = 0.5 - const ngmGains = totalEURGains / pricePerNGM - // We divide by 1 because we assume 1 NGM > gain per 1 NGM - const expectedReturns = parseFloat(ngmGains / 1).toFixed(2) - // TODO the FE is the one converting to percentage now, so we need to divide by 100 - return expectedReturns / 100 + const ngmGains = totalEURGainsPerTokenInvested / pricePerNGM + + return ngmGains.toFixed(2) // we don't need more then a precision of 2 } module.exports = { diff --git a/lib/reducers/terraV3-reducers.js b/lib/reducers/terraV3-reducers.js index bb89c4316b..ba2e873456 100644 --- a/lib/reducers/terraV3-reducers.js +++ b/lib/reducers/terraV3-reducers.js @@ -1,6 +1,5 @@ const cosmosV2Reducers = require('./cosmosV2-reducers') -const BigNumber = require('bignumber.js') -const { atoms, denomLookup } = cosmosV2Reducers +const { atoms, denomLookup, gasPriceReducer } = cosmosV2Reducers // Terra has a slightly different structure and needs its own undelegationEndTimeReducer function undelegationEndTimeReducer(transaction) { @@ -25,25 +24,10 @@ function undelegationEndTimeReducer(transaction) { } } -function gasPriceReducer(gasPrice) { - if (!gasPrice) { - throw new Error( - 'The token you are trying to request data for is not supported by Lunie.' - ) - } - - // we want to show only atoms as this is what users know - const denom = denomLookup(gasPrice.denom) - return { - denom: denom, - price: BigNumber(gasPrice.price).div(1000000) // Danger: this might not be the case for all future tokens - } -} - function balanceReducer(coin, fiatValue, gasPrices) { return { ...coin, - fiatValue, + fiatValue: fiatValue || 0, gasPrice: gasPriceReducer( gasPrices.find(gasprice => denomLookup(gasprice.denom) === coin.denom) ).price @@ -62,7 +46,7 @@ function rewardReducer(rewards, validatorsDictionary) { formattedRewards.forEach(({ reward, validator }) => reward.forEach(denomReward => { multiDenomRewardsArray.push({ - denom: denomReward.denom, + denom: denomLookup(denomReward.denom), amount: atoms(denomReward.amount), validator: validator }) diff --git a/lib/source/cosmosV0-source.js b/lib/source/cosmosV0-source.js index 39b67026cb..2d9f0f8514 100644 --- a/lib/source/cosmosV0-source.js +++ b/lib/source/cosmosV0-source.js @@ -5,6 +5,17 @@ const _ = require('lodash') const { encodeB32, decodeB32, pubkeyToAddress } = require('../tools') const { UserInputError } = require('apollo-server') +const gasPrices = [ + { + denom: `uatom`, + price: '0.65e-2' + }, + { + denom: `umuon`, + price: '0.65e-2' + } +] + class CosmosV0API extends RESTDataSource { constructor(network) { super() @@ -14,6 +25,7 @@ class CosmosV0API extends RESTDataSource { this.networkTitle = network.title this.delegatorBech32Prefix = network.address_prefix this.validatorConsensusBech32Prefix = `${network.address_prefix}valcons` + this.gasPrices = gasPrices this.setReducers() } @@ -29,6 +41,15 @@ class CosmosV0API extends RESTDataSource { this.reducers = require('../reducers/cosmosV0-reducers') } + // hacky way to get error text + async getError(url) { + try { + return await this.get(url) + } catch (error) { + return error.extensions.response.body.error + } + } + async getRetry(url, intent = 0) { // check cache size, and flush it if it's bigger than something if ((await this.cache.getTotalSize()) > 100000) { @@ -322,7 +343,7 @@ class CosmosV0API extends RESTDataSource { let balances = response || [] const coins = balances.map(this.reducers.coinReducer) return coins.map(coin => { - return this.reducers.balanceReducer(coin) + return this.reducers.balanceReducer(coin, this.gasPrices) }) } diff --git a/lib/source/cosmosV2-source.js b/lib/source/cosmosV2-source.js index bee3345d3e..958b9231cf 100644 --- a/lib/source/cosmosV2-source.js +++ b/lib/source/cosmosV2-source.js @@ -1,4 +1,5 @@ const CosmosV0API = require('./cosmosV0-source') +const PAGE_RECORDS_COUNT = 100 class CosmosV2API extends CosmosV0API { setReducers() { @@ -16,28 +17,55 @@ class CosmosV2API extends CosmosV0API { } async loadPaginatedTxs(url, page = 1, totalAmount = 0) { - const pagination = `&limit=1000000000&page=${page}` + if (page < 1) { + return [] + } + const pagination = `&limit=${PAGE_RECORDS_COUNT}&page=${page}` let allTxs = [] const { txs, total_count } = await this.getRetry(`${url}${pagination}`) allTxs = allTxs.concat(txs) - + // limitation by totalAmount or by page limit + if (totalAmount !== 0 || page === 1) { + return allTxs + } // there is a bug in page_number in gaia-13007 so we can't use is if (allTxs.length + totalAmount < Number(total_count)) { return allTxs.concat( - await this.loadPaginatedTxs(url, page + 1, totalAmount + allTxs.length) + await this.loadPaginatedTxs(url, page - 1, totalAmount + allTxs.length) ) } return allTxs } + async getPageCount(url) { + // hacky way to get page count — requesting too many pages and fetching the error + let error = await this.getError( + url + `&limit=${PAGE_RECORDS_COUNT}&page=10000000000000` + ) + /* The error message received looks like this: + * { + * error: "TxSearch: response error: RPC error -32603 - Internal error: page should be within [0, 7] range, given 100" + * } + * We are therefor looking for [0, 7]. The latter of the 2 array entries gives us the last page. + */ + const pages = error.match(/\[[0-9]*, ([0-9]*)\]/) + return pages[1] + } + async getTransactions(address) { this.checkAddress(address) + // getting page count + const senderPage = await this.getPageCount(`/txs?message.sender=${address}`) + const recipientPage = await this.getPageCount( + `/txs?transfer.recipient=${address}` + ) + const txs = await Promise.all([ - this.loadPaginatedTxs(`/txs?message.sender=${address}`), - this.loadPaginatedTxs(`/txs?transfer.recipient=${address}`) + this.loadPaginatedTxs(`/txs?message.sender=${address}`, senderPage), + this.loadPaginatedTxs(`/txs?transfer.recipient=${address}`, recipientPage) ]).then(([senderTxs, recipientTxs]) => [].concat(senderTxs, recipientTxs)) return this.reducers.formatTransactionsReducer(txs, this.reducers) diff --git a/lib/source/emoneyV0-source.js b/lib/source/emoneyV0-source.js index 7f7a88fdd4..2d1bbc3994 100644 --- a/lib/source/emoneyV0-source.js +++ b/lib/source/emoneyV0-source.js @@ -6,23 +6,23 @@ const apiURL = `https://api.exchangeratesapi.io/latest?` const gasPrices = [ { denom: 'echf', - price: '0.400000' + price: '0.400' }, { denom: 'eeur', - price: '0.400000' + price: '0.400' }, { denom: 'ejpy', - price: '48.800000' + price: '48.800' }, { denom: 'eusd', - price: '0.440000' + price: '0.440' }, { denom: 'ungm', - price: '0.800000' + price: '0.800' } ] diff --git a/lib/source/terraV3-source.js b/lib/source/terraV3-source.js index 645f405d15..5013ec68e7 100644 --- a/lib/source/terraV3-source.js +++ b/lib/source/terraV3-source.js @@ -9,23 +9,23 @@ const annualProvision = '21700000000000' // 21.7 million in uluna const gasPrices = [ { denom: 'ukrw', - price: '0.091000' + price: '0.091' }, { denom: 'uluna', - price: '0.001000' + price: '0.001' }, { denom: 'umnt', - price: '0.091000' + price: '0.091' }, { denom: 'usdr', - price: '0.091000' + price: '0.091' }, { denom: 'uusd', - price: '0.091000' + price: '0.091' } ]