Compare commits

..

80 Commits

Author SHA1 Message Date
8539b56a48 5.3.0 2019-04-24 14:22:53 +01:00
f59c37827a Merge pull request #108 from 67P/feature/kredits-formatter
Add kredits-formatter and additionally format balance
2019-04-24 14:20:44 +01:00
58db57ee45 Merge branch 'master' into feature/kredits-formatter 2019-04-24 13:10:48 +00:00
b64a7ca299 Merge pull request #113 from 67P/feature/gitea_site
Add Gitea site/username to serializer and seeds
2019-04-24 12:58:44 +00:00
6f09ca8d13 Merge pull request #114 from 67P/chore/scripts
Improve/fix scripts
2019-04-24 12:57:43 +00:00
6f53c8097e Wrap anything that could break in the try/catch block 2019-04-24 14:55:35 +02:00
6b2ac15f56 Improve error handling for list-contributors script 2019-04-24 13:46:27 +01:00
359989f235 Fix function name for total kredits issued/earned 2019-04-24 13:45:56 +01:00
5894f6323b Add Gitea username to contributor seeds 2019-04-24 13:43:46 +01:00
09b78e1e8f Add Gitea site/username to contributor serializer 2019-04-23 20:28:56 +01:00
48c8f6b9b3 Merge branch 'master' into feature/kredits-formatter 2019-04-23 12:56:55 +00:00
542ebaf3f3 5.2.0 2019-04-23 13:52:46 +01:00
d82ffba75e Update ABI 2019-04-23 13:52:37 +01:00
bdb2cee0c4 Merge pull request #110 from 67P/feature/contribution-balances
Add contract calls for total contribution balances
2019-04-23 13:47:50 +01:00
cd45ce260f Merge pull request #112 from 67P/feature/update-contributor-profile
Update contributor profile
2019-04-20 09:22:31 +00:00
3a97983540 Merge pull request #111 from 67P/feature/contributor-schema-validation
Add Contributor validation against JSON schema
2019-04-20 08:47:49 +01:00
9714926e11 Add function to update contributor profile to wrapper
The function updates the contributor profile,
adds the new profile to IPFS and does the contract call to update
the profile hash
2019-04-20 02:17:38 +02:00
59614201b5 Ups... 2019-04-20 02:15:53 +02:00
e591742e40 Add Contributor validation against JSON schema
based on the Contribution validation.
2019-04-20 01:10:46 +02:00
791190f5e7 Cleanup promise call 2019-04-20 00:30:20 +02:00
24b66daf2a Update ABI 2019-04-19 14:16:40 +02:00
ad034d7712 Naming is hard 2019-04-19 14:15:30 +02:00
375d8f3275 Cleanup 2019-04-19 13:34:39 +02:00
80dc787971 Merge pull request #109 from 67P/dev/list_contributors_error_handling
Handle errors in contributor list script
2019-04-19 11:22:38 +00:00
7967dc26f2 Update ABIs 2019-04-19 13:20:25 +02:00
c248725cc1 Add balances to getContributorById call 2019-04-19 13:19:55 +02:00
59135bf312 Add contract calls for total contribution balances
Those methods return the total kredits amounts of contribtions.
2019-04-19 13:06:36 +02:00
1d771c43e8 Handle errors in contributor list script 2019-04-19 12:02:28 +01:00
3cb94fb660 Add kredits-formatter and additionally format balance
This adds a `balanceInt` value to the contributor data that has the
token balance formatted as full Kredits. (similar to Ether)
2019-04-19 11:57:35 +02:00
5820d71b2c Merge pull request #96 from 67P/feature/pagination
Add pagination for .all methods
2019-04-17 13:53:17 +00:00
4771c0c8a0 Merge branch 'master' into feature/pagination 2019-04-17 13:52:53 +00:00
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
6f97c905d6 Add count property and DRY 2019-04-13 13:05:47 +02:00
1b5f7ff95d Merge pull request #93 from 67P/deployments/weltempfaenger-release
Production release to rinkeby
2019-04-13 11:07:58 +01:00
f6189bf910 Add pagination for .all methods
I removed rsvp as a dependency as we only use Promise.all
2019-04-12 21:21:19 +02: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
46 changed files with 41470 additions and 347 deletions

2
.gitignore vendored
View File

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

View File

