· 4 years ago · Jun 01, 2021, 02:16 AM
1import requests
2import math
3import functools
4import datetime
5import time
6import os
7import numpy as np
8
9
10MINA_GRAPHQL_API = "https://graphql.minaexplorer.com/"
11SNARKS_RETURNED_LIMIT = 10000
12SNARKS_REFRESH_INTERVAL = 1800
13SNARKS_TIMEDELTA= 1800
14
15
16def percentile(N, percent, key=lambda x: x):
17 """
18 Find the percentile of a list of values.
19
20 @parameter N - is a list of values. Note N MUST BE already sorted.
21 @parameter percent - a float value from 0.0 to 1.0.
22 @parameter key - optional key function to compute value from each element of N.
23
24 @return - the percentile of the values
25 """
26 if not N:
27 return None
28 k = (len(N) - 1) * percent
29 f = math.floor(k)
30 c = math.ceil(k)
31 if f == c:
32 return key(N[int(k)])
33 d0 = key(N[int(f)]) * (c - k)
34 d1 = key(N[int(c)]) * (k - f)
35 return d0 + d1
36
37
38def get_latest_snark_price(interval=3600):
39 """
40 Call the Mina Protocol graphql API to find the latest price for snarks
41
42 @parameter interval - a integer representing seconds of interval
43
44 @return - a list of latest price for snarks during the interval
45 """
46 upper_bound = datetime.datetime.now()
47 lower_bound = upper_bound - datetime.timedelta(seconds=interval)
48 query = """
49 {{
50 snarks(
51 limit: {}
52 sortBy: FEE_DESC
53 query: {{
54 AND: [
55 {{ dateTime_gte: \"{}\" }}
56 {{ dateTime_lte: \"{}\" }}
57 ]
58 }}
59 ) {{
60 prover
61 fee
62 }}
63 }}
64 """
65
66 lower_fmt = lower_bound.isoformat("T") + "Z"
67 upper_fmt = upper_bound.isoformat("T") + "Z"
68
69 query = query.format(SNARKS_RETURNED_LIMIT, lower_fmt, upper_fmt)
70 response = requests.post(MINA_GRAPHQL_API, json={"query": query})
71
72 if response.status_code != 200:
73 Exception("Could not load the latest snarks from api")
74
75 return response.json()
76
77def set_snarking_fee(target_fee):
78 command = f"mina client set-snark-work-fee {target_fee}"
79 os.system(command)
80
81
82import statistics
83
84p01 = functools.partial(percentile, percent=0.10)
85
86while 1:
87 try:
88 snarks = get_latest_snark_price(interval=SNARKS_TIMEDELTA)['data']['snarks']
89 snarks_fees = np.array(list(map(lambda snark: int(snark['fee']), snarks)))
90 snarks_target_fee = 0
91
92 if len(snarks_fees) > 0:
93 snarks_fees.sort()
94 #print(snarks_fees)
95 #snarks_target_fee = np.percentile(snarks_fees, 0.05)
96 #snarks_target_fee = np.mean(snarks_fees)
97 snarks_count_hist, snarks_fees_hist = np.histogram(snarks_fees)
98 smi = np.argmax(snarks_count_hist)
99 fees_range = snarks_fees_hist[[smi, smi+1]]
100
101 print(f"Min fee range: {fees_range[0]}")
102 print(f"Max fee range: {fees_range[1]}")
103
104 snarks_target_fee = np.quantile(fees_range, 0.1)
105
106 set_snarking_fee(snarks_target_fee)
107 print("-----------------------------------")
108 except Exception as e:
109 print(f" {e} error when fetching, retrying in {SNARKS_REFRESH_INTERVAL} seconds")
110 time.sleep(SNARKS_REFRESH_INTERVAL)
111