Use ethers.js instead of the old web3
the web3 we are using is old and everything will change with web3 1.0 which is currently in beta for ages. ethers.js seems to be a bit more lightweight and implements pretty much the same API so let's give it a try.
This commit is contained in:
@@ -18,8 +18,8 @@ export default Component.extend({
|
|||||||
inProgress: false,
|
inProgress: false,
|
||||||
|
|
||||||
isValidAddress: function() {
|
isValidAddress: function() {
|
||||||
return this.get('kredits.web3')
|
// TODO: add proper address validation
|
||||||
.isAddress(this.get('newContributor.address'));
|
return this.get('newContributor.address') !== ''
|
||||||
}.property('kredits.web3', 'newContributor.address'),
|
}.property('kredits.web3', 'newContributor.address'),
|
||||||
|
|
||||||
isValidName: function() {
|
isValidName: function() {
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ export default Component.extend({
|
|||||||
inProgress: false,
|
inProgress: false,
|
||||||
|
|
||||||
isValidRecipient: computed('proposal.recipientAddress', function() {
|
isValidRecipient: computed('proposal.recipientAddress', function() {
|
||||||
return this.get('kredits.web3').isAddress(this.get('proposal.recipientAddress'));
|
// TODO: add proper address validation
|
||||||
|
return this.get('proposal.recipientAddress') !== ''
|
||||||
}),
|
}),
|
||||||
|
|
||||||
isValidAmount: computed('proposal.amount', function() {
|
isValidAmount: computed('proposal.amount', function() {
|
||||||
|
|||||||
+20
-37
@@ -50,74 +50,57 @@ export default Ember.Controller.extend({
|
|||||||
watchContractEvents: function() {
|
watchContractEvents: function() {
|
||||||
this.get('kredits.kreditsContract')
|
this.get('kredits.kreditsContract')
|
||||||
.then((contract) => {
|
.then((contract) => {
|
||||||
let events = contract.get('content').allEvents();
|
contract.onproposalvoted = this._handleProposalVoted.bind(this); //function(a,b,c) { console.log('voted', a, b, c) }
|
||||||
events.watch((error, data) => {
|
contract.onproposalcreated = this._handleProposalCreated.bind(this);
|
||||||
Ember.Logger.debug('[index] Received contract event', data);
|
contract.onproposalexecuted = this._handleProposalExecuted.bind(this);
|
||||||
|
// TODO: transfer on the token contract
|
||||||
switch (data.event) {
|
|
||||||
case 'ProposalCreated':
|
|
||||||
this._handleProposalCreated(data);
|
|
||||||
break;
|
|
||||||
case 'ProposalExecuted':
|
|
||||||
this._handleProposalExecuted(data);
|
|
||||||
break;
|
|
||||||
case 'ProposalVoted':
|
|
||||||
this._handleProposalVoted(data);
|
|
||||||
break;
|
|
||||||
case 'Transfer':
|
|
||||||
this._handleTransfer(data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}.on('init'),
|
}.on('init'),
|
||||||
|
|
||||||
_handleProposalCreated(data) {
|
_handleProposalCreated(proposalId, creatorAddress, recipientAddress, amount) {
|
||||||
if (Ember.isPresent(this.get('model.proposals')
|
if (Ember.isPresent(this.get('model.proposals')
|
||||||
.findBy('id', data.args.id.toNumber()))) {
|
.findBy('id', proposalId.toNumber()))) {
|
||||||
Ember.Logger.debug('[index] proposal exists, not adding from event');
|
Ember.Logger.debug('[index] proposal exists, not adding from event');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let proposal = Proposal.create({
|
let proposal = Proposal.create({
|
||||||
id: data.args.id.toNumber(),
|
id: proposalId.toNumber(),
|
||||||
creatorAddress: data.args.creator,
|
creatorAddress: creatorAddress,
|
||||||
recipientAddress: data.args.recipient,
|
recipientAddress: recipientAddress,
|
||||||
recipientName: null,
|
recipientName: null,
|
||||||
votesCount: 0,
|
votesCount: 0,
|
||||||
votesNeeded: 2,
|
votesNeeded: 2,
|
||||||
amount: data.args.amount.toNumber(),
|
amount: amount.toNumber(),
|
||||||
executed: false,
|
executed: false
|
||||||
url: data.args.url,
|
|
||||||
ipfsHash: data.args.ipfsHash
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.get('model.proposals').pushObject(proposal);
|
this.get('model.proposals').pushObject(proposal);
|
||||||
},
|
},
|
||||||
|
|
||||||
_handleProposalExecuted(data) {
|
_handleProposalExecuted(proposalId, recipientId, amount) {
|
||||||
if (this.get('model.proposals')
|
if (this.get('model.proposals')
|
||||||
.findBy('id', data.args.id.toNumber())
|
.findBy('id', recipientId.toNumber())
|
||||||
.get('executed')) {
|
.get('executed')) {
|
||||||
Ember.Logger.debug('[index] proposal already executed, not adding from event');
|
Ember.Logger.debug('[index] proposal already executed, not adding from event');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.get('model.proposals')
|
this.get('model.proposals')
|
||||||
.findBy('id', data.args.id.toNumber())
|
.findBy('id', recipientId.toNumber())
|
||||||
.setProperties({
|
.setProperties({
|
||||||
'executed': true,
|
'executed': true,
|
||||||
'votesCount': 2 // TODO use real count
|
'votesCount': 2 // TODO use real count
|
||||||
});
|
});
|
||||||
|
|
||||||
this.get('model.contributors')
|
this.get('model.contributors')
|
||||||
.findBy('address', data.args.recipient)
|
.findBy('id', recipientId)
|
||||||
.incrementProperty('balance', data.args.amount.toNumber());
|
.incrementProperty('kredits', amount.toNumber());
|
||||||
},
|
},
|
||||||
|
|
||||||
_handleProposalVoted(data) {
|
_handleProposalVoted(proposalId, voter, totalVotes) {
|
||||||
this.get('model.proposals')
|
this.get('model.proposals')
|
||||||
.findBy('id', data.args.id.toNumber())
|
.findBy('id', proposalId.toNumber())
|
||||||
.incrementProperty('votesCount', 1);
|
.incrementProperty('votesCount', 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -134,8 +117,8 @@ export default Ember.Controller.extend({
|
|||||||
actions: {
|
actions: {
|
||||||
|
|
||||||
confirmProposal(proposalId) {
|
confirmProposal(proposalId) {
|
||||||
this.get('kredits').vote(proposalId).then(transactionId => {
|
this.get('kredits').vote(proposalId).then(transaction => {
|
||||||
window.confirm('Vote submitted to Ethereum blockhain: '+transactionId);
|
window.confirm('Vote submitted to Ethereum blockhain: '+transaction.hash);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -8,8 +8,8 @@ export default Ember.Route.extend({
|
|||||||
const kredits = this.get('kredits');
|
const kredits = this.get('kredits');
|
||||||
|
|
||||||
if (kredits.get('web3') && kredits.get('web3Provided')) {
|
if (kredits.get('web3') && kredits.get('web3Provided')) {
|
||||||
kredits.get('web3').eth.getAccounts((error, accounts) => {
|
kredits.get('listAccounts').then((accounts) => {
|
||||||
if (error || accounts.length === 0) {
|
if (accounts.length === 0) {
|
||||||
if (confirm('It looks like you have an Ethereum wallet available. Please unlock your account.')) {
|
if (confirm('It looks like you have an Ethereum wallet available. Please unlock your account.')) {
|
||||||
transition.retry();
|
transition.retry();
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,7 @@ export default Ember.Route.extend({
|
|||||||
|
|
||||||
let kredits = this.get('kredits');
|
let kredits = this.get('kredits');
|
||||||
let totalSupply = kredits.get('tokenContract')
|
let totalSupply = kredits.get('tokenContract')
|
||||||
.then((contract) => contract.invoke('totalSupply'));
|
.then((contract) => contract.totalSupply());
|
||||||
|
|
||||||
return Ember.RSVP.hash({
|
return Ember.RSVP.hash({
|
||||||
contributors: kredits.getContributors(),
|
contributors: kredits.getContributors(),
|
||||||
|
|||||||
+39
-64
@@ -1,4 +1,4 @@
|
|||||||
import Web3 from 'npm:web3';
|
import ethers from 'npm:ethers';
|
||||||
import bs58 from 'npm:bs58';
|
import bs58 from 'npm:bs58';
|
||||||
import NpmBuffer from 'npm:buffer';
|
import NpmBuffer from 'npm:buffer';
|
||||||
|
|
||||||
@@ -24,18 +24,6 @@ const {
|
|||||||
|
|
||||||
const Buffer = NpmBuffer.Buffer;
|
const Buffer = NpmBuffer.Buffer;
|
||||||
|
|
||||||
function contractProxy(object) {
|
|
||||||
let proxy = Ember.ObjectProxy.extend({
|
|
||||||
invoke(contractMethod, ...args) {
|
|
||||||
debug('[kredits] invoke', contractMethod, ...args);
|
|
||||||
let contract = this.get('content');
|
|
||||||
return RSVP.denodeify(contract[contractMethod])(...args);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return proxy.create({ content: object });
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Service.extend({
|
export default Service.extend({
|
||||||
|
|
||||||
ipfs: injectService(),
|
ipfs: injectService(),
|
||||||
@@ -44,41 +32,42 @@ export default Service.extend({
|
|||||||
web3Provided: false, // Web3 provided (using Mist Browser, Metamask et al.)
|
web3Provided: false, // Web3 provided (using Mist Browser, Metamask et al.)
|
||||||
|
|
||||||
web3: function() {
|
web3: function() {
|
||||||
if (this.get('web3Instance')) {
|
if (this.get('web3Provider')) {
|
||||||
return this.get('web3Instance');
|
return this.get('web3Provider');
|
||||||
}
|
}
|
||||||
|
|
||||||
let web3Instance;
|
let web3Provider;
|
||||||
|
|
||||||
if (typeof window.web3 !== 'undefined') {
|
if (typeof window.web3 !== 'undefined') {
|
||||||
debug('[kredits] Using user-provided instance, e.g. from Mist browser or Metamask');
|
debug('[kredits] Using user-provided instance, e.g. from Mist browser or Metamask');
|
||||||
web3Instance = new Web3(window.web3.currentProvider);
|
let networkId = parseInt(web3.version.network);
|
||||||
|
web3Provider = new ethers.providers.Web3Provider(web3.currentProvider, {chainId: networkId});
|
||||||
this.set('web3Provided', true);
|
this.set('web3Provided', true);
|
||||||
} else {
|
} else {
|
||||||
debug('[kredits] Creating new instance from npm module class');
|
debug('[kredits] Creating new instance from npm module class');
|
||||||
let providerUrl = localStorage.getItem('config:web3ProviderUrl') || config.web3ProviderUrl;
|
let providerUrl = localStorage.getItem('config:web3ProviderUrl') || config.web3ProviderUrl;
|
||||||
let provider = new Web3.providers.HttpProvider(providerUrl);
|
let networkId = web3.version.network;
|
||||||
web3Instance = new Web3(provider);
|
web3Provider = new ethers.providers.Web3Provider(web3.currentProvider, {chainId: network});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set('web3Instance', web3Instance);
|
this.set('web3Provider', web3Provider);
|
||||||
window.web3 = web3Instance;
|
return web3Provider;
|
||||||
|
}.property('web3Provider'),
|
||||||
|
|
||||||
return web3Instance;
|
listAccounts: function() {
|
||||||
}.property('web3Instance'),
|
return this.get('web3').listAccounts();
|
||||||
|
}.property('web3'),
|
||||||
|
|
||||||
currentUserAccounts: function() {
|
currentUserAccounts: function() {
|
||||||
return (this.get('web3Provided') && this.get('web3').eth.accounts) || [];
|
// TODO: listAccounts returns now a promise
|
||||||
|
return [];
|
||||||
|
return ethers.listAccounts();
|
||||||
|
// return (this.get('web3Provided') && this.get('web3').eth.accounts) || [];
|
||||||
}.property('web3Provided', 'web3'),
|
}.property('web3Provided', 'web3'),
|
||||||
|
|
||||||
registryContract: computed('web3', function() {
|
registryContract: computed('web3', function() {
|
||||||
let networkId = this.get('web3').version.network;
|
let networkId = this.get('web3').chainId;
|
||||||
let contract = this.get('web3')
|
let registry = new ethers.Contract(addresses['Registry'][networkId], abis['Registry'], this.get('web3'));
|
||||||
.eth
|
return registry;
|
||||||
.contract(abis['Registry'])
|
|
||||||
.at(addresses['Registry'][networkId]);
|
|
||||||
|
|
||||||
return RSVP.resolve(contractProxy(contract));
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
contributorsContract: computed('web3', function() {
|
contributorsContract: computed('web3', function() {
|
||||||
@@ -94,22 +83,16 @@ export default Service.extend({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
contractFor(name) {
|
contractFor(name) {
|
||||||
return this.get('registryContract')
|
return this.get('registryContract').functions.getProxyFor(name)
|
||||||
.then((contract) => contract.invoke('getProxyFor', name))
|
|
||||||
.then((address) => {
|
.then((address) => {
|
||||||
debug('[kredits] get contract', name, address);
|
debug('[kredits] get contract', name, address);
|
||||||
let contract = this.get('web3')
|
return new ethers.Contract(address, abis[name], this.get('web3').getSigner());
|
||||||
.eth
|
|
||||||
.contract(abis[name])
|
|
||||||
.at(address);
|
|
||||||
|
|
||||||
return contractProxy(contract);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getContributorData(id) {
|
getContributorData(id) {
|
||||||
return this.get('contributorsContract')
|
return this.get('contributorsContract')
|
||||||
.then((contract) => contract.invoke('contributors', id))
|
.then((contract) => contract.contributors(id))
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
debug('[kredits] contributor', data);
|
debug('[kredits] contributor', data);
|
||||||
|
|
||||||
@@ -120,9 +103,8 @@ export default Service.extend({
|
|||||||
hashFunction: hashFunction.toNumber(),
|
hashFunction: hashFunction.toNumber(),
|
||||||
size: size.toNumber()
|
size: size.toNumber()
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.get('tokenContract')
|
return this.get('tokenContract')
|
||||||
.then((contract) => contract.invoke('balanceOf', address))
|
.then((contract) => contract.balanceOf(address))
|
||||||
.then((balance) => {
|
.then((balance) => {
|
||||||
balance = balance.toNumber();
|
balance = balance.toNumber();
|
||||||
|
|
||||||
@@ -144,7 +126,7 @@ export default Service.extend({
|
|||||||
|
|
||||||
getContributors() {
|
getContributors() {
|
||||||
return this.get('contributorsContract')
|
return this.get('contributorsContract')
|
||||||
.then((contract) => contract.invoke('contributorsCount'))
|
.then((contract) => contract.contributorsCount())
|
||||||
.then(contributorsCount => {
|
.then(contributorsCount => {
|
||||||
debug('[kredits] contributorsCount:', contributorsCount.toNumber());
|
debug('[kredits] contributorsCount:', contributorsCount.toNumber());
|
||||||
let contributors = [];
|
let contributors = [];
|
||||||
@@ -159,24 +141,19 @@ export default Service.extend({
|
|||||||
|
|
||||||
getProposalData(i) {
|
getProposalData(i) {
|
||||||
return this.get('kreditsContract')
|
return this.get('kreditsContract')
|
||||||
.then((contract) => contract.invoke('proposals', i))
|
.then((contract) => contract.proposals(i))
|
||||||
.then(p => {
|
.then(p => {
|
||||||
|
let ipfsHash = this.getMultihashFromBytes32({ digest: p.ipfsHash, hashFunction: p.hashFunction, size: p.hashSize });
|
||||||
let ipfsHash = this.getMultihashFromBytes32({
|
|
||||||
digest: p[6],
|
|
||||||
hashFunction: p[7].toNumber(),
|
|
||||||
size: p[8].toNumber()
|
|
||||||
});
|
|
||||||
|
|
||||||
let proposal = Proposal.create({
|
let proposal = Proposal.create({
|
||||||
id : i,
|
id : i,
|
||||||
creatorAddress : p[0],
|
creatorAddress : p.creator,
|
||||||
recipientId : p[1].toNumber(),
|
recipientId : p.recipientId.toNumber(),
|
||||||
votesCount : p[2].toNumber(),
|
votesCount : p.votesCount.toNumber(),
|
||||||
votesNeeded : p[3].toNumber(),
|
votesNeeded : p.votesNeeded.toNumber(),
|
||||||
amount : p[4].toNumber(),
|
amount : p.amount.toNumber(),
|
||||||
executed : p[5],
|
executed : p.executed,
|
||||||
ipfsHash : ipfsHash
|
ipfsHash : contributionIpfsHash
|
||||||
});
|
});
|
||||||
|
|
||||||
if (proposal.get('ipfsHash')) {
|
if (proposal.get('ipfsHash')) {
|
||||||
@@ -193,7 +170,7 @@ export default Service.extend({
|
|||||||
|
|
||||||
getProposals() {
|
getProposals() {
|
||||||
return this.get('kreditsContract')
|
return this.get('kreditsContract')
|
||||||
.then((contract) => contract.invoke('proposalsCount'))
|
.then((contract) => contract.proposalsCount())
|
||||||
.then(proposalsCount => {
|
.then(proposalsCount => {
|
||||||
let proposals = [];
|
let proposals = [];
|
||||||
|
|
||||||
@@ -209,7 +186,7 @@ export default Service.extend({
|
|||||||
debug('[kredits] vote for', proposalId);
|
debug('[kredits] vote for', proposalId);
|
||||||
|
|
||||||
return this.get('kreditsContract')
|
return this.get('kreditsContract')
|
||||||
.then((contract) => contract.invoke('vote', proposalId))
|
.then((contract) => contract.vote(proposalId))
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
debug('[kredits] vote response', data);
|
debug('[kredits] vote response', data);
|
||||||
return data;
|
return data;
|
||||||
@@ -262,8 +239,7 @@ export default Service.extend({
|
|||||||
|
|
||||||
return this.get('kreditsContract')
|
return this.get('kreditsContract')
|
||||||
.then((contract) => {
|
.then((contract) => {
|
||||||
return contract.invoke(
|
return contract.addContributor(
|
||||||
'addContributor',
|
|
||||||
contributor.address,
|
contributor.address,
|
||||||
digest,
|
digest,
|
||||||
hashFunction,
|
hashFunction,
|
||||||
@@ -290,8 +266,7 @@ export default Service.extend({
|
|||||||
.then(ipfsHash => {
|
.then(ipfsHash => {
|
||||||
return this.get('kreditsContract')
|
return this.get('kreditsContract')
|
||||||
.then((contract) => {
|
.then((contract) => {
|
||||||
return contract.invoke(
|
return contract.addProposal(
|
||||||
'addProposal',
|
|
||||||
recipientAddress,
|
recipientAddress,
|
||||||
amount,
|
amount,
|
||||||
url,
|
url,
|
||||||
|
|||||||
Generated
+664
-578
File diff suppressed because it is too large
Load Diff
+4
-3
@@ -55,12 +55,12 @@
|
|||||||
"ember-parachute": "0.1.0",
|
"ember-parachute": "0.1.0",
|
||||||
"ember-resolver": "^2.0.3",
|
"ember-resolver": "^2.0.3",
|
||||||
"ember-truth-helpers": "1.3.0",
|
"ember-truth-helpers": "1.3.0",
|
||||||
|
"ethers": "^3.0.8",
|
||||||
"ipfs-api": "^19.0.0",
|
"ipfs-api": "^19.0.0",
|
||||||
"kosmos-schemas": "^1.1.2",
|
"kosmos-schemas": "^1.1.2",
|
||||||
"kredits-contracts": "github:67P/truffle-kredits#master",
|
"kredits-contracts": "github:67P/truffle-kredits#master",
|
||||||
"loader.js": "^4.0.10",
|
"loader.js": "^4.0.10",
|
||||||
"tv4": "^1.3.0",
|
"tv4": "^1.3.0"
|
||||||
"web3": "^0.18.2"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.12.0"
|
"node": ">= 0.12.0"
|
||||||
@@ -70,5 +70,6 @@
|
|||||||
"paths": [
|
"paths": [
|
||||||
"lib/contracts"
|
"lib/contracts"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"dependencies": {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user