Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow disabling checkout via admin #9870

Merged
merged 5 commits into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/assets/v2/js/cart-ethereum-polygon.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ Vue.component('grantsCartEthereumPolygon', {
const tokenIsMatic = tokenDetails && tokenDetails.name === 'MATIC';

// Check user matic balance against required amount
if (userMaticBalance.toNumber() && userMaticBalance.lt(requiredAmounts[tokenSymbol].amount) && tokenIsMatic) {
if (userMaticBalance.toString() !== '0' && userMaticBalance.lt(requiredAmounts[tokenSymbol].amount) && tokenIsMatic) {
requiredAmounts[tokenSymbol].isBalanceSufficient = false;
requiredAmounts[tokenSymbol].amount = parseFloat(((
requiredAmounts[tokenSymbol].amount - userMaticBalance
Expand Down Expand Up @@ -511,7 +511,7 @@ Vue.component('grantsCartEthereumPolygon', {
.balanceOf(userAddress)
.call({ from: userAddress }));

if (userTokenBalance.toNumber() && userTokenBalance.lt(requiredAmounts[tokenSymbol].amount)) {
if (userTokenBalance.toString() !== '0' && userTokenBalance.lt(requiredAmounts[tokenSymbol].amount)) {
requiredAmounts[tokenSymbol].isBalanceSufficient = false;
requiredAmounts[tokenSymbol].amount = parseFloat(((
requiredAmounts[tokenSymbol].amount - userTokenBalance
Expand Down
4 changes: 2 additions & 2 deletions app/assets/v2/js/cart.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ Vue.component('grants-cart', {
zkSyncEstimatedGasCost: undefined, // Used to tell user which checkout method is cheaper
polygonSupportedTokens: [], // Used to inform user which tokens in their cart are on Polygon
polygonEstimatedGasCost: undefined, // Used to tell user which checkout method is cheaper
isZkSyncDown: false, // disable zkSync when true
isPolygonDown: false, // disable polygon when true
isZkSyncDown: document.disableZksync, // disable zkSync when true
isPolygonDown: document.disablePolygon, // disable polygon when true
isPolkadotExtInstalled: false,
chainScripts: {
'POLKADOT': [
Expand Down
4 changes: 3 additions & 1 deletion app/grants/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ class GrantCLRCalculationAdmin(admin.ModelAdmin):
'grant','grantclr','clr_prediction_curve'
]
search_fields = [
'grantclr'
'grant__title',
'grantclr__round_num',
'grantclr__pk'
]

class CLRMatchAdmin(admin.ModelAdmin):
Expand Down
72 changes: 57 additions & 15 deletions app/grants/clr.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def get_totals_by_pair(contrib_dict):
return pair_totals


def calculate_clr(curr_agg, trust_dict, pair_totals, v_threshold, total_pot, match_cap_per_grant):
def calculate_clr(curr_agg, trust_dict, pair_totals, v_threshold, total_pot):
'''
calculates the clr amount at the given threshold and total pot
args:
Expand Down Expand Up @@ -245,17 +245,13 @@ def calculate_clr(curr_agg, trust_dict, pair_totals, v_threshold, total_pot, mat
if type(tot) == complex:
tot = float(tot.real)

# ensure CLR match for a grant in CLR round does not exceed 2.5 of the total pot
if total_pot != match_cap_per_grant and tot > match_cap_per_grant:
tot = match_cap_per_grant

bigtot += tot
totals[proj] = {'number_contributions': _num, 'contribution_amount': _sum, 'clr_amount': tot}
totals[proj] = {'id': proj, 'number_contributions': _num, 'contribution_amount': _sum, 'clr_amount': tot}

return bigtot, totals


def calculate_clr_for_prediction(bigtot, totals, curr_agg, trust_dict, v_threshold, total_pot, grant_id, amount):
def calculate_clr_for_prediction(bigtot, totals, curr_agg, trust_dict, v_threshold, total_pot, grant_id, amount, match_cap_per_grant):
'''
clubbed function that runs all calculation functions and returns the result for a single grant_id

Expand Down Expand Up @@ -319,10 +315,10 @@ def calculate_clr_for_prediction(bigtot, totals, curr_agg, trust_dict, v_thresho
if type(tot) == complex:
tot = float(tot.real)

totals[grant_id] = {'number_contributions': _num, 'contribution_amount': _sum, 'clr_amount': tot}
totals[grant_id] = {'id': grant_id, 'number_contributions': _num, 'contribution_amount': _sum, 'clr_amount': tot}

# normalise the result
grants_clr = normalise(bigtot + tot, totals, total_pot)
grants_clr = normalise(bigtot + tot, totals, total_pot, match_cap_per_grant)

# find grant we added the contribution to and get the new clr amount
grant_clr = grants_clr.get(grant_id)
Expand All @@ -339,7 +335,7 @@ def calculate_clr_for_prediction(bigtot, totals, curr_agg, trust_dict, v_thresho
return (grants_clr, 0.0, 0, 0.0)


def normalise(bigtot, totals, total_pot):
def normalise(bigtot, totals, total_pot, match_cap_per_grant):
'''
given the total amount distributed (bigtot) and the total_pot size normalise the distribution
args:
Expand All @@ -351,8 +347,10 @@ def normalise(bigtot, totals, total_pot):
[{'id': proj, 'number_contributions': _num, 'contribution_amount': _sum, 'clr_amount': tot}]

'''
# check if saturation is reached
is_saturated = bigtot >= total_pot
# check for saturation and normalise if reached
if bigtot >= total_pot:
if is_saturated:
# print(f'saturation reached. Total Pot: ${total_pot} | Total Allocated ${bigtot}. Normalizing')
for key, t in totals.items():
t['clr_amount'] = ((t['clr_amount'] / bigtot) * total_pot)
Expand All @@ -363,6 +361,48 @@ def normalise(bigtot, totals, total_pot):
for key, t in totals.items():
t['clr_amount'] = t['clr_amount'] * (1 + percentage_increase)

# apply the match cap post-normalisation
totals = apply_cap(totals, match_cap_per_grant, is_saturated)

return totals


def apply_cap(totals, match_cap_per_grant, should_spread):
# work out how much of the pool is remaining after capping each grant
remainder = 0 # amount left to be redistributed after cap
uncapped = 0 # total amount matched for grants which haven't capped

# cap each of the clr_amounts
for key, t in totals.items():
if t['clr_amount'] >= match_cap_per_grant:
# grant has exceeded the cap
# - so cap the clr_amount
# - add the extra funds to remainder
remainder += t['clr_amount'] - match_cap_per_grant
t['clr_amount'] = match_cap_per_grant

else:
# grant has not exceed cap so add amount to uncapped
uncapped += t['clr_amount']

# check that we have both capped and uncapped grants and that we should be spreading the remainder
if should_spread and remainder > 0 and uncapped > 0:
# div so we can spread the remainder proportionally
per_remainder = remainder / uncapped
# reset remainder to check if any grants enter the cap region after spreading the remainder
remainder = 0
# spread the remainder
for key, t in totals.items():
if t['clr_amount'] < match_cap_per_grant:
t['clr_amount'] += per_remainder * t['clr_amount']
# check if the cap is hit after spreading the remainder
if t['clr_amount'] >= match_cap_per_grant:
remainder += t['clr_amount'] - match_cap_per_grant

# apply the cap again (recursively)
if remainder > 0:
apply_cap(totals, match_cap_per_grant, should_spread)

return totals


Expand Down Expand Up @@ -404,11 +444,13 @@ def predict_clr(save_to_db=False, from_date=None, clr_round=None, network='mainn
pair_totals = get_totals_by_pair(curr_agg)

grant_clr_percentage_cap = clr_round.grant_clr_percentage_cap if clr_round.grant_clr_percentage_cap else 100
bigtot, totals = calculate_clr(curr_agg, trust_dict, pair_totals, v_threshold, total_pot)

# $ value of the percentage cap
match_cap_per_grant = total_pot * (float(grant_clr_percentage_cap) / 100)
bigtot, totals = calculate_clr(curr_agg, trust_dict, pair_totals, v_threshold, total_pot, match_cap_per_grant)

# normalise against a deepcopy of the totals to avoid mutations
curr_grants_clr = normalise(bigtot, copy.deepcopy(totals), total_pot)
curr_grants_clr = normalise(bigtot, copy.deepcopy(totals), total_pot, match_cap_per_grant)

# for slim calc - only update the current distribution and skip calculating predictions
if what == 'slim':
Expand Down Expand Up @@ -474,7 +516,7 @@ def predict_clr(save_to_db=False, from_date=None, clr_round=None, network='mainn
else:
# calculate clr with additional donation amount
grants_clr, predicted_clr, _, _ = calculate_clr_for_prediction(
bigtot, totals, curr_agg, trust_dict, v_threshold, total_pot, grant.id, amount
bigtot, totals, curr_agg, trust_dict, v_threshold, total_pot, grant.id, amount, match_cap_per_grant
)

# record each point of the prediction
Expand All @@ -501,7 +543,7 @@ def predict_clr(save_to_db=False, from_date=None, clr_round=None, network='mainn
if from_date > (clr_calc_start_time - timezone.timedelta(hours=1)):
grant.save()

debug_output.append({'grant': grant.id, "clr_prediction_curve": (potential_donations, potential_clr), "grants_clr": grants_clr})
debug_output.append({'grant': grant.id, "title": grant.title, "clr_prediction_curve": (potential_donations, potential_clr), "grants_clr": grants_clr})

print(f"\nTotal execution time: {(timezone.now() - clr_calc_start_time)}\n")

Expand Down
6 changes: 4 additions & 2 deletions app/grants/management/commands/estimate_clr.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def add_arguments(self, parser):
parser.add_argument('what', type=str, default="full")
parser.add_argument('sync', type=str, default="false")
parser.add_argument('--use-sql', type=bool, default=False)
parser.add_argument('--skip-save', type=bool, default=False)
# slim = just run 0 contribution match upcate calcs
# full, run [0, 1, 10, 100, calcs across all grants]

Expand All @@ -48,6 +49,7 @@ def handle(self, *args, **options):
what = options['what']
sync = options['sync']
use_sql = options['use_sql']
skip_save = options['skip_save']
print (network, clr_pk, what, sync, use_sql)

if clr_pk and clr_pk.isdigit():
Expand All @@ -60,7 +62,7 @@ def handle(self, *args, **options):
if sync == 'true':
# run it sync -> useful for payout / debugging
predict_clr(
save_to_db=True,
save_to_db=True if not skip_save else False,
from_date=timezone.now(),
clr_round=clr_round,
network=network,
Expand All @@ -70,7 +72,7 @@ def handle(self, *args, **options):
else:
# runs it as celery task.
process_predict_clr(
save_to_db=True,
save_to_db=True if not skip_save else False,
from_date=timezone.now(),
clr_round=clr_round,
network=network,
Expand Down
5 changes: 5 additions & 0 deletions app/grants/templates/grants/cart-vue.html
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@ <h4 class="font-weight-bold mb-5 my-md-0">Discover Grants</h4>
document.authenticated = {{ authenticated | yesno:"true,false" }};
document.isFullyVerified = '{{is_fully_verified}}' === 'True';
document.polygonGasPrice = "{{ gas_prices|get_item:'polygon' }}"

// Checkout Status
document.disableZksync = '{{ disableZksync }}' === 'true';
document.disablePolygon = '{{ disablePolygon }}' === 'true';

</script>
{% bundle merge_js file qrcode %}
<script src="qrcode.min.js" base-dir="/node_modules/qrcodejs/"></script>
Expand Down
12 changes: 12 additions & 0 deletions app/grants/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2417,10 +2417,22 @@ def get_replaced_tx(request):


def grants_cart_view(request):

try:
checkout_status = StaticJsonEnv.objects.get(key='L2_CHECKOUT_STATUS').data
disableZksync = checkout_status['disableZksync']
disablePolygon = checkout_status['disablePolygon']
except:
disableZksync = 'false'
disablePolygon = 'false'

context = {
'title': 'Grants Cart',
'EMAIL_ACCOUNT_VALIDATION': EMAIL_ACCOUNT_VALIDATION,
'disableZksync': disableZksync,
'disablePolygon': disablePolygon
}

if request.user.is_authenticated:
profile = request.user.profile
context['username'] = profile.username
Expand Down
4 changes: 3 additions & 1 deletion app/quests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,10 @@ class QuestAttempt(SuperModel):
state = models.IntegerField(default=0)

def __str__(self):
handle = self.profile.handle if self.profile else 'deleted profile'
title = self.quest.title if self.quest else 'deleted quest'
"""Return the string representation of this obj."""
return f'{self.pk}, {self.profile.handle} => {self.quest.title} state: {self.state} success: {self.success}'
return f'{self.pk}, {handle} => {title} state: {self.state} success: {self.success}'


class QuestFeedback(SuperModel):
Expand Down