Exemple #1
0
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'}))
Exemple #2
0
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
Exemple #3
0
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