Compare commits

..

47 Commits

Author SHA1 Message Date
2a1ae117e8 5.1.1 2019-04-16 12:50:07 +01:00
8abc7ba77f Merge pull request #104 from 67P/chore/update-kosmos-schema
Update kosmos-schema dependency
2019-04-16 11:19:03 +00:00
f696721918 Readme: add note about locally running out of funds 2019-04-16 13:17:54 +02:00
00b58dec66 Update kosmos-schema dependency 2019-04-16 13:16:05 +02:00
560315cbca Merge pull request #102 from 67P/chore/add-yarn-support
Add yarn lock files
2019-04-15 15:54:38 +00:00
24933f31a7 Add yarn lock files 2019-04-15 17:34:48 +02:00
b13bf6e8b0 Readme: add note about locally running out of funds 2019-04-15 15:59:54 +02:00
8dcad88372 Merge pull request #99 from 67P/update-seeds
Update seeds
2019-04-15 10:39:10 +00:00
dc6d2716aa Update seeds 2019-04-15 12:33:51 +02:00
80ad9db630 5.1.0 2019-04-13 12:41:49 +01:00
1b5f7ff95d Merge pull request #93 from 67P/deployments/weltempfaenger-release
Production release to rinkeby
2019-04-13 11:07:58 +01:00
b6c06c289c Merge pull request #95 from 67P/cosmetics
Cosmetic cleanups
2019-04-12 18:55:59 +00:00
f405e39c04 Merge pull request #94 from 67P/bugfix/schema_changes
Refactor contribution serializer and validation
2019-04-12 18:54:56 +00:00
1dbf3b5742 Cosmetic cleanups 2019-04-12 20:16:24 +02:00
952b5153fd Validate proposed contributions 2019-04-11 13:46:42 +02:00
d953141f52 Refactor contribution serializer and validation 2019-04-11 13:05:40 +02:00
aa57d7c70b Adjust seeds for new requirements 2019-04-11 11:02:15 +02:00
4c0bb879e8 Show IPFS hash in list script output 2019-04-11 11:01:45 +02:00
9c5a517fb9 5.0.0 2019-04-11 08:45:49 +02:00
b00ddda312 Merge pull request #92 from 67P/feature/contribution_schema
Validate contribution docs against schema
2019-04-11 08:40:38 +02:00
130e2a7797 Validate contribution docs against schema
Currently requires an open PR branch for the schemas, which is adding
date and time for contributions.

refs #30
2019-04-10 18:37:02 +02:00
27e5190e29 Production release to rinkeby
Deployed all apps and created a new Kredits DAO
2019-04-10 18:28:24 +02:00
b9c171884b Merge pull request #91 from 67P/feature/store-balance-as-wei
Store kredits tokens as wei with 18 decimals
2019-04-10 15:51:36 +02:00
4d2e0ea84b Update Token symbol 2019-04-10 15:50:33 +02:00
26d12ba239 Store kredits tokens as wei with 18 decimals
This stores the tokens with 18 decimals as most other tokens and as
assumed by a potential future token standard EIP 777.
2019-04-10 13:59:00 +02:00
1aae62e139 Merge pull request #88 from 67P/bugfix/confirmed-contributions
Fix confirmed contribution check
2019-04-09 22:36:37 +02:00
f21c4cf9de Fix confirmed contribution check
If the blocknumber is higher or equal the contribution.confirmedAt block
number then the contribution is confirmed and can be claimed.
2019-04-09 22:30:17 +02:00
6778b9060f 4.0.2 2019-04-09 12:47:59 +02:00
4d36f78824 4.0.1 2019-04-09 12:47:37 +02:00
98ecf28262 Merge pull request #87 from 67P/dev/dependency_install
Rename postinstall script
2019-04-09 12:45:41 +02:00
f5564fa923 Formatting, whitespace 2019-04-09 12:45:20 +02:00
096a9f3cea Update README for install-all script 2019-04-09 12:45:09 +02:00
3d24835908 Merge pull request #86 from 67P/dev/bootstrap
Don't run `npm install` on bootstrap
2019-04-09 09:50:51 +02:00
8cbef8458d Rename postinstall script
Prevents it being run when contracts are installed as dependency.
2019-04-09 09:48:00 +02:00
9ca0580db6 Merge pull request #85 from 67P/dev/fix_seeds
Fix contributor ID in seeds
2019-04-09 07:33:42 +00:00
dfe38e7d21 Don't run npm install on bootstrap
When one wants to install, they can install. When one wants to
bootstrap, they should be able to only bootstrap.
2019-04-09 08:44:56 +02:00
377560805f Fix contributor ID in seeds
We have one contributor less, after having removed the initial dummy
account recently.
2019-04-09 08:43:13 +02:00
65d9cf2a06 Fix bootstrap
This runs npm install for every app through a postinstall hook.
2019-04-08 18:10:13 +02:00
b35dc2049b Merge pull request #82 from 67P/dev/list_contributions
Improve list-contributions script
2019-04-06 19:40:24 +00:00
26c2710149 Improve list-contributions script
* Improve sort order of table columns
* Print if the contribution is confirmed
* Log error if something goes wrong
2019-04-06 17:56:48 +02:00
cc24c27444 Merge pull request #80 from 67P/chore/rename-ipfshash-1
Rename ipfsHash to hashDigest in Contributor
2019-04-06 13:55:19 +00:00
f717968402 Better function naming to update contributor profiles 2019-04-06 15:42:16 +02:00
14d7fbd75e Rename ipfsHash to hashDigest in Contributor
naming should be consistent with the other contracts and digest is more
correct.
2019-04-06 15:24:44 +02:00
7eb1fedb42 Merge pull request #76 from 67P/features/dynamic-core-flag
Dynamic function to test for core contributor flag
2019-04-06 15:19:01 +02:00
cbfe39f804 Merge pull request #78 from 67P/feature/veto-period
Set contribution veto period to 1 week
2019-04-06 00:30:30 +02:00
a0e4f5410d Set veto period to 1 week
This makes a contribution claimable after roughly 7 days
2019-04-05 20:30:02 +02:00
766463b57b Dynamic function to test for core contributor flag
This removes the isCore flag and allows us to dynamically calculate the
core flag for contributors.

For now this is just us (the first 6 contirbutors)

