Skip to content

Instantly share code, notes, and snippets.

@JiapengLi
Created August 18, 2021 04:31
Show Gist options
  • Select an option

  • Save JiapengLi/c55e03e4aa203d659aee1227cb42d289 to your computer and use it in GitHub Desktop.

Select an option

Save JiapengLi/c55e03e4aa203d659aee1227cb42d289 to your computer and use it in GitHub Desktop.
import os, sys
import datetime
import re
import json
import time
from math import radians, cos, sin, asin, sqrt, log10, pow, pi
from numpy import random
import concurrent
import requests
import sqlite3
import pandas as pd
import numpy as np
import simplekml
import h3
from simplekml.base import check
from .utils import *
from . import kmlstyle
import traceback
from collections import UserList
class HeliumApi:
def __init__(self, url, proxy = False):
self.url = url
self.proxy = proxy
self.s = requests.session()
self.cursors = []
self.data = []
self.data_len = 0
self.data_cnt = 0
def fullurl(self, path):
return f'{self.url}/{path}'
def request(self, path, para={}, new=True):
if new:
s = requests.session()
else:
s = self.s
url = self.fullurl(path)
res = None
#print(f"{url} {para} {new}")
try:
if para == {}:
res = s.get(url)
else:
res = s.get(url, params=para)
except Exception as e:
print(traceback.format_exc())
res = None
return res
def recursion(self, path, latest=0, para={}, cursor="", known_cursors=[]):
para_tmp = para.copy()
if cursor == None:
return self.data
else:
c = None
if cursor == "":
self.data = []
self.cursors = []
self.data_len = 0
self.data_cnt = 0
else:
para_tmp['cursor'] = cursor
self.cursors.append(cursor)
t0 = time.time()
cnt = 5
while cnt > 0:
self.data_cnt += 1
res = self.request(path, para_tmp)
if res and res.status_code == 200:
break
time.sleep(2)
cnt -= 1
if res:
print(f"error {res.status_code}")
if 'data' in res.json() and len(res.json()['data']) > 0:
self.data += res.json()['data']
dtlen = len(self.data)
if dtlen - self.data_len >= 1000:
print(f"{self.fullurl(path)}: {dtlen} downloaded")
self.data_len = dtlen
if 'cursor' in res.json() and len(res.json()['cursor']) > 0:
c = res.json()['cursor']
# if
if latest != 0 and len(self.data) >= latest:
c = None
# if cursor is a known one exit
if c and c in known_cursors:
c = None
print(f"{self.data_cnt}, {self.data_len} {time.time() - t0:.2f}")
return self.recursion(path, latest, para_tmp, c)
# https://api.helium.io/v1/hotspots
def hotspots(self, latest=0, hotspots=None):
if not hotspots:
# fetch all or `latest` number of hotspots
return self.recursion(f"hotspots", latest)
else:
self.data = [None] * len(hotspots)
params = zip([f'hotspots/{hotspot}' for hotspot in hotspots], [None] * len(hotspots), [True] * len(hotspots))
params = list(params)
print(params)
with concurrent.futures.ThreadPoolExecutor() as executor:
futures = {executor.submit(self.request, a, b, c): (a, b, c) for a, b, c in params}
for future in concurrent.futures.as_completed(futures):
self.data[params.index(futures[future])] = future.result().json()['data']
return self.data
#GET https://api.helium.io/v1/hotspots/:address
def hotspot(self, hotspot):
return self.request(f'hotspots/{hotspot}').json()
def hotspot_activity(self, hotspot, latest=0):
return self.recursion(f'hotspots/{hotspot}/activity', latest=latest)
def hotspot_name(self, name):
return self.request(f'hotspots/name/{name}').json()['data']
def hotspot_rewards_para(self, hotspot, min_time = None, max_time = None, date = None):
if min_time == None:
utc_time = datetime.datetime.now(tz=pytz.timezone('Asia/Shanghai'))
min_time = "2018-01-01T00:00:00Z"
max_time = utc_time.strftime('%Y-%m-%dT%H:%M:%SZ')
if date != None:
if date > 0:
date = 0 - date
utc_time = datetime.datetime.now(tz=pytz.timezone('Etc/GMT-8'))
today = datetime.datetime.strptime(utc_time.strftime('%Y-%m-%d'), '%Y-%m-%d')
today = today.replace(tzinfo=pytz.timezone('Etc/GMT-8')).astimezone(tz=pytz.timezone('UTC'))
if isinstance(date, int):
day_start = today + datetime.timedelta(hours=24*date)
day_end = day_start + datetime.timedelta(hours=24)
min_time = day_start.strftime('%Y-%m-%dT%H:%M:%SZ')
max_time = day_end.strftime('%Y-%m-%dT%H:%M:%SZ')
para = {'min_time': min_time, 'max_time': max_time}
return para
def hotspot_rewards(self, hotspot, min_time = None, max_time = None, date = None):
para = self.hotspot_rewards_para(hotspot, min_time, max_time, date)
res = self.request(f'hotspots/{hotspot}/rewards/sum', para)
if res:
#print(res.json())
return res.json()
else:
return {
'data': {
'total': 0
}
}
def hotspot_rewards_days(self, hotspot, dates=[]):
self.data = [None] * len(dates)
para = [self.hotspot_rewards_para(hotspot,date=date) for date in dates]
params = list(zip([f'hotspots/{hotspot}/rewards/sum'] * len(dates), para, [True] * len(dates)))
with concurrent.futures.ThreadPoolExecutor() as executor:
futures = {executor.submit(self.request, a, b, c): (a, b, c) for a, b, c in params}
for future in concurrent.futures.as_completed(futures):
self.data[params.index(futures[future])] = future.result().json()['data']
return self.data
def pending_transactions(self, hash):
res = self.request(f'pending_transactions/{hash}')
return res.json()['data']
def height(self):
res = self.request('blocks/height')
return res.json()['data']['height']
def vars_activity(self):
return self.recursion(f'vars/activity', latest=0)
def location_box(self, swlat, swlon, nelat, nelon):
para = {
'swlat': swlat,
'swlon': swlon,
'nelat': nelat,
'nelon': nelon,
}
return self.recursion(f"hotspots/location/box", para=para)
def accounts_activity(self, account):
return self.recursion(f'accounts/{account}/activity')
def accounts_hotspots(self, account, latest=0):
return self.recursion(f'accounts/{account}/hotspots', latest=latest)
def transactions(self, height):
return self.recursion(f'blocks/{height}/transactions')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment