Skip to content

Commit

Permalink
Add management command + claim button for managing round 8 payouts (#…
Browse files Browse the repository at this point in the history
…8139)

* Add management command for managing round 8 payouts

* WIP: Rough implementation of 'claim match' button

* Update contract address

* Fix amounts that are set

* Account for multiple grants with the same receiving address

* Update expected_total_dai_amount to be DB driven

* Use checksum address

* since grants can now be in multiple matching rounds, adjust their payouts so we only pay 1 round at a time

* kevins commits

* Finish claim button

Co-authored-by: owocki <[email protected]>
  • Loading branch information
mds1 and owocki authored Dec 22, 2020
1 parent d7346e6 commit 5edf8b0
Show file tree
Hide file tree
Showing 7 changed files with 505 additions and 3 deletions.
4 changes: 3 additions & 1 deletion app/app/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,9 @@ def preprocess(request):
'ptoken_factory_address': settings.PTOKEN_FACTORY_ADDRESS,
'ptoken_factory_abi': settings.PTOKEN_FACTORY_ABI,
'ptoken_address': ptoken.token_address if ptoken else '',
'ptoken_id': ptoken.id if ptoken else None
'ptoken_id': ptoken.id if ptoken else None,
'match_payouts_abi': settings.MATCH_PAYOUTS_ABI,
'match_payouts_address': settings.MATCH_PAYOUTS_ADDRESS,
}
context['json_context'] = json.dumps(context)
context['last_posts'] = cache.get_or_set('last_posts', fetchPost, 5000)
Expand Down
4 changes: 4 additions & 0 deletions app/app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -885,3 +885,7 @@ def callback(request):
# Idena
IDENA_TOKEN_EXPIRY = 60 * 60 # 1 Hours
IDENA_NONCE_EXPIRY = 60 * 2 # 2 Min

# Match Payouts contract
MATCH_PAYOUTS_ABI = '[ { "inputs": [ { "internalType": "address", "name": "_owner", "type": "address" }, { "internalType": "address", "name": "_funder", "type": "address" }, { "internalType": "contract IERC20", "name": "_dai", "type": "address" } ], "stateMutability": "nonpayable", "type": "constructor" }, { "anonymous": false, "inputs": [], "name": "Finalized", "type": "event" }, { "anonymous": false, "inputs": [], "name": "Funded", "type": "event" }, { "anonymous": false, "inputs": [], "name": "FundingWithdrawn", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "address", "name": "recipient", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "PayoutAdded", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "address", "name": "recipient", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } ], "name": "PayoutClaimed", "type": "event" }, { "inputs": [ { "internalType": "address", "name": "_recipient", "type": "address" } ], "name": "claimMatchPayout", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "dai", "outputs": [ { "internalType": "contract IERC20", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "enablePayouts", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "finalize", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "funder", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "", "type": "address" } ], "name": "payouts", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [ { "components": [ { "internalType": "address", "name": "recipient", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], "internalType": "struct MatchPayouts.PayoutFields[]", "name": "_payouts", "type": "tuple[]" } ], "name": "setPayouts", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "state", "outputs": [ { "internalType": "enum MatchPayouts.State", "name": "", "type": "uint8" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "withdrawFunding", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ]'
MATCH_PAYOUTS_ADDRESS = '0xf2354570bE2fB420832Fb7Ff6ff0AE0dF80CF2c6'
38 changes: 38 additions & 0 deletions app/assets/v2/js/grants/_detail-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,44 @@ Vue.mixin({
}
vm.submitted = false;
return true; // no errors, continue to create grant
},
claimMatch: async function(recipient) {
// Helper method to manage state
const waitingState = (state) => {
indicateMetamaskPopup(!state);
$('#claim-match').prop('disabled', state);
};

// Connect wallet
if (!provider) {
await onConnect();
}

// Confirm wallet was connected (user may have closed wallet connection prompt)
if (!provider) {
return;
}
waitingState(true);
const user = (await web3.eth.getAccounts())[0];

// Get contract instance
const matchPayouts = await new web3.eth.Contract(
JSON.parse(document.contxt.match_payouts_abi),
document.contxt.match_payouts_address
);

// Claim payout
matchPayouts.methods.claimMatchPayout(recipient)
.send({from: user})
.on('transactionHash', async function(txHash) {
waitingState(false);
$('#match-payout-section').hide();
_alert("Match payout claimed! Funds will be sent to this grant's address", 'success');
})
.on('error', function (error) {
waitingState(false);
_alert(error, 'error');
});
}
},
computed: {
Expand Down
10 changes: 8 additions & 2 deletions app/grants/management/commands/payout_round.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,13 @@ def handle(self, *args, **options):

# finalize rankings
if what == 'finalize':
total_owed_grants = sum(grant.clr_match_estimate_this_round for grant in grants)
total_owed_grants = 0
for grant in grants:
try:
for gclr in grant.clr_calculations.filter(grantclr__in=gclrs, latest=True):
total_owed_grants += gclr.clr_prediction_curve[0][1]
except:
pass
total_owed_matches = sum(sm.amount for sm in scheduled_matches)
print(f"there are {grants.count()} grants to finalize worth ${round(total_owed_grants,2)}")
print(f"there are {scheduled_matches.count()} Match Payments already created worth ${round(total_owed_matches,2)}")
Expand All @@ -97,7 +103,7 @@ def handle(self, *args, **options):
if user_input != 'y':
return
for grant in grants:
amount = grant.clr_match_estimate_this_round
amount = sum(ele.clr_prediction_curve[0][1] for ele in grant.clr_calculations.filter(grantclr__in=gclrs, latest=True))
has_already_kyc = grant.clr_matches.filter(has_passed_kyc=True).exists()
if not amount:
continue
Expand Down
Loading

0 comments on commit 5edf8b0

Please sign in to comment.