From 7f56e1163a2f2d4718214964fbb35b059eac07f1 Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Thu, 19 Apr 2018 15:23:15 +0200 Subject: [PATCH 1/5] Add accounts to contributor serialization --- lib/serializers/contributor.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/serializers/contributor.js b/lib/serializers/contributor.js index 985641d..d426370 100644 --- a/lib/serializers/contributor.js +++ b/lib/serializers/contributor.js @@ -35,6 +35,7 @@ class Contributor { name, kind, url, + accounts, github_uid, github_username, wiki_username, -- 2.25.1 From b6bc5af7bf4c9b7aded6a032bd7acb0bd57e475d Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Thu, 19 Apr 2018 15:39:00 +0200 Subject: [PATCH 2/5] Serialize details in contributions --- lib/serializers/contribution.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/serializers/contribution.js b/lib/serializers/contribution.js index e57365c..149b077 100644 --- a/lib/serializers/contribution.js +++ b/lib/serializers/contribution.js @@ -41,6 +41,7 @@ class Contribution { kind, description, url, + details } = deserialized; let data = { @@ -51,7 +52,7 @@ class Contribution { }, kind, description, - "details": {} + "details": details || {} }; if (url) { -- 2.25.1 From 4cf1f4eea768bc8b8038712cecc7edc365d9c06d Mon Sep 17 00:00:00 2001 From: bumi Date: Thu, 19 Apr 2018 15:59:40 +0200 Subject: [PATCH 3/5] Use prompt instead of argv arguments in scripts This makes it easier to handle truffle arguments which we for example need to specify the network. So we ask the user for input instead on using the argv array which might change. --- package-lock.json | 19 +++++++++++++++++++ package.json | 1 + scripts/add-contributor.js | 12 +++++------- scripts/add-proposal.js | 12 +++++------- scripts/cli.js | 16 +++++++--------- scripts/multihash.js | 2 +- scripts/send-funds.js | 16 ++++++++-------- 7 files changed, 46 insertions(+), 32 deletions(-) diff --git a/package-lock.json b/package-lock.json index e3024a1..473e969 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4230,6 +4230,16 @@ "resolved": "https://registry.npmjs.org/promisify-es6/-/promisify-es6-1.0.3.tgz", "integrity": "sha512-N9iVG+CGJsI4b4ZGazjwLnxErD2d9Pe4DPvvXSxYA9tFNu8ymXME4Qs5HIQ0LMJpNM7zj+m0NlNnNeqFpKzqnA==" }, + "promptly": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/promptly/-/promptly-3.0.3.tgz", + "integrity": "sha512-EWnzOsxVKUjqKeE6SStH1/cO4+DE44QolaoJ4ojGd9z6pcNkpgfJKr1ncwxrOFHSTIzoudo7jG8y0re30/LO1g==", + "dev": true, + "requires": { + "pify": "3.0.0", + "read": "1.0.7" + } + }, "protocol-buffers-schema": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.3.2.tgz", @@ -4343,6 +4353,15 @@ } } }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dev": true, + "requires": { + "mute-stream": "0.0.7" + } + }, "read-chunk": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz", diff --git a/package.json b/package.json index b2e9257..9cf8786 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "homepage": "https://github.com/67P/truffle-kredits#readme", "devDependencies": { "ganache-cli": "^6.0.3", + "promptly": "^3.0.3", "truffle": "^4.1.3", "zeppelin-solidity": "^1.7.0" }, diff --git a/scripts/add-contributor.js b/scripts/add-contributor.js index e003bd9..2636c2a 100644 --- a/scripts/add-contributor.js +++ b/scripts/add-contributor.js @@ -1,8 +1,9 @@ const Registry = artifacts.require('./Registry.sol'); const Operator = artifacts.require('./Operator.sol'); const Contributors = artifacts.require('./Contributors.sol'); +const promptly = require('promptly'); -var bs58 = require('bs58'); +const bs58 = require('bs58'); function getBytes32FromMultiash(multihash) { const decoded = bs58.decode(multihash); @@ -22,12 +23,9 @@ module.exports = function(callback) { var operator = await Operator.at(operatorAddress); var contributors = await Contributors.at(contributorsAddress); - let contributorToAddAddress = process.argv[4]; - if(!contributorToAddAddress) { - console.log('please provide an address'); - proxess.exit(); - } - let ipfsHash = process.argv[5] || 'QmQyZJT9uikzDYTZLhhyVZ5ReZVCoMucYzyvDokDJsijhj'; + let contributorToAddAddress = await promptly.prompt('Contributor address: '); + let ipfsHash = await promptly.prompt('IPFS hash (blank for default): ', { default: 'QmQNA1hhVyL1Vm6HiRxXe9xmc6LUMBDyiNMVgsjThtyevs' }); + let contributorMultihash = getBytes32FromMultiash(ipfsHash); let isCore = true; let contributorResult = await contributors.addContributor(contributorToAddAddress, contributorMultihash.digest, contributorMultihash.hashFunction, contributorMultihash.size, isCore); diff --git a/scripts/add-proposal.js b/scripts/add-proposal.js index 35a8c55..6dbe117 100644 --- a/scripts/add-proposal.js +++ b/scripts/add-proposal.js @@ -1,8 +1,9 @@ const Registry = artifacts.require('./Registry.sol'); const Operator = artifacts.require('./Operator.sol'); const Contributors = artifacts.require('./Contributors.sol'); +const promptly = require('promptly'); -var bs58 = require('bs58'); +const bs58 = require('bs58'); function getBytes32FromMultiash(multihash) { const decoded = bs58.decode(multihash); @@ -22,12 +23,9 @@ module.exports = function(callback) { var operator = await Operator.at(operatorAddress); var contributors = await Contributors.at(contributorsAddress); - let recipientAddress = process.argv[4]; - if(!recipientAddress) { - console.log('please provide an address'); - process.exit(); - } - let ipfsHash = process.argv[5] || 'QmQNA1hhVyL1Vm6HiRxXe9xmc6LUMBDyiNMVgsjThtyevs'; + let recipientAddress = await promptly.prompt('Contributor address: '); + let ipfsHash = await promptly.prompt('IPFS hash (blank for default): ', { default: 'QmQNA1hhVyL1Vm6HiRxXe9xmc6LUMBDyiNMVgsjThtyevs' }); + let multihash = getBytes32FromMultiash(ipfsHash); let contributorId = await contributors.getContributorIdByAddress(recipientAddress); diff --git a/scripts/cli.js b/scripts/cli.js index 20ac150..ca0b005 100644 --- a/scripts/cli.js +++ b/scripts/cli.js @@ -1,17 +1,15 @@ const REPL = require('repl'); +const promptly = require('promptly'); module.exports = function(callback) { const Registry = artifacts.require('./Registry.sol'); Registry.deployed().then(async (registry) => { - let contractName = process.argv[4]; - let method = process.argv[5]; - let args = process.argv.slice(6); - - if (!contractName) { - console.log("Usage:"); - console.log(" truffle exec scripts/cli.js [ ]"); - callback(); - return; + let contractName = await promptly.prompt('Contract Name: '); + let method = await promptly.prompt('Function: '); + let argumentInput = await promptly.prompt('Arguments (comma separated): ', { default: '' }); + let args = []; + if (argumentInput !== '') { + args = argumentInput.split(',').map(a => a.trim()); } let contractAddress = await registry.getProxyFor(contractName); diff --git a/scripts/multihash.js b/scripts/multihash.js index bf59b2f..e80719c 100644 --- a/scripts/multihash.js +++ b/scripts/multihash.js @@ -1,4 +1,4 @@ -var bs58 = require('bs58'); +const bs58 = require('bs58'); function getBytes32FromMultiash(multihash) { const decoded = bs58.decode(multihash); diff --git a/scripts/send-funds.js b/scripts/send-funds.js index 262e286..eff869a 100644 --- a/scripts/send-funds.js +++ b/scripts/send-funds.js @@ -1,12 +1,12 @@ +const promptly = require('promptly'); + +module.exports = async function(callback) { + let recipient = await promptly.prompt('Recipient address: '); + let amount = await promptly.prompt('Amount: ', {default: '1'}); + amount = parseInt(amount); + + console.log(`sending ${amount} ETH from ${web3.eth.accounts[0]} to ${recipient}`); -module.exports = function(callback) { - let recipient = process.argv[4]; - if (!recipient) { - console.log('Please provide a recipient address'); - process.exit(); - } - let amount = parseInt(process.argv[5]) || 1; - console.log(recipient); web3.eth.sendTransaction({to: recipient, value: web3.toWei(amount), from: web3.eth.accounts[0]}, console.log); callback(); -- 2.25.1 From df0455e5e084fe28b782798aec523297916931a7 Mon Sep 17 00:00:00 2001 From: bumi Date: Thu, 19 Apr 2018 22:19:48 +0200 Subject: [PATCH 4/5] hacking --- lib/addresses/Contributors.json | 2 +- lib/addresses/Operator.json | 2 +- lib/addresses/Registry.json | 2 +- lib/addresses/Token.json | 2 +- lib/contracts/base.js | 4 ++ lib/contracts/contributor.js | 3 +- lib/contracts/index.js | 3 +- lib/contracts/registry.js | 8 ++++ lib/healthcheck.js | 24 ++++++++++ lib/kredits.js | 38 ++++++++++++---- scripts/add-contributor.js | 80 ++++++++++++++++++++------------- truffle.js | 2 +- 12 files changed, 124 insertions(+), 46 deletions(-) create mode 100644 lib/contracts/registry.js create mode 100644 lib/healthcheck.js diff --git a/lib/addresses/Contributors.json b/lib/addresses/Contributors.json index 7c8cb62..9b722e1 100644 --- a/lib/addresses/Contributors.json +++ b/lib/addresses/Contributors.json @@ -1 +1 @@ -{"42":"0x205fe1b3dac678b594c5f0535e7d158e38591f93","100":"0xa7fc9b1f678c41396b53904f94f50a42ff44d826"} \ No newline at end of file +{"42":"0x205fe1b3dac678b594c5f0535e7d158e38591f93","100":"0x6ebe4c6a39216e37f5efafd9ce89e2bed293270e"} \ No newline at end of file diff --git a/lib/addresses/Operator.json b/lib/addresses/Operator.json index b865526..0298bb1 100644 --- a/lib/addresses/Operator.json +++ b/lib/addresses/Operator.json @@ -1 +1 @@ -{"42":"0x9fd66ee78a5ebe86006f12b37ff59c63f9caa15b","100":"0x95d3bd7d136bb0b7ac9988097e964236f8a9976e"} \ No newline at end of file +{"42":"0x9fd66ee78a5ebe86006f12b37ff59c63f9caa15b","100":"0x38062ac7ac5f910471ce490eabf0af1c4ac92c5f"} \ No newline at end of file diff --git a/lib/addresses/Registry.json b/lib/addresses/Registry.json index 8bdcb57..2e23736 100644 --- a/lib/addresses/Registry.json +++ b/lib/addresses/Registry.json @@ -1 +1 @@ -{"42":"0xc270e6ea4fe303df9f1a3d4a132ac425264082e7","100":"0x513f8e80a8fbb9fa188320ecf231efcf2f6da9c5"} \ No newline at end of file +{"42":"0xc270e6ea4fe303df9f1a3d4a132ac425264082e7","100":"0x2cf47d9c33590ade7261bba063082e5ee1469911"} \ No newline at end of file diff --git a/lib/addresses/Token.json b/lib/addresses/Token.json index 9242b73..ecb7bba 100644 --- a/lib/addresses/Token.json +++ b/lib/addresses/Token.json @@ -1 +1 @@ -{"42":"0xf71ccf7ab48044ef9ae0b5e6983dbd3266b78b36","100":"0x3fc29fbe40c2d0ca78c7e81342f00226650fe2ad"} \ No newline at end of file +{"42":"0xf71ccf7ab48044ef9ae0b5e6983dbd3266b78b36","100":"0x98547fe20531018a2fd5e4a70be11c4ecbeb0520"} \ No newline at end of file diff --git a/lib/contracts/base.js b/lib/contracts/base.js index de43c19..ba113b5 100644 --- a/lib/contracts/base.js +++ b/lib/contracts/base.js @@ -3,6 +3,10 @@ class Base { this.contract = contract; } + get address() { + return this.contract.address; + } + get functions() { return this.contract.functions; } diff --git a/lib/contracts/contributor.js b/lib/contracts/contributor.js index 127e2dc..a112f2c 100644 --- a/lib/contracts/contributor.js +++ b/lib/contracts/contributor.js @@ -42,13 +42,14 @@ class Contributor extends Base { .add(json) .then((ipfsHashAttr) => { let contributor = [ - contributorAttr.address, + contributorAttr.account, ipfsHashAttr.hashDigest, ipfsHashAttr.hashFunction, ipfsHashAttr.hashSize, contributorAttr.isCore, ]; + console.log(contributor); return this.functions.addContributor(...contributor); }); } diff --git a/lib/contracts/index.js b/lib/contracts/index.js index 9fd06ae..f9f209b 100644 --- a/lib/contracts/index.js +++ b/lib/contracts/index.js @@ -1,5 +1,6 @@ module.exports = { Contributors: require('./contributor'), Operator: require('./operator'), - Token: require('./token') + Token: require('./token'), + Registry: require('./registry') } diff --git a/lib/contracts/registry.js b/lib/contracts/registry.js new file mode 100644 index 0000000..3ff8562 --- /dev/null +++ b/lib/contracts/registry.js @@ -0,0 +1,8 @@ +const Base = require('./base'); + +class Registry extends Base { +} + +module.exports = Registry; + + diff --git a/lib/healthcheck.js b/lib/healthcheck.js new file mode 100644 index 0000000..b440d5e --- /dev/null +++ b/lib/healthcheck.js @@ -0,0 +1,24 @@ +class Healthcheck { + constructor(kredits) { + this.kredits = kredits; + } + + check() { + return this.kredits.ipfs._ipfsAPI.id() + .catch((error) => { + throw new Error(`IPFS node not available; config: ${JSON.stringify(this.kredits.ipfs.config)} - ${error.message}`); + }) + .then(() => { + return Object.keys(this.kredits.contracts).map((name) => { + let contract = this.kredits.contracts[name]; + this.kredits.provider.getCode(contract.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 ${contract.address} on network ${this.kredits.provider.chainId}`); + } + }); + }); + }); + } +} diff --git a/lib/kredits.js b/lib/kredits.js index 8182137..e7eefc5 100644 --- a/lib/kredits.js +++ b/lib/kredits.js @@ -1,13 +1,13 @@ const ethers = require('ethers'); const RSVP = require('rsvp'); -const abis = { +const ABIs = { Contributors: require('./abis/Contributors.json'), Operator: require('./abis/Operator.json'), Registry: require('./abis/Registry.json'), Token: require('./abis/Token.json') }; -const addresses = { +const ADDRESSES = { Registry: require('./addresses/Registry.json') }; @@ -22,7 +22,7 @@ function capitalize(word) { class Kredits { static get contractNames() { - return Object.keys(abis); + return Object.keys(ABIs); } constructor(provider, signer, addresses) { @@ -30,11 +30,26 @@ class Kredits { this.signer = signer; // Initialize our registry contract - this.addresses = addresses; + this.addresses = addresses || ADDRESSES[this.provider.chainId]; + this.abis = ABIs; this.contracts = {}; this.ipfs = new IPFS(); } + init(names) { + let contractsToLoad = names || Kredits.contractNames; + let addressPromises = contractsToLoad.map((contractName) => { + return this.Registry.functions.getProxyFor(contractName).then((address) => { + this.addresses[contractName] = address; + }).catch((error) => { + throw new Error(`Failed to get address for ${contractName} from registry at ${this.Registry.address} + - correct registry? does it have version entry? - ${error.message}` + ); + }); + }); + return RSVP.all(addressPromises).then(() => { return this }); + } + static setup(provider, signer, ipfsConfig = null) { let ipfsAPI = new IPFS(ipfsConfig); @@ -64,11 +79,11 @@ class Kredits { } static initRegistryContract(provider) { - let address = addresses['Registry'][provider.chainId]; + 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'])} + supported networks: ${Object.keys(ADDRESSES['Registry'])} `); } provider.getCode(address).then((code) => { @@ -78,10 +93,14 @@ class Kredits { throw new Error(`Registry not found at ${address} on network ${provider.chainId}`); } }); - let abi = abis['Registry']; + let abi = ABIs['Registry']; return new ethers.Contract(address, abi, provider); } + get Registry() { + return this.contractFor('registry'); + } + get Contributor() { // TODO: rename to contributor return this.contractFor('contributors'); @@ -103,10 +122,11 @@ class Kredits { let contractName = capitalize(name); let address = this.addresses[contractName]; - if (!address || !abis[contractName]) { + let abi = this.abis[contractName]; + if (!address || !abi) { throw new Error(`Address or ABI not found for ${contractName}`); } - let contract = new ethers.Contract(address, abis[contractName], this.signer); + let contract = new ethers.Contract(address, abi, this.signer); this.contracts[name] = new contracts[contractName](contract); this.contracts[name].ipfs = this.ipfs; diff --git a/scripts/add-contributor.js b/scripts/add-contributor.js index 2636c2a..6f5f043 100644 --- a/scripts/add-contributor.js +++ b/scripts/add-contributor.js @@ -3,43 +3,63 @@ const Operator = artifacts.require('./Operator.sol'); const Contributors = artifacts.require('./Contributors.sol'); const promptly = require('promptly'); +const IPFS = require('../lib/utils/ipfs'); +const ipfs = new IPFS(); const bs58 = require('bs58'); -function getBytes32FromMultiash(multihash) { - const decoded = bs58.decode(multihash); +const ethers = require('ethers'); +const Kredits = require('../lib/kredits'); - return { - digest: `0x${decoded.slice(2).toString('hex')}`, - hashFunction: decoded[0], - size: decoded[1], - }; +async function prompt(message, options) { + if (!options) { + options = {default: ''} + } + return await promptly.prompt(message, options); } - module.exports = function(callback) { Registry.deployed().then(async (registry) => { - var operatorAddress = await registry.getProxyFor('Operator'); - var contributorsAddress = await registry.getProxyFor('Contributors'); - var operator = await Operator.at(operatorAddress); - var contributors = await Contributors.at(contributorsAddress); + console.log(`Using registry at: ${registry.address}`); + let networkId = parseInt(web3.version.network); + console.log(web3.currentProvider); + let provider = new ethers.providers.Web3Provider( + web3.currentProvider, + { chainId: networkId } + ) + console.log(provider.getSigner()); + const kredits = await new Kredits(provider, provider.getSigner(), {Registry: registry.address}).init(); + console.log(`Using contributors at: ${kredits.Contributor.address}`); + let contributorAttributes = { + account: await prompt('Contributor address: ', {}), + name: await prompt('Name: '), + isCore: await prompt('core? y/n') === 'y', + kind: await prompt('Kind (default person): ', {default: 'person'}), + url: await prompt('URL: '), + github_username: await prompt('GitHub username: '), + github_uid: await prompt('GitHub UID: '), + wiki_username: await prompt('Wiki username: '), + } - let contributorToAddAddress = await promptly.prompt('Contributor address: '); - let ipfsHash = await promptly.prompt('IPFS hash (blank for default): ', { default: 'QmQNA1hhVyL1Vm6HiRxXe9xmc6LUMBDyiNMVgsjThtyevs' }); - - let contributorMultihash = getBytes32FromMultiash(ipfsHash); - let isCore = true; - let contributorResult = await contributors.addContributor(contributorToAddAddress, contributorMultihash.digest, contributorMultihash.hashFunction, contributorMultihash.size, isCore); - console.log('Contributor added, tx: ', contributorResult.tx); - - let contributorId = await contributors.getContributorIdByAddress(contributorToAddAddress); - let proposalMultihash = getBytes32FromMultiash('QmQNA1hhVyL1Vm6HiRxXe9xmc6LUMBDyiNMVgsjThtyevs'); - let proposalResult = await operator.addProposal(contributorId, 23, proposalMultihash.digest, proposalMultihash.hashFunction, proposalMultihash.size); - console.log('Proposal added, tx: ', proposalResult.tx); - - let proposalId = await operator.proposalsCount(); - let votingResult = await operator.vote(proposalId.toNumber()-1); - console.log('Voted for proposal', proposalId.toString(), votingResult.tx); - - callback(); + contributorAttributes = { + account: '0x398ac9cdb122e6f526c8bf8dd80eeeb18fce8821', + name: 'bumi', + isCore: '1' + } + console.log("\nCreating new contributor with following attributes:"); + console.log(contributorAttributes); + kredits.Contributor.functions.addContributor('0x398ac9cdb122e6f526c8bf8dd80eeeb18fce8821', + '0x272bbfc66166f26cae9c9b96b7f9590e095f02edf342ac2dd71e1667a12116ca', 18, 32, true).then((r) => { + console.log(r); + process.exit(); + }); + /* + kredits.Contributor.add(contributorAttributes).then((result) => { + console.log(result); + callback(); + }).catch((error) => { + console.log('Failed to create contributor'); + callback(error); + }); + */ }); } diff --git a/truffle.js b/truffle.js index 77e88c5..e7e7beb 100644 --- a/truffle.js +++ b/truffle.js @@ -3,7 +3,7 @@ module.exports = { networks: { development: { host: "127.0.0.1", - port: 7545, + port: 8545, network_id: "*" // Match any network id }, kovan: { -- 2.25.1 From 61455e6844f40f9579d08de6780240328066bbda Mon Sep 17 00:00:00 2001 From: bumi Date: Thu, 19 Apr 2018 22:20:44 +0200 Subject: [PATCH 5/5] correct ganache port --- truffle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truffle.js b/truffle.js index e7e7beb..77e88c5 100644 --- a/truffle.js +++ b/truffle.js @@ -3,7 +3,7 @@ module.exports = { networks: { development: { host: "127.0.0.1", - port: 8545, + port: 7545, network_id: "*" // Match any network id }, kovan: { -- 2.25.1