Merge branch 'master' into feature/kredits-formatter

This commit is contained in:
bumi 2019-04-23 12:56:55 +00:00 committed by GitHub
commit 48c8f6b9b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 141 additions and 49 deletions

View File

@ -118,6 +118,26 @@ contract Contribution is AragonApp {
// Custom functions // Custom functions
// //
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) { 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];

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;
@ -43,6 +47,12 @@ 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++) {
@ -118,7 +128,7 @@ contract Contributor is AragonApp {
return contributors[id]; return contributors[id];
} }
function getContributorById(uint32 _id) public view returns (uint32 id, address account, bytes32 hashDigest, 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;
@ -128,6 +138,9 @@ contract Contributor is AragonApp {
isCore = isCoreTeam(id); 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;
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -39,12 +39,16 @@ class Contributor extends Record {
}); });
} }
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,
@ -56,6 +60,30 @@ class Contributor extends Record {
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,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,7 +19,7 @@ class Contributor {
* @method * @method
* @public * @public
*/ */
static serialize(deserialized) { serialize () {
let { let {
name, name,
kind, kind,
@ -57,7 +27,7 @@ class Contributor {
github_uid, github_uid,
github_username, github_username,
wiki_username, wiki_username,
} = deserialized; } = this;
let data = { let data = {
"@context": "https://schema.kosmos.org", "@context": "https://schema.kosmos.org",
@ -91,6 +61,55 @@ 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, wiki_username;
let github = accounts.find((a) => a.site === 'github.com');
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,
};
}
} }
module.exports = Contributor; module.exports = Contributor;

View File

@ -26,7 +26,7 @@ module.exports = async function(callback) {
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: '),
}; };

View File

@ -22,6 +22,7 @@ module.exports = async function(callback) {
let blockNumber = await kredits.provider.getBlockNumber(); let blockNumber = await kredits.provider.getBlockNumber();
let contributions = await kredits.Contribution.all(); let contributions = await kredits.Contribution.all();
console.log(`Current block number: ${blockNumber}`);
contributions.forEach((c) => { contributions.forEach((c) => {
const confirmed = c.confirmedAtBlock <= blockNumber; const confirmed = c.confirmedAtBlock <= blockNumber;
@ -30,7 +31,7 @@ module.exports = async function(callback) {
c.contributorId, c.contributorId,
`${c.description}`, `${c.description}`,
c.amount.toString(), c.amount.toString(),
confirmed, `${confirmed} (${c.confirmedAtBlock})`,
c.vetoed, c.vetoed,
c.claimed, c.claimed,
c.ipfsHash c.ipfsHash
@ -38,6 +39,9 @@ module.exports = async function(callback) {
}); });
console.log(table.toString()); console.log(table.toString());
let totalContributionBalances = await kredits.Contribution.functions.totalCount(true);
console.log(`Total confirmed balance: ${totalContributionBalances}`);
} catch (err) { } catch (err) {
console.log(err); console.log(err);
} }

View File

@ -15,12 +15,16 @@ 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', 'Name', 'Core?', 'Balance', 'IPFS'] head: ['ID', 'Account', 'Name', 'Core?', 'Balance', 'Kredits earned', 'Contributions count', 'IPFS']
}) })
let contributors = await kredits.Contributor.all() try {
const contributors = await kredits.Contributor.all()
} catch(e) {
callback(e);
return;
}
contributors.forEach((c) => { contributors.forEach((c) => {
table.push([ table.push([
@ -28,11 +32,15 @@ module.exports = async function(callback) {
c.account, c.account,
`${c.name}`, `${c.name}`,
c.isCore, c.isCore,
c.balanceInt, c.balanceInt.toString(),
c.totalKreditsEarned.toString(),
c.contributionsCount.toString(),
c.ipfsHash c.ipfsHash
]) ])
}) })
console.log(table.toString()) console.log(table.toString())
callback() callback()
} }