@@ -2,12 +2,13 @@
# Kredits Contracts # Kredits Contracts
This repository contains the Solidity smart contracts organized as [Aragon](https://hack.aragon.org/) This repository contains the Solidity smart contracts organized as
apps and JavaScript API wrapper for [Kosmos Kredits](https://wiki.kosmos.org/Kredits). [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 It is based on [aragonOS](https://hack.aragon.org/docs/aragonos-intro.html) and
follows the aragonOS conventions. follows the aragonOS conventions. Aragon itself uses the [Truffle
Aragon itself uses the [Truffle framework](http://truffleframework.com/) for some things. framework](http://truffleframework.com/) for some things.
## Development ## Development
@@ -22,7 +23,7 @@ Each of the aragon apps are separate packages:
$ cd apps/[app] $ cd apps/[app]
$ npm install $ 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 ### Local development chain
@@ -35,7 +36,7 @@ development ganache.
$ npm run devchain (or aragon devchain --port 7545) $ 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) $ npm run devchain -- --reset (or aragon devchain --port 7545 --reset)
@@ -51,6 +52,7 @@ Ethereum RPC port.
2. Deploy each app to the devchain 2. Deploy each app to the devchain
(make sure you've run `npm install` for every app - see installation)
$ npm run deploy:apps $ npm run deploy:apps
3. Deploy a new KreditsKit and create a new DAO with the latest app versions 3. Deploy a new KreditsKit and create a new DAO with the latest app versions
@@ -71,15 +73,15 @@ If you want to reset your local setup:
## Contract architecture ## Contract architecture
Contracts are organized in independent apps (see `/apps`) and are developed Contracts are organized in independent apps (see `/apps`) and are developed and
and deployed independently. Each app has a version and can be "installed" deployed independently. Each app has a version and can be "installed" on the
on the Kredits DAO independently. Kredits DAO independently.
![](docs/kredits-diagram.png) ![](docs/kredits-diagram.png)
A DAO can be deployed using the `scripts/deploy-kit.js` script or with the 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 `npm run deploy:dao` command. This deploys a new Kredits DAO, installs the
the latest app versions and sets the required permissions. latest app versions and sets the required permissions.
See each app in `/apps/*` for details. 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 $ truffle exec scripts/add-{contributor, contribution, proposal}.js
### list-{contributor, contribution, proposal}.js ### list-{contributors, contributions, proposals}.js
List contract entries List contract entries
$ truffle exec scripts/list-{contributor, contribution, proposal}.js $ truffle exec scripts/list-{contributors, contributions, proposals}.js
### send-funds.js ### send-funds.js
@@ -172,14 +174,32 @@ Runs `npm install` for each app and publishes a new version.
or or
$ npm run deploy:apps $ 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 ## ACL / Permissions
## Upgradeable contracts ## Upgradeable contracts
We use aragonOS for upgradeablity of the different contracts. We use aragonOS for upgradeablity of the different contracts. Refer to the
Refer to the [aragonOS upgradeablity documentation](https://hack.aragon.org/docs/upgradeability-intro) [aragonOS upgradeablity documentation](https://hack.aragon.org/docs/upgradeability-intro)
for more details. for more details.
### Example ### Example

View File

@@ -32,7 +32,7 @@ contract Contribution is AragonApp {
uint8 hashFunction; uint8 hashFunction;
uint8 hashSize; uint8 hashSize;
string tokenMetadataURL; string tokenMetadataURL;
uint claimAfterBlock; uint256 confirmedAtBlock;
bool vetoed; bool vetoed;
bool exists; bool exists;
} }
@@ -48,7 +48,7 @@ contract Contribution is AragonApp {
mapping(uint32 => ContributionData) public contributions; mapping(uint32 => ContributionData) public contributions;
uint32 public contributionsCount; uint32 public contributionsCount;
uint32 public blocksToWait = 0; uint32 public blocksToWait;
event ContributionAdded(uint32 id, uint32 indexed contributorId, uint32 amount); event ContributionAdded(uint32 id, uint32 indexed contributorId, uint32 amount);
event ContributionClaimed(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 { function initialize(bytes32[4] _appIds) public onlyInit {
appIds = _appIds; appIds = _appIds;
blocksToWait = 40320; // 7 days; 15 seconds block time
initialized(); initialized();
} }
@@ -117,7 +118,27 @@ contract Contribution is AragonApp {
// Custom functions // 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 totalKreditsEarned(bool confirmedOnly) public view returns (uint256 count) {
for (uint32 i = 1; i <= contributionsCount; i++) {
ContributionData memory c = contributions[i];
if (block.number >= c.confirmedAtBlock || !confirmedOnly) {
count += c.amount; // should use safemath
}
}
}
function totalKreditsEarnedByContributor(uint32 contributorId, bool confirmedOnly) public view returns (uint256 count) {
uint256 tokenBalance = ownedContributions[contributorId].length;
for (uint256 i = 0; i < tokenBalance; i++) {
uint32 cId = ownedContributions[contributorId][i];
ContributionData memory c = contributions[cId];
if (block.number >= c.confirmedAtBlock || !confirmedOnly) {
count += c.amount; // should use safemath
}
}
}
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; id = contributionId;
ContributionData storage c = contributions[id]; ContributionData storage c = contributions[id];
return ( return (
@@ -128,7 +149,7 @@ contract Contribution is AragonApp {
c.hashDigest, c.hashDigest,
c.hashFunction, c.hashFunction,
c.hashSize, c.hashSize,
c.claimAfterBlock, c.confirmedAtBlock,
c.exists, c.exists,
c.vetoed c.vetoed
); );
@@ -145,7 +166,11 @@ contract Contribution is AragonApp {
c.hashDigest = hashDigest; c.hashDigest = hashDigest;
c.hashFunction = hashFunction; c.hashFunction = hashFunction;
c.hashSize = hashSize; c.hashSize = hashSize;
c.claimAfterBlock = block.number; // + blocksToWait; if (contributionId < 10) {
c.confirmedAtBlock = block.number;
} else {
c.confirmedAtBlock = block.number + blocksToWait;
}
contributionsCount++; contributionsCount++;
@@ -159,6 +184,7 @@ contract Contribution is AragonApp {
ContributionData storage c = contributions[contributionId]; ContributionData storage c = contributions[contributionId];
require(c.exists, 'NOT_FOUND'); require(c.exists, 'NOT_FOUND');
require(!c.claimed, 'ALREADY_CLAIMED'); require(!c.claimed, 'ALREADY_CLAIMED');
require(block.number < c.confirmedAtBlock, 'VETO_PERIOD_ENDED');
c.vetoed = true; c.vetoed = true;
emit ContributionVetoed(contributionId, msg.sender); emit ContributionVetoed(contributionId, msg.sender);
@@ -169,7 +195,7 @@ contract Contribution is AragonApp {
require(c.exists, 'NOT_FOUND'); require(c.exists, 'NOT_FOUND');
require(!c.claimed, 'ALREADY_CLAIMED'); require(!c.claimed, 'ALREADY_CLAIMED');
require(!c.vetoed, 'VETOED'); require(!c.vetoed, 'VETOED');
require(block.number > c.claimAfterBlock, 'NOT_CLAIMABLE'); require(block.number >= c.confirmedAtBlock, 'NOT_CLAIMABLE');
c.claimed = true; c.claimed = true;
address token = getTokenContract(); address token = getTokenContract();

View File

@@ -11,10 +11,10 @@
"start": "npm run start:aragon:ipfs", "start": "npm run start:aragon:ipfs",
"start:aragon:ipfs": "aragon run", "start:aragon:ipfs": "aragon run",
"start:aragon:http": "aragon run --http localhost:8001 --http-served-from ./dist", "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", "test": "aragon contracts test",
"compile": "aragon contracts compile", "compile": "aragon contracts compile",
"sync-assets": "copy-aragon-ui-assets -n aragon-ui ./dist", "sync-assets": "",
"build:app": "", "build:app": "",
"build:script": "", "build:script": "",
"build": "", "build": "",

View File

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

8145
apps/contribution/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,10 @@ import "@aragon/os/contracts/kernel/IKernel.sol";
interface ITokenBalance { interface ITokenBalance {
function balanceOf(address contributorAccount) public view returns (uint256); function balanceOf(address contributorAccount) public view returns (uint256);
} }
interface IContributionBalance {
function totalKreditsEarnedByContributor(uint32 contributorId, bool confirmedOnly) public view returns (uint256 count);
function balanceOf(address owner) public view returns (uint256);
}
contract Contributor is AragonApp { contract Contributor is AragonApp {
bytes32 public constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb; bytes32 public constant KERNEL_APP_ADDR_NAMESPACE = 0xd6f028ca0e8edb4a8c9757ca4fdccab25fa1e0317da1188108f7d2dee14902fb;
@@ -13,10 +17,9 @@ contract Contributor is AragonApp {
struct Contributor { struct Contributor {
address account; address account;
bytes32 ipfsHash; bytes32 hashDigest;
uint8 hashFunction; uint8 hashFunction;
uint8 hashSize; uint8 hashSize;
bool isCore;
bool exists; bool exists;
} }
@@ -28,19 +31,11 @@ contract Contributor is AragonApp {
enum Apps { Contribution, Contributor, Proposal, Token } enum Apps { Contribution, Contributor, Proposal, Token }
bytes32[4] public appIds; 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 ContributorAccountUpdated(uint32 id, address oldAccount, address newAccount);
event ContributorAdded(uint32 id, address account); event ContributorAdded(uint32 id, address account);
function initialize(address root,bytes32[4] _appIds) public onlyInit { 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; appIds = _appIds;
initialized(); initialized();
@@ -52,10 +47,16 @@ contract Contributor is AragonApp {
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Token)]); return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Token)]);
} }
function getContributionContract() public view returns (address) {
IKernel k = IKernel(kernel());
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contribution)]);
}
function coreContributorsCount() view public returns (uint32) { function coreContributorsCount() view public returns (uint32) {
uint32 count = 0; uint32 count = 0;
for (uint32 i = 1; i <= contributorsCount; i++) { for (uint32 i = 1; i <= contributorsCount; i++) {
if (contributors[i].isCore) { if (isCoreTeam(i)) {
count += 1; count += 1;
} }
} }
@@ -69,24 +70,23 @@ contract Contributor is AragonApp {
ContributorAccountUpdated(id, oldAccount, newAccount); 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]; Contributor storage c = contributors[id];
bytes32 oldIpfsHash = c.ipfsHash; bytes32 oldHashDigest = c.hashDigest;
c.ipfsHash = ipfsHash; c.hashDigest = hashDigest;
c.hashFunction = hashFunction; c.hashFunction = hashFunction;
c.hashSize = hashSize; 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)); require(!addressExists(account));
uint32 _id = contributorsCount + 1; uint32 _id = contributorsCount + 1;
assert(!contributors[_id].exists); // this can not be acually assert(!contributors[_id].exists); // this can not be acually
Contributor storage c = contributors[_id]; Contributor storage c = contributors[_id];
c.exists = true; c.exists = true;
c.isCore = isCore; c.hashDigest = hashDigest;
c.ipfsHash = ipfsHash;
c.hashFunction = hashFunction; c.hashFunction = hashFunction;
c.hashSize = hashSize; c.hashSize = hashSize;
c.account = account; c.account = account;
@@ -96,8 +96,10 @@ contract Contributor is AragonApp {
emit ContributorAdded(_id, account); emit ContributorAdded(_id, account);
} }
function isCore(uint32 id) view public returns (bool) { function isCoreTeam(uint32 id) view public returns (bool) {
return contributors[id].isCore; // 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) { function exists(uint32 id) view public returns (bool) {
@@ -105,7 +107,8 @@ contract Contributor is AragonApp {
} }
function addressIsCore(address account) view public returns (bool) { 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) { function addressExists(address account) view public returns (bool) {
@@ -125,16 +128,19 @@ contract Contributor is AragonApp {
return contributors[id]; 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, uint256 totalKreditsEarned, uint256 contributionsCount, bool exists ) {
id = _id; id = _id;
Contributor storage c = contributors[_id]; Contributor storage c = contributors[_id];
account = c.account; account = c.account;
ipfsHash = c.ipfsHash; hashDigest = c.hashDigest;
hashFunction = c.hashFunction; hashFunction = c.hashFunction;
hashSize = c.hashSize; hashSize = c.hashSize;
isCore = c.isCore; isCore = isCoreTeam(id);
address token = getTokenContract(); address token = getTokenContract();
balance = ITokenBalance(token).balanceOf(c.account); balance = ITokenBalance(token).balanceOf(c.account);
address contribution = getContributionContract();
totalKreditsEarned = IContributionBalance(contribution).totalKreditsEarnedByContributor(_id, true);
contributionsCount = IContributionBalance(contribution).balanceOf(c.account);
exists = c.exists; 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') 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", "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 { function initialize(bytes32[4] _appIds) public onlyInit {
appIds = _appIds; appIds = _appIds;
name = 'Kredits';
symbol = '₭S';
decimals = 18;
initialized(); initialized();
} }
function mintFor(address contributorAccount, uint256 amount, uint32 contributionId) public isInitialized auth(MINT_TOKEN_ROLE) { 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); emit LogMint(contributorAccount, amount, contributionId);
} }

View File

@@ -1,4 +1,4 @@
{ {
"name": "Token", "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') 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,48 @@
const contractCalls = [ 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', [{
['Contributor', 'add', [{ account: '0x49575f3DD9a0d60aE661BC992f72D837A77f05Bc', name: 'raucao', isCore: true, kind: 'person', url: '', github_username: 'skddc', github_uid: 842, wiki_username: 'raucau' }, { gasLimit: 200000 }]], account: '0x7e8f313c56f809188313aa274fa67ee58c31515d',
['Proposal', 'addProposal', [{ contributorId: 2, amount: 500, kind: 'code', description: '[67P/kredits-contracts] Ran the seeds', url: '' }, { gasLimit: 350000 }]], name: 'bumi',
['Proposal', 'addProposal', [{ contributorId: 3, amount: 500, kind: 'code', description: '[67P/kredits-contracts] Ran the seeds', url: '' }, { gasLimit: 350000 }]], kind: 'person',
['Proposal', 'addProposal', [{ contributorId: 3, amount: 500, kind: 'code', description: '[67P/kredits-contracts] Hacked on kredits', url: '' }, { gasLimit: 350000 }]], url: '',
github_username: 'bumi',
github_uid: 318,
gitea_username: 'bumi',
wiki_username: 'Bumi'
}, { gasLimit: 200000 }]],
['Contributor', 'add', [{
account: '0x49575f3DD9a0d60aE661BC992f72D837A77f05Bc',
name: 'raucao',
kind: 'person',
url: '',
github_username: 'skddc',
github_uid: 842,
gitea_username: 'raucao',
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 }]], ['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: 1, contributorIpfsHash: 'QmWKCYGr2rSf6abUPaTYqf98urvoZxGrb7dbspFZA6oyVF', date: '2019-04-11', 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: 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 }]] ['Contribution', 'claim', [1, { gasLimit: 300000 }]]
]; ];
const funds = [ const funds = [
'0x7e8f313c56f809188313aa274fa67ee58c31515d', '0x7e8f313c56f809188313aa274fa67ee58c31515d',
'0xa502eb4021f3b9ab62f75b57a94e1cfbf81fd827' '0xa502eb4021f3b9ab62f75b57a94e1cfbf81fd827'
]; ];
module.exports = { contractCalls, funds }; module.exports = { contractCalls, funds };

View File

@@ -1,5 +1,13 @@
# Contribution deployments # 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 ## 2019-04-04
✔ Successfully published kredits-contribution.open.aragonpm.eth v4.0.0: ✔ Successfully published kredits-contribution.open.aragonpm.eth v4.0.0:

View File

@@ -1,5 +1,13 @@
# Contributor deployments # 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 ## 2019-04-04
✔ Successfully published kredits-contributor.open.aragonpm.eth v3.0.0: ✔ Successfully published kredits-contributor.open.aragonpm.eth v3.0.0:

View File

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

View File

@@ -1,5 +1,13 @@
# Proposal deployments # 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 ## 2019-04-04
✔ Successfully published kredits-proposal.open.aragonpm.eth v4.0.0: ✔ Successfully published kredits-proposal.open.aragonpm.eth v4.0.0:

View File

@@ -1,5 +1,13 @@
# Token deployments # 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 ## 2019-04-04
✔ Successfully published kredits-token.open.aragonpm.eth v3.0.0: ✔ 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", "4": "0x76e069b47b79442657eaf0555a32c6b16fa1b8b4"
"41787949": "0xa35aacdfccac54d3d96e0d29050c773b251c2c83"
} }

