diff --git a/contracts/lib/ethereans/bank/Bank.sol b/contracts/lib/ethereans/bank/Bank.sol index fa27df6..e12081d 100644 --- a/contracts/lib/ethereans/bank/Bank.sol +++ b/contracts/lib/ethereans/bank/Bank.sol @@ -3,8 +3,17 @@ pragma solidity ^0.4.9; contract Bank { - - - - + event Withdrawn(address reciever, uint256 amount); + event Deposited(address sender,uint256 value); + //allow deposit and call event + function deposit() payable { + Deposited(msg.sender, msg.value); + } + + //withdraw if locked and not paid, updates epoch + function withdrawal(address dest, uint amount) + internal { + if(!dest.send(amount)) throw; + Withdrawn(msg.sender, amount); + } } \ No newline at end of file diff --git a/contracts/lib/ethereans/bank/CollaborationBank.sol b/contracts/lib/ethereans/bank/CollaborationBank.sol new file mode 100644 index 0000000..cad9581 --- /dev/null +++ b/contracts/lib/ethereans/bank/CollaborationBank.sol @@ -0,0 +1,94 @@ +pragma solidity ^0.4.0; + +/** + * Abstract contract used for recieving donations or profits + * Withdraw is divided by total tokens each account owns + * Unlock period allows transfers + * Lock period allow withdraws + * Child contract that implement minting should use modifier not_locked in minting function + * Inspired by ProfitContainer and Lockable by vDice + * + * By Ricardo Guilherme Schmidt + * Released under GPLv3 License + */ + +import "./Bank.sol"; +import "../management/EpochLocker.sol"; +import "../token/LockerToken.sol"; + +contract CollaborationBank is Bank, EpochLocker { + + LockerToken public token; + //used for calculating balance and for checking if account withdrawn + uint256 public currentPayEpoch; + //stores the balance from the lock time + uint256 public epochBalance; + //used for checking if account withdrawn + mapping (address => uint) lastPaidOutEpoch; + //events + event Withdrawn(address tokenHolder, uint256 amountPaidOut); + event Deposited(address donator,uint256 value); + + function CollaborationBank(LockerToken _token) EpochLocker(8 minutes, 12 minutes){ + token = _token; + + } + + //update the balance and payout epoch + modifier update_epoch { + if(currentPayEpoch < CURRENT_EPOCH) { + currentPayEpoch = CURRENT_EPOCH; + epochBalance = this.balance; + } + _; + } + + //checks if user already withdrawn + modifier not_paid { + if (lastPaidOutEpoch[msg.sender] == currentPayEpoch) throw; + _; + } + + //check overflow in multiply + function safeMultiply(uint256 _a, uint256 _b) private { + if (!(_b == 0 || ((_a * _b) / _b) == _a)) throw; + } + + //allow deposit and call event + function () + payable { + deposit(); + } + + //withdraw if locked and not paid, updates epoch + function withdrawal() + external + check_lock(true) + update_epoch + not_paid { + uint256 _tokenBalance = token.balanceOf(msg.sender); + uint256 _tokenSupply = token.totalSupply(); + safeMultiply(_tokenBalance, epochBalance); + lastPaidOutEpoch[msg.sender] = currentPayEpoch; + if (this.balance >= epochBalance || _tokenBalance == 0 || _tokenSupply == 0) throw; + super.withdrawal(msg.sender, (_tokenBalance * epochBalance) / _tokenSupply); + } + + //if this coin owns tokens of other CollaborationBank, allow withdraw + function withdrawalFrom(CollaborationBank _otherCollaborationToken) { + _otherCollaborationToken.withdrawal(); + } + + //return expected payout in lock or estimated when not locked + function expectedPayout(address _tokenHolder) + external + constant + returns (uint256 payout) { + if (now < NEXT_LOCK) //unlocked, estimate + payout = (token.balanceOf(_tokenHolder) * this.balance) / token.totalSupply(); + else + payout = (token.balanceOf(_tokenHolder) * epochBalance) / token.totalSupply(); + } + + +} diff --git a/contracts/lib/ethereans/management/EpochLocker.sol b/contracts/lib/ethereans/management/EpochLocker.sol new file mode 100644 index 0000000..c98c240 --- /dev/null +++ b/contracts/lib/ethereans/management/EpochLocker.sol @@ -0,0 +1,51 @@ +pragma solidity ^0.4.8; + +/** + * Abstract contract that locks and unlock in period of a time. + * + */ + +import "lib/ethereans/management/Lockable.sol"; + +contract EpochLocker is Lockable { + + uint256 public creationTime = now; + uint256 public unlockedTime = 25 days; + uint256 public lockedTime = 5 days; + uint256 public constant EPOCH_LENGTH = unlockedTime + lockedTime; + uint256 public constant CURRENT_EPOCH = (now - creationTime) / EPOCH_LENGTH + 1; + uint256 public constant NEXT_LOCK = (creationTime + CURRENT_EPOCH * unlockedTime) + (CURRENT_EPOCH - 1) * lockedTime; + + + function EpochLocker(uint256 _unlockedTime, uint256 _lockedTime){ + unlockedTime = _unlockedTime; + lockedTime = _lockedTime; + } + + //update lock value if needed or throw if unexpected lock + modifier check_lock(bool lockedOnly) { + if(lockedOnly){ //method allowed when locked + if (NEXT_LOCK < now) { //is locked! + if (!lock) setLock(true); //storage says other thing, update it. + _; //continue + } + else { //is not locked! + if (!lock) throw; //unlocked and storage already say so, throw to prevent event flood. + setLock(false); //update storage + return; //prevent method from running post states. + } + }else{ //method allowed when unlocked. + if (NEXT_LOCK < now) { //is locked! + if (lock) throw; //no need to update storage. + setLock(true); //update storage + return; //prevent method from running post states. + } + else { //is not locked! + if (lock) setLock(false); //storage says other thing, update it. + _; //continue + } + } + } + + +} \ No newline at end of file diff --git a/contracts/lib/ethereans/management/Lockable.sol b/contracts/lib/ethereans/management/Lockable.sol new file mode 100644 index 0000000..0edd67e --- /dev/null +++ b/contracts/lib/ethereans/management/Lockable.sol @@ -0,0 +1,14 @@ +pragma solidity ^0.4.8; + +import "./Owned.sol"; + +contract Lockable { + bool public lock = true; + event Locked(bool lock); + + function setLock(bool _lock) internal { + Locked(_lock); + lock = _lock; + } + +} \ No newline at end of file diff --git a/contracts/lib/ethereans/management/Owned.sol b/contracts/lib/ethereans/management/Owned.sol index 76683cc..141010d 100644 --- a/contracts/lib/ethereans/management/Owned.sol +++ b/contracts/lib/ethereans/management/Owned.sol @@ -3,7 +3,11 @@ pragma solidity ^0.4.8; contract Owned { address public owner= msg.sender; event NewOwner(address owner); - + + function Owned(){ + NewOwner(owner); + } + modifier only_owner { if (msg.sender != owner) throw; _; diff --git a/contracts/lib/ethereans/token/CollaborationToken.sol b/contracts/lib/ethereans/token/CollaborationToken.sol deleted file mode 100644 index 6a44312..0000000 --- a/contracts/lib/ethereans/token/CollaborationToken.sol +++ /dev/null @@ -1,158 +0,0 @@ -pragma solidity ^0.4.0; - -/** - * Abstract contract used for recieving donations or profits - * Withdraw is divided by total tokens each account owns - * Unlock period allows transfers - * Lock period allow withdraws - * Child contract that implement minting should use modifier not_locked in minting function - * Inspired by ProfitContainer and Lockable by vDice - * - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -import "./AbstractToken.sol"; - -contract CollaborationToken is AbstractToken { - //creation time, defined when contract is created - uint256 public creationTime = now; - //time constants, defines epoch size and periods - uint256 public constant UNLOCKED_TIME = 25 days; - uint256 public constant LOCKED_TIME = 5 days; - uint256 public constant EPOCH_LENGTH = UNLOCKED_TIME + LOCKED_TIME; - //current epoch constant formula, recalculated in any contract call - uint256 public constant CURRENT_EPOCH = (now - creationTime) / EPOCH_LENGTH + 1; - //next lock constant formula, recalculated in any contract call - uint256 public constant NEXT_LOCK = (creationTime + CURRENT_EPOCH * UNLOCKED_TIME) + (CURRENT_EPOCH - 1) * LOCKED_TIME; - //used for calculating balance and for checking if account withdrawn - uint256 public currentPayEpoch; - //stores the balance from the lock time - uint256 public epochBalance; - //stores lock state, used for events - bool public lock; - //used for hecking if account withdrawn - mapping (address => uint) lastPaidOutEpoch; - //events - event Withdrawn(address tokenHolder, uint256 amountPaidOut); - event Deposited(address donator,uint256 value); - event Locked(); - event Unlocked(); - - //checks if not locked and call event on change - modifier not_locked { - if (NEXT_LOCK < now) { - if (lock) throw; - lock = true; - Locked(); - return; - } - else { - if (lock) { - lock = false; - Unlocked(); - } - } - _; - } - - //checks if is locked and call event on change - modifier locked { - if (NEXT_LOCK < now) { - if (!lock){ - lock = true; - Locked(); - } - } - else { - if (!lock) throw; - lock = false; - Unlocked(); - return; - } - _; - } - - //update the balance and payout epoch - modifier update_epoch { - if(currentPayEpoch < CURRENT_EPOCH) { - currentPayEpoch = CURRENT_EPOCH; - epochBalance = this.balance; - } - _; - } - - //checks if user already withdrawn - modifier not_paid { - if (lastPaidOutEpoch[msg.sender] == currentPayEpoch) throw; - _; - } - - //check overflow in multiply - modifier safe_multiply(uint256 _a, uint256 _b) { - if (!(_b == 0 || ((_a * _b) / _b) == _a)) throw; - _; - } - - //allow deposit and call event - function () - payable { - Deposited(msg.sender, msg.value); - } - - //withdraw if locked and not paid, updates epoch - function withdrawal() - external - locked - update_epoch - not_paid - safe_multiply(balanceOf(msg.sender), epochBalance) { - uint256 _currentEpoch = CURRENT_EPOCH; - uint256 _tokenBalance = balanceOf(msg.sender); - uint256 _totalSupply = totalSupply; - if (this.balance == 0 || _tokenBalance == 0) throw; - lastPaidOutEpoch[msg.sender] = currentPayEpoch; - uint256 amountToPayOut = (_tokenBalance * epochBalance) / _totalSupply; - if(!msg.sender.send(amountToPayOut)) { - throw; - } - Withdrawn(msg.sender, amountToPayOut); - } - - //if this coin owns tokens of other lockablecoin, allow withdraw - function withdrawalFrom(CollaborationToken _otherCollaborationToken) { - _otherCollaborationToken.withdrawal(); - } - - //return expected payout in lock or estimated when not locked - function expectedPayout(address _tokenHolder) - external - constant - returns (uint256 payout) { - if (now < NEXT_LOCK) //unlocked, estimate - payout = (balanceOf(_tokenHolder) * this.balance) / totalSupply; - else - payout = (balanceOf(_tokenHolder) * epochBalance) / totalSupply; - } - - //overwrite not allow transfer during lock - function transfer(address _to, uint256 _value) - not_locked - returns (bool ok) { - return super.transfer(_to,_value); - } - - //overwrite not allow transfer during lock - function transferFrom(address _from, address _to, uint256 _value) - not_locked - returns (bool ok) { - return super.transferFrom(_from,_to,_value); - } - - //overwrite not allow transfer during lock - function approve(address _spender, uint256 _value) - returns (bool ok) { - return super.approve(_spender,_value); - } - -} diff --git a/contracts/lib/ethereans/token/JustifiedCollaborationToken.sol b/contracts/lib/ethereans/token/JustifiedCollaborationToken.sol index f2f19ea..303cf06 100644 --- a/contracts/lib/ethereans/token/JustifiedCollaborationToken.sol +++ b/contracts/lib/ethereans/token/JustifiedCollaborationToken.sol @@ -8,9 +8,9 @@ pragma solidity ^0.4.1; */ import "../management/Owned.sol"; -import "./CollaborationToken.sol"; +import "./AbstractToken.sol"; -contract JustifiedCollaborationToken is CollaborationToken, Owned { +contract JustifiedCollaborationToken is AbstractToken, Owned { event Claim(bytes32 _data); mapping (bytes32 => Receipt) public receipts; mapping (address => bool) public minters; @@ -23,7 +23,6 @@ contract JustifiedCollaborationToken is CollaborationToken, Owned { } function claim(address _beneficiary, uint256 _value, bytes32 _data) - not_locked only_owner { if(receipts[_data].claimed) throw; receipts[_data] = Receipt ({beneficiary: _beneficiary, value: _value, claimed: true}); diff --git a/contracts/lib/ethereans/token/LockerToken.sol b/contracts/lib/ethereans/token/LockerToken.sol new file mode 100644 index 0000000..ed915ca --- /dev/null +++ b/contracts/lib/ethereans/token/LockerToken.sol @@ -0,0 +1,43 @@ +pragma solidity ^0.4.0; + +/** + * Abstract contract to accept lock and linked locker. + * + * By Ricardo Guilherme Schmidt + * Released under GPLv3 License + */ + +import "./AbstractToken.sol"; +import "../management/Lockable.sol"; + +contract LockerToken is AbstractToken, Lockable, Owned { + Lockable public locker = this; + + function unlinkLocker() only_owner { + locker = this; + } + function linkLocker(Lockable _locker) only_owner { + locker = _locker; + } + function setlock(bool _lock) only_owner { + setLock(_lock); + } + + modifier when_locked(bool value){ + if (lock != value && locker.lock() != value) throw; + _; + } + + //overwrite not allow transfer during lock + function transfer(address _to, uint256 _value) when_locked(true) + returns (bool ok) { + return super.transfer(_to,_value); + } + + //overwrite not allow transfer during lock + function transferFrom(address _from, address _to, uint256 _value) when_locked(true) + returns (bool ok) { + return super.transferFrom(_from,_to,_value); + } + +} diff --git a/contracts/src/BountyBank.sol b/contracts/src/BountyBank.sol new file mode 100644 index 0000000..5a97762 --- /dev/null +++ b/contracts/src/BountyBank.sol @@ -0,0 +1,64 @@ +pragma solidity ^0.4.9; + +import "lib/ethereans/management/Owned.sol"; + +contract BountyBank is Owned { + + enum State {CLOSED, OPEN, CLAIMED} + + struct Bounty { + State state; + uint closedAt; + mapping (address => uint) deposits; + mapping (address => uint) claimers; + uint balance; + uint points; + } + + mapping (uint => Bounty) bounties; + uint count = 0; + + function deposit(uint num) payable { + if(bounties[num].state != State.OPEN || msg.value == 0) throw; + bounties[num].deposits[msg.sender] += msg.value; + bounties[num].balance += msg.value; + } + + function withdraw(uint num) { + uint value = bounties[num].deposits[msg.sender]; + if(bounties[num].state != State.OPEN || value == 0) throw; + delete bounties[num].deposits[msg.sender]; + if(!msg.sender.send(value)) throw; + } + + function open(uint num) only_owner { + if(bounties[num].state == State.CLAIMED) throw; + bounties[num].state = State.OPEN; + } + + function setClaimer(uint num, address claimer, uint points) only_owner { + if(bounties[num].state == State.CLAIMED) throw; + bounties[num].claimers[claimer] += points; + bounties[num].points += points; + } + + function close(uint num) only_owner { + if(bounties[num].state == State.CLAIMED) throw; + bounties[num].state = State.CLOSED; + bounties[num].closedAt = now; + } + + function claim(uint num){ + if (bounties[num].state == State.OPEN) throw; + uint totalPoints = bounties[num].points; + if(totalPoints == 0) throw; + uint points = bounties[num].claimers[msg.sender]; + if (points == 0) throw; + delete bounties[num].claimers[msg.sender]; + uint award = (bounties[num].balance / totalPoints)*points; + bounties[num].points -= points; + bounties[num].balance -= award; + if(!msg.sender.send(award)) throw; + } + + } \ No newline at end of file diff --git a/contracts/src/AbstractBounty.sol b/contracts/src/BountyBank2.sol similarity index 85% rename from contracts/src/AbstractBounty.sol rename to contracts/src/BountyBank2.sol index 94c180d..8dbab75 100644 --- a/contracts/src/AbstractBounty.sol +++ b/contracts/src/BountyBank2.sol @@ -9,7 +9,7 @@ import "lib/ethereans/management/Owned.sol" ; contract GitBountyBank is Owned { mapping (uint => Bounty) bounties; - uint lockPeriod = 1 month; + uint lockPeriod = 30 days; struct Bounty { bool open; uint closedAt; @@ -45,9 +45,9 @@ contract GitBountyBank is Owned { payable returns (uint reciept) { if (!bounties[num].open) throw; reciept = bounties[num].depositIndex; - bounties[num].deposits[reciept] = { owner: account, amount: msg.value }; + bounties[num].deposits[reciept] = Account({ owner: account, amount: msg.value }); bounties[num].depositIndex++; - bounties[num].balance += msg.value; + bounties[num].deposited += msg.value; return reciept; } @@ -56,7 +56,7 @@ contract GitBountyBank is Owned { if(bounties[num].deposits[reciept].owner != account) throw; uint avaliable = bounties[num].deposits[reciept].amount; delete bounties[num].deposits[reciept]; - bounties[num].balance -= avaliable; + bounties[num].deposited -= avaliable; if(!account.send(avaliable)) throw; } @@ -64,7 +64,8 @@ contract GitBountyBank is Owned { if (bounties[num].open || now < bounties[num].closedAt+lockPeriod) throw; uint balance = bounties[num].deposited - bounties[num].claimed; uint remainingStats = bounties[num].stats - bounties[num].statsClaimed; - bounties[num].claims[commitid] = { owner: account, amount: stats }; + bounties[num].claims[commitid] = Account({ owner: beneficiary, amount: stats }); + //bounties[num].claimed+= } diff --git a/contracts/src/DGit.sol b/contracts/src/DGit.sol new file mode 100644 index 0000000..e66792e --- /dev/null +++ b/contracts/src/DGit.sol @@ -0,0 +1,86 @@ +pragma solidity ^0.4.8; + +/** + * Contract that oracle github API + * + * GitHubOracle register users and create GitHubToken contracts + * Registration requires user create a gist with only their account address + * GitHubOracle will create one GitHubToken contract per repository + * GitHubToken mint tokens by commit only for registered users in GitHubOracle + * GitHubToken is a LockableCoin, that accept donatations and can be withdrawn by Token Holders + * The lookups are done by Oraclize that charge a small fee + * The contract itself will never charge any fee + * + * By Ricardo Guilherme Schmidt + * Released under GPLv3 License + */ + +import "lib/oraclize/oraclizeAPI_0.4.sol"; +import "lib/ethereans/management/Owned.sol"; +import "./GitHubAPI.sol"; +import "./DGitDB.sol"; +import "./GitRepository.sol"; + +contract DGit is Owned, DGitI { + + DGitDBI public db; + GitHubAPI public gitHubApi; + + function initialize() only_owner { + db = DBFactory.newStorage(); + gitHubApi = QueryFactory.newGitHubAPI(); + } + + function register(string _github_user, string _gistid) payable{ + gitHubApi.register.value(msg.value)(msg.sender,_github_user,_gistid); + } + function claimCommit(string _repository, string _commitid) payable{ + gitHubApi.claimCommit.value(msg.value)(_repository,_commitid); + } + function addRepository(string _repository) payable{ + gitHubApi.addRepository.value(msg.value)(_repository); + } + function updateIssue(string _repository, string issue) payable{ + gitHubApi.updateIssue.value(msg.value)(_repository,issue); + } + function getRepository(uint projectId) constant returns (address){ + return db.getRepositoryAddress(projectId); + } + function getRepository(string full_name) constant returns (address){ + return db.getRepositoryAddress(full_name); + } + + modifier only_gitapi{ + if (msg.sender != address(gitHubApi)) throw; + _; + } + + event UserSet(string githubLogin); + function __register(address addrLoaded, uint256 userId, string login) + only_gitapi { + UserSet(login); + db.addUser(userId, login, 0, addrLoaded); + } + + event GitRepositoryRegistered(uint256 projectId, string full_name, uint256 watchers, uint256 subscribers); + function __setRepository(uint256 projectId, string full_name, uint256 watchers, uint256 subscribers) only_gitapi //[83725290, "ethereans/github-token", 4, 2] + { + uint256 ownerId; string memory name; //TODO + address repository = db.getRepositoryAddress(projectId); + if(repository == 0x0){ + GitRepositoryRegistered(projectId,full_name,watchers,subscribers); + repository = GitFactory.newGitRepository(projectId,full_name); + db.addRepository(projectId,ownerId,name,full_name,repository); + } + GitRepositoryI(repository).setStats(subscribers,watchers); + } + + event NewClaim(string repository, bytes20 commitid, uint userId, uint total ); + function __claimCommit(string repository, bytes20 commitid, uint userId, uint total) + only_gitapi { + NewClaim(repository,commitid,userId,total); + GitRepositoryI repoaddr = GitRepositoryI(db.getRepositoryAddress(repository)); + repoaddr.claim(commitid, db.getUserAddress(userId), total); + } + +} \ No newline at end of file diff --git a/contracts/src/storage/GitHubOracleStorage.sol b/contracts/src/DGitDB.sol similarity index 57% rename from contracts/src/storage/GitHubOracleStorage.sol rename to contracts/src/DGitDB.sol index 12db397..71b3051 100644 --- a/contracts/src/storage/GitHubOracleStorage.sol +++ b/contracts/src/DGitDB.sol @@ -10,8 +10,25 @@ pragma solidity ^0.4.8; */ import "lib/ethereans/management/Owned.sol"; -import "./GitHubOracleStorageI.sol"; -contract GitHubOracleStorage is GitHubOracleStorageI, Owned { + +contract DGitDBI { + function addRepository(uint256 _id, uint256 _owner, string _name, string _full_name, address _addr); + function addUser(uint256 _id, string _login, uint8 _type, address _addr); + function setRepositoryAddress(uint256 _repositoryId, address _repositoryAddress); + function setRepositoryName(uint256 _repositoryId, string _full_name, string _name); + function setUserAddress(uint userId, address account); + function setUserName(uint256 _userId, string _name); + function getRepositoryId(string _full_name) constant returns (uint256); + function getRepositoryName(uint256 _id) constant returns (string); + function getRepositoryAddress(uint256 _id) constant returns(address); + function getRepositoryAddress(string _full_name) constant returns(address); + function getUserAddress(uint256 _id) constant returns(address); + function getUserAddress(string _login) constant returns(address); + function getClaimed(uint256 _repoid, bytes20 _commitid) constant returns (uint); + function setClaimed(uint256 _repoid, bytes20 _commitid, uint _userid, uint _points); +} + +contract DGitDB is DGitDBI, Owned { mapping (string => uint256) repositoryNames; mapping (string => uint256) userNames; @@ -23,24 +40,40 @@ contract GitHubOracleStorage is GitHubOracleStorageI, Owned { string name; string full_name; address addr; - uint256 claimed; + uint points; + mapping (bytes20 => Commit) commits; + } + struct Commit { + uint points; + uint userId; + } + struct User { string login; uint8 utype; address addr; - uint256 claimed; + } + + function setClaimed(uint256 _repoid, bytes20 _commitid, uint _userid, uint _points) + only_owner { + repositories[_repoid].commits[_commitid].userId = _userid; + repositories[_repoid].commits[_commitid].points = _points; + repositories[_repoid].points += _points; } + function getClaimed(uint256 _repoid, bytes20 _commitid) constant returns (uint){ + return repositories[_repoid].commits[_commitid].userId; + } function addRepository(uint256 _id, uint256 _owner, string _name, string _full_name, address _addr) only_owner { - repositories[_id] = Repository({owner:_owner,name:_name,full_name:_full_name,addr:_addr,claimed:0}); + repositories[_id] = Repository({owner:_owner,name:_name,full_name:_full_name,addr:_addr,points:0}); repositoryNames[_full_name] = _id; } function addUser(uint256 _id, string _login, uint8 _utype, address _addr) only_owner{ - users[_id] = User({login:_login,utype:_utype,addr:_addr, claimed:0}); + users[_id] = User({login:_login,utype:_utype,addr:_addr}); userNames[_login] = _id; } @@ -88,4 +121,12 @@ contract GitHubOracleStorage is GitHubOracleStorageI, Owned { return repositories[_id].full_name; } +} + +library DBFactory { + + function newStorage() returns (DGitDBI){ + return new DGitDB(); + } + } \ No newline at end of file diff --git a/contracts/src/GitHubOracle.sol b/contracts/src/GitHubAPI.sol similarity index 55% rename from contracts/src/GitHubOracle.sol rename to contracts/src/GitHubAPI.sol index 07ade2e..2e786ba 100644 --- a/contracts/src/GitHubOracle.sol +++ b/contracts/src/GitHubAPI.sol @@ -1,47 +1,41 @@ -pragma solidity ^0.4.8; - -/** - * Contract that oracle github API - * - * GitHubOracle register users and create GitHubToken contracts - * Registration requires user create a gist with only their account address - * GitHubOracle will create one GitHubToken contract per repository - * GitHubToken mint tokens by commit only for registered users in GitHubOracle - * GitHubToken is a LockableCoin, that accept donatations and can be withdrawn by Token Holders - * The lookups are done by Oraclize that charge a small fee - * The contract itself will never charge any fee - * - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -import "lib/StringLib.sol"; -import "lib/JSONLib.sol"; +pragma solidity ^0.4.9; import "lib/oraclize/oraclizeAPI_0.4.sol"; +import "lib/StringLib.sol"; +import "lib/JSONLib.sol"; import "lib/ethereans/management/Owned.sol"; -import "./git-repository/GitRepositoryFactoryI.sol"; -import "./storage/GitHubOracleStorageI.sol"; +contract GitHubAPI{ + function register(address _sender, string _github_user, string _gistid) payable; + function claimCommit(string _repository, string _commitid) payable; + function addRepository(string _repository) payable; + function updateIssue(string _repository, string issue) payable; +} -contract GitHubOracle is Owned, usingOraclize { - - using StringLib for string; - - GitRepositoryFactoryI public gitRepositoryFactoryI; - GitHubOracleStorageI public db; +contract DGitI { + function __register(address addrLoaded, uint256 userId, string login); + function __setRepository(uint256 projectId, string full_name, uint256 watchers, uint256 subscribers); + function __claimCommit(string repository, bytes20 commitid, uint userid, uint total); +} +contract GitHubAPIOraclize is GitHubAPI, Owned, usingOraclize{ + using StringLib for string; + + DGitI dGit; + function GitHubAPIOraclize(){ + dGit = DGitI(msg.sender); + } + string private credentials = ""; //store encrypted values of api access credentials + string private secret = ""; + string private client = ""; + string private script = "QmS3kHrUQ12ovovKPk9vxKjDPm7kVWcieaMcZc9w8JbNQt"; + enum OracleType { SET_REPOSITORY, SET_USER, CLAIM_COMMIT, UPDATE_ISSUE } mapping (bytes32 => OracleType) claimType; //temporary db enumerating oraclize calls mapping (bytes32 => CommitClaim) commitClaim; //temporary db for oraclize commit token claim calls mapping (bytes32 => UserClaim) userClaim; //temporary db for oraclize user register queries - string private credentials = ""; //store encrypted values of api access credentials - string private secret = ""; - string private client = ""; - string private script = ""; - //stores temporary data for oraclize user register request struct UserClaim { address sender; @@ -50,69 +44,38 @@ contract GitHubOracle is Owned, usingOraclize { //stores temporary data for oraclize repository commit claim struct CommitClaim { string repository; - string commitid; + bytes20 commitid; } - - function GitHubOracle(GitHubOracleStorageI _db, GitRepositoryFactoryI _gitRepositoryFactoryI){ // - gitRepositoryFactoryI = _gitRepositoryFactoryI; - db = _db; - } - - //register or change a github user ethereum address 100000000000000000 - function register(string _github_user, string _gistid) - payable { + //register or change a github user ethereum address. 100000000000000000 + + function register(address _sender, string _github_user, string _gistid) + payable only_owner{ bytes32 ocid = oraclize_query("nested", StringLib.concat("[identity] ${[URL] https://gist.githubusercontent.com/",_github_user,"/",_gistid,"/raw/}, ${[URL] json(https://api.github.com/gists/").concat(_gistid,credentials,").owner.[id,login]}")); claimType[ocid] = OracleType.SET_USER; - userClaim[ocid] = UserClaim({sender: msg.sender, githubid: _github_user}); + userClaim[ocid] = UserClaim({sender: _sender, githubid: _github_user}); } function claimCommit(string _repository, string _commitid) - payable { + payable only_owner{ + //uint256 repoid = db.getRepositoryId(_repository); + //if (repoid == 0) throw; + bytes20 commitid = _commitid.parseBytes20(); + //if(db.getClaimed(repoid,commitid) == 0) throw; bytes32 ocid = oraclize_query("URL", StringLib.concat("json(https://api.github.com/repos/",_repository,"/commits/", _commitid, credentials).concat(").[author,stats].[id,total]")); claimType[ocid] = OracleType.CLAIM_COMMIT; - commitClaim[ocid] = CommitClaim( { repository: _repository, commitid:_commitid}); + commitClaim[ocid] = CommitClaim( { repository: _repository, commitid:commitid}); } function addRepository(string _repository) - payable { + payable only_owner{ bytes32 ocid = oraclize_query("URL", StringLib.concat("json(https://api.github.com/repos/",_repository,credentials,").$.id,full_name,watchers,subscribers_count"),4000000); claimType[ocid] = OracleType.SET_REPOSITORY; } - - function getRepository(uint id) constant returns (address){ - return db.getRepositoryAddress(projectId); - } - - function getRepository(string full_name) constant returns (address){ - return db.getRepositoryAddress(full_name); - } - - function setScript(string _script){ - script = _script; - } - - //owner management - function setAPICredentials(string _client_id, string _client_secret) - only_owner { - credentials = StringLib.concat("?client_id=${[decrypt] ", _client_id,"}&client_secret=${[decrypt] ", _client_secret,"}"); + function updateIssue(string _repository, string issue) payable only_owner{ + bytes32 ocid = oraclize_query("computation", [script, StringLib.concat("--reponame ",_repository, " --issueid ", issue, " --script issue-status").concat(" --client ", client, " --secret ", secret)]); } - function clearAPICredentials() - only_owner { - credentials = ""; - } - - - function bountyIssue(uint repositoryId, uint issueId) payable{ - - } - - - //Internal Functions - - - // event OracleEvent(bytes32 myid, string result, bytes proof); //oraclize response callback @@ -130,7 +93,6 @@ contract GitHubOracle is Owned, usingOraclize { delete claimType[myid]; //should always be deleted } - event UserSet(string githubLogin); function _register(bytes32 myid, string result) internal { uint256 userId; string memory login; address addrLoaded; @@ -140,34 +102,25 @@ contract GitHubOracle is Owned, usingOraclize { (addrLoaded,pos) = JSONLib.getNextAddr(v,pos); (userId,pos) = JSONLib.getNextUInt(v,pos); (login,pos) = JSONLib.getNextString(v,pos); - if(userClaim[myid].sender == addrLoaded && userClaim[myid].githubid.compare(login) == 0){ - UserSet(login); - db.addUser(userId, login, utype, addrLoaded); - } //TODO: update user login and address; + if(userClaim[myid].sender == addrLoaded){ + dGit.__register(addrLoaded, userId, login); + } delete userClaim[myid]; //should always be deleted } - event GitRepositoryRegistered(uint256 projectId, string full_name, uint256 watchers, uint256 subscribers); - function _setRepository(bytes32 myid, string result) //[83725290, "ethereans/github-token", 4, 2] + function _setRepository(bytes32 myid, string result) internal //[83725290, "ethereans/github-token", 4, 2] { uint256 projectId; string memory full_name; uint256 watchers; uint256 subscribers; - uint256 ownerId; string memory name; //TODO + //uint256 ownerId; string memory name; //TODO bytes memory v = bytes(result); uint8 pos = 0; (projectId,pos) = JSONLib.getNextUInt(v,pos); (full_name,pos) = JSONLib.getNextString(v,pos); (watchers,pos) = JSONLib.getNextUInt(v,pos); (subscribers,pos) = JSONLib.getNextUInt(v,pos); - address repository = db.getRepositoryAddress(projectId); - if(repository == 0x0){ - GitRepositoryRegistered(projectId,full_name,watchers,subscribers); - repository = gitRepositoryFactoryI.newGitRepository(projectId,full_name); - db.addRepository(projectId,ownerId,name,full_name,repository); - } - GitRepositoryI(repository).setStats(subscribers,watchers); + dGit.__setRepository(projectId,full_name,watchers,subscribers); } - event NewClaim(string repository, string commitid, uint userid, uint total ); function _claimCommit(bytes32 myid, string result) internal { uint256 total; uint256 userId; @@ -175,13 +128,36 @@ contract GitHubOracle is Owned, usingOraclize { uint8 pos = 0; (userId,pos) = JSONLib.getNextUInt(v,pos); (total,pos) = JSONLib.getNextUInt(v,pos); - NewClaim(commitClaim[myid].repository,commitClaim[myid].commitid,userId,total); - GitRepositoryI repository = GitRepositoryI(db.getRepositoryAddress(commitClaim[myid].repository)); - repository.claim(commitClaim[myid].commitid.parseBytes20(), db.getUserAddress(userId), total); - delete commitClaim[myid]; //should always be deleted + dGit.__claimCommit(commitClaim[myid].repository,commitClaim[myid].commitid,userId,total); + delete commitClaim[myid]; + } + + //owner management + function setAPICredentials(string _client_id, string _client_secret) + only_owner { + client = _client_id; + secret = _client_secret; + credentials = StringLib.concat("?client_id=${[decrypt] ", _client_id,"}&client_secret=${[decrypt] ", _client_secret,"}"); + } + + + function setScript(string _script) only_owner{ + script = _script; } - + function clearAPICredentials() + only_owner { + credentials = ""; + } + +} + +library QueryFactory { + + function newGitHubAPI() returns (GitHubAPI){ + return new GitHubAPIOraclize(); + } + } \ No newline at end of file diff --git a/contracts/src/GitHubIssues.sol b/contracts/src/GitHubIssues.sol deleted file mode 100644 index 577defe..0000000 --- a/contracts/src/GitHubIssues.sol +++ /dev/null @@ -1,45 +0,0 @@ -pragma solidity ^0.4.8; - -/** - * DO NOT USE: under development - */ - import "./GitHubOracle.sol"; - import "./AbstractBounty.sol"; - - contract GitHubIssues is AbstractBounty { - - //Address of the oracle, used for github login address lookup - GitHubOracle public oracle; - //stores repository name, used for claim calls - string private repository; - string private uid; - mapping (uint => Issue) issues; - - struct Issue { - bool state; - uint balance; - uint unlock; - address claimer; - bool claimed; - } - - - modifier only_oracle { - if (msg.sender != address(oracle)) throw; - _; - } - - function GitHubIssues(uint _uid, string _repository, GitHubOracle _oracle) { - uid = _uid; - oracle = _oracle; - repository = _repository; - } - - function setState(uint num, bool open){ - issues[num] = open; - } - - function placeBounty(uint num){ - issues[num] - } - } \ No newline at end of file diff --git a/contracts/src/git-repository/GitRepository.sol b/contracts/src/GitRepository.sol similarity index 52% rename from contracts/src/git-repository/GitRepository.sol rename to contracts/src/GitRepository.sol index cf15a3a..aa74e43 100644 --- a/contracts/src/git-repository/GitRepository.sol +++ b/contracts/src/GitRepository.sol @@ -15,16 +15,28 @@ pragma solidity ^0.4.8; * Released under GPLv3 License */ +import "lib/ethereans/bank/CollaborationBank.sol"; import "lib/ethereans/management/Owned.sol"; -import "./GitRepositoryI.sol"; +import "./BountyBank.sol"; import "./GitRepositoryToken.sol"; -import "./GitRepositoryStorage.sol"; + + +contract GitRepositoryI { + function isClaimed(bytes20 _commitid) constant returns (bool); + function claim(bytes20 _commitid, address _user, uint _total); + function setStats(uint256 _subscribers, uint256 _watchers); +} contract GitRepository is GitRepositoryI, Owned { - //Address of the oracle, used for github login address lookup - GitRepositoryStorage public db; GitRepositoryToken public token; + CollaborationBank public donationBank; + BountyBank public bountyBank; + mapping (address=>uint) donators; + + string public name; + uint256 public uid; + mapping (bytes20 => bool) public commits; uint256 public subscribers; uint256 public watchers; @@ -37,27 +49,34 @@ contract GitRepository is GitRepositoryI, Owned { _; } + function () payable { + donationBank.deposit(); + donators[msg.sender] += msg.value; + } + function GitRepository(uint256 _uid, string _name) { - db = new GitRepositoryStorage(_uid,_name); + uid = _uid; + name = _name; token = new GitRepositoryToken(_name); + donationBank = new CollaborationBank(token); + token.linkLocker(donationBank); + bountyBank = new BountyBank(); } //checks if a commit is already claimed function isClaimed(bytes20 _commitid) constant returns (bool) { - return db.commits(_commitid) != 0x0; + return commits[_commitid]; } //oracle claim request function claim(bytes20 _commitid, address _user, uint _total) only_owner { - if(_total > 0 && !token.lock()){ - if(_user != 0x0 && db.commits(_commitid) != 0x0){ - Claim(_commitid); - db.setClaimed(_commitid,_user); - token.mint(_user, _total); - } + if(_total > 0 && !token.lock() && _user != 0x0 && !commits[_commitid]){ + Claim(_commitid); + commits[_commitid] = true; + token.mint(_user, _total); } } @@ -67,6 +86,22 @@ contract GitRepository is GitRepositoryI, Owned { watchers = _watchers; } - + function bountyState(uint issue, bool open) only_owner { + if (open) bountyBank.open(issue); + else bountyBank.close(issue); + } + + function bountyState(uint issue, address claimer, uint points) only_owner { + bountyBank.setClaimer(issue,claimer,points); + } } + +library GitFactory { + + function newGitRepository(uint256 _uid, string _name) returns (GitRepositoryI){ + GitRepository repo = new GitRepository(_uid,_name); + return repo; + } + +} \ No newline at end of file diff --git a/contracts/src/git-repository/GitRepositoryToken.sol b/contracts/src/GitRepositoryToken.sol similarity index 88% rename from contracts/src/git-repository/GitRepositoryToken.sol rename to contracts/src/GitRepositoryToken.sol index 7b7a9c6..3a9b81d 100644 --- a/contracts/src/git-repository/GitRepositoryToken.sol +++ b/contracts/src/GitRepositoryToken.sol @@ -15,10 +15,10 @@ pragma solidity ^0.4.8; * Released under GPLv3 License */ -import "lib/ethereans/token/CollaborationToken.sol"; +import "lib/ethereans/token/LockerToken.sol"; import "lib/ethereans/management/Owned.sol"; -contract GitRepositoryToken is CollaborationToken, Owned { +contract GitRepositoryToken is LockerToken { function GitRepositoryToken(string _repository) { setAttribute("name", _repository); @@ -27,7 +27,7 @@ contract GitRepositoryToken is CollaborationToken, Owned { } function mint(address _who, uint256 _value) - only_owner { + only_owner when_locked(false) { _mint(_who,_value); } diff --git a/contracts/src/git-repository/GitRepositoryFactory.sol b/contracts/src/git-repository/GitRepositoryFactory.sol deleted file mode 100644 index 1c20269..0000000 --- a/contracts/src/git-repository/GitRepositoryFactory.sol +++ /dev/null @@ -1,19 +0,0 @@ -pragma solidity ^0.4.8; - -/** - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -import "./GitRepository.sol"; -import "./GitRepositoryFactoryI.sol"; - -contract GitRepositoryFactory is GitRepositoryFactoryI { - - function newGitRepository(uint256 _uid, string _name) external returns (GitRepositoryI){ - GitRepository repo = new GitRepository(_uid,_name); - repo.setOwner(msg.sender); - return GitRepositoryI(repo); - } - -} \ No newline at end of file diff --git a/contracts/src/git-repository/GitRepositoryFactoryI.sol b/contracts/src/git-repository/GitRepositoryFactoryI.sol deleted file mode 100644 index 1ec1469..0000000 --- a/contracts/src/git-repository/GitRepositoryFactoryI.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma solidity ^0.4.8; - -/** - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -import "./GitRepositoryI.sol"; - -contract GitRepositoryFactoryI { - function newGitRepository(uint256 _uid, string _name) external returns (GitRepositoryI); -} diff --git a/contracts/src/git-repository/GitRepositoryI.sol b/contracts/src/git-repository/GitRepositoryI.sol deleted file mode 100644 index bc26d63..0000000 --- a/contracts/src/git-repository/GitRepositoryI.sol +++ /dev/null @@ -1,12 +0,0 @@ -pragma solidity ^0.4.8; - -/** - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -contract GitRepositoryI { - function isClaimed(bytes20 _commitid) constant returns (bool); - function claim(bytes20 _commitid, address _user, uint _total); - function setStats(uint256 _subscribers, uint256 _watchers); -} \ No newline at end of file diff --git a/contracts/src/git-repository/GitRepositoryStorage.sol b/contracts/src/git-repository/GitRepositoryStorage.sol deleted file mode 100644 index a392ced..0000000 --- a/contracts/src/git-repository/GitRepositoryStorage.sol +++ /dev/null @@ -1,41 +0,0 @@ - pragma solidity ^0.4.8; - -/** - * Contract that oracle github API - * - * GitHubRegistry is a storage contract - * - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ -import "lib/ethereans/management/Owned.sol"; - -contract GitRepositoryStorage is Owned { - - string public name; - uint256 public uid; - - //storage of sha3(login) of github users - mapping (bytes32 => address) users; - - mapping (bytes20 => address) public commits; - - function setClaimed(bytes20 _commitid, address _claimer) - only_owner { - commits[_commitid] = _claimer; - } - - function setUser(bytes32 _user, address _account) - only_owner { - users[_user] = _account; - if(_account == 0x0){ - delete users[_user]; - } - } - - function GitRepositoryStorage(uint256 _uid, string _name){ - uid = _uid; - name = _name; - } - -} \ No newline at end of file diff --git a/contracts/src/storage/GitHubOracleStorageI.sol b/contracts/src/storage/GitHubOracleStorageI.sol deleted file mode 100644 index 9095ce5..0000000 --- a/contracts/src/storage/GitHubOracleStorageI.sol +++ /dev/null @@ -1,27 +0,0 @@ -pragma solidity ^0.4.8; - -/** - * Contract that oracle github API - * - * GitHubRegistry is a storage contract - * - * By Ricardo Guilherme Schmidt - * Released under GPLv3 License - */ - -contract GitHubOracleStorageI { - - function addRepository(uint256 _id, uint256 _owner, string _name, string _full_name, address _addr); - function addUser(uint256 _id, string _login, uint8 _type, address _addr); - function setRepositoryAddress(uint256 _repositoryId, address _repositoryAddress); - function setRepositoryName(uint256 _repositoryId, string _full_name, string _name); - function setUserAddress(uint userId, address account); - function setUserName(uint256 _userId, string _name); - function getRepositoryId(string _full_name) constant returns (uint256); - function getRepositoryName(uint256 _id) constant returns (string); - function getRepositoryAddress(uint256 _id) constant returns(address); - function getRepositoryAddress(string _full_name) constant returns(address); - function getUserAddress(uint256 _id) constant returns(address); - function getUserAddress(string _login) constant returns(address); - -} \ No newline at end of file diff --git a/ethereum.json b/ethereum.json index 5501975..43136e9 100644 --- a/ethereum.json +++ b/ethereum.json @@ -1,7 +1,7 @@ { "contracts": "contracts", - "deploy": ["GitHubOracleStorage", "GitRepositoryFactory", "GitHubOracle"], + "deploy": ["DGit"], "plugins": { "oraclize": { diff --git a/scenarios/DeployRegClaim.yaml b/scenarios/DeployRegClaim.yaml deleted file mode 100644 index 9b70d55..0000000 --- a/scenarios/DeployRegClaim.yaml +++ /dev/null @@ -1,143 +0,0 @@ -# -# Scenario3 -# -# Created on: 20/03/2017 02:44:46 -# - -# Create contract GitRepositoryFactory -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: null - value: '0x0' - contract: - name: GitRepositoryFactory - dir: contracts/ - sources: - - lib/ethereans/bank/Bank.sol - - lib/ethereans/management/Owned.sol - - lib/ethereans/management/Secret.sol - - lib/ethereans/token/AbstractToken.sol - - lib/ethereans/token/CollaborationToken.sol - - lib/ethereans/token/JustifiedCollaborationToken.sol - - lib/ethereans/token/Token.sol - - lib/ethereans/token/WrappedEthToken.sol - - lib/ethereans/util/Bytes32Lib.sol - - lib/ethereans/util/IntLib.sol - - lib/JSONLib.sol - - lib/StringLib.sol - - lib/oraclize/oraclizeAPI_0.4.sol - - src/AbstractBounty.sol - - src/GitHubIssues.sol - - src/GitHubOracle.sol - - src/git-repository/GitRepository.sol - - src/git-repository/GitRepositoryFactory.sol - - src/git-repository/GitRepositoryFactoryI.sol - - src/git-repository/GitRepositoryI.sol - - src/git-repository/GitRepositoryStorage.sol - - src/git-repository/GitRepositoryToken.sol - - src/storage/GitHubOracleStorage.sol - - src/storage/GitHubOracleStorageI.sol - args: [] - -# Create contract GitHubOracleStorage -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: null - value: '0x0' - contract: - name: GitHubOracleStorage - dir: contracts/ - sources: - - lib/ethereans/bank/Bank.sol - - lib/ethereans/management/Owned.sol - - lib/ethereans/management/Secret.sol - - lib/ethereans/token/AbstractToken.sol - - lib/ethereans/token/CollaborationToken.sol - - lib/ethereans/token/JustifiedCollaborationToken.sol - - lib/ethereans/token/Token.sol - - lib/ethereans/token/WrappedEthToken.sol - - lib/ethereans/util/Bytes32Lib.sol - - lib/ethereans/util/IntLib.sol - - lib/JSONLib.sol - - lib/StringLib.sol - - lib/oraclize/oraclizeAPI_0.4.sol - - src/AbstractBounty.sol - - src/GitHubIssues.sol - - src/GitHubOracle.sol - - src/git-repository/GitRepository.sol - - src/git-repository/GitRepositoryFactory.sol - - src/git-repository/GitRepositoryFactoryI.sol - - src/git-repository/GitRepositoryI.sol - - src/git-repository/GitRepositoryStorage.sol - - src/git-repository/GitRepositoryToken.sol - - src/storage/GitHubOracleStorage.sol - - src/storage/GitHubOracleStorageI.sol - args: [] - -# Create contract GitHubOracle -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: null - value: '0x0' - contract: - name: GitHubOracle - dir: contracts/ - sources: - - lib/ethereans/bank/Bank.sol - - lib/ethereans/management/Owned.sol - - lib/ethereans/management/Secret.sol - - lib/ethereans/token/AbstractToken.sol - - lib/ethereans/token/CollaborationToken.sol - - lib/ethereans/token/JustifiedCollaborationToken.sol - - lib/ethereans/token/Token.sol - - lib/ethereans/token/WrappedEthToken.sol - - lib/ethereans/util/Bytes32Lib.sol - - lib/ethereans/util/IntLib.sol - - lib/JSONLib.sol - - lib/StringLib.sol - - lib/oraclize/oraclizeAPI_0.4.sol - - src/AbstractBounty.sol - - src/GitHubIssues.sol - - src/GitHubOracle.sol - - src/git-repository/GitRepository.sol - - src/git-repository/GitRepositoryFactory.sol - - src/git-repository/GitRepositoryFactoryI.sol - - src/git-repository/GitRepositoryI.sol - - src/git-repository/GitRepositoryStorage.sol - - src/git-repository/GitRepositoryToken.sol - - src/storage/GitHubOracleStorage.sol - - src/storage/GitHubOracleStorageI.sol - args: - - '0xdf315f7485c3a86eb692487588735f224482abe3' - - '0x17956ba5f4291844bc25aedb27e69bc11b5bda39' - -# Call method setOwner(address) -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: '0xdf315f7485c3a86eb692487588735f224482abe3' - value: '0x0' - call: setOwner(address) - args: - - '0x06b179aabf198ced0f98c8ceca905a920a137ef4' - -# Call method addRepository(string) -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: '0x06b179aabf198ced0f98c8ceca905a920a137ef4' - value: '0x16345785d8a0000' - call: addRepository(string) - args: - - ethereans/github-token - -# Call method register(string,string) -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: '0x06b179aabf198ced0f98c8ceca905a920a137ef4' - value: '0x38D7EA4C68000' - call: 'register(string,string)' - args: - - 3esmit - - 31a58f2ddf2258697cce1b969e7c298b - -# Call method claimCommit(string,string) -- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' - to: '0x06b179aabf198ced0f98c8ceca905a920a137ef4' - value: '0x2386f26fc10000' - call: 'claimCommit(string,string)' - args: - - ethereans/github-token - - 09ba429f22eec6cefcfa7a862f60b9d4cc1cfa14 \ No newline at end of file diff --git a/scenarios/InitRegAddClaim.yaml b/scenarios/InitRegAddClaim.yaml new file mode 100644 index 0000000..fd5dbc5 --- /dev/null +++ b/scenarios/InitRegAddClaim.yaml @@ -0,0 +1,38 @@ +# +# Scenario1 +# +# Created on: 27/03/2017 03:30:55 +# + +# Call method initialize() +- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' + to: '0x086ca7abad7f9773db72e2efd83dd22f5f408862' + value: '0x0' + call: initialize() + args: [] + +# Call method register(string,string) +- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' + to: '0x086ca7abad7f9773db72e2efd83dd22f5f408862' + value: '0x0' + call: 'register(string,string)' + args: + - 3esmit + - 31a58f2ddf2258697cce1b969e7c298b + +# Call method addRepository(string) +- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' + to: '0x086ca7abad7f9773db72e2efd83dd22f5f408862' + value: '0x8ac7230489e80000' + call: addRepository(string) + args: + - status-im/github-oracle + +# Call method claimCommit(string,string) +- from: '0xdedb49385ad5b94a16f236a6890cf9e0b1e30392' + to: '0x086ca7abad7f9773db72e2efd83dd22f5f408862' + value: '0x0' + call: 'claimCommit(string,string)' + args: + - status-im/github-oracle + - 3c461c5bfe3107923a13270f7037854f1ae8ca36 diff --git a/scripts/github-oracle/github_oracle.py b/scripts/github-oracle/github_oracle.py new file mode 100644 index 0000000..37f5ea8 --- /dev/null +++ b/scripts/github-oracle/github_oracle.py @@ -0,0 +1,101 @@ +import os, argparse +import json, urllib2, datetime +from collections import defaultdict +start = '' + +script = os.environ['ARG0'] +args = os.environ['ARG1'] +auth = os.environ['ARG2'] + + +if(auth): + #check if is client secret or token + + + + +repo_link = "" +if(args): + repo_link = "https://api.github.com/repos/" + args.reponame +else: + repo_link = "https://api.github.com/repositories/" + args.repoid + + + + +if script == 'issue-status': + issueStatus(args.issueid) +elif script == 'issue-commits': + issueCommits(args.issueid) +elif script == 'related-issues': + relatedIssues(args.issueid) +elif script == 'commit-points': + pullCommitPoints(args.pullid) +elif script == 'commit-data': + commitData(args.commit) + + + + + + + +def relatedIssues(issue): + link_issue = repo_link + "/issues/" + issue + "/timeline" + auth + print link_issue + req = urllib2.Request(link_issue) + req.add_header("Accept", "application/vnd.github.mockingbird-preview") + issue = json.load(urllib2.urlopen(req)) + for elem in issue: + if(elem["event"] == "cross-referenced"): + if(elem["source"]["type"] == "issue"): + #print elem["source"]["issue"]["number"]; + pullCommitPoints(json.dumps(elem["source"]["issue"]["number"])) + + + +def issueStatus(issue): + link_issue = repo_link + "/issues/" + issue + auth + issue = json.load(urllib2.urlopen(link_issue)) + if(issue['state'] == "closed"): + print datetime.datetime.strptime( json.dumps(issue['closed_at'])[1:-1], "%Y-%m-%dT%H:%M:%SZ" ).strftime('%s') +","+ json.dumps(issue['closed_by']['login']) + else: + print "open" + + +def pullCommitPoints(pr): + link_pull = repo_link + "/pulls/" + pr + auth + pull = json.load(urllib2.urlopen(link_pull)) + if(pull['merged_at']): + link_pulls_commits = repo_link + "/pulls/" + pr + "/commits" +auth + points = defaultdict(int) + commits = json.load(urllib2.urlopen(link_pulls_commits)) + for commit in commits: + if(commit['url']): + link_commit = json.dumps(commit['url'])[1:-1] +auth + _commit = json.load(urllib2.urlopen(link_commit)) + author = json.dumps(_commit['author']['login'])[1:-1] + points[author] += int(json.dumps(_commit['stats']['total'])) + print points.items() + + +def issueCommits(args.issueid): + link_issue = repo_link + "/issues/" + issue + "/timeline" + auth + req = urllib2.Request(link_issue) + req.add_header("Accept", "application/vnd.github.mockingbird-preview") + issue = json.load(urllib2.urlopen(req)) + for elem in issue: + if(elem["event"] == "cross-referenced"): + if(elem["source"]["type"] == "issue"): + #print elem["source"]["issue"]["number"]; + pullCommitPoints(json.dumps(elem["source"]["issue"]["number"])) + +def commitData(commit): + link_commit = repo_link +"/commits/"+ commit; + req = urllib2.Request(link_commit) + req.add_header("Accept", "application/vnd.github.mockingbird-preview") + commit = json.load(urllib2.urlopen(req)) + print json.dumps(commit) + + +