Add JS wrapper for Kit contract #130

Merged
bumi merged 4 commits from feature/kredits-kit-wrapper into master 2019-06-09 11:56:33 +00:00
5 changed files with 72 additions and 22 deletions

1
lib/abis/KreditsKit.json Normal file
View File

@ -0,0 +1 @@
[{"constant":true,"inputs":[],"name":"ens","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"fac","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"appId","type":"bytes32"}],"name":"latestVersionAppBase","outputs":[{"name":"base","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"appIds","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_fac","type":"address"},{"name":"_ens","type":"address"},{"name":"_appIds","type":"bytes32[4]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"dao","type":"address"}],"name":"DeployInstance","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"dao","type":"address"},{"indexed":false,"name":"appProxy","type":"address"},{"indexed":false,"name":"appId","type":"bytes32"}],"name":"InstalledApp","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"appProxy","type":"address"},{"indexed":false,"name":"appId","type":"bytes32"}],"name":"InstalledApp","type":"event"},{"constant":false,"inputs":[],"name":"newInstance","outputs":[{"name":"dao","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]

View File

@ -7,6 +7,10 @@ class Base {
return this.contract.functions; return this.contract.functions;
} }
get address () {
return this.contract.address;
}
get ipfs () { get ipfs () {
if (!this._ipfsAPI) { throw new Error('IPFS API not configured; please set an ipfs instance'); } if (!this._ipfsAPI) { throw new Error('IPFS API not configured; please set an ipfs instance'); }
return this._ipfsAPI; return this._ipfsAPI;

49
lib/kreditskit.js Normal file
View File

@ -0,0 +1,49 @@
const ethers = require('ethers');
const ABI = require('./abis/KreditsKit.json');
const Addresses = require('./addresses/KreditsKit.json');
class KreditsKit {
constructor (provider, signer, options = {}) {
let { address, abi } = options;
this.provider = provider;
this.signer = signer;
this.options = options;
this.address = address;
this.abi = abi || ABI;
}
init () {
return this.provider.getNetwork().then((network) => {
this.address = this.address || Addresses[network.chainId.toString()];
this.contract = new ethers.Contract(
this.address,
this.abi,
(this.signer || this.provider)
);
return this;
});
}
appIdFor (contractName) {
// see appIds in KreditsKit.sol for more details
const knownContracts = ['Contribution', 'Contributor', 'Proposal', 'Token'];
return this.contract.functions.appIds(knownContracts.indexOf(contractName));
}
newDAO (options = {}) {
return this.contract.functions.newInstance(options).then(transaction => {
return transaction.wait().then(result => {
const deployEvent = result.events.find(e => e.event === 'DeployInstance');
return {
daoAddress: deployEvent.args.dao,
transactionHash: transaction.hash,
};
});
});
}
}
module.exports = KreditsKit;

View File

@ -1,13 +1,13 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const ethers = require('ethers');
const fileInject = require('./helpers/file_inject.js'); const fileInject = require('./helpers/file_inject.js');
const getNetworkId = require('./helpers/networkid.js'); const getNetworkId = require('./helpers/networkid.js');
const KreditsKit = require('../lib/kreditskit');
const addressesPath = path.join(__dirname, '..', 'lib/addresses'); const addressesPath = path.join(__dirname, '..', 'lib/addresses');
const KreditsKit = artifacts.require('KreditsKit')
module.exports = async function(callback) { module.exports = async function(callback) {
const networkId = await getNetworkId(web3) const networkId = await getNetworkId(web3)
console.log(`Deploying to networkId: ${networkId}`) console.log(`Deploying to networkId: ${networkId}`)
@ -20,25 +20,21 @@ module.exports = async function(callback) {
} }
console.log(`Using KreditsKit at: ${kreditsKitAddress}`); console.log(`Using KreditsKit at: ${kreditsKitAddress}`);
let kreditsKit = KreditsKit.at(kreditsKitAddress) const provider = new ethers.providers.Web3Provider(web3.currentProvider);
let signer = provider.getSigner();
kreditsKit.newInstance().then((ret) => { let kit = await new KreditsKit(provider, signer).init()
console.log(ret.logs);
const installedEvents = ret.logs.filter(log => log.event === 'InstalledApp').map(log => log.args)
const deployEvents = ret.logs.filter(log => log.event === 'DeployInstance').map(log => log.args)
if (deployEvents.length > 1) { // TODO: get rid of the hard coded gas limit
callback(new Error("More than one DAO was deployed. Something is wrong")) kit.newDAO({ gasLimit: 10000000 }).then(result => {
} console.log(result);
const daoAddress = deployEvents[0].dao; fileInject(path.join(addressesPath, 'dao.json'), networkId, result.daoAddress)
fileInject(path.join(addressesPath, 'dao.json'), networkId, daoAddress) console.log(`\n\nCreated new DAO at: ${result.daoAddress}`)
console.log(`\n\nCreated new DAO at: ${daoAddress}`)
callback(); callback();
}).catch((err) => { }).catch((err) => {
console.log('failed to create a new instance') console.log('failed to create a new DAO')
callback(err) callback(err)
}) })
} }