diff --git a/app/components/add-proposal/component.js b/app/components/add-proposal/component.js index aba9926..e7acf1a 100644 --- a/app/components/add-proposal/component.js +++ b/app/components/add-proposal/component.js @@ -8,7 +8,7 @@ export default Component.extend({ // Default attributes used by reset attributes: { - recipientId: null, + contributorId: null, kind: 'community', amount: null, description: null, @@ -22,7 +22,7 @@ export default Component.extend({ contributors: [], - isValidRecipient: isPresent('recipientId'), + isValidRecipient: isPresent('contributorId'), isValidAmount: computed('amount', function() { return parseInt(this.get('amount'), 10) > 0; }), diff --git a/app/components/add-proposal/template.hbs b/app/components/add-proposal/template.hbs index c7bb975..4f3cb9f 100644 --- a/app/components/add-proposal/template.hbs +++ b/app/components/add-proposal/template.hbs @@ -1,9 +1,9 @@

- {{#each contributors as |contributor|}} - + {{/each}}

diff --git a/app/controllers/index.js b/app/controllers/index.js index aadce1b..764a620 100644 --- a/app/controllers/index.js +++ b/app/controllers/index.js @@ -42,10 +42,9 @@ export default Controller.extend({ this.get('proposals').pushObject(proposal); }, - _handleProposalExecuted(proposalId, recipientId, amount) { - // TODO: check if proposalId is already a string + _handleProposalExecuted(proposalId, contributorId, amount) { let proposal = this.get('proposals') - .findBy('id', proposalId.toString()); + .findBy('id', proposalId); if (proposal.get('isExecuted')) { Ember.Logger.debug('[index] proposal already executed, not adding from event'); @@ -57,13 +56,13 @@ export default Controller.extend({ }); this.get('contributors') - .findBy('id', recipientId.toString()) + .findBy('id', contributorId) .incrementProperty('balance', amount); }, _handleProposalVoted(proposalId, voter, totalVotes) { this.get('proposals') - .findBy('id', proposalId.toString()) + .findBy('id', proposalId) .setProperties({ 'votesCount': totalVotes }); }, diff --git a/app/controllers/proposals/new.js b/app/controllers/proposals/new.js index bc1ce67..d6426f1 100644 --- a/app/controllers/proposals/new.js +++ b/app/controllers/proposals/new.js @@ -11,7 +11,7 @@ export default Controller.extend({ actions: { save(proposal) { // contributorIpfsHash is needed for the proposal ipfs data. I'm not happy to do this here but I think to load all the contributors in addProposal again is a bit too much. I hope we can refactor it later. - let contributor = this.get('contributors').findBy('id', proposal.recipientId); + let contributor = this.get('contributors').findBy('id', proposal.contributorId); proposal.contributorIpfsHash = contributor.get('ipfsHash'); return this.get('kredits').addProposal(proposal) diff --git a/app/lib/kredits/contracts/operator.js b/app/lib/kredits/contracts/operator.js index 0ad7f8d..c3e3898 100644 --- a/app/lib/kredits/contracts/operator.js +++ b/app/lib/kredits/contracts/operator.js @@ -47,7 +47,7 @@ export default class Operator extends Base { .add(json) .then((ipfsHashAttr) => { let proposal = [ - proposalAttr.recipientId, + proposalAttr.contributorId, proposalAttr.amount, ipfsHashAttr.ipfsHash, ipfsHashAttr.hashFunction, diff --git a/app/lib/kredits/kredits.js b/app/lib/kredits/kredits.js index b087371..46a893f 100644 --- a/app/lib/kredits/kredits.js +++ b/app/lib/kredits/kredits.js @@ -27,22 +27,44 @@ export default class Kredits { this.ipfsConfig = ipfsConfig; this.ipfs = new IPFS(ipfsConfig); - let registryContract = this.initRegistryContract(provider); + return this.ipfs._ipfsAPI.id().catch((error) => { + throw new Error(`IPFS node not available; config: ${JSON.stringify(ipfsConfig)} - ${error.message}`); + }).then(() => { - let addresses = Object.keys(contracts).reduce((mem, name) => { - let contractName = capitalize(name); - mem[contractName] = registryContract.functions.getProxyFor(contractName); - return mem; - }, {}); + let registryContract = this.initRegistryContract(provider); - return RSVP.hash(addresses) - .then((addresses) => { - return new Kredits(provider, signer, addresses); - }); + let addresses = Object.keys(contracts).reduce((mem, name) => { + let contractName = capitalize(name); + mem[contractName] = registryContract.functions.getProxyFor(contractName).catch((error) => { + throw new Error(`Failed to get address for ${contractName} from registry at ${registryContract.address} + - correct registry? does it have version entry? - ${error.message}` + ); + }); + return mem; + }, {}); + + return RSVP.hash(addresses) + .then((addresses) => { + return new Kredits(provider, signer, addresses); + }); + }); } static initRegistryContract(provider) { let address = addresses['Registry'][provider.chainId]; + if (!address) { + throw new Error(`Registry address not found; invalid network? + requested network: ${provider.chainId} + supported networks: ${Object.keys(addresses['Registry'])} + `); + } + provider.getCode(address).then((code) => { + // not sure if we always get the same return value of the code is not available + // that's why checking if it is < 5 long + if (code === '0x00' || code.length < 5) { + throw new Error(`Registry not found at ${address} on network ${provider.chainId}`); + } + }); let abi = abis['Registry']; console.log('Initialize registry contract:', address, abi, provider); return new ethers.Contract(address, abi, provider); @@ -69,6 +91,9 @@ export default class Kredits { let contractName = capitalize(name); let address = this.addresses[contractName]; + if (!address || !abis[contractName]) { + throw new Error(`Address or ABI not found for ${contractName}`); + } let contract = new ethers.Contract(address, abis[contractName], this.signer); this.contracts[name] = new contracts[contractName](contract); diff --git a/app/lib/kredits/utils/ipfs.js b/app/lib/kredits/utils/ipfs.js index 5a2a7e4..bc6ccda 100644 --- a/app/lib/kredits/utils/ipfs.js +++ b/app/lib/kredits/utils/ipfs.js @@ -51,5 +51,4 @@ export default class IPFS { return multihashes.encode(digest, hashData.hashFunction, hashData.hashSize); } - } diff --git a/app/models/proposal.js b/app/models/proposal.js index 7bd376c..b18471f 100644 --- a/app/models/proposal.js +++ b/app/models/proposal.js @@ -8,8 +8,8 @@ export default EmberObject.extend({ // Contract id: bignumber('idRaw', 'toString'), - creatorAddress: null, - recipientId: bignumber('recipientIdRaw', 'toString'), + creatorAccount: null, + contributorId: bignumber('contributorIdRaw', 'toString'), amount: bignumber('amountRaw', 'toNumber'), votesCount: bignumber('votesCountRaw', 'toNumber'), votesNeeded: bignumber('votesNeededRaw', 'toNumber'), @@ -28,7 +28,7 @@ export default EmberObject.extend({ // Relationships // TODO: Optimize it. We don't need to find the contributor every time we add a new one - contributor: computed('recipientId', 'kredits.contributors.[]', function() { - return this.get('kredits.contributors').findBy('id', this.get('recipientId')); + contributor: computed('contributorId', 'kredits.contributors.[]', function() { + return this.get('kredits.contributors').findBy('id', this.get('contributorId')); }) }); diff --git a/app/routes/application.js b/app/routes/application.js index 3119aad..8a6a815 100644 --- a/app/routes/application.js +++ b/app/routes/application.js @@ -13,6 +13,8 @@ export default Route.extend({ transition.retry(); } } + }).catch((error) => { + console.log('Error initializing Kredits', error); }); }, diff --git a/app/utils/cps/bignumber.js b/app/utils/cps/bignumber.js index 701eed1..f86cab2 100644 --- a/app/utils/cps/bignumber.js +++ b/app/utils/cps/bignumber.js @@ -1,4 +1,5 @@ import computed from 'ember-computed'; +import ethers from 'npm:ethers'; export default function(dependentKey, converterMethod) { return computed(dependentKey, { @@ -6,6 +7,7 @@ export default function(dependentKey, converterMethod) { return this.get(dependentKey)[converterMethod](); }, set (key, value) { + value = ethers.utils.bigNumberify(value); this.set(dependentKey, value); return value[converterMethod](); } diff --git a/tests/unit/controllers/index-test.js b/tests/unit/controllers/index-test.js index fec0ad3..827d256 100644 --- a/tests/unit/controllers/index-test.js +++ b/tests/unit/controllers/index-test.js @@ -12,20 +12,12 @@ moduleFor('controller:index', 'Unit | Controller | index', { }); let addFixtures = function(controller) { - controller.set('model', { - contributors: [], - proposals: [] - }); - [ { github_username: "neo", github_uid: "318", balance: 10000 }, { github_username: "morpheus", github_uid: "843", balance: 15000 }, { github_username: "trinity", github_uid: "123", balance: 5000 }, { github_username: "mouse", github_uid: "696", balance: 0 } ].forEach(fixture => { - // we expect a bignumer but I don't want to add the bignumber dependency here... so this is some hack to return an object that looks good enough for the test - let fakeBignumber = function(balance) { return { toNumber: function() { return balance; } }; }; - fixture.balance = fakeBignumber(fixture.balance); controller.get('kredits.contributors').push(Contributor.create(fixture)); }); };