Coverage for src/api/hive.py: 0%
102 statements
« prev ^ index » next coverage.py v7.8.2, created at 2025-06-03 19:06 +0000
« prev ^ index » next coverage.py v7.8.2, created at 2025-06-03 19:06 +0000
1import logging
2from time import sleep
4from beem import Hive
5from beem.account import Account
6from dateutil.parser import isoparse
7from hiveengine.api import Api
9from src.api import spl, hive_node
10from src.utils import progress_util
12HIVE_BLOG_URL = 'https://api.hive.blog'
14# hive-engine nodes see https://beacon.peakd.com/
15hive_engine_nodes = [
16 'https://api2.hive-engine.com/rpc/',
17 'https://api.hive-engine.com/rpc/',
18 # 'https://engine.rishipanthee.com/', # is preferred
19 'https://herpc.dtools.dev/',
20 'https://engine.deathwing.me/',
21 'https://ha.herpc.dtools.dev/',
22 'https://api.primersion.com/',
23 'https://herpc.kanibot.com/',
24 'https://he.sourov.dev/',
25 'https://herpc.actifit.io/',
26 'https://ctpmain.com/',
27 'https://he.ausbit.dev/']
29# hive nodes see https://beacon.peakd.com/
30hive_nodes = [
31 'https://api.deathwing.me',
32 'https://api.hive.blog',
33 'https://hive-api.arcange.eu',
34 'https://api.openhive.network'
35 # 'https://api.c0ff33a.uk',
36 # 'https://rpc.ausbit.dev',
37 # 'https://hived.emre.sh',
38 # 'https://api.openhive.network',
39 # 'https://anyx.io',
40 # 'https://techcoderx.com',
41 # 'https://hive-api.arcange.eu',
42 # 'https://hived.privex.io',
43 # 'https://hive.roelandp.nl'
44]
47def get_liquidity_positions(account, token_pair):
48 query = {"account": account, "tokenPair": token_pair}
49 result = find_one_with_retry('marketpools', 'liquidityPositions', query)
51 if len(result) > 0 and result[0]:
52 return float(result[0]['shares'])
53 else:
54 # no liquidity pool found
55 return None
58def get_quantity(token_pair):
59 query = {"tokenPair": token_pair}
60 result = find_one_with_retry('marketpools', 'pools', query)
62 return float(result[0]['baseQuantity']), \
63 float(result[0]['quoteQuantity']), \
64 float(result[0]['totalShares'])
67def find_one_with_retry(contract_name, table_name, query):
68 result = None
69 success = False
70 iterations = 3
72 # Might consider special handling when a RPCErrorDoRetry is raised
74 # First try with preferred node.
75 try:
76 api = Api(url=hive_node.PREFERRED_NODE)
77 result = api.find_one(contract_name=contract_name, table_name=table_name, query=query)
78 success = True
79 except Exception as e:
80 logging.warning('find_one_with_retry (' + type(e).__name__ + ') preferred node: ' + hive_node.PREFERRED_NODE +
81 '. Continue try on other nodes')
82 for iter_ in range(iterations):
83 for node in hive_engine_nodes:
84 # noinspection PyBroadException
85 try:
86 api = Api(url=node)
87 result = api.find_one(contract_name=contract_name, table_name=table_name, query=query)
88 success = True
89 hive_node.PREFERRED_NODE = node
90 break
91 except Exception as e:
92 logging.warning('find_one_with_retry (' + type(e).__name__ + ') on node: ' + str(
93 node) + '. Continue retry on next node')
94 sleep(1)
96 if success:
97 break
99 if not success:
100 raise Exception('find_one_with_retry failed 5 times over all nodes'
101 ' contract:' + str(contract_name) +
102 ' table_name:' + str(table_name) +
103 ' query:' + str(query) +
104 ' stop update .....')
105 return result
108def get_market_with_retry(token):
109 market = find_one_with_retry('market', 'metrics', {'symbol': token})
110 if market:
111 return market[0]
112 else:
113 return None
116def get_spl_transactions(account_name,
117 from_date,
118 till_date,
119 last_id=-1,
120 filter_spl_transactions=None,
121 results=None):
122 if filter_spl_transactions is None:
123 filter_spl_transactions = ['sm_purchase', 'sm_market_purchase', 'sm_sell_cards', 'sm_claim_reward']
125 if results is None:
126 results = []
128 history = get_account_history_with_retry(account_name, last_id)
129 if history:
130 done = False
131 for h in history:
132 timestamp = isoparse(h['timestamp'])
134 days_to_go = (timestamp - from_date).days
135 progress_util.update_season_msg('...retrieve hive transaction for \'' + str(account_name) +
136 '\' - days to go: ' + str(days_to_go))
138 last_id = h['index']
139 operation = h['id']
140 if from_date < timestamp:
141 if operation in filter_spl_transactions:
142 if till_date > timestamp:
143 results.append({'trx_info': spl.get_transaction(h['trx_id'])['trx_info'],
144 'operation': h['id'],
145 'timestamp': timestamp})
146 else:
147 logging.info('Skip.. after till date...')
148 else:
149 done = True
150 break
152 if not done:
153 get_spl_transactions(account_name,
154 from_date,
155 till_date,
156 last_id=last_id - 1,
157 filter_spl_transactions=filter_spl_transactions,
158 results=results)
159 return results
162def get_account_history_with_retry(account_name, last_id):
163 limit = 100
164 retries = 0
165 while retries < len(hive_nodes):
166 try:
167 account = get_hive_account(account_name, retries)
168 history = account.get_account_history(last_id, limit, only_ops=['custom_json'])
169 success = False
170 return_list = []
171 for h in history:
172 success = True
173 return_list.append(h)
175 if success:
176 logging.info("get_account_history success continue....")
177 return return_list
179 logging.warning("Retrying with a different hive node...")
180 retries += 1
181 except Exception as e:
182 logging.warning(f"Error occurred: {e}")
183 logging.warning("Retrying with a different hive node...")
184 retries += 1
185 logging.error("Max retries reached. Unable to fetch account history.")
186 return None
189def get_hive_account(account_name, retry=0):
190 # Now you can use the initialized Hive instance to get account history
191 hive = Hive(node=hive_nodes[retry])
192 return Account(account_name, hive_instance=hive)