View File

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

View File

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

View File

@@ -1,21 +1,9 @@
const ethers = require('ethers'); const Record = require('./record');
const ContributionSerializer = require('../serializers/contribution'); const ContributionSerializer = require('../serializers/contribution');
const Base = require('./base');
class Contribution extends Base { class Contribution extends Record {
all() { get count () {
return this.functions.contributionsCount() return this.functions.contributionsCount();
.then(async (count) => {
let contributions = [];
for (let id = 1; id <= count; id++) {
const contribution = await this.getById(id)
contributions.push(contribution);
}
return contributions;
});
} }
getById(id) { getById(id) {
@@ -47,13 +35,17 @@ class Contribution extends Base {
}); });
} }
addContribution(contributionAttr, callOptions = {}) { async addContribution(contributionAttr, callOptions = {}) {
let json = ContributionSerializer.serialize(contributionAttr); const contribution = new ContributionSerializer(contributionAttr);
// TODO: validate against schema
try { await contribution.validate(); }
catch (error) { return Promise.reject(error); }
const jsonStr = contribution.serialize();
return this.ipfs return this.ipfs
.add(json) .add(jsonStr)
.then((ipfsHashAttr) => { .then(ipfsHashAttr => {
let contribution = [ let contribution = [
contributionAttr.amount, contributionAttr.amount,
contributionAttr.contributorId, contributionAttr.contributorId,

View File

@@ -1,34 +1,18 @@
const ethers = require('ethers'); const Record = require('./record');
const RSVP = require('rsvp');
const ContributorSerializer = require('../serializers/contributor'); const ContributorSerializer = require('../serializers/contributor');
const Base = require('./base'); const formatKredits = require('../utils/format-kredits');
class Contributor extends Base { class Contributor extends Record {
all() { get count () {
return this.functions.contributorsCount() return this.functions.contributorsCount();
.then(count => {
let contributors = [];
for (let id = 1; id <= count; id++) {
contributors.push(this.getById(id));
}
return RSVP.all(contributors);
});
} }
getById(id) { getById(id) {
return this.functions.getContributorById(id) return this.functions.getContributorById(id)
.then((data) => { .then(data => {
// TODO: remove when naming updated on the contract data.balanceInt = formatKredits(data.balance);
data.hashDigest = data.ipfsHash;
return data;
})
// Fetch IPFS data if available
.then((data) => {
return this.ipfs.catAndMerge(data, ContributorSerializer.deserialize); return this.ipfs.catAndMerge(data, ContributorSerializer.deserialize);
}); })
} }
filterByAccount(search) { filterByAccount(search) {
@@ -55,24 +39,51 @@ class Contributor extends Base {
}); });
} }
add(contributorAttr, callOptions = {}) { async add(contributorAttr, callOptions = {}) {
let json = ContributorSerializer.serialize(contributorAttr); let contributor = new ContributorSerializer(contributorAttr);
// TODO: validate against schema
try { await contributor.validate(); }
catch (error) { return Promise.reject(error); }
const jsonStr = contributor.serialize();
return this.ipfs return this.ipfs
.add(json) .add(jsonStr)
.then((ipfsHashAttr) => { .then((ipfsHashAttr) => {
let contributor = [ let contributor = [
contributorAttr.account, contributorAttr.account,
ipfsHashAttr.hashDigest, ipfsHashAttr.hashDigest,
ipfsHashAttr.hashFunction, ipfsHashAttr.hashFunction,
ipfsHashAttr.hashSize, ipfsHashAttr.hashSize,
contributorAttr.isCore,
]; ];
return this.functions.addContributor(...contributor, callOptions); return this.functions.addContributor(...contributor, callOptions);
}); });
} }
updateProfile(contributorId, updateAttr, callOptions = {}) {
return this.getById(contributorId).then(async (contributor) => {
let updatedContributorAttr = Object.assign(contributor, updateAttr)
let updatedContributor = new ContributorSerializer(updatedContributorAttr);
try { await updatedContributor.validate(); }
catch (error) { return Promise.reject(error); }
const jsonStr = updatedContributor.serialize();
return this.ipfs
.add(jsonStr)
.then(ipfsHashAttr => {
return this.functions.updateContributorProfileHash(
contributorId,
ipfsHashAttr.hashDigest,
ipfsHashAttr.hashFunction,
ipfsHashAttr.hashSize,
callOptions
);
});
});
}
} }
module.exports = Contributor; module.exports = Contributor;

View File

@@ -1,21 +1,9 @@
const ethers = require('ethers'); const Record = require('./record');
const RSVP = require('rsvp');
const ContributionSerializer = require('../serializers/contribution'); const ContributionSerializer = require('../serializers/contribution');
const Base = require('./base');
class Proposal extends Base { class Proposal extends Record {
all() { get count () {
return this.functions.proposalsCount() return this.functions.proposalsCount();
.then(count => {
let proposals = [];
for (let id = 1; id <= count; id++) {
proposals.push(this.getById(id));
}
return RSVP.all(proposals);
});
} }
getById(id) { getById(id) {
@@ -25,12 +13,16 @@ class Proposal extends Base {
}); });
} }
addProposal(proposalAttr, callOptions = {}) { async addProposal(proposalAttr, callOptions = {}) {
let json = ContributionSerializer.serialize(proposalAttr); const contribution = new ContributionSerializer(proposalAttr);
// TODO: validate against schema
try { await contribution.validate(); }
catch (error) { return Promise.reject(error); }
const jsonStr = contribution.serialize();
return this.ipfs return this.ipfs
.add(json) .add(jsonStr)
.then((ipfsHashAttr) => { .then((ipfsHashAttr) => {
let proposal = [ let proposal = [
proposalAttr.contributorId, proposalAttr.contributorId,

14
lib/contracts/record.js Normal file
View File

@@ -0,0 +1,14 @@
const Base = require('./base');
const paged = require('../utils/pagination');
class Record extends Base {
all(options = {}) {
return this.count
.then((count) => {
let records = paged(count, options).map((id) => this.getById(id));
return Promise.all(records);
});
}
}
module.exports = Record

View File

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

View File

@@ -1,5 +1,4 @@
const ethers = require('ethers'); const ethers = require('ethers');
const RSVP = require('rsvp');
const Preflight = require('./utils/preflight'); const Preflight = require('./utils/preflight');
@@ -57,7 +56,8 @@ class Kredits {
); );
}); });
}); });
return RSVP.all(addressPromises).then(() => { return this });
return Promise.all(addressPromises).then(() => { return this });
}); });
} }

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 * Serialization and validation for JSON-LD document of the contribution.
* https://github.com/67P/kosmos-schemas/blob/master/schemas/contribution.json
* *
* @class * @class
* @public * @public
*/ */
class Contribution { class Contribution {
/**
* Deserialize JSON to object
*
* @method
* @public
*/
static deserialize(serialized) {
let {
kind,
description,
details,
url,
} = JSON.parse(serialized.toString('utf8'));
return { constructor(attrs) {
kind, Object.keys(attrs).forEach(a => this[a] = attrs[a]);
description,
details,
url,
ipfsData: serialized,
};
} }
/** /**
* Serialize object to JSON * Serialize object to JSON
* *
* @method * @public
* @public */
*/ serialize () {
static serialize(deserialized) {
let { let {
contributorIpfsHash, contributorIpfsHash,
date,
time,
kind, kind,
description, description,
url, url,
details details
} = deserialized; } = this;
let data = { let data = {
"@context": "https://schema.kosmos.org", "@context": "https://schema.kosmos.org",
@@ -50,6 +35,8 @@ class Contribution {
"contributor": { "contributor": {
"ipfs": contributorIpfsHash "ipfs": contributorIpfsHash
}, },
date,
time,
kind, kind,
description, description,
"details": details || {} "details": details || {}
@@ -62,6 +49,44 @@ class Contribution {
// Write it pretty to ipfs // Write it pretty to ipfs
return JSON.stringify(data, null, 2); 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; module.exports = Contribution;

View File

@@ -1,3 +1,5 @@
const schemas = require('kosmos-schemas');
const validator = require('../utils/validator');
/** /**
* Handle serialization for JSON-LD object of the contributor, according to * Handle serialization for JSON-LD object of the contributor, according to
* https://github.com/67P/kosmos-schemas/blob/master/schemas/contributor.json * https://github.com/67P/kosmos-schemas/blob/master/schemas/contributor.json
@@ -6,41 +8,9 @@
* @public * @public
*/ */
class Contributor { class Contributor {
/**
* Deserialize JSON to object
*
* @method
* @public
*/
static deserialize(serialized) {
let {
name,
kind,
url,
accounts,
} = JSON.parse(serialized.toString('utf8'));
let github_username, github_uid, wiki_username; constructor(attrs) {
let github = accounts.find((a) => a.site === 'github.com'); Object.keys(attrs).forEach(a => this[a] = attrs[a]);
let wiki = accounts.find((a) => a.site === 'wiki.kosmos.org');
if (github) {
(({ username: github_username, uid: github_uid} = github));
}
if (wiki) {
(({ username: wiki_username } = wiki));
}
return {
name,
kind,
url,
accounts,
github_uid,
github_username,
wiki_username,
ipfsData: serialized,
};
} }
/** /**
@@ -49,15 +19,16 @@ class Contributor {
* @method * @method
* @public * @public
*/ */
static serialize(deserialized) { serialize () {
let { let {
name, name,
kind, kind,
url, url,
github_uid, github_uid,
github_username, github_username,
gitea_username,
wiki_username, wiki_username,
} = deserialized; } = this;
let data = { let data = {
"@context": "https://schema.kosmos.org", "@context": "https://schema.kosmos.org",
@@ -80,6 +51,14 @@ class Contributor {
}); });
} }
if (gitea_username) {
data.accounts.push({
"site": "gitea.kosmos.org",
"username": gitea_username,
"url": `https://gitea.kosmos.org/${gitea_username}`
});
}
if (wiki_username) { if (wiki_username) {
data.accounts.push({ data.accounts.push({
"site": "wiki.kosmos.org", "site": "wiki.kosmos.org",
@@ -91,6 +70,60 @@ class Contributor {
// Write it pretty to ipfs // Write it pretty to ipfs
return JSON.stringify(data, null, 2); 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['contributor']);
return valid ? Promise.resolve() : Promise.reject(validator.error);
}
/**
* Deserialize JSON to object
*
* @method
* @public
*/
static deserialize (serialized) {
let {
name,
kind,
url,
accounts,
} = JSON.parse(serialized.toString('utf8'));
let github_username, github_uid, gitea_username, wiki_username;
let github = accounts.find(a => a.site === 'github.com');
let gitea = accounts.find(a => a.site === 'gitea.kosmos.org');
let wiki = accounts.find(a => a.site === 'wiki.kosmos.org');
if (github) {
(({ username: github_username, uid: github_uid} = github));
}
if (gitea) {
(({ username: gitea_username } = gitea));
}
if (wiki) {
(({ username: wiki_username } = wiki));
}
return {
name,
kind,
url,
accounts,
github_uid,
github_username,
gitea_username,
wiki_username,
ipfsData: serialized,
};
}
} }
module.exports = Contributor; module.exports = Contributor;

View File

@@ -0,0 +1,10 @@
const ethersUtils = require('ethers').utils;
module.exports = function (value, options = {}) {
let etherValue = ethersUtils.formatEther(value);
if (options.asFloat) {
return parseFloat(etherValue);
} else {
return parseInt(etherValue);
}
}

46
lib/utils/pagination.js Normal file
View File

@@ -0,0 +1,46 @@
function pageNumber(number, size, recordCount) {
let numberOfPages = Math.ceil(recordCount / size);
number = parseInt(number) || 1;
// Ensure page number is in range
number = number < 1 ? 1 : number;
number = number > numberOfPages ? numberOfPages : number;
return number;
}
function buildIds(order, number, size, recordCount) {
let offset = size * (number - 1);
let start;
let mapFunction;
if (order === 'asc') {
start = 1 + offset;
mapFunction = (_, i) => start + i;
} else {
start = recordCount - offset;
mapFunction = (_, i) => start - i;
}
// Ensure size is in range
let end = offset + size;
if (end > recordCount) {
let diff = end - recordCount;
size = size - diff;
}
return Array.from({ length: size }, mapFunction);
}
module.exports = function paged(recordCount, options = {}) {
let { order, page } = options;
order = order || 'desc';
page = page || {};
let size = parseInt(page.size) || 25;
let number = pageNumber(page.number, size, recordCount);
return buildIds(order, number, size, recordCount);
};

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

View File

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

View File

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

View File

@@ -23,18 +23,17 @@ module.exports = async function(callback) {
let contributorAttributes = { let contributorAttributes = {
account: await prompt('Contributor address: ', {}), account: await prompt('Contributor address: ', {}),
name: await prompt('Name: '), name: await prompt('Name: '),
isCore: await prompt('core? y/n') === 'y',
kind: await prompt('Kind (default person): ', {default: 'person'}), kind: await prompt('Kind (default person): ', {default: 'person'}),
url: await prompt('URL: '), url: await prompt('URL: '),
github_username: await prompt('GitHub username: '), github_username: await prompt('GitHub username: '),
github_uid: await prompt('GitHub UID: '), github_uid: parseInt(await prompt('GitHub UID: ')),
wiki_username: await prompt('Wiki username: '), wiki_username: await prompt('Wiki username: '),
}; };
console.log("\nAdding contributor:"); console.log("\nAdding contributor:");
console.log(contributorAttributes); 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("\n\nResult:");
console.log(result); console.log(result);
callback(); callback();

View File

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

View File

@@ -15,21 +15,36 @@ module.exports = async function(callback) {
console.log(`Using Contribution at: ${kredits.Contribution.contract.address}`); console.log(`Using Contribution at: ${kredits.Contribution.contract.address}`);
const table = new Table({ 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) => { console.log(`Current block number: ${blockNumber}`);
table.push([ contributions.forEach((c) => {
c.id.toString(), const confirmed = c.confirmedAtBlock <= blockNumber;
c.contributorId,
c.amount.toString(), table.push([
c.claimed, c.id.toString(),
c.vetoed, c.contributorId,
`${c.description}` `${c.description}`,
]) c.amount.toString(),
}) `${confirmed} (${c.confirmedAtBlock})`,
console.log(table.toString()) c.vetoed,
callback() c.claimed,
c.ipfsHash
])
});
console.log(table.toString());
let totalKreditsEarned = await kredits.Contribution.functions.totalKreditsEarned(true);
console.log(`Total confirmed kredits: ${totalKreditsEarned}`);
} catch (err) {
console.log(err);
}
callback();
} }

View File

@@ -1,5 +1,6 @@
const promptly = require('promptly'); const promptly = require('promptly');
const Table = require('cli-table'); const Table = require('cli-table');
const ethers = require('ethers');
const initKredits = require('./helpers/init_kredits.js'); const initKredits = require('./helpers/init_kredits.js');
@@ -14,23 +15,31 @@ module.exports = async function(callback) {
console.log(`Using Contributor at: ${kredits.Contributor.contract.address}`); console.log(`Using Contributor at: ${kredits.Contributor.contract.address}`);
const table = new Table({ const table = new Table({
head: ['ID', 'Account', 'Core?', 'Name', 'Balance'] head: ['ID', 'Account', 'Name', 'Core?', 'Balance', 'Kredits earned', 'Contributions count', 'IPFS']
}) })
let contributors = await kredits.Contributor.all() try {
const contributors = await kredits.Contributor.all()
contributors.forEach((c) => {
table.push([
c.id.toString(),
c.account,
`${c.name}`,
c.isCore,
c.balanceInt.toString(),
c.totalKreditsEarned.toString(),
c.contributionsCount.toString(),
c.ipfsHash
])
})
console.log(table.toString())
} catch(e) {
callback(e);
return;
}
contributors.forEach((c) => {
table.push([
c.id.toString(),
c.account,
c.isCore,
`${c.name}`,
c.balance.toString()
])
})
console.log(table.toString())
callback() callback()
} }

8242
yarn.lock Normal file

File diff suppressed because it is too large Load Diff