From fc5a41123a9a0dbf050fc655ac5f4da664f89a95 Mon Sep 17 00:00:00 2001 From: Michael Bumann Date: Tue, 11 Jun 2019 21:48:50 +0200 Subject: [PATCH 1/4] Add IPFS pinning script This script loads the IPFS hashes for contributors and contributions and pins them on the connected IPFS node. usage: $ node script/ipfs-pinner.js $ ETH_RPC_URL=http://localhost:7547 APM_DOMAIN=aragonpm.eth node scripts/ipfs.pinner.js --- scripts/ipfs-pinner.js | 60 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 scripts/ipfs-pinner.js diff --git a/scripts/ipfs-pinner.js b/scripts/ipfs-pinner.js new file mode 100644 index 0000000..b53608a --- /dev/null +++ b/scripts/ipfs-pinner.js @@ -0,0 +1,60 @@ +//const Kredits = require('kredits-contracts'); +const Kredits = require('../lib/kredits'); +const multihashes = require('multihashes'); + +async function pinContributor (kredits, id) { + const data = await kredits.Contributor.functions.getContributorById(id); + const ipfsHash = multihashes.toB58String(kredits.ipfs.encodeHash(data)); + console.log(`Pinning Contributor ${id} ${ipfsHash}`); + kredits.ipfs._ipfsAPI.pin.add(ipfsHash, (err) => { + if (err) { + console.log(`Failed to pin ${ipfsHash}`); + console.log(err); + } + }); +} + +async function pinContribution (kredits, id) { + const data = await kredits.Contribution.functions.getContribution(id); + const ipfsHash = multihashes.toB58String(kredits.ipfs.encodeHash(data)); + console.log(`Pinning Contribution ${id} ${ipfsHash}`); + kredits.ipfs._ipfsAPI.pin.add(ipfsHash, (err) => { + if (err) { + console.log(`Failed to pin ${ipfsHash}`); + console.log(err); + } + }); +} + +async function all (kredits) { + const contributionCount = await kredits.Contribution.count; + for (let id=1; id<=contributionCount; id++) { + pinContribution(kredits, id); + } + const contributorCount = await kredits.Contributor.count; + for (let id=1; id<=contributorCount; id++) { + pinContributor(kredits, id); + } +} + +function subscribe (kredits) { + kredits.Contribution.on('ContributionAdded', async (id) => { + pinContribution(kredits, id); + }); + kredits.Contributor.on('ContributorAdded', async (id) => { + pinContribution(kredits, id); + }); + kredits.Contributor.on('ContributorProfileUpdated', async (id) => { + pinContributor(kredits, id); + }); +} + +const network = process.env.ETH_NETWORK || 'rinkeby'; +const rpcUrl = process.env.ETH_RPC_URL; +const apm = process.env.APM_DOMAIN || 'open.aragonpm.eth'; + +Kredits.for({ network, rpcUrl }, { apm }).init().then(async (kredits) => { + all(kredits); + subscribe (kredits); + console.log(`Subscribed to new events for DAO: ${kredits.Kernel.contract.address}`); +}); From b09c2830c8fd429e7b9c2e5b1deee81990f9864c Mon Sep 17 00:00:00 2001 From: Michael Bumann Date: Tue, 11 Jun 2019 23:45:27 +0200 Subject: [PATCH 2/4] Make IPFS node configurable --- scripts/ipfs-pinner.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/ipfs-pinner.js b/scripts/ipfs-pinner.js index b53608a..4bd1359 100644 --- a/scripts/ipfs-pinner.js +++ b/scripts/ipfs-pinner.js @@ -52,8 +52,15 @@ function subscribe (kredits) { const network = process.env.ETH_NETWORK || 'rinkeby'; const rpcUrl = process.env.ETH_RPC_URL; const apm = process.env.APM_DOMAIN || 'open.aragonpm.eth'; +const ipfsConfig = { + host: process.env.IPFS_HOST || 'localhost', + port: process.env.IPFS_PORT || '5001', + protocol: process.env.IPFS_PROTOCOL || 'http' +}; -Kredits.for({ network, rpcUrl }, { apm }).init().then(async (kredits) => { +console.log(`Using IPFS:`, ipfsConfig); + +Kredits.for({ network, rpcUrl }, { apm, ipfsConfig }).init().then(async (kredits) => { all(kredits); subscribe (kredits); console.log(`Subscribed to new events for DAO: ${kredits.Kernel.contract.address}`); From 6d6c6056f01d45aaee9b0de102f1cb1cae14ea2e Mon Sep 17 00:00:00 2001 From: Michael Bumann Date: Wed, 12 Jun 2019 01:08:07 +0200 Subject: [PATCH 3/4] Refactor IPFS pinner --- lib/contracts/contribution.js | 5 +++ lib/contracts/contributor.js | 5 +++ lib/contracts/record.js | 12 +++++++ lib/utils/ipfs-pinner.js | 32 ++++++++++++++++++ lib/utils/ipfs.js | 8 +++++ scripts/ipfs-pinner.js | 63 ++++++----------------------------- 6 files changed, 73 insertions(+), 52 deletions(-) create mode 100644 lib/utils/ipfs-pinner.js diff --git a/lib/contracts/contribution.js b/lib/contracts/contribution.js index df52220..2856949 100644 --- a/lib/contracts/contribution.js +++ b/lib/contracts/contribution.js @@ -14,6 +14,10 @@ class Contribution extends Record { }); } + getData (id) { + return this.functions.getContribution(id); + } + getByContributorId (contributorId) { return this.functions.getContributorAddressById(contributorId) .then(address => this.getByContributorAddress(address)); @@ -62,6 +66,7 @@ class Contribution extends Record { deprecate('The function `addContribution()` is deprecated and will be removed in the next major version. Use `add()` instead'); return this.add(...arguments); } + } module.exports = Contribution; diff --git a/lib/contracts/contributor.js b/lib/contracts/contributor.js index 3ca68b2..6a1c1ed 100644 --- a/lib/contracts/contributor.js +++ b/lib/contracts/contributor.js @@ -15,6 +15,10 @@ class Contributor extends Record { }); } + getData (id) { + return this.functions.getContributorById(id); + } + filterByAccount (search) { return this._byAccount(search, 'filter'); } @@ -84,6 +88,7 @@ class Contributor extends Record { }); }); } + } module.exports = Contributor; diff --git a/lib/contracts/record.js b/lib/contracts/record.js index 1e1f83a..52099af 100644 --- a/lib/contracts/record.js +++ b/lib/contracts/record.js @@ -9,6 +9,18 @@ class Record extends Base { return Promise.all(records); }); } + + pinIpfsHashes () { + return this.count.then(count => { + let promises = [...Array(count).keys()].map(i => { + let id = i + 1; // 0 => 1 - ids start with 1 and not with 0 + return this.getData(id).then(data => { + return this.ipfs.pin(data); + }); + }); + return Promise.all(promises); + }); + } } module.exports = Record; diff --git a/lib/utils/ipfs-pinner.js b/lib/utils/ipfs-pinner.js new file mode 100644 index 0000000..59d158f --- /dev/null +++ b/lib/utils/ipfs-pinner.js @@ -0,0 +1,32 @@ +class IpfsPinner { + constructor (kredits) { + this.kredits = kredits; + } + + pinAll () { + return Promise.all([ + this.kredits.Contributor.pinIpfsHashes(), + this.kredits.Contribution.pinIpfsHashes(), + ]); + } + + monitor (callback) { + this.kredits.Contribution.on('ContributionAdded', (id) => { + this.kredits.Contribution.getData(id) + .then(data => { return this.kredits.ipfs.pin(data); }) + .then(callback); + }); + this.kredits.Contributor.on('ContributorAdded', (id) => { + this.kredits.Contribution.getData(id) + .then(data => { return this.kredits.ipfs.pin(data); }) + .then(callback); + }); + this.kredits.Contributor.on('ContributorProfileUpdated', (id) => { + this.kredits.Contributor.getData(id) + .then(data => { return this.kredits.ipfs.pin(data); }) + .then(callback); + }); + } + +} +module.exports = IpfsPinner; diff --git a/lib/utils/ipfs.js b/lib/utils/ipfs.js index 105379f..c4b1beb 100644 --- a/lib/utils/ipfs.js +++ b/lib/utils/ipfs.js @@ -41,6 +41,14 @@ class IPFS { return this._ipfsAPI.cat(ipfsHash); } + pin (hashData) { + let ipfsHash = hashData; // default - if it is a string + if (hashData.hasOwnProperty('hashSize')) { + ipfsHash = this.encodeHash(hashData); + } + return this._ipfsAPI.pin.add(multihashes.toB58String(ipfsHash)); + } + decodeHash (ipfsHash) { let multihash = multihashes.decode(multihashes.fromB58String(ipfsHash)); return { diff --git a/scripts/ipfs-pinner.js b/scripts/ipfs-pinner.js index 4bd1359..6614b44 100644 --- a/scripts/ipfs-pinner.js +++ b/scripts/ipfs-pinner.js @@ -1,53 +1,7 @@ //const Kredits = require('kredits-contracts'); +//const Kredits = require('kredits-contracts/utils/ipfs-pinner'); const Kredits = require('../lib/kredits'); -const multihashes = require('multihashes'); - -async function pinContributor (kredits, id) { - const data = await kredits.Contributor.functions.getContributorById(id); - const ipfsHash = multihashes.toB58String(kredits.ipfs.encodeHash(data)); - console.log(`Pinning Contributor ${id} ${ipfsHash}`); - kredits.ipfs._ipfsAPI.pin.add(ipfsHash, (err) => { - if (err) { - console.log(`Failed to pin ${ipfsHash}`); - console.log(err); - } - }); -} - -async function pinContribution (kredits, id) { - const data = await kredits.Contribution.functions.getContribution(id); - const ipfsHash = multihashes.toB58String(kredits.ipfs.encodeHash(data)); - console.log(`Pinning Contribution ${id} ${ipfsHash}`); - kredits.ipfs._ipfsAPI.pin.add(ipfsHash, (err) => { - if (err) { - console.log(`Failed to pin ${ipfsHash}`); - console.log(err); - } - }); -} - -async function all (kredits) { - const contributionCount = await kredits.Contribution.count; - for (let id=1; id<=contributionCount; id++) { - pinContribution(kredits, id); - } - const contributorCount = await kredits.Contributor.count; - for (let id=1; id<=contributorCount; id++) { - pinContributor(kredits, id); - } -} - -function subscribe (kredits) { - kredits.Contribution.on('ContributionAdded', async (id) => { - pinContribution(kredits, id); - }); - kredits.Contributor.on('ContributorAdded', async (id) => { - pinContribution(kredits, id); - }); - kredits.Contributor.on('ContributorProfileUpdated', async (id) => { - pinContributor(kredits, id); - }); -} +const IpfsPinner = require('../lib/utils/ipfs-pinner'); const network = process.env.ETH_NETWORK || 'rinkeby'; const rpcUrl = process.env.ETH_RPC_URL; @@ -60,8 +14,13 @@ const ipfsConfig = { console.log(`Using IPFS:`, ipfsConfig); -Kredits.for({ network, rpcUrl }, { apm, ipfsConfig }).init().then(async (kredits) => { - all(kredits); - subscribe (kredits); - console.log(`Subscribed to new events for DAO: ${kredits.Kernel.contract.address}`); +Kredits.for({ network, rpcUrl }, { apm, ipfsConfig }).init().then(kredits => { + const ipfsPinner = new IpfsPinner(kredits); + ipfsPinner.pinAll().then(pins => { + console.log('Pinned', JSON.stringify(pins, null, 2)); + }); + ipfsPinner.monitor((pin) => { + console.log('Pinned', JSON.stringify(pin)); + }); + console.log(`Subscribed to DAO: ${kredits.Kernel.contract.address}`); }); From 9fd9dbc1b596bb0425c46605370c5f37efdcc8a5 Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Thu, 13 Jun 2019 18:31:47 +0200 Subject: [PATCH 4/4] Handle errors in IPFS pin script --- scripts/ipfs-pinner.js | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/scripts/ipfs-pinner.js b/scripts/ipfs-pinner.js index 6614b44..985dc01 100644 --- a/scripts/ipfs-pinner.js +++ b/scripts/ipfs-pinner.js @@ -1,26 +1,31 @@ -//const Kredits = require('kredits-contracts'); -//const Kredits = require('kredits-contracts/utils/ipfs-pinner'); const Kredits = require('../lib/kredits'); const IpfsPinner = require('../lib/utils/ipfs-pinner'); const network = process.env.ETH_NETWORK || 'rinkeby'; const rpcUrl = process.env.ETH_RPC_URL; const apm = process.env.APM_DOMAIN || 'open.aragonpm.eth'; + const ipfsConfig = { host: process.env.IPFS_HOST || 'localhost', port: process.env.IPFS_PORT || '5001', - protocol: process.env.IPFS_PROTOCOL || 'http' + protocol: process.env.IPFS_PROTOCOL || 'http', }; - console.log(`Using IPFS:`, ipfsConfig); -Kredits.for({ network, rpcUrl }, { apm, ipfsConfig }).init().then(kredits => { - const ipfsPinner = new IpfsPinner(kredits); - ipfsPinner.pinAll().then(pins => { - console.log('Pinned', JSON.stringify(pins, null, 2)); - }); - ipfsPinner.monitor((pin) => { - console.log('Pinned', JSON.stringify(pin)); - }); - console.log(`Subscribed to DAO: ${kredits.Kernel.contract.address}`); -}); +(async () => { + try { + const kredits = await Kredits.for({ network, rpcUrl }, { apm, ipfsConfig }).init(); + const ipfsPinner = new IpfsPinner(kredits); + + ipfsPinner.pinAll().then(pins => { + console.log('Pinned', JSON.stringify(pins, null, 2)); + }); + ipfsPinner.monitor((pin) => { + console.log('Pinned', JSON.stringify(pin)); + }); + console.log(`Subscribed to DAO: ${kredits.Kernel.contract.address}`); + } catch(e) { + console.log(e); + process.exit(1); + } +})();