def do_snapshot(dat): if 'form' not in dat: return False if dat['form']['asset_id'] is None: Redisdb.rpush("messages", " Missing distribution asset") return False if dat['form']['assethold_id'] is None: Redisdb.rpush("messages", " Missing holding asset") return False asset_id = dat['form']['assethold_id'] Redisdb.delete("balance:" + asset_id) Redisdb.delete("distribute:" + asset_id) Redisdb.set("total_balance:" + asset_id, 0) Redisdb.set("total_owners:" + asset_id, 0) if asset_id is None or Redisdb.get("snapshot_started") is not None: return False snap_info = {} snap_info['total_balance'] = 0 snap_info['total_owners'] = 0 snap_info['asset_hold_id'] = asset_id snap_info['asset_distribute_id'] = dat['form']['asset_id'] snap_info['asset_hold'] = Bitshares.rpc.get_assets([asset_id])[0] snap_info['asset_hold_minimum'] = float(dat['form']['hold_minimum']) snap_info['asset_distribute'] = Bitshares.rpc.get_assets( [dat['form']['asset_id']])[0] snap_info['distribution_amount'] = int(dat['form']['amount']) snap_info['distribution_ratio'] = float(dat['form']['ratio']) snap_info['distribution_minimum'] = float(dat['form']['minimum']) snap_info['transfer_fee'] = float(dat['form']['transfer_fee']) # query fees fees = Bitshares.rpc.get_global_properties()['parameters']['current_fees'] Redisdb.set("snapshot_info", pickle.dumps(snap_info)) Redisdb.rpush("messages", "*|snapshot_start") obtain_balances(asset_id) Redisdb.rpush("operations", pickle.dumps({'operation': 'snapshot_end'}))
def distribution_setup(): """ Makes a preview of the distribution :return: """ snap_info = pickle.loads(Redisdb.get("snapshot_info")) holders = Redisdb.hgetall("balance:" + snap_info['asset_hold_id']) lst = [] cnt = 0 balance = 0 for h in holders: hdata = pickle.loads(holders[h]) lst.append([hdata['account'], hdata['datetime'], hdata['amount'], 0]) balance += hdata['amount'] cnt += 1 if cnt % 1000 == 0: Redisdb.rpush( "messages", datetime.datetime.now().isoformat() + " CSV list " + str(cnt)) # refresh snapshot info snap_info['total_balance'] = balance snap_info['total_owners'] = int( Redisdb.get("total_owners:" + snap_info['asset_hold_id'])) Redisdb.set("snapshot_info", pickle.dumps(snap_info)) msg = "|".join([datetime.datetime.now().isoformat(), str(int(snap_info['total_balance'])), \ str(int(snap_info['total_owners'])), str(int(snap_info['total_owners']*snap_info['transfer_fee']))]) Redisdb.rpush("messages", "*|snapshot_end|" + msg) # The list is sorted from more to less holding Redisdb.rpush("messages", datetime.datetime.now().isoformat() + " CSV list sorting") lst.sort(key=lambda x: x[2], reverse=True) Redisdb.rpush("messages", datetime.datetime.now().isoformat() + " CSV list sorting OK") # calculus of the distribution tmplt_distr = "{0:." + str( snap_info['asset_distribute']['precision']) + "f}" tmplt_hold = "{0:." + str(snap_info['asset_hold']['precision']) + "f}" total_distr_amount = 0 for l in enumerate(lst): if snap_info['distribution_amount'] > 0: amount = round( l[1][2] / balance * snap_info['distribution_amount'], snap_info['asset_distribute']['precision']) elif snap_info['distribution_ratio'] > 0: amount = round(l[1][2] * snap_info['distribution_ratio'], snap_info['asset_distribute']['precision']) if amount < snap_info['distribution_minimum']: # truncate the list lst = lst[:l[0]] break total_distr_amount += amount lst[l[0]][3] = tmplt_distr.format(amount) lst[l[0]][2] = tmplt_hold.format(l[1][2]) # feed the distribution container for l in lst: Redisdb.hset("distribute:" + snap_info['asset_hold_id'], l[0], l[3]) if snap_info['distribution_amount'] > 0: rest = snap_info['distribution_amount'] - total_distr_amount else: rest = 0 # TODO: what to do with the rest? return lst
def obtain_balances(asset_id): snap_datetime = datetime.datetime.now().isoformat() info = pickle.loads(Redisdb.get("snapshot_info")) n_from = 0 n_call = 0 total_balance = 0 batch_balance = 0 total_holders = 0 while True: data = { "jsonrpc": "2.0", "params": [ "asset", "get_asset_holders", [info['asset_hold_id'], n_from, 100] ], "method": "call", "id": n_call } try: rtn = requests.post('http://209.188.21.157:8090/rpc', data=json.dumps(data)) if rtn.status_code != 200: return False rst = rtn.json()['result'] except Exception as err: print(err.__repr__()) print() return False bal = [] to_exit = False for r in rst: amount = round( int(r['amount']) / 10**info['asset_hold']['precision'], info['asset_hold']['precision']) if amount < info['asset_hold_minimum']: to_exit = True break else: total_balance += amount batch_balance += amount total_holders += 1 Redisdb.hset( "balance:" + info['asset_hold_id'], r['account_id'], pickle.dumps({ 'account': r['account_id'], 'datetime': snap_datetime, 'amount': amount })) if len(rst) < 100 or to_exit: Redisdb.rpush( "messages", datetime.datetime.now().isoformat() + " Total count:" + str(total_holders)) Redisdb.set("total_balance:" + info['asset_hold_id'], total_balance) Redisdb.set("total_owners:" + info['asset_hold_id'], total_holders) break if total_holders % 1000 == 0: Redisdb.rpush( "messages", datetime.datetime.now().isoformat() + " Holders: {} Balance: {} Median: {}".format( total_holders, total_balance, round( batch_balance / 1000, 2))) batch_balance = 0 n_from += 100 n_call += 1 print(n_call) return True