From cb66913ac7b8fb5989f59cc22edf7b2ce2c4158b Mon Sep 17 00:00:00 2001 From: Fabian Date: Sat, 25 Jan 2020 19:12:58 -0400 Subject: [PATCH] release (#283) * 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 Co-authored-by: Ana G. <40721795+Bitcoinera@users.noreply.github.com> Co-authored-by: iambeone Co-authored-by: Mario Pino --- data/networks-local.js | 3 ++ data/networks.json | 82 +++++++++++++++++++---------- lib/controller/transaction/index.js | 10 +++- lib/reducers/cosmosV0-reducers.js | 31 ++++++----- lib/schema.js | 9 +++- lib/source/cosmosV0-source.js | 37 +++++++------ lib/source/cosmosV2-source.js | 11 +++- tests/network-configs.test.js | 6 ++- 8 files changed, 119 insertions(+), 70 deletions(-) diff --git a/data/networks-local.js b/data/networks-local.js index 9cd7b08447..d74dba797e 100644 --- a/data/networks-local.js +++ b/data/networks-local.js @@ -8,6 +8,9 @@ module.exports = [ rpc_url: config.testnetRPC, api_url: config.testnetAPI, bech32_prefix: 'cosmos', + address_prefix: 'cosmos', + address_creator: 'cosmos', + ledger_app: 'cosmos', source_class_name: 'source/cosmosV2-source', block_listener_class_name: 'block-listeners/cosmos-node-subscription', testnet: true, diff --git a/data/networks.json b/data/networks.json index f6dad606c5..a2d5b35864 100644 --- a/data/networks.json +++ b/data/networks.json @@ -6,6 +6,9 @@ "rpc_url": "wss://gaia-13007.lunie.io:26657/websocket", "api_url": "https://gaia-13007.lunie.io", "bech32_prefix": "cosmos", + "address_prefix": "cosmos", + "address_creator": "cosmos", + "ledger_app": "cosmos", "source_class_name": "source/cosmosV2-source", "block_listener_class_name": "block-listeners/cosmos-node-subscription", "testnet": true, @@ -24,9 +27,10 @@ "action_deposit": true, "action_vote": true, "action_proposal": true, - "default": true, + "default": false, "stakingDenom": "MUON", - "enabled": true + "enabled": true, + "icon": "https://app.lunie.io/img/networks/cosmos-hub-mainnet.png" }, { "id": "cosmos-hub-mainnet", @@ -35,8 +39,11 @@ "rpc_url": "wss://cosmos-hub-3.lunie.io/websocket", "api_url": "https://cosmos-hub-3.lunie.io", "bech32_prefix": "cosmos", + "address_prefix": "cosmos", + "address_creator": "cosmos", + "ledger_app": "cosmos", "source_class_name": "source/cosmosV2-source", - "block_listener_class_name": "block-listeners/cosmos-node-subscription", + "block_listener_class_name": "block-listeners/cosmos-node-subscription", "testnet": false, "feature_session": true, "feature_explore": true, @@ -53,9 +60,10 @@ "action_deposit": true, "action_vote": true, "action_proposal": true, - "default": false, + "default": true, "stakingDenom": "ATOM", - "enabled": true + "enabled": true, + "icon": "https://app.lunie.io/img/networks/cosmos-hub-mainnet.png" }, { "id": "regen-testnet", @@ -64,8 +72,11 @@ "rpc_url": "wss://regen-congo-1.lunie.io/websocket", "api_url": "https://regen-congo-1.lunie.io", "bech32_prefix": "xrn:", + "address_prefix": "xrn:", + "address_creator": "cosmos", + "ledger_app": "cosmos", "source_class_name": "source/regenV0-source", - "block_listener_class_name": "block-listeners/cosmos-node-subscription", + "block_listener_class_name": "block-listeners/cosmos-node-subscription", "testnet": true, "feature_session": true, "feature_explore": true, @@ -84,17 +95,21 @@ "action_proposal": true, "default": false, "stakingDenom": "TREE", - "enabled": true + "enabled": true, + "icon": "https://app.lunie.io/img/networks/regen-testnet.png" }, { "id": "terra-testnet", - "title": "Terra", + "title": "Terra Testnet", "chain_id": "soju-0013", - "api_url": "http://terra-testnet.lunie.io/", + "api_url": "https://terra-testnet.lunie.io", "rpc_url": "wss://terra-testnet.lunie.io/websocket", "bech32_prefix": "terra", + "address_prefix": "terra", + "address_creator": "cosmos", + "ledger_app": "cosmos", "source_class_name": "source/terraV3-source", - "block_listener_class_name": "block-listeners/cosmos-node-subscription", + "block_listener_class_name": "block-listeners/cosmos-node-subscription", "testnet": true, "feature_session": true, "feature_explore": true, @@ -103,46 +118,51 @@ "feature_proposals": false, "feature_activity": true, "feature_explorer": true, - "action_send": false, - "action_claim_rewards": false, - "action_delegate": false, - "action_redelegate": false, - "action_undelegate": false, + "action_send": true, + "action_claim_rewards": true, + "action_delegate": true, + "action_redelegate": true, + "action_undelegate": true, "action_deposit": false, "action_vote": false, "action_proposal": false, "default": false, "stakingDenom": "LUNA", - "enabled": true + "enabled": true, + "icon": "https://app.lunie.io/img/networks/terra-testnet.png" }, { "id": "emoney-testnet", - "title": "e-Money", + "title": "e-Money Testnet", "chain_id": "lilmermaid-4", - "api_url": "https://emoney-lilmermaid-4.lunie.io/", + "api_url": "https://emoney-lilmermaid-4.lunie.io", "rpc_url": "wss://emoney-lilmermaid-4.lunie.io/websocket", "bech32_prefix": "emoney", + "address_prefix": "emoney", + "address_creator": "cosmos", + "ledger_app": "cosmos", "source_class_name": "source/emoneyV0-source", "block_listener_class_name": "block-listeners/cosmos-node-subscription", "testnet": true, "feature_session": true, "feature_explore": true, - "feature_portfolio": false, + "feature_portfolio": true, "feature_validators": true, "feature_proposals": false, - "feature_activity": false, - "feature_explorer": false, - "action_send": false, - "action_claim_rewards": false, - "action_delegate": false, - "action_redelegate": false, - "action_undelegate": false, + "feature_activity": true, + "feature_explorer": true, + "action_send": true, + "action_claim_rewards": true, + "action_delegate": true, + "action_redelegate": true, + "action_undelegate": true, "action_deposit": false, "action_vote": false, "action_proposal": false, "default": false, "stakingDenom": "NGM", - "enabled": false + "enabled": true, + "icon": "https://app.lunie.io/img/networks/emoney-testnet.png" }, { "id": "livepeer-mainnet", @@ -151,6 +171,9 @@ "api_url": "https://livepeer-mainnet.lunie.io/", "rpc_url": "wss://livepeer-mainnet.lunie.io/websocket", "bech32_prefix": "0x", + "address_prefix": "0x", + "address_creator": "ethereum", + "ledger_app": "ethereum", "source_class_name": "source/livepeerV0-source", "block_listener_class_name": "block-listeners/livepeer-node-polling", "testnet": false, @@ -171,6 +194,7 @@ "action_proposal": false, "default": false, "stakingDenom": "LPT", - "enabled": false + "enabled": false, + "icon": "https://app.lunie.io/img/networks/livepeer-mainnet.png" } -] +] \ No newline at end of file diff --git a/lib/controller/transaction/index.js b/lib/controller/transaction/index.js index d3298dba8b..b18b8c601f 100644 --- a/lib/controller/transaction/index.js +++ b/lib/controller/transaction/index.js @@ -64,13 +64,18 @@ module.exports = { broadcast } +// TODO implment broadcasting across network types async function broadcastTransaction(networkId, senderAddress, url, signedTx) { // broadcast transaction with signatures included // `block` means we wait for the tx to be included into a block before returning. this helps with figuring out "out of gas" issues which only appear when the block is created const body = createBroadcastBody(signedTx, `sync`) - console.log('broadcast to:', url) + + url = url.trim('/') // there is an error broadcasting if the URL ends with //txs + const broadcastUrl = `${url}/txs` + + console.log('broadcast to:', broadcastUrl, 'with body', body) // eslint-disable-next-line no-undef - const res = await fetch(`${url}/txs`, { + const res = await fetch(broadcastUrl, { method: `POST`, headers: { 'Content-Type': 'application/json' @@ -108,6 +113,7 @@ function createBroadcastBody(signedTx, returnType = `sync`) { } function assertOk(res) { + if (!res) throw new Error(`Error sending transaction`) if (Array.isArray(res)) { if (res.length === 0) throw new Error(`Error sending transaction`) diff --git a/lib/reducers/cosmosV0-reducers.js b/lib/reducers/cosmosV0-reducers.js index 11c2d47dde..7f72a9ca15 100644 --- a/lib/reducers/cosmosV0-reducers.js +++ b/lib/reducers/cosmosV0-reducers.js @@ -33,22 +33,13 @@ function proposalFinalized(proposal) { } function accountInfoReducer(accountValue, accountType) { - if (accountType === `cosmos-sdk/Account`) { - return { - address: accountValue.address, - accountNumber: accountValue.account_number, - sequence: accountValue.sequence - } - // here I am assuming that all three kinds of vesting accounts keep the same structure - } else if (accountType.includes(`VestingAccount`)) { - const account = accountValue.BaseVestingAccount.BaseAccount - return { - address: account.address, - accountNumber: account.account_number, - sequence: account.sequence - } - } else { - console.error('Unknown Cosmos account type') + if (accountType.includes(`VestingAccount`)) { + accountValue = accountValue.BaseVestingAccount.BaseAccount + } + return { + address: accountValue.address, + accountNumber: accountValue.account_number, + sequence: accountValue.sequence } } @@ -278,6 +269,13 @@ function coinReducer(coin) { } } +function balanceReducer(coin, fiatValue) { + return { + ...coin, + fiatValue + } +} + function delegationReducer(delegation, validator) { // in cosmos SDK v0 we need to convert shares (cosmos internal representation) to token balance const balance = calculateTokens(validator, delegation.shares) @@ -423,6 +421,7 @@ module.exports = { blockReducer, delegationReducer, coinReducer, + balanceReducer, transactionReducer, undelegationReducer, rewardReducer, diff --git a/lib/schema.js b/lib/schema.js index 998b55dbaa..998e177f8d 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -97,9 +97,12 @@ const typeDefs = gql` rpc_url: String api_url: String bech32_prefix: String + address_prefix: String + address_creator: String + ledger_app: String testnet: Boolean - feature_explore: Boolean feature_session: Boolean + feature_explore: Boolean feature_portfolio: Boolean feature_validators: Boolean feature_proposals: Boolean @@ -113,8 +116,10 @@ const typeDefs = gql` action_deposit: Boolean action_vote: Boolean action_proposal: Boolean - experimental: Boolean + default: Boolean stakingDenom: String + enabled: Boolean + icon: String } type Delegation { diff --git a/lib/source/cosmosV0-source.js b/lib/source/cosmosV0-source.js index 93f44e2434..fa4b0f6b23 100644 --- a/lib/source/cosmosV0-source.js +++ b/lib/source/cosmosV0-source.js @@ -12,8 +12,8 @@ class CosmosV0API extends RESTDataSource { this.initialize({}) this.networkId = network.id this.networkTitle = network.title - this.delegatorBech32Prefix = network.bech32_prefix - this.validatorConsensusBech32Prefix = `${network.bech32_prefix}valcons` + this.delegatorBech32Prefix = network.address_prefix + this.validatorConsensusBech32Prefix = `${network.address_prefix}valcons` this.setReducers() } @@ -284,28 +284,31 @@ class CosmosV0API extends RESTDataSource { return this.reducers.blockReducer(this.networkId, block, transactions) } - async addFiatValue(balances, fiatCurrency) { + async calculateFiatValues(balances, fiatCurrency) { return Promise.all( - balances.map( - balance => - (balance = { - ...balance, - fiatValue: this.calculateFiatValue - ? this.calculateFiatValue(balance, fiatCurrency) - : null - }) - ) + balances.map(balance => ({ + denom: this.reducers.coinReducer(balance).denom, + fiatValue: this.calculateFiatValue + ? this.calculateFiatValue(balance, fiatCurrency) + : null + })) ) } - async getBalancesFromAddress(address, fiatCurrency) { + async getBalancesFromAddress(address, fiatCurrency = `EUR`) { this.checkAddress(address) const response = await this.query(`bank/balances/${address}`) let balances = response || [] - balances = balances.map(this.reducers.coinReducer) + const coins = balances.map(this.reducers.coinReducer) // We calculate the fiatValue field for networks with multiple tokens // For now, it is just e-Money - return await this.addFiatValue(balances, fiatCurrency) + const fiatBalances = await this.calculateFiatValues(balances, fiatCurrency) + return coins.map(coin => { + return this.reducers.balanceReducer( + coin, + fiatBalances.find(({ denom }) => denom === coin.denom).fiatValue + ) + }) } async getAccountInfo(address) { @@ -479,15 +482,11 @@ class CosmosV0API extends RESTDataSource { this.loadPaginatedTxs(`/txs?action=submit_proposal&proposer=${address}`), this.loadPaginatedTxs(`/txs?action=deposit&depositor=${address}`), this.loadPaginatedTxs(`/txs?action=vote&voter=${address}`), - // this.get(`/txs?action=create_validator&destination-validator=${valAddress}`), // TODO - // this.get(`/txs?action=edit_validator&destination-validator=${valAddress}`), // TODO this.loadPaginatedTxs(`/txs?action=delegate&delegator=${address}`), this.loadPaginatedTxs( `/txs?action=begin_redelegate&delegator=${address}` ), this.loadPaginatedTxs(`/txs?action=begin_unbonding&delegator=${address}`), - // this.get(`/txs?action=unjail&source-validator=${address}`), // TODO - // this.get(`/txs?action=set_withdraw_address&delegator=${address}`), // other this.loadPaginatedTxs( `/txs?action=withdraw_delegator_reward&delegator=${address}` ), diff --git a/lib/source/cosmosV2-source.js b/lib/source/cosmosV2-source.js index 4e6e1724ee..3776197879 100644 --- a/lib/source/cosmosV2-source.js +++ b/lib/source/cosmosV2-source.js @@ -44,7 +44,16 @@ class CosmosV2API extends CosmosV0API { const dupFreeTxs = uniqWith(txs, (a, b) => a.txhash === b.txhash) const sortedTxs = sortBy(dupFreeTxs, ['timestamp']) const reversedTxs = reverse(sortedTxs) - return reversedTxs.map(tx => + // here we filter out all transactions related to validators + const filteredTxs = reversedTxs.filter( + tx => + tx.tx.value.msg[0].type !== + `cosmos-sdk/MsgWithdrawValidatorCommission` && + tx.tx.value.msg[0].type !== `cosmos-sdk/MsgSetWithdrawAddress` && + tx.tx.value.msg[0].type !== `cosmos-sdk/MsgEditValidator` && + tx.tx.value.msg[0].type !== `cosmos-sdk/MsgUnjail` + ) + return filteredTxs.map(tx => this.reducers.transactionReducer(tx, this.reducers) ) } diff --git a/tests/network-configs.test.js b/tests/network-configs.test.js index db91d7ec72..75209db421 100644 --- a/tests/network-configs.test.js +++ b/tests/network-configs.test.js @@ -8,6 +8,9 @@ const schema = Joi.object({ rpc_url: Joi.string().uri(), api_url: Joi.string().uri(), bech32_prefix: Joi.string(), + address_prefix: Joi.string(), + address_creator: Joi.string(), + ledger_app: Joi.string(), source_class_name: Joi.string(), block_listener_class_name: Joi.string(), testnet: Joi.boolean(), @@ -29,7 +32,8 @@ const schema = Joi.object({ default: Joi.boolean(), stakingDenom: Joi.string().uppercase(), enabled: Joi.boolean(), - experimental: Joi.boolean().optional() + experimental: Joi.boolean().optional(), + icon: Joi.string().optional() }) describe('Network configs', function() {