diff --git a/imports/api/blockchain/modules/web3Util.js b/imports/api/blockchain/modules/web3Util.js index 9da11d610..e0681dc38 100644 --- a/imports/api/blockchain/modules/web3Util.js +++ b/imports/api/blockchain/modules/web3Util.js @@ -4,6 +4,7 @@ import abi from 'human-standard-token-abi'; import { BigNumber } from 'bignumber.js'; import { token } from '/lib/token'; + // Set web3 provider let web3; const provider = Meteor.settings.public.web3.network.testnet; @@ -51,13 +52,14 @@ const _writeZeroes = (quantity) => { const _smallNumber = (valueBN, tokenCode) => { const coin = _getCoin(tokenCode); let text = valueBN.toString(); - let template = _writeZeroes(coin.decimals + 1) + const template = _writeZeroes(coin.decimals + 1); if (text.length < template.length) { text = `${_writeZeroes(template.length - text.length)}${text}`; } const comma = text.insert('.', (text.length - coin.decimals)); const final = new BigNumber(comma); return final.toNumber(); }; + /** * @summary adjusts decimals of supported tokens, inverse of _addDecimal() * @param {string} value value in lowest decimal diff --git a/imports/api/notifier/notifier.js b/imports/api/notifier/notifier.js index e21048a35..e37fa9f2e 100644 --- a/imports/api/notifier/notifier.js +++ b/imports/api/notifier/notifier.js @@ -35,7 +35,6 @@ const _notify = (transaction) => { } if (Meteor.isClient) { - console.log('SALE LLAMADA DE A') Meteor.call( 'sendNotification', toId, @@ -44,7 +43,6 @@ const _notify = (transaction) => { transaction, ); } else if (Meteor.isServer) { - console.log('SALE LLAMADA DE B') Meteor.call( 'sendNotification', toId, diff --git a/imports/api/server/methods.js b/imports/api/server/methods.js index 4e88f90e4..5a2e77269 100644 --- a/imports/api/server/methods.js +++ b/imports/api/server/methods.js @@ -5,7 +5,7 @@ import { Email } from 'meteor/email'; import { TAPi18n } from 'meteor/tap:i18n'; import { ServiceConfiguration } from 'meteor/service-configuration'; -import { genesisTransaction, loadExternalCryptoBalance } from '/imports/api/transactions/transaction'; +import { genesisTransaction, loadExternalCryptoBalance, tallyBlockchainVotes } from '/imports/api/transactions/transaction'; import { Contracts } from '/imports/api/contracts/Contracts'; import { getTime } from '/imports/api/time'; import { logUser, log } from '/lib/const'; @@ -145,6 +145,33 @@ Meteor.methods({ loadExternalCryptoBalance(userId); }, + /** + * @summary on every contract where theres a pending with the given hash, updates status + * @param {string} hash to be updated + * @param {string} status new condition + */ + updateTransactionStatus(hash, status) { + check(hash, String); + check(status, String); + + const allContracts = Contracts.find({ 'blockchain.tickets': { $elemMatch: { hash } } }).fetch(); + let contract; + + for (let i = 0; i < allContracts.length; i +=1 ) { + let contract = allContracts[i]; + for (let j = 0; j < contract.blockchain.tickets.length; j += 1) { + if (contract.blockchain.tickets[j].hash === hash) { + contract.blockchain.tickets[j].status = status; + break; + } + } + Contracts.update({ _id: contract._id }, { $set: { 'blockchain.tickets': contract.blockchain.tickets }}) + tallyBlockchainVotes(contract._id); + } + + log(`{ method: 'updateTransactionStatus', user: ${logUser()}, hash: '${hash}' }`); + }, + /** * @summary updates API keys to prevent failure of having multiple nodes with a same db */ diff --git a/imports/api/transactions/transaction.js b/imports/api/transactions/transaction.js index df165e80f..46e6ac874 100644 --- a/imports/api/transactions/transaction.js +++ b/imports/api/transactions/transaction.js @@ -724,7 +724,7 @@ const _insertBlockchainTicket = (_id, tickets) => { /** * @summary counts the total blockchain based votes on a given contract -* @param {object} contract where to count votes +* @param {string} _id where to count votes */ const _tallyBlockchainVotes = (_id) => { const contract = Contracts.findOne({ _id }); @@ -942,3 +942,4 @@ export const getVotes = _getVotes; export const transact = _transact; export const genesisTransaction = _genesisTransaction; export const loadExternalCryptoBalance = _loadExternalCryptoBalance; +export const tallyBlockchainVotes = _tallyBlockchainVotes; diff --git a/imports/startup/both/modules/metamask.js b/imports/startup/both/modules/metamask.js index e4e3f4cf2..06f3a4ecb 100644 --- a/imports/startup/both/modules/metamask.js +++ b/imports/startup/both/modules/metamask.js @@ -7,6 +7,8 @@ import { displayNotice } from '/imports/ui/modules/notice'; import { addDecimal, getCoin } from '/imports/api/blockchain/modules/web3Util'; import { token } from '/lib/token'; +import { Transactions } from '/imports/api/transactions/Transactions'; + import abi from 'human-standard-token-abi'; const Web3 = require('web3'); @@ -79,6 +81,44 @@ const _getTransactionStatus = (hash) => { return false; }; +/** +* @summary syncs app with blockchain data +* @param {object} contract to verify if still pending +*/ +const _syncBlockchain = (contract) => { + if (contract && contract.blockchain && contract.blockchain.tickets.length > 0) { + const blockchain = contract.blockchain; + const contractId = contract._id; + if (contract.blockchain.tickets[0].status === 'PENDING') { + _getTransactionStatus(contract.blockchain.tickets[0].hash).then( + function (receipt) { + if (receipt) { + if (receipt.status) { + blockchain.tickets[0].status = 'CONFIRMED'; + // reload user balance on confirmed transaction + Meteor.call('loadUserTokenBalance', Meteor.userId(), (loadBalanceError) => { + if (loadBalanceError) { + console.log(loadBalanceError, 'error reloading user balance after Metamask transaction'); + } + }); + } else { + blockchain.tickets[0].status = 'FAIL'; + } + Transactions.update({ _id: contractId }, { $set: { 'blockchain.tickets': blockchain.tickets } }); + + Meteor.call('updateTransactionStatus', contract.blockchain.tickets[0].hash, blockchain.tickets[0].status, (error) => { + if (error) { + console.log(error, 'error updating transactions with this hash on server.'); + } + }); + } + } + ); + } + } +}; + + /** * @summary send crypto with mask; * @param {string} from blockchain address @@ -318,3 +358,4 @@ if (Meteor.isServer) { export const transactWithMetamask = _transactWithMetamask; export const getTransactionStatus = _getTransactionStatus; export const setupWeb3 = _web3; +export const syncBlockchain = _syncBlockchain; diff --git a/imports/ui/templates/components/decision/balance/balance.js b/imports/ui/templates/components/decision/balance/balance.js index 18597cbd5..37f5b59c9 100644 --- a/imports/ui/templates/components/decision/balance/balance.js +++ b/imports/ui/templates/components/decision/balance/balance.js @@ -123,6 +123,10 @@ Template.balance.helpers({ }, balance() { const instance = Template.instance(); + if (this.blockchain && this.blockchain.score && this.isButton) { + const confirmed = _currencyValue(this.blockchain.score.finalConfirmed, this.token); + return `${numeral(confirmed).format(instance.coin.format)}`; + } if (this.isCrypto && this.value) { const coinData = getCoin(instance.coin.code); return _formatCryptoValue(removeDecimal(this.value, coinData.decimals).toNumber(), instance.coin.code); @@ -131,18 +135,18 @@ Template.balance.helpers({ return numeral(balance).format(Template.instance().coin.format); }, hasPending() { - console.log('PENDING CHECK'); - console.log(this); - if (this.blockchain.score) { + if (this.blockchain && this.blockchain.score) { return (this.blockchain.score.finalPending); } return false; }, pending() { - const instance = Template.instance(); - const coinData = getCoin(instance.coin.code); - const pending = _currencyValue(this.blockchain.score.finalPending, this.token); - return `${numeral(pending).format(instance.coin.format)} ${TAPi18n.__('pending')}`; + if (this.blockchain && this.blockchain.score) { + const instance = Template.instance(); + const pending = _currencyValue(this.blockchain.score.finalPending, this.token); + return `${numeral(pending).format(instance.coin.format)} ${TAPi18n.__('pending')}`; + } + return ''; }, }); diff --git a/imports/ui/templates/layout/url/home/home.js b/imports/ui/templates/layout/url/home/home.js index db80c0ee8..204b03cba 100644 --- a/imports/ui/templates/layout/url/home/home.js +++ b/imports/ui/templates/layout/url/home/home.js @@ -115,10 +115,7 @@ Template.homeFeed.helpers({ return tally; }, mainLedger() { - // options=this.options kind='DELEGATION' singlePost=true hidePost=false peerFeed=false postFeed=false homeFeed=true const tally = this; - console.log(`mainLedger`); - console.log(tally); return { options: tally.options, kind: 'DELEGATION', diff --git a/imports/ui/templates/widgets/tally/tally.js b/imports/ui/templates/widgets/tally/tally.js index 548010ed4..f5dd00ae5 100644 --- a/imports/ui/templates/widgets/tally/tally.js +++ b/imports/ui/templates/widgets/tally/tally.js @@ -88,7 +88,6 @@ const _isWinningVote = (winningBallot, voterBallot) => { const _buildFeed = (id, fields, instance, contract, noTitle) => { // added stuff - // if (fields.kind === instance.data.options.kind) { const currentFeed = instance.feed.get(); const post = fields; post._id = id; @@ -105,7 +104,6 @@ const _buildFeed = (id, fields, instance, contract, noTitle) => { currentFeed.push(voteContract); instance.feed.set(_.uniq(currentFeed)); } - // } }; Template.tally.onCreated(function () { diff --git a/imports/ui/templates/widgets/transaction/transaction.js b/imports/ui/templates/widgets/transaction/transaction.js index 51907eb49..dec73669c 100644 --- a/imports/ui/templates/widgets/transaction/transaction.js +++ b/imports/ui/templates/widgets/transaction/transaction.js @@ -7,8 +7,9 @@ import { Meteor } from 'meteor/meteor'; import { getVotes } from '/imports/api/transactions/transaction'; import { timeCompressed } from '/imports/ui/modules/chronos'; import { token } from '/lib/token'; -import { getTransactionStatus } from '/imports/startup/both/modules/metamask'; import { Transactions } from '/imports/api/transactions/Transactions'; +import { syncBlockchain } from '/imports/startup/both/modules/metamask'; + import '/imports/ui/templates/widgets/transaction/transaction.html'; import '/imports/ui/templates/widgets/preview/preview.js'; @@ -81,49 +82,19 @@ const _getContractToken = (transaction) => { return coin; }; -/** -* @summary syncs app with blockchain data -* @param {object} contract to verify if still pending -*/ -const _syncBlockchain = (contract, instance) => { - if (contract && contract.blockchain && contract.blockchain.tickets.length > 0) { - const blockchain = contract.blockchain; - const contractId = contract._id; - if (contract.blockchain.tickets[0].status === 'PENDING') { - getTransactionStatus(contract.blockchain.tickets[0].hash).then( - function (receipt) { - if (receipt) { - if (receipt.status) { - blockchain.tickets[0].status = 'CONFIRMED'; - // reload user balance on confirmed transaction - Meteor.call('loadUserTokenBalance', Meteor.userId(), (loadBalanceError) => { - if (loadBalanceError) { - console.log(loadBalanceError, 'error reloading user balance after Metamask transaction'); - } - }); - } else { - blockchain.tickets[0].status = 'FAIL'; - } - Transactions.update({ _id: contractId }, { $set: { 'blockchain.tickets': blockchain.tickets } }); - instance.status.set(blockchain.tickets[0].status.toLowerCase()); - } - } - ); - } - } -}; - Template.transaction.onCreated(function () { Template.instance().totalVotes = new ReactiveVar(0); Template.instance().loading = new ReactiveVar(false); - - if (Template.currentData().contract && Template.currentData().contract.kind === 'CRYPTO' && Template.currentData().contract.blockchain.tickets.length > 0) { - Template.instance().status = new ReactiveVar(Template.currentData().contract.blockchain.tickets[0].status.toLowerCase()); - } + Template.instance().alreadyConfirmed = false; + Template.instance().txStatus = ''; + // const data = Template.currentData(); + // if (data.contract && data.contract.kind === 'CRYPTO' && data.contract.blockchain && data.contract.blockchain.tickets.length > 0) { + // Template.instance().status = new ReactiveVar(data.blockchain.tickets[0].status.toLowerCase()); + //} }); Template.transaction.onRendered(function () { - _syncBlockchain(this.data.contract, Template.instance()); + syncBlockchain(this.data.contract); }); Template.transaction.helpers({ @@ -273,14 +244,39 @@ Template.transaction.helpers({ return ''; }, blockchainInfo() { + const instance = Template.instance(); if (this.contract.kind === 'CRYPTO' && this.contract.blockchain) { - return `${TAPi18n.__(`transaction-status-${Template.instance().status.get()}-onchain`)} - ${this.contract.blockchain.tickets[0].hash}`; + if (instance.txStatus === '') { + const tx = Transactions.findOne({ _id: this.contract._id }); + if (tx) { + const status = tx.blockchain.tickets[0].status.toLowerCase(); + if (status !== 'PENDING') { + instance.txStatus = status; + } + return `${TAPi18n.__(`transaction-status-${status}-onchain`)} - ${this.contract.blockchain.tickets[0].hash}`; + } + } else { + return `${TAPi18n.__(`transaction-status-${instance.txStatus}-onchain`)} - ${this.contract.blockchain.tickets[0].hash}`; + } } return ''; }, transactionIcon() { + const instance = Template.instance(); if (this.contract.kind === 'CRYPTO' && this.contract.blockchain) { - return `arrow-right-${Template.instance().status.get()}.png`; + if (instance.txStatus === '') { + const tx = Transactions.findOne({ _id: this.contract._id }); + if (tx) { + const status = tx.blockchain.tickets[0].status.toLowerCase(); + if (status !== 'PENDING') { + instance.txStatus = status; + } + console.log('FIND'); + return `arrow-right-${status}.png`; + } + } else { + return `arrow-right-${instance.txStatus}.png`; + } } return 'arrow-right.png'; },