Also we do not need the default contributor anymore because the deploy
user has the role to manage contributors and can create the first real
contributors.
2019-04-05 18:55:21 +02:00
41 changed files with 41197 additions and 245 deletions

2
.gitignore vendored
View File

@@ -4,3 +4,5 @@ node_modules
**/node_modules
.ganache-db
.tm_properties
yarn-error.log
.DS_Store

View File

@@ -2,12 +2,13 @@
# Kredits Contracts
This repository contains the Solidity smart contracts organized as [Aragon](https://hack.aragon.org/)
apps and JavaScript API wrapper for [Kosmos Kredits](https://wiki.kosmos.org/Kredits).
This repository contains the Solidity smart contracts organized as
[Aragon](https://hack.aragon.org/) apps and JavaScript API wrapper for [Kosmos
Kredits](https://wiki.kosmos.org/Kredits).
It is based on [aragonOS](https://hack.aragon.org/docs/aragonos-intro.html) and
follows the aragonOS conventions.
Aragon itself uses the [Truffle framework](http://truffleframework.com/) for some things.
It is based on [aragonOS](https://hack.aragon.org/docs/aragonos-intro.html) and
follows the aragonOS conventions. Aragon itself uses the [Truffle
framework](http://truffleframework.com/) for some things.
## Development
@@ -22,35 +23,36 @@ Each of the aragon apps are separate packages:
$ cd apps/[app]
$ npm install
or use the bootstrap command (see below)
You can use `npm run install-all` to install all app dependencies at once.
### Local development chain
For local development it is recommended to use
[ganache](http://truffleframework.com/ganache/) to run a local development
For local development it is recommended to use
[ganache](http://truffleframework.com/ganache/) to run a local development
chain. Using the ganache simulator no full Ethereum node is required.
We use the default aragon-cli devchain command to confgure and run a local
We use the default aragon-cli devchain command to confgure and run a local
development ganache.
$ npm run devchain (or aragon devchain --port 7545)
To clear/reset the chain use:
To clear/reset the chain use (e.g. if you run out of funds on your devchain)
$ npm run devchain -- --reset (or aragon devchain --port 7545 --reset)
We default to port 7545 for development to not get in conflict with the default
We default to port 7545 for development to not get in conflict with the default
Ethereum RPC port.
### Bootstrap
1. Run an Ethereum node and ipfs
$ npm run devchain
$ ipfs daemon
2. Deploy each app to the devchain
(make sure you've run `npm install` for every app - see installation)
$ npm run deploy:apps
3. Deploy a new KreditsKit and create a new DAO with the latest app versions
@@ -58,7 +60,7 @@ Ethereum RPC port.
$ npm run deploy:kit
$ npm run deploy:dao
4. Execute seeds to create demo contributors, contributons, etc. (optional)
4. Execute seeds to create demo contributors, contributons, etc. (optional)
$ npm run seeds
@@ -71,15 +73,15 @@ If you want to reset your local setup:
## Contract architecture
Contracts are organized in independent apps (see `/apps`) and are developed
and deployed independently. Each app has a version and can be "installed"
on the Kredits DAO independently.
Contracts are organized in independent apps (see `/apps`) and are developed and
deployed independently. Each app has a version and can be "installed" on the
Kredits DAO independently.
![](docs/kredits-diagram.png)
A DAO can be deployed using the `scripts/deploy-kit.js` script or with the
`npm run deploy:dao` command. This deploys a new Kredits DAO, installs
the latest app versions and sets the required permissions.
A DAO can be deployed using the `scripts/deploy-kit.js` script or with the
`npm run deploy:dao` command. This deploys a new Kredits DAO, installs the
latest app versions and sets the required permissions.
See each app in `/apps/*` for details.
@@ -113,11 +115,11 @@ Script to add a new entries to the contracts using the JS wrapper
$ truffle exec scripts/add-{contributor, contribution, proposal}.js
### list-{contributor, contribution, proposal}.js
### list-{contributors, contributions, proposals}.js
List contract entries
$ truffle exec scripts/list-{contributor, contribution, proposal}.js
$ truffle exec scripts/list-{contributors, contributions, proposals}.js
### send-funds.js
@@ -150,7 +152,7 @@ Deploys a new KreditsKit that allows to create a new DAO
or
$ npm run deploy:kit
`ENS` address is required as environment variable.
`ENS` address is required as environment variable.
`DAO_FACTORY` can optionally be set as environment variable. (see aragon)
### new-dao.js
@@ -161,7 +163,7 @@ Creates and configures a new DAO instance.
or
$ npm run deploy:dao
KreditsKit address is load from `lib/addresses/KreditsKit.json` or can be
KreditsKit address is load from `lib/addresses/KreditsKit.json` or can be
configured through the `KREDITS_KIT` environment variable.
### deploy-apps.sh
@@ -172,14 +174,32 @@ Runs `npm install` for each app and publishes a new version.
or
$ npm run deploy:apps
## Deployment
### Apps deployment
To deploy a new app version run:
$ aragon apm publish major --environment=NETWORK_TO_DEPLOY
### KreditsKit
deploy the KreditsKit as Kit to create new DAOs
$ truffle exec scripts/deploy-kit.js --network=NETWORK_TO_DEPLOY
### Creating a new DAO
make sure all apps and the KreditsKit are deployed, then create a new DAO:
$ truffle exec scripts/new-dao.js --network=NETWORK_TO_DEPLOY
## ACL / Permissions
## Upgradeable contracts
We use aragonOS for upgradeablity of the different contracts.
Refer to the [aragonOS upgradeablity documentation](https://hack.aragon.org/docs/upgradeability-intro)
We use aragonOS for upgradeablity of the different contracts. Refer to the
[aragonOS upgradeablity documentation](https://hack.aragon.org/docs/upgradeability-intro)
for more details.
### Example

View File

@@ -32,7 +32,7 @@ contract Contribution is AragonApp {
uint8 hashFunction;
uint8 hashSize;
string tokenMetadataURL;
uint claimAfterBlock;
uint256 confirmedAtBlock;
bool vetoed;
bool exists;
}
@@ -48,7 +48,7 @@ contract Contribution is AragonApp {
mapping(uint32 => ContributionData) public contributions;
uint32 public contributionsCount;
uint32 public blocksToWait = 0;
uint32 public blocksToWait;
event ContributionAdded(uint32 id, uint32 indexed contributorId, uint32 amount);
event ContributionClaimed(uint32 id, uint32 indexed contributorId, uint32 amount);
@@ -56,6 +56,7 @@ contract Contribution is AragonApp {
function initialize(bytes32[4] _appIds) public onlyInit {
appIds = _appIds;
blocksToWait = 40320; // 7 days; 15 seconds block time
initialized();
}
@@ -117,7 +118,7 @@ contract Contribution is AragonApp {
// Custom functions
//
function getContribution(uint32 contributionId) public view returns (uint32 id, uint32 contributorId, uint32 amount, bool claimed, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint claimAfterBlock, bool exists, bool vetoed) {
function getContribution(uint32 contributionId) public view returns (uint32 id, uint32 contributorId, uint32 amount, bool claimed, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint256 confirmedAtBlock, bool exists, bool vetoed) {
id = contributionId;
ContributionData storage c = contributions[id];
return (
@@ -128,7 +129,7 @@ contract Contribution is AragonApp {
c.hashDigest,
c.hashFunction,
c.hashSize,
c.claimAfterBlock,
c.confirmedAtBlock,
c.exists,
c.vetoed
);
@@ -145,7 +146,11 @@ contract Contribution is AragonApp {
c.hashDigest = hashDigest;
c.hashFunction = hashFunction;
c.hashSize = hashSize;
c.claimAfterBlock = block.number; // + blocksToWait;
if (contributionId < 10) {
c.confirmedAtBlock = block.number;
} else {
c.confirmedAtBlock = block.number + blocksToWait;
}
contributionsCount++;
@@ -159,6 +164,7 @@ contract Contribution is AragonApp {
ContributionData storage c = contributions[contributionId];
require(c.exists, 'NOT_FOUND');
require(!c.claimed, 'ALREADY_CLAIMED');
require(block.number < c.confirmedAtBlock, 'VETO_PERIOD_ENDED');
c.vetoed = true;
emit ContributionVetoed(contributionId, msg.sender);
@@ -169,7 +175,7 @@ contract Contribution is AragonApp {
require(c.exists, 'NOT_FOUND');
require(!c.claimed, 'ALREADY_CLAIMED');
require(!c.vetoed, 'VETOED');
require(block.number > c.claimAfterBlock, 'NOT_CLAIMABLE');
require(block.number >= c.confirmedAtBlock, 'NOT_CLAIMABLE');
c.claimed = true;
address token = getTokenContract();

View File

@@ -11,10 +11,10 @@
"start": "npm run start:aragon:ipfs",
"start:aragon:ipfs": "aragon run",
"start:aragon:http": "aragon run --http localhost:8001 --http-served-from ./dist",
"start:app": "npm run sync-assets && npm run build:script -- --no-minify && parcel serve app/index.html -p 8001 --out-dir dist/ --no-cache",
"start:app": "",
"test": "aragon contracts test",
"compile": "aragon contracts compile",
"sync-assets": "copy-aragon-ui-assets -n aragon-ui ./dist",
"sync-assets": "",
"build:app": "",
"build:script": "",
"build": "",

View File

@@ -1,4 +1,4 @@
const CounterApp = artifacts.require('Contribution.sol')
const Contribution = artifacts.require('Contribution.sol')
contract('Contribution', (accounts) => {
it('should be tested')

8145
apps/contribution/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -13,10 +13,9 @@ contract Contributor is AragonApp {
struct Contributor {
address account;
bytes32 ipfsHash;
bytes32 hashDigest;
uint8 hashFunction;
uint8 hashSize;
bool isCore;
bool exists;
}
@@ -28,19 +27,11 @@ contract Contributor is AragonApp {
enum Apps { Contribution, Contributor, Proposal, Token }
bytes32[4] public appIds;
event ContributorProfileUpdated(uint32 id, bytes32 oldIpfsHash, bytes32 newIpfsHash);
event ContributorProfileUpdated(uint32 id, bytes32 oldHashDigest, bytes32 newHashDigest); // what should be logged
event ContributorAccountUpdated(uint32 id, address oldAccount, address newAccount);
event ContributorAdded(uint32 id, address account);
function initialize(address root,bytes32[4] _appIds) public onlyInit {
uint32 _id = contributorsCount + 1;
Contributor storage c = contributors[_id];
c.exists = true;
c.isCore = true;
c.account = root;
contributorIds[root] = _id;
contributorsCount += 1;
appIds = _appIds;
initialized();
@@ -55,7 +46,7 @@ contract Contributor is AragonApp {
function coreContributorsCount() view public returns (uint32) {
uint32 count = 0;
for (uint32 i = 1; i <= contributorsCount; i++) {
if (contributors[i].isCore) {
if (isCoreTeam(i)) {
count += 1;
}
}
@@ -69,24 +60,23 @@ contract Contributor is AragonApp {
ContributorAccountUpdated(id, oldAccount, newAccount);
}
function updateContributorIpfsHash(uint32 id, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize) public isInitialized auth(MANAGE_CONTRIBUTORS_ROLE) {
function updateContributorProfileHash(uint32 id, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(MANAGE_CONTRIBUTORS_ROLE) {
Contributor storage c = contributors[id];
bytes32 oldIpfsHash = c.ipfsHash;
c.ipfsHash = ipfsHash;
bytes32 oldHashDigest = c.hashDigest;
c.hashDigest = hashDigest;
c.hashFunction = hashFunction;
c.hashSize = hashSize;
ContributorProfileUpdated(id, oldIpfsHash, c.ipfsHash);
ContributorProfileUpdated(id, oldHashDigest, c.hashDigest);
}
function addContributor(address account, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize, bool isCore) public isInitialized auth(MANAGE_CONTRIBUTORS_ROLE) {
function addContributor(address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(MANAGE_CONTRIBUTORS_ROLE) {
require(!addressExists(account));
uint32 _id = contributorsCount + 1;
assert(!contributors[_id].exists); // this can not be acually
Contributor storage c = contributors[_id];
c.exists = true;
c.isCore = isCore;
c.ipfsHash = ipfsHash;
c.hashDigest = hashDigest;
c.hashFunction = hashFunction;
c.hashSize = hashSize;
c.account = account;
@@ -96,8 +86,10 @@ contract Contributor is AragonApp {
emit ContributorAdded(_id, account);
}
function isCore(uint32 id) view public returns (bool) {
return contributors[id].isCore;
function isCoreTeam(uint32 id) view public returns (bool) {
// TODO: for simplicity we simply define the first contributors as core
// later this needs to be changed to something more dynamic
return id < 7;
}
function exists(uint32 id) view public returns (bool) {
@@ -105,7 +97,8 @@ contract Contributor is AragonApp {
}
function addressIsCore(address account) view public returns (bool) {
return getContributorByAddress(account).isCore;
uint32 id = getContributorIdByAddress(account);
return isCoreTeam(id);
}
function addressExists(address account) view public returns (bool) {
@@ -125,14 +118,14 @@ contract Contributor is AragonApp {
return contributors[id];
}
function getContributorById(uint32 _id) public view returns (uint32 id, address account, bytes32 ipfsHash, uint8 hashFunction, uint8 hashSize, bool isCore, uint256 balance, bool exists ) {
function getContributorById(uint32 _id) public view returns (uint32 id, address account, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, bool isCore, uint256 balance, bool exists ) {
id = _id;
Contributor storage c = contributors[_id];
account = c.account;
ipfsHash = c.ipfsHash;
hashDigest = c.hashDigest;
hashFunction = c.hashFunction;
hashSize = c.hashSize;
isCore = c.isCore;
isCore = isCoreTeam(id);
address token = getTokenContract();
balance = ITokenBalance(token).balanceOf(c.account);
exists = c.exists;

View File

@@ -1,5 +1,5 @@
const CounterApp = artifacts.require('CounterApp.sol')
const Contributor = artifacts.require('Contributor.sol')
contract('CounterApp', (accounts) => {
contract('Contributor', (accounts) => {
it('should be tested')
})

8145
apps/contributor/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
{
"name": "Proposal",
"description": "Kredits proposal app"
"description": "Kredits Proposal app"
}

View File

@@ -0,0 +1,5 @@
const Proposal = artifacts.require('Proposal.sol')
contract('Proposal', (accounts) => {
it('should be tested')
})

8145
apps/proposal/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -14,11 +14,15 @@ contract Token is ERC20Token, AragonApp {
function initialize(bytes32[4] _appIds) public onlyInit {
appIds = _appIds;
name = 'Kredits';
symbol = '₭S';
decimals = 18;
initialized();
}
function mintFor(address contributorAccount, uint256 amount, uint32 contributionId) public isInitialized auth(MINT_TOKEN_ROLE) {
_mint(contributorAccount, amount);
uint256 amountInWei = amount.mul(1 ether);
_mint(contributorAccount, amountInWei);
emit LogMint(contributorAccount, amount, contributionId);
}

View File

@@ -1,4 +1,4 @@
{
"name": "Token",
"description": "Kredits token app"
"description": "Kredits Token app"
}

View File

@@ -1,5 +1,5 @@
const CounterApp = artifacts.require('CounterApp.sol')
const Token = artifacts.require('Token.sol')
contract('CounterApp', (accounts) => {
contract('Token', (accounts) => {
it('should be tested')
})

8145
apps/token/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,19 @@
const contractCalls = [
['Contributor', 'add', [{ account: '0x7e8f313c56f809188313aa274fa67ee58c31515d', name: 'bumi', isCore: true, kind: 'person', url: '', github_username: 'bumi', github_uid: 318, wiki_username: 'bumi' }, { gasLimit: 200000 }]],
['Contributor', 'add', [{ account: '0x49575f3DD9a0d60aE661BC992f72D837A77f05Bc', name: 'raucao', isCore: true, kind: 'person', url: '', github_username: 'skddc', github_uid: 842, wiki_username: 'raucau' }, { gasLimit: 200000 }]],
['Proposal', 'addProposal', [{ contributorId: 2, amount: 500, kind: 'code', description: '[67P/kredits-contracts] Ran the seeds', url: '' }, { gasLimit: 350000 }]],
['Proposal', 'addProposal', [{ contributorId: 3, amount: 500, kind: 'code', description: '[67P/kredits-contracts] Ran the seeds', url: '' }, { gasLimit: 350000 }]],
['Proposal', 'addProposal', [{ contributorId: 3, amount: 500, kind: 'code', description: '[67P/kredits-contracts] Hacked on kredits', url: '' }, { gasLimit: 350000 }]],
['Contributor', 'add', [{ account: '0x7e8f313c56f809188313aa274fa67ee58c31515d', name: 'bumi', kind: 'person', url: '', github_username: 'bumi', github_uid: 318, wiki_username: 'Bumi' }, { gasLimit: 200000 }]],
['Contributor', 'add', [{ account: '0x49575f3DD9a0d60aE661BC992f72D837A77f05Bc', name: 'raucao', kind: 'person', url: '', github_username: 'skddc', github_uid: 842, wiki_username: 'Basti' }, { gasLimit: 200000 }]],
['Contributor', 'add', [{ account: '0xF722709ECC3B05c19d02E82a2a4A4021B8F48C62', name: 'Manuel', kind: 'person', url: '', github_username: 'fsmanuel', github_uid: 54812, wiki_username: 'Manuel' }, { gasLimit: 200000 }]],
['Proposal', 'addProposal', [{ contributorId: 1, contributorIpfsHash: 'QmWKCYGr2rSf6abUPaTYqf98urvoZxGrb7dbspFZA6oyVF', date: '2019-04-09', amount: 500, kind: 'dev', description: '[67P/kredits-contracts] Ran the seeds', url: '' }, { gasLimit: 350000 }]],
['Proposal', 'addProposal', [{ contributorId: 2, contributorIpfsHash: 'QmcHzEeAM26HV2zHTf5HnZrCtCtGdEccL5kUtDakAB7ozB', date: '2019-04-10', amount: 500, kind: 'dev', description: '[67P/kredits-contracts] Ran the seeds', url: '' }, { gasLimit: 350000 }]],
['Proposal', 'addProposal', [{ contributorId: 2, contributorIpfsHash: 'QmcHzEeAM26HV2zHTf5HnZrCtCtGdEccL5kUtDakAB7ozB', date: '2019-04-11', amount: 500, kind: 'dev', description: '[67P/kredits-contracts] Hacked on kredits', url: '' }, { gasLimit: 350000 }]],
['Proposal', 'vote', [1, { gasLimit: 550000 }]],
['Contribution', 'addContribution', [{ contributorId: 2, amount: 5000, kind: 'dev', description: '[67P/kredits-contracts] Introduce contribution token', url: '' }, { gasLimit: 350000 }]],
['Contribution', 'addContribution', [{ contributorId: 3, amount: 1500, kind: 'dev', description: '[67P/kredits-web] Reviewed stuff', url: '' }, { gasLimit: 350000 }]],
['Contribution', 'addContribution', [{ contributorId: 1, contributorIpfsHash: 'QmWKCYGr2rSf6abUPaTYqf98urvoZxGrb7dbspFZA6oyVF', date: '2019-04-11', amount: 5000, kind: 'dev', description: '[67P/kredits-contracts] Introduce contribution token', url: '' }, { gasLimit: 350000 }]],
['Contribution', 'addContribution', [{ contributorId: 2, contributorIpfsHash: 'QmcHzEeAM26HV2zHTf5HnZrCtCtGdEccL5kUtDakAB7ozB', date: '2019-04-11', amount: 1500, kind: 'dev', description: '[67P/kredits-web] Reviewed stuff', url: '' }, { gasLimit: 350000 }]],
['Contribution', 'claim', [1, { gasLimit: 300000 }]]
];
const funds = [
'0x7e8f313c56f809188313aa274fa67ee58c31515d',
'0xa502eb4021f3b9ab62f75b57a94e1cfbf81fd827'
];
module.exports = { contractCalls, funds };

View File

@@ -1,5 +1,13 @@
# Contribution deployments
## 2019-04-10 - Weltempfänger release
✔ Successfully published kredits-contribution.open.aragonpm.eth v5.0.0:
Contract address: 0xe0f7dB486321b917e3A986Bdb2F2b9d51BA98fa9
Content (ipfs): QmU3XEBb4f5jU8MFFEpwaa95C1mhc82UeYLRWLrKsvcQNw
Transaction hash: 0xd736ff5f79f8142be3fad1a50580fb40aa468838da397f8630285fd91a445af3
## 2019-04-04
✔ Successfully published kredits-contribution.open.aragonpm.eth v4.0.0:

View File

@@ -1,5 +1,13 @@
# Contributor deployments
## 2019-04-10 - Weltempfänger release
✔ Successfully published kredits-contributor.open.aragonpm.eth v4.0.0:
Contract address: 0x08a6D4D915FCAA5524F05F5F715a6C17cB6eeA6B
Content (ipfs): QmR62PWwe1EzommfkhJDYcTvHoZjbXuv9dTG6vCn5dWCsb
Transaction hash: 0xd5317c9e207a413485c55ec3046b09d467d978443680304737a6d7d3db0c90e1
## 2019-04-04
✔ Successfully published kredits-contributor.open.aragonpm.eth v3.0.0:

View File

@@ -1,5 +1,10 @@
# Kredits deployment
## 2019-04-10 - Weltempfänger release
Using KreditsKit at: 0x76e069b47b79442657eaf0555a32c6b16fa1b8b4
Created new DAO at: 0xc34edf7d11b7f8433d597f0bb0697acdff55ef14
## 2019-04-04
Using KreditsKit at: 0x76e069b47b79442657eaf0555a32c6b16fa1b8b4

View File

@@ -1,5 +1,13 @@
# Proposal deployments
## 2019-04-10 - Weltempfänger release
✔ Successfully published kredits-proposal.open.aragonpm.eth v5.0.0:
Contract address: 0x4ce5b0286483c66b861e5599a199054687434552
Content (ipfs): QmNYXEcmvKTGxYiob7WUf85oZhdmFDCuGiA6TsRrDE9TYb
Transaction hash: 0x0482b58a1ba87d494c6391026399d0ac41b45384330d916f3f99ba70e501584b
## 2019-04-04
✔ Successfully published kredits-proposal.open.aragonpm.eth v4.0.0:

View File

@@ -1,5 +1,13 @@
# Token deployments
## 2019-04-10 - Weltempfänger release
✔ Successfully published kredits-token.open.aragonpm.eth v4.0.0:
Contract address: 0x05E0C2bbdA8e5BeE22AC1E20C1457dA4de63aE26
Content (ipfs): QmUuYLRMRNZcundUk2pxVaSjMNvtB7hzdf3eyoaUNqDPow
Transaction hash: 0x98c28b5ca645904d56eb83c4783682f018c0fcee015b3a3d5fa8bd609223fb89
## 2019-04-04
✔ Successfully published kredits-token.open.aragonpm.eth v3.0.0:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,3 @@
{
"4": "0x76e069b47b79442657eaf0555a32c6b16fa1b8b4",
"41787949": "0xa35aacdfccac54d3d96e0d29050c773b251c2c83"
"4": "0x76e069b47b79442657eaf0555a32c6b16fa1b8b4"
}

View File

@@ -1,4 +1,3 @@
{
"4": "0xcd75458fbc4aa2231252d5b21f1391fd031e5cb2",
"41787949": "0x183af3950364390a266edff2a0e7c4c2f95c0691"
"4": "0xc34edf7d11b7f8433d597f0bb0697acdff55ef14"
}

View File

@@ -20,4 +20,5 @@ class Base {
return this.contract.on(type, callback);
}
}
module.exports = Base;

View File

@@ -47,13 +47,17 @@ class Contribution extends Base {
});
}
addContribution(contributionAttr, callOptions = {}) {
let json = ContributionSerializer.serialize(contributionAttr);
// TODO: validate against schema
async addContribution(contributionAttr, callOptions = {}) {
const contribution = new ContributionSerializer(contributionAttr);
try { await contribution.validate(); }
catch (error) { return Promise.reject(error); }
const jsonStr = contribution.serialize();
return this.ipfs
.add(json)
.then((ipfsHashAttr) => {
.add(jsonStr)
.then(ipfsHashAttr => {
let contribution = [
contributionAttr.amount,
contributionAttr.contributorId,

View File

@@ -1,4 +1,3 @@
const ethers = require('ethers');
const RSVP = require('rsvp');
const ContributorSerializer = require('../serializers/contributor');
@@ -20,12 +19,6 @@ class Contributor extends Base {
getById(id) {
return this.functions.getContributorById(id)
.then((data) => {
// TODO: remove when naming updated on the contract
data.hashDigest = data.ipfsHash;
return data;
})
// Fetch IPFS data if available
.then((data) => {
return this.ipfs.catAndMerge(data, ContributorSerializer.deserialize);
});
@@ -67,7 +60,6 @@ class Contributor extends Base {
ipfsHashAttr.hashDigest,
ipfsHashAttr.hashFunction,
ipfsHashAttr.hashSize,
contributorAttr.isCore,
];
return this.functions.addContributor(...contributor, callOptions);

View File

@@ -1,4 +1,3 @@
const ethers = require('ethers');
const RSVP = require('rsvp');
const ContributionSerializer = require('../serializers/contribution');
@@ -25,12 +24,16 @@ class Proposal extends Base {
});
}
addProposal(proposalAttr, callOptions = {}) {
let json = ContributionSerializer.serialize(proposalAttr);
// TODO: validate against schema
async addProposal(proposalAttr, callOptions = {}) {
const contribution = new ContributionSerializer(proposalAttr);
try { await contribution.validate(); }
catch (error) { return Promise.reject(error); }
const jsonStr = contribution.serialize();
return this.ipfs
.add(json)
.add(jsonStr)
.then((ipfsHashAttr) => {
let proposal = [
proposalAttr.contributorId,

View File

@@ -4,4 +4,3 @@ class Token extends Base {
}
module.exports = Token;

View File

@@ -1,48 +1,33 @@
const schemas = require('kosmos-schemas');
const validator = require('../utils/validator');
/**
* Handle serialization for JSON-LD object of the contribution, according to
* https://github.com/67P/kosmos-schemas/blob/master/schemas/contribution.json
* Serialization and validation for JSON-LD document of the contribution.
*
* @class
* @public
*/
class Contribution {
/**
* Deserialize JSON to object
*
* @method
* @public
*/
static deserialize(serialized) {
let {
kind,
description,
details,
url,
} = JSON.parse(serialized.toString('utf8'));
return {
kind,
description,
details,
url,
ipfsData: serialized,
};
constructor(attrs) {
Object.keys(attrs).forEach(a => this[a] = attrs[a]);
}
/**
* Serialize object to JSON
*
* @method
* @public
*/
static serialize(deserialized) {
/**
* Serialize object to JSON
*
* @public
*/
serialize () {
let {
contributorIpfsHash,
date,
time,
kind,
description,
url,
details
} = deserialized;
} = this;
let data = {
"@context": "https://schema.kosmos.org",
@@ -50,6 +35,8 @@ class Contribution {
"contributor": {
"ipfs": contributorIpfsHash
},
date,
time,
kind,
description,
"details": details || {}
@@ -62,6 +49,44 @@ class Contribution {
// Write it pretty to ipfs
return JSON.stringify(data, null, 2);
}
/**
* Validate serialized data against schema
*
* @public
*/
validate () {
const serialized = JSON.parse(this.serialize());
const valid = validator.validate(serialized, schemas['contribution']);
return valid ? Promise.resolve() : Promise.reject(validator.error);
}
/**
* Deserialize JSON to object
*
* @public
*/
static deserialize (serialized) {
let {
date,
time,
kind,
description,
details,
url,
} = JSON.parse(serialized.toString('utf8'));
return {
date,
time,
kind,
description,
details,
url,
ipfsData: serialized,
};
}
}
module.exports = Contribution;

15
lib/utils/validator.js Normal file
View File

@@ -0,0 +1,15 @@
const tv4 = require('tv4');
const validator = tv4.freshApi();
validator.addFormat({
'date': function(value) {
const dateRegexp = /^[0-9]{4,}-[0-9]{2}-[0-9]{2}$/;
return dateRegexp.test(value) ? null : "A valid ISO 8601 full-date string is expected";
},
'time': function(value) {
const timeRegexp = /^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([\+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))$/;
return timeRegexp.test(value) ? null : "A valid ISO 8601 full-time string is expected";
}
})
module.exports = validator;

145
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "kredits-contracts",
"version": "4.0.0",
"version": "5.1.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -833,14 +833,12 @@
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
"dev": true
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
},
"any-observable": {
"version": "0.2.0",
@@ -951,7 +949,6 @@
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
"integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
"dev": true,
"requires": {
"chalk": "^1.1.3",
"esutils": "^2.0.2",
@@ -962,7 +959,6 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"dev": true,
"requires": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
@@ -977,7 +973,6 @@
"version": "6.26.3",
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz",
"integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==",
"dev": true,
"requires": {
"babel-code-frame": "^6.26.0",
"babel-generator": "^6.26.0",
@@ -1004,7 +999,6 @@
"version": "6.26.1",
"resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
"integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
"dev": true,
"requires": {
"babel-messages": "^6.23.0",
"babel-runtime": "^6.26.0",
@@ -1019,8 +1013,7 @@
"jsesc": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
"integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
"dev": true
"integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s="
}
}
},
@@ -1155,7 +1148,6 @@
"version": "6.24.1",
"resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
"integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0",
"babel-template": "^6.24.1"
@@ -1165,7 +1157,6 @@
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
"integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
"dev": true,
"requires": {
"babel-runtime": "^6.22.0"
}
@@ -1179,6 +1170,23 @@
"babel-runtime": "^6.22.0"
}
},
"babel-plugin-static-fs": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/babel-plugin-static-fs/-/babel-plugin-static-fs-1.2.0.tgz",
"integrity": "sha512-7zsDPvDzCBwfbU53WKym5LxTe1PxQHE/dGo+EfIELlBcn08TpU7SlPJILcc6YVAyTrpVUNioQfWiUyMWk1DJVg==",
"requires": {
"babel-template": "^6.3.13",
"babel-types": "^6.4.1",
"events": "^1.1.0"
},
"dependencies": {
"events": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
}
}
},
"babel-plugin-syntax-async-functions": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
@@ -1514,7 +1522,6 @@
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
"integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=",
"dev": true,
"requires": {
"babel-core": "^6.26.0",
"babel-runtime": "^6.26.0",
@@ -1529,7 +1536,6 @@
"version": "0.4.18",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
"integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
"dev": true,
"requires": {
"source-map": "^0.5.6"
}
@@ -1540,7 +1546,6 @@
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"dev": true,
"requires": {
"core-js": "^2.4.0",
"regenerator-runtime": "^0.11.0"
@@ -1550,7 +1555,6 @@
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
"integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
"dev": true,
"requires": {
"babel-runtime": "^6.26.0",
"babel-traverse": "^6.26.0",
@@ -1563,7 +1567,6 @@
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
"integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
"dev": true,
"requires": {
"babel-code-frame": "^6.26.0",
"babel-messages": "^6.23.0",
@@ -1580,7 +1583,6 @@
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
"integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
"dev": true,
"requires": {
"babel-runtime": "^6.26.0",
"esutils": "^2.0.2",
@@ -1609,8 +1611,7 @@
"babylon": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
"integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
"dev": true
"integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ=="
},
"balanced-match": {
"version": "1.0.0",
@@ -1802,6 +1803,16 @@
"concat-map": "0.0.1"
}
},
"brfs-babel": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/brfs-babel/-/brfs-babel-1.0.0.tgz",
"integrity": "sha1-Zy32AGfQKSEMSTKNeLOXnVe1Cxg=",
"requires": {
"babel-core": "^6.4.0",
"babel-plugin-static-fs": "^1.1.0",
"through2": "^2.0.0"
}
},
"brorand": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
@@ -2287,7 +2298,6 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz",
"integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==",
"dev": true,
"requires": {
"safe-buffer": "~5.1.1"
}
@@ -2313,14 +2323,12 @@
"core-js": {
"version": "2.6.5",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz",
"integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==",
"dev": true
"integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A=="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"cors": {
"version": "2.8.5",
@@ -2432,7 +2440,6 @@
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
@@ -2628,7 +2635,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
"integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
"dev": true,
"requires": {
"repeating": "^2.0.0"
}
@@ -2831,14 +2837,12 @@
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"esutils": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
"dev": true
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
},
"etag": {
"version": "1.8.1",
@@ -9899,8 +9903,7 @@
"globals": {
"version": "9.18.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
"integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
"dev": true
"integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ=="
},
"go-ipfs": {
"version": "0.4.17",
@@ -10018,7 +10021,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -10100,7 +10102,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
"integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=",
"dev": true,
"requires": {
"os-homedir": "^1.0.0",
"os-tmpdir": "^1.0.1"
@@ -10322,7 +10323,6 @@
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"dev": true,
"requires": {
"loose-envify": "^1.0.0"
}
@@ -10770,7 +10770,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
"integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
"dev": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -10934,8 +10933,7 @@
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"isexe": {
"version": "2.0.0",
@@ -11021,8 +11019,7 @@
"js-tokens": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
"integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
"dev": true
"integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
},
"jsbn": {
"version": "0.1.1",
@@ -11102,8 +11099,7 @@
"json5": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
"dev": true
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
},
"jsonfile": {
"version": "2.4.0",
@@ -11178,6 +11174,14 @@
"graceful-fs": "^4.1.9"
}
},
"kosmos-schemas": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/kosmos-schemas/-/kosmos-schemas-2.0.0.tgz",
"integrity": "sha512-zIjWcDxaN94m1vPgUaI5LRX6y07Ihw9ScPoGKf1NkZ0sLgD/CRV8YIKRyDafH5mThe3uBN2+F6H6Gp5qhNhALg==",
"requires": {
"brfs-babel": "^1.0.0"
}
},
"lcid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
@@ -11718,7 +11722,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dev": true,
"requires": {
"js-tokens": "^3.0.0 || ^4.0.0"
}
@@ -12026,7 +12029,6 @@
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"requires": {
"minimist": "0.0.8"
},
@@ -12034,8 +12036,7 @@
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
}
}
},
@@ -12127,8 +12128,7 @@
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"multiaddr": {
"version": "3.1.0",
@@ -12322,8 +12322,7 @@
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
"dev": true
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
},
"number-to-bn": {
"version": "1.7.0",
@@ -12463,8 +12462,7 @@
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
"dev": true
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
},
"os-locale": {
"version": "1.4.0",
@@ -12478,8 +12476,7 @@
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
},
"over": {
"version": "0.0.5",
@@ -12775,8 +12772,7 @@
"private": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
"integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
"dev": true
"integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="
},
"process": {
"version": "0.5.2",
@@ -12787,8 +12783,7 @@
"process-nextick-args": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
"dev": true
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
},
"promise": {
"version": "1.3.0",
@@ -13158,7 +13153,6 @@
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"dev": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@@ -13178,8 +13172,7 @@
"regenerator-runtime": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
"dev": true
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
},
"regenerator-transform": {
"version": "0.10.1",
@@ -13222,7 +13215,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
"integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
"dev": true,
"requires": {
"is-finite": "^1.0.0"
}
@@ -13663,8 +13655,7 @@
"slash": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
"integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
"dev": true
"integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU="
},
"slice-ansi": {
"version": "0.0.4",
@@ -13766,8 +13757,7 @@
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
},
"source-map-support": {
"version": "0.5.11",
@@ -13962,7 +13952,6 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -14003,8 +13992,7 @@
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
"dev": true
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
},
"swarm-js": {
"version": "0.1.37",
@@ -14177,7 +14165,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dev": true,
"requires": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
@@ -14223,8 +14210,7 @@
"to-fast-properties": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
"integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
"dev": true
"integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="
},
"tough-cookie": {
"version": "2.4.3",
@@ -14253,8 +14239,7 @@
"trim-right": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
"integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
"dev": true
"integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM="
},
"truffle": {
"version": "4.1.14",
@@ -14450,6 +14435,11 @@
"safe-buffer": "^5.0.1"
}
},
"tv4": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz",
"integrity": "sha1-0CDIRvrdUMhVq7JeuuzGj8EPeWM="
},
"tweetnacl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.1.tgz",
@@ -15603,8 +15593,7 @@
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
"dev": true
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
},
"y18n": {
"version": "3.2.1",

View File

@@ -1,17 +1,18 @@
{
"name": "kredits-contracts",
"version": "4.0.0",
"version": "5.1.1",
"description": "Ethereum contracts and npm wrapper for Kredits",
"main": "./lib/kredits.js",
"directories": {
"test": "test"
},
"scripts": {
"install-all": "./scripts/every-app.sh \"npm install\"",
"build-json": "npm run compile-contracts && node ./scripts/build-json.js",
"repl": "truffle exec scripts/repl.js",
"seeds": "truffle exec scripts/seeds.js",
"compile-contracts": "aragon contracts compile --all",
"bootstrap": "./scripts/every-app \"npm install \" && npm run reset:hard && npm run seeds",
"bootstrap": "npm run reset:hard && npm run seeds",
"reset": "npm run deploy:kit && npm run deploy:dao",
"reset:hard": "npm run deploy:apps && npm run reset",
"deploy:kit": "npm run compile-contracts && aragon contracts exec scripts/deploy-kit.js",
@@ -44,7 +45,9 @@
"dependencies": {
"ethers": "^4.0.27",
"ipfs-http-client": "^30.1.1",
"rsvp": "^4.8.2"
"kosmos-schemas": "^2.0.0",
"rsvp": "^4.8.2",
"tv4": "^1.3.0"
},
"keywords": [
"kosmos",

View File

@@ -1,4 +1,5 @@
const promptly = require('promptly');
const { inspect } = require('util');
const initKredits = require('./helpers/init_kredits.js');
@@ -26,23 +27,32 @@ module.exports = async function(callback) {
console.log(`Creating a contribution for contributor account ${contributorAccount} ID: ${contributorId}`);
[ dateNow, timeNow ] = (new Date()).toISOString().split('T');
let contributionAttributes = {
contributorId,
date: dateNow,
time: timeNow,
amount: await promptly.prompt('Amount: '),
description: await promptly.prompt('Description: '),
kind: await promptly.prompt('Kind: ', { default: 'dev' }),
url: await promptly.prompt('URL: ', { default: '' })
}
const contributorData = await kredits.Contributor.getById(contributorId);
contributionAttributes.contributorIpfsHash = contributorData.ipfsHash;
console.log("\nAdding contribution:");
console.log(contributionAttributes);
kredits.Contribution.addContribution(contributionAttributes, { gasLimit: 300000 }).then((result) => {
console.log("\n\nResult:");
console.log(result);
callback();
}).catch((error) => {
console.log('Failed to create contribution');
callback(error);
});
kredits.Contribution.addContribution(contributionAttributes, { gasLimit: 300000 })
.then(result => {
console.log("\n\nResult:");
console.log(result);
callback();
})
.catch(error => {
console.log('Failed to create contribution');
callback(inspect(error));
});
}

View File

@@ -23,7 +23,6 @@ module.exports = async function(callback) {
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: '),
@@ -34,7 +33,7 @@ module.exports = async function(callback) {
console.log("\nAdding contributor:");
console.log(contributorAttributes);
kredits.Contributor.add(contributorAttributes, { gasLimit: 250000 }).then((result) => {
kredits.Contributor.add(contributorAttributes, { gasLimit: 350000 }).then((result) => {
console.log("\n\nResult:");
console.log(result);
callback();

View File

@@ -1,4 +1,5 @@
const promptly = require('promptly');
const { inspect } = require('util');
const initKredits = require('./helpers/init_kredits.js');
@@ -25,23 +26,31 @@ module.exports = async function(callback) {
}
console.log(`Creating a proposal for contributor ID #${contributorId} account: ${contributorAccount}`);
[ dateNow, timeNow ] = (new Date()).toISOString().split('T');
let contributionAttributes = {
contributorId,
date: dateNow,
time: timeNow,
amount: await promptly.prompt('Amount: '),
description: await promptly.prompt('Description: '),
kind: await promptly.prompt('Kind: ', { default: 'dev' }),
url: await promptly.prompt('URL: ', { default: '' })
}
const contributorData = await kredits.Contributor.getById(contributorId);
contributionAttributes.contributorIpfsHash = contributorData.ipfsHash;
console.log("\nAdding proposal:");
console.log(contributionAttributes);
kredits.Proposal.addProposal(contributionAttributes, { gasLimit: 300000 }).then((result) => {
console.log("\n\nResult:");
console.log(result);
callback();
}).catch((error) => {
console.log('Failed to create proposal');
callback(error);
});
kredits.Proposal.addProposal(contributionAttributes, { gasLimit: 300000 })
.then((result) => {
console.log("\n\nResult:");
console.log(result);
callback();
}).catch((error) => {
console.log('Failed to create proposal');
callback(inspect(error));
});
}

View File

@@ -15,21 +15,32 @@ module.exports = async function(callback) {
console.log(`Using Contribution at: ${kredits.Contribution.contract.address}`);
const table = new Table({
head: ['ID', 'Contributor account', 'Amount', 'Claimed?', 'Vetoed?', 'Description']
head: ['ID', 'Contributor ID', 'Description', 'Amount', 'Confirmed?', 'Vetoed?', 'Claimed?', 'IPFS']
})
let contributions = await kredits.Contribution.all()
try {
let blockNumber = await kredits.provider.getBlockNumber();
let contributions = await kredits.Contribution.all();
contributions.forEach((c) => {
table.push([
c.id.toString(),
c.contributorId,
c.amount.toString(),
c.claimed,
c.vetoed,
`${c.description}`
])
})
console.log(table.toString())
callback()
contributions.forEach((c) => {
const confirmed = c.confirmedAtBlock <= blockNumber;
table.push([
c.id.toString(),
c.contributorId,
`${c.description}`,
c.amount.toString(),
confirmed,
c.vetoed,
c.claimed,
c.ipfsHash
])
});
console.log(table.toString());
} catch (err) {
console.log(err);
}
callback();
}

View File

@@ -1,5 +1,6 @@
const promptly = require('promptly');
const Table = require('cli-table');
const ethers = require('ethers');
const initKredits = require('./helpers/init_kredits.js');
@@ -16,7 +17,7 @@ module.exports = async function(callback) {
const table = new Table({
head: ['ID', 'Account', 'Core?', 'Name', 'Balance']
head: ['ID', 'Account', 'Name', 'Core?', 'Balance', 'IPFS']
})
let contributors = await kredits.Contributor.all()
@@ -25,9 +26,10 @@ module.exports = async function(callback) {
table.push([
c.id.toString(),
c.account,
c.isCore,
`${c.name}`,
c.balance.toString()
c.isCore,
ethers.utils.formatEther(c.balance),
c.ipfsHash
])
})
console.log(table.toString())

8242
yarn.lock Normal file

File diff suppressed because it is too large Load Diff