Coverage for src / api / hive.py: 0%

102 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-01 10:28 +0000

1import logging 

2from time import sleep 

3 

4from beem import Hive 

5from beem.account import Account 

6from dateutil.parser import isoparse 

7from hiveengine.api import Api 

8 

9from src.api import spl, hive_node 

10from src.utils import progress_util 

11 

12HIVE_BLOG_URL = 'https://api.hive.blog' 

13 

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/'] 

28 

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] 

45 

46 

47def get_liquidity_positions(account, token_pair): 

48 query = {"account": account, "tokenPair": token_pair} 

49 result = find_one_with_retry('marketpools', 'liquidityPositions', query) 

50 

51 if len(result) > 0 and result[0]: 

52 return float(result[0]['shares']) 

53 else: 

54 # no liquidity pool found 

55 return None 

56 

57 

58def get_quantity(token_pair): 

59 query = {"tokenPair": token_pair} 

60 result = find_one_with_retry('marketpools', 'pools', query) 

61 

62 return float(result[0]['baseQuantity']), \ 

63 float(result[0]['quoteQuantity']), \ 

64 float(result[0]['totalShares']) 

65 

66 

67def find_one_with_retry(contract_name, table_name, query): 

68 result = None 

69 success = False 

70 iterations = 3 

71 

72 # Might consider special handling when a RPCErrorDoRetry is raised 

73 

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) 

95 

96 if success: 

97 break 

98 

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 

106 

107 

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 

114 

115 

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'] 

124 

125 if results is None: 

126 results = [] 

127 

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']) 

133 

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)) 

137 

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 

151 

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 

160 

161 

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) 

174 

175 if success: 

176 logging.info("get_account_history success continue....") 

177 return return_list 

178 

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 

187 

188 

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)