diff --git a/app/controllers/index.js b/app/controllers/index.js index 764a620..3fb693f 100644 --- a/app/controllers/index.js +++ b/app/controllers/index.js @@ -1,4 +1,3 @@ -import Ember from 'ember'; import Controller from 'ember-controller'; import { alias, filter, filterBy, sort } from 'ember-computed'; import injectService from 'ember-service/inject'; @@ -6,15 +5,6 @@ import injectService from 'ember-service/inject'; export default Controller.extend({ kredits: injectService(), - init() { - this._super(...arguments); - let contract = this.get('kredits.kredits').Operator.contract; - contract.onproposalvoted = this._handleProposalVoted.bind(this); - contract.onproposalcreated = this._handleProposalCreated.bind(this); - contract.onproposalexecuted = this._handleProposalExecuted.bind(this); - // TODO: transfer on the token contract - }, - contributors: alias('kredits.contributors'), contributorsWithKredits: filter('contributors', function(contributor) { return contributor.get('balance') !== 0; @@ -29,54 +19,6 @@ export default Controller.extend({ proposalsClosedSorted: sort('proposalsClosed', 'proposalsSorting'), proposalsOpenSorted: sort('proposalsOpen', 'proposalsSorting'), - _handleProposalCreated(proposalId) { - // TODO: check if proposalId is already a string - let proposal = this.get('proposals') - .findBy('id', proposalId.toString()); - if (proposal) { - Ember.Logger.debug('[index] proposal exists, not adding from event'); - return; - } - - proposal = this.get('kredits.kredits').Operator.getById(proposalId); - this.get('proposals').pushObject(proposal); - }, - - _handleProposalExecuted(proposalId, contributorId, amount) { - let proposal = this.get('proposals') - .findBy('id', proposalId); - - if (proposal.get('isExecuted')) { - Ember.Logger.debug('[index] proposal already executed, not adding from event'); - return; - } - - proposal.setProperties({ - 'executed': true, - }); - - this.get('contributors') - .findBy('id', contributorId) - .incrementProperty('balance', amount); - }, - - _handleProposalVoted(proposalId, voter, totalVotes) { - this.get('proposals') - .findBy('id', proposalId) - .setProperties({ 'votesCount': totalVotes }); - }, - - _handleTransfer(from, to, value) { - value = value.toNumber(); - this.get('contributors') - .findBy('address', from) - .decrementProperty('balance', value); - this.get('contributors') - .findBy('address', to) - .incrementProperty('balance', value); - }, - - actions: { confirmProposal(proposalId) { this.get('kredits').vote(proposalId).then(transaction => { diff --git a/app/lib/kredits/contracts/base.js b/app/lib/kredits/contracts/base.js index a7a35aa..c54ca22 100644 --- a/app/lib/kredits/contracts/base.js +++ b/app/lib/kredits/contracts/base.js @@ -7,4 +7,11 @@ export default class Base { return this.contract.functions; } + on(type, callback) { + let eventMethod = `on${type.toLowerCase()}`; + // Don't use this.contract.events here. Seems to be a bug in ethers.js + this.contract[eventMethod] = callback; + + return this; + } } diff --git a/app/routes/application.js b/app/routes/application.js index 8a6a815..f136ff8 100644 --- a/app/routes/application.js +++ b/app/routes/application.js @@ -19,6 +19,9 @@ export default Route.extend({ }, afterModel() { - return this.get('kredits').loadContributorsAndProposals(); + return this.get('kredits').loadContributorsAndProposals() + .then(() => { + this.get('kredits').addContractEventHandlers(); + }); } }); diff --git a/app/services/kredits.js b/app/services/kredits.js index cc25378..91cfa3f 100644 --- a/app/services/kredits.js +++ b/app/services/kredits.js @@ -86,8 +86,8 @@ export default Service.extend({ contributors: this.getContributors(), proposals: this.getProposals(), }).then(({ contributors, proposals }) => { - this.set('contributors', contributors); - this.set('proposals', proposals); + this.get('contributors').pushObjects(contributors); + this.get('proposals').pushObjects(proposals); }); }, @@ -96,11 +96,6 @@ export default Service.extend({ debug('[kredits] build', name, attributes); let model = getOwner(this).lookup(`model:${name}`); - // coerce id to string - if (attributes.id) { - attributes.id = attributes.id.toString(); - } - model.setProperties(attributes); return model; }, @@ -169,5 +164,73 @@ export default Service.extend({ return this.get('kredits').Contributor.getById(id); } }); - }) + }), + + findProposalById(proposalId) { + return this.get('proposals').findBy('id', proposalId.toString()); + }, + + // Contract events + addContractEventHandlers() { + // Operator events + this.get('kredits').Operator + .on('ProposalCreated', this.handleProposalCreated.bind(this)) + .on('ProposalVoted', this.handleProposalVoted.bind(this)) + .on('ProposalExecuted', this.handleProposalExecuted.bind(this)); + + // Token events + this.get('kredits').Token + .on('Transfer', this.handleTransfer.bind(this)); + }, + + handleProposalCreated(proposalId) { + let proposal = this.findProposalById(proposalId); + + if (proposal) { + debug('[events] proposal exists, not adding from event'); + return; + } + + this.get('kredits').Operator.getById(proposalId) + .then((proposal) => { + proposal = this.buildModel('proposal', proposal); + this.get('proposals').pushObject(proposal); + }); + }, + + // TODO: We may want to reload that proposal to show the voter as voted + handleProposalVoted(proposalId, voterId, totalVotes) { + let proposal = this.findProposalById(proposalId); + + if (proposal) { + proposal.set('votesCount', totalVotes); + } + }, + + handleProposalExecuted(proposalId, contributorId, amount) { + let proposal = this.findProposalById(proposalId); + + if (proposal.get('isExecuted')) { + debug('[events] proposal already executed, not adding from event'); + return; + } + + proposal.set('executed', true); + + this.get('contributors') + .findBy('id', contributorId.toString()) + .incrementProperty('balance', amount.toNumber()); + }, + + handleTransfer(from, to, value) { + value = value.toNumber(); + + this.get('contributors') + .findBy('address', from) + .decrementProperty('balance', value); + + this.get('contributors') + .findBy('address', to) + .incrementProperty('balance', value); + }, }); diff --git a/tests/unit/controllers/index-test.js b/tests/unit/controllers/index-test.js index 827d256..bbc749f 100644 --- a/tests/unit/controllers/index-test.js +++ b/tests/unit/controllers/index-test.js @@ -23,12 +23,7 @@ let addFixtures = function(controller) { }; test('doesn\'t contain people with 0 balance', function(assert) { - // This is a bit strange... we do not want the controller to call the init function defined in the controller that - // initializes the event handlers on the contracts. Main reason is that we do not have proper contracts in test mode. - // this seems to work. but probably kills some controller stuff, which is fine in this test - let controller = this.subject({ - init: function() { } - }); + let controller = this.subject(); addFixtures(controller); let contributorsSorted = controller.get('contributorsSorted');