Update and adapt for new kredits contracts release

This commit is contained in:
Râu Cao 2022-10-31 13:01:29 +01:00
parent c27fefcfdc
commit 710bd90172
Signed by: raucao
GPG Key ID: 15E65F399D084BA9
4 changed files with 4956 additions and 1893 deletions

View File

@ -10,15 +10,20 @@ contributions.
## Setup ## Setup
### Ethereum wallet ### Wallet
You will need an Ethereum wallet for your bot, so it can interact with the You will need a keypair/wallet for your bot, so it can interact with the smart
Ethereum smart contracts. `npm run create-wallet` will do the job for you. contracts. `npm run create-wallet` will do the job for you.
The wallet must be funded with enough ETH to interact with the contracts. The wallet must be funded with enough native chain tokens to interact with the
contracts (i.e. it must be able to pay gas/tx fees)
### Contract permissions ### Contract permissions
**Warning: outdated instructions!**
*TODO adapt instructions for new permission model*
The bot wallet needs the following Aragon contract permissions to interact The bot wallet needs the following Aragon contract permissions to interact
with [kredits-contracts]: with [kredits-contracts]:
@ -41,11 +46,10 @@ As usual in Hubot, you can add all config as environment variables.
| --- | --- | | --- | --- |
| `KREDITS_WEBHOOK_TOKEN` | A string for building your secret webhook URLs | | `KREDITS_WEBHOOK_TOKEN` | A string for building your secret webhook URLs |
| `KREDITS_ROOM` | The bot will talk to you in this room | | `KREDITS_ROOM` | The bot will talk to you in this room |
| `KREDITS_WALLET_PATH` | Path to an Etherum wallet JSON file (default: `./wallet.json`) | | `KREDITS_WALLET_PATH` | Path to an wallet JSON file (default: `./wallet.json`) |
| `KREDITS_WALLET_PASSWORD` | Wallet password | | `KREDITS_WALLET_PASSWORD` | Wallet password |
| `KREDITS_PROVIDER_URL` | Ethereum JSON-RPC URL (default: `http://localhost:7545`) | | `KREDITS_PROVIDER_URL` | JSON-RPC URL of a blockchain node (default: `http://localhost:7545`) |
| `KREDITS_WEB_URL` | URL of the Kredits Web app (default: `https://kredits.kosmos.org`) | | `KREDITS_WEB_URL` | URL of the Kredits Web app (default: `https://kredits.kosmos.org`) |
| `KREDITS_DAO_ADDRESS` | DAO Kernel address |
| `KREDITS_SESSION_SECRET` | Secret used by [grant](https://www.npmjs.com/package/grant) to sign the session ID | | `KREDITS_SESSION_SECRET` | Secret used by [grant](https://www.npmjs.com/package/grant) to sign the session ID |
| `KREDITS_GRANT_HOST` | Host used by [grant](https://www.npmjs.com/package/grant) to generate OAuth redirect URLs (default: `localhost:8888`) | | `KREDITS_GRANT_HOST` | Host used by [grant](https://www.npmjs.com/package/grant) to generate OAuth redirect URLs (default: `localhost:8888`) |
| `KREDITS_GRANT_PROTOCOL` | Protocol (http or https) used by [grant](https://www.npmjs.com/package/grant") to generate the OAuth redirect URLs (default: "http") | | `KREDITS_GRANT_PROTOCOL` | Protocol (http or https) used by [grant](https://www.npmjs.com/package/grant") to generate the OAuth redirect URLs (default: "http") |

View File

@ -1,14 +1,11 @@
const fs = require('fs'); const fs = require('fs');
const util = require('util');
const fetch = require('node-fetch');
const ethers = require('ethers'); const ethers = require('ethers');
const NonceManager = require('@ethersproject/experimental').NonceManager; const NonceManager = require('@ethersproject/experimental').NonceManager;
const Kredits = require('kredits-contracts'); const Kredits = require('@kredits/contracts');
const walletPath = process.env.KREDITS_WALLET_PATH || './wallet.json'; const walletPath = process.env.KREDITS_WALLET_PATH || './wallet.json';
const walletJson = fs.readFileSync(walletPath); const walletJson = fs.readFileSync(walletPath);
const providerUrl = process.env.KREDITS_PROVIDER_URL; const providerUrl = process.env.KREDITS_PROVIDER_URL || 'http://localhost:7545';
const daoAddress = process.env.KREDITS_DAO_ADDRESS;
const ipfsConfig = { const ipfsConfig = {
host: process.env.IPFS_API_HOST || 'localhost', host: process.env.IPFS_API_HOST || 'localhost',
@ -38,12 +35,9 @@ module.exports = async function(robot) {
// Ethereum provider/node setup // Ethereum provider/node setup
// //
let ethProvider; robot.logger.info('[hubot-kredits] Using blockchain node/API at', providerUrl);
if (providerUrl) {
ethProvider = new ethers.providers.JsonRpcProvider(providerUrl); const ethProvider = new ethers.providers.JsonRpcProvider(providerUrl);
} else {
ethProvider = new ethers.getDefaultProvider('rinkeby');
}
const signer = new NonceManager(wallet.connect(ethProvider)); const signer = new NonceManager(wallet.connect(ethProvider));
// //
@ -51,9 +45,6 @@ module.exports = async function(robot) {
// //
const opts = { ipfsConfig }; const opts = { ipfsConfig };
if (daoAddress) {
opts.addresses = { Kernel: daoAddress };
}
let kredits; let kredits;
try { try {
@ -63,8 +54,8 @@ module.exports = async function(robot) {
process.exit(1); process.exit(1);
} }
const Contributor = kredits.Contributor; const Contributor = kredits.Contributor;
const Proposal = kredits.Proposal;
const Contribution = kredits.Contribution; const Contribution = kredits.Contribution;
// TODO const Reimbursement = kredits.Reimbursement;
robot.logger.info('[hubot-kredits] Wallet address: ' + wallet.address); robot.logger.info('[hubot-kredits] Wallet address: ' + wallet.address);
@ -73,9 +64,9 @@ module.exports = async function(robot) {
// //
ethProvider.getBalance(wallet.address).then(balance => { ethProvider.getBalance(wallet.address).then(balance => {
robot.logger.info('[hubot-kredits] Wallet balance: ' + ethers.utils.formatEther(balance) + 'ETH'); robot.logger.info('[hubot-kredits] Wallet balance: ' + ethers.utils.formatEther(balance) + ' RBTC');
if (balance.lt(ethers.utils.parseEther('0.0001'))) { if (balance.lt(ethers.utils.parseEther('0.0001'))) {
messageRoom(`Yo gang, I\'m broke! Please drop me some ETH to ${wallet.address}. kthxbai.`); messageRoom(`Yo gang, I\'m broke! Please send some RBTC to ${wallet.address}. kthxbai.`);
} }
}); });
@ -83,30 +74,9 @@ module.exports = async function(robot) {
// Robot chat commands/interaction // Robot chat commands/interaction
// //
robot.respond(/got ETH\??/i, res => { robot.respond(/got RBTC\??/i, res => {
ethProvider.getBalance(wallet.address).then((balance) => { ethProvider.getBalance(wallet.address).then((balance) => {
res.send(`My wallet contains ${ethers.utils.formatEther(balance)} ETH`); res.send(`My wallet contains ${ethers.utils.formatEther(balance)} RBTC`);
});
});
robot.respond(/propose (\d*)\s?\S*\s?to (\S+)(?:\sfor (.*))?$/i, res => {
let [_, amount, githubUser, description] = res.match;
let url = null;
createProposal(githubUser, amount, description, url).then((result) => {
messageRoom('Sounds good! Will be listed on https://kredits.kosmos.org in a bit...');
});
});
robot.respond(/list open proposals/i, res => {
Proposal.all().then((proposals) => {
proposals.forEach((proposal) => {
if (!proposal.executed) {
Contributor.getById(proposal.contributorId).then((contributor) => {
messageRoom(`* ${proposal.amount} kredits to ${contributor.name} for ${proposal.description}`);
});
}
});
messageRoom('https://kredits.kosmos.org');
}); });
}); });
@ -115,31 +85,23 @@ module.exports = async function(robot) {
// //
function watchContractEvents() { function watchContractEvents() {
ethProvider.getBlockNumber().then((blockNumber) => { ethProvider.getBlockNumber().then(blockNumber => {
// current block is the last mined one, thus we check from the next // current block is the last mined one, thus we check from the next
// mined one onwards to prevent getting previous events // mined one onwards to prevent getting previous events
let nextBlock = blockNumber + 1; let nextBlock = blockNumber + 1;
robot.logger.debug(`[hubot-kredits] Watching events from block ${nextBlock} onward`); robot.logger.debug(`[hubot-kredits] Watching events from block ${nextBlock} onward`);
ethProvider.resetEventsBlock(nextBlock); ethProvider.resetEventsBlock(nextBlock);
Proposal.on('ProposalCreated', handleProposalCreated); // TODO handle all known events (that make sense here)
// Contribution.on('ContributorAdded', handleContributorAdded);
Contribution.on('ContributionAdded', handleContributionAdded); Contribution.on('ContributionAdded', handleContributionAdded);
}); });
} }
function handleProposalCreated(proposalId, creatorAccount, contributorId, amount) {
Contributor.getById(contributorId).then((contributor) => {
Proposal.getById(proposalId).then((proposal) => {
robot.logger.debug(`[hubot-kredits] Proposal created (${proposal.description})`);
// messageRoom(`Let's give ${contributor.name} some kredits for ${proposal.url} (${proposal.description}): https://kredits.kosmos.org`);
});
});
}
function handleContributionAdded(contributionId, contributorId, amount) { function handleContributionAdded(contributionId, contributorId, amount) {
Contributor.getById(contributorId).then((contributor) => { Contributor.getById(contributorId).then(_ => {
Contribution.getById(contributionId).then((contribution) => { Contribution.getById(contributionId).then(contribution => {
robot.logger.debug(`[hubot-kredits] Contribution #${contribution.id} added (${contribution.description})`); robot.logger.debug(`[hubot-kredits] Contribution #${contribution.id} added (${amount} kredits for "${contribution.description}")`);
}); });
}); });
} }

6759
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@
"grant-express": "^4.6.1", "grant-express": "^4.6.1",
"group-array": "^1.0.0", "group-array": "^1.0.0",
"kosmos-schemas": "^1.1.2", "kosmos-schemas": "^1.1.2",
"kredits-contracts": "^6.0.0", "@kredits/contracts": "git+https://gitea.kosmos.org/kredits/contracts#deploy-rsk",
"node-cron": "^2.0.3", "node-cron": "^2.0.3",
"node-fetch": "^2.3.0", "node-fetch": "^2.3.0",
"prompt": "^1.0.0", "prompt": "^1.0.0",