예제 #1
0
def do_batch(dat):
    """
	Make a batch of transfers
	:param dat:
	:return:
	"""
    import config
    snap_info = pickle.loads(Redisdb.get("snapshot_info"))
    # TODO: obtener la cuenta a partir de la clave pública
    # TODO: obtener balance de la moneda a repartir y de la moneda del fee
    #
    try:
        Bitshares = config.BitShares(node=config.WSS_NODE, wif=dat['key'])
    except Exception as err:
        print(err.__repr__())
        Redisdb.rpush("messages", "*|launch_error|key not found")
        print(0)
        return False

    for job in dat['job']:
        try:
            test = Bitshares.transfer(job[0].decode('utf8'), float(job[1]),
                                      dat['asset'], "", "1.2.4411")
        except Exception as err:
            print(err.__repr__())
            print(0)

    Redisdb.decr("batch_jobs", int(1))
    Redisdb.rpush(
        "messages",
        datetime.datetime.now().isoformat() +
        " Jobs queue: {}".format(int(Redisdb.get("batch_jobs"))))
예제 #2
0
def do_batch(dat):
    """
	Make a batch of transfers
	:param dat:
	:return:
	"""
    import config
    snap_info = pickle.loads(Redisdb.get("snapshot_info"))
    try:
        Bitshares = config.BitShares(node=config.WSS_NODE,
                                     wif=dat['form']['key'])
        oaccount = Bitshares.wallet.getAccounts()[0]
    except Exception as err:
        print(err.__repr__())
        Redisdb.rpush("messages", "*|launch_error|key not found")
        print(0)
        return False

    for job in dat['job']:
        try:
            wif = dat['key']
            pub = format(account.PrivateKey(wif).pubkey, config.PREFIX)
            to_account_id = job[0].decode('utf8')
            amount = 10
            asset_id = dat['asset']['id']
            message = "abcdefgABCDEFG0123456789"
            nonce = "5862723643998573708"

            fee = objects.Asset(amount=0, asset_id="1.3.0")
            amount = objects.Asset(amount=int(amount), asset_id=asset_id)
            encrypted_memo = memo.encode_memo(
                account.PrivateKey(wif),
                account.PublicKey(pub, prefix=config.PREFIX), nonce, message)
            memoStruct = {
                "from": pub,
                "to": pub,
                "nonce": nonce,
                "message": encrypted_memo,
            }
            memoObj = objects.Memo(**memoStruct)
            tmp = operations.Transfer(
                **{
                    "fee": fee,
                    "from": dat['from'],
                    "to": to_account_id,
                    "amount": amount,
                    "memo": memoObj,
                    "prefix": config.PREFIX
                })
            print()
            #test = Bitshares.transfer(job[0].decode('utf8'), float(job[1]), dat['asset'], "", dat['from'])
        except Exception as err:
            print(err.__repr__())
            print(0)

    Redisdb.decr("batch_jobs", int(1))
    Redisdb.rpush(
        "messages",
        datetime.datetime.now().isoformat() +
        " Jobs queue: {}".format(int(Redisdb.get("batch_jobs"))))
예제 #3
0
def snapshot_end():
    # persist db to disk
    Redisdb.rpush("operations", pickle.dumps({'operation': 'db_save'}))

    Redisdb.rpush("messages",
                  datetime.datetime.now().isoformat() + " Snapshot end")
    Redisdb.rpush("messages", "--------------")
    Redisdb.rpush("operations", pickle.dumps({'operation': 'csv_generation'}))
예제 #4
0
def getinfo(args, tag, path, query_string):
    """
	http://127.0.0.1:8099/get/froga?sadf=324&asd=34
	args = {'asd': ['34'], 'sadf': ['324']} froga
	:param req: 
	:param tag: 
	:return: 
	"""
    rtn = {'data': None}
    #print("getinfo:", args, tag, path, query_string)
    if tag == 'getaccount':
        if 'account' in args:
            rtn['data'] = get_account(args['account'][0])
    elif tag == 'getasset':
        if 'asset' in args:
            rtn['data'] = get_asset(args['asset'][0])
    elif tag == 'getmessage':
        msg_arr = []
        while True:
            msg = Redisdb.lpop("messages")
            if msg is None:
                break
            msg_arr.append(msg.decode('utf8'))
            if len(msg_arr) > 100:
                break
        if len(msg_arr) > 0:
            rtn['data'] = msg_arr
    rtn['request'] = path + "?" + query_string
    return rtn
예제 #5
0
def csv_gen():
    """
	Generate CSV files for download
	TOP 100 holders
	TAIL 100 holders
	:return:
	"""

    import csv
    from distribution import distribution_setup

    Redisdb.rpush(
        "messages",
        datetime.datetime.now().isoformat() + " CSV generate list...")

    lst = distribution_setup()

    # top 1000 to csv
    lst = lst[:1000]

    snap_info = pickle.loads(Redisdb.get("snapshot_info"))

    # write to file
    fname = 'distribution_{}_{}.csv'.format(
        snap_info['asset_hold_id'],
        datetime.datetime.now().isoformat())
    with open('./web/tmp/' + fname, 'w', newline='') as fcsv:
        cw = csv.writer(fcsv,
                        delimiter=';',
                        quotechar='"',
                        quoting=csv.QUOTE_NONNUMERIC)
        cw.writerow([
            "Account", "Date",
            "Amount of " + snap_info['asset_hold']['symbol'],
            "Will take of " + snap_info['asset_distribute']['symbol']
        ])
        for l in lst:
            cw.writerow(l)

    msg = "|".join([datetime.datetime.now().isoformat(), './tmp/' + fname])
    Redisdb.rpush("messages", "*|csv_exported|" + msg)

    msg = datetime.datetime.now().isoformat() + "|" + \
      "Account;Date;Amount of " + snap_info['asset_hold']['symbol'] + ";Will take of " + snap_info['asset_distribute']['symbol'] + "|"
    msg2 = ""
    for l in lst[:10]:
        for f in l:
            msg2 += f + ";"
        msg2 += "#"
    Redisdb.rpush("messages", "*|csv_data|" + msg + msg2)

    print(0)
예제 #6
0
def snapshot(data):
    """
	Signals the start of snapshot
	:param data:
	:return:
	"""
    Redisdb.rpush("messages", "---------------")
    msg = datetime.datetime.now().isoformat() + " Snapshot Starts"
    Redisdb.rpush("messages", msg)
    data['operation'] = 'launch_snapshot'
    Redisdb.rpush("operations", pickle.dumps(data))
예제 #7
0
def launch(data):
    """
	Signals start distribution
	:param data:
	:return:
	"""
    Redisdb.rpush("messages", "---------------")
    Redisdb.rpush("messages",
                  datetime.datetime.now().isoformat() + " Distribution Starts")
    data['operation'] = 'launch_distribution'
    Redisdb.rpush("operations", pickle.dumps(data))
예제 #8
0
def end_check():
    """
	Check for the finalization of snapshot tasks
	:param dat:
	:param q:
	:return:
	"""
    while True:
        print("snap_end", Redisdb.get("batch_jobs"))
        if int(Redisdb.get("batch_jobs")) == 0:
            # persist db to disk
            Redisdb.rpush("operations", pickle.dumps({'operation': 'db_save'}))

            Redisdb.rpush(
                "messages",
                datetime.datetime.now().isoformat() + " Distribution end")
            Redisdb.rpush("messages", "--------------")
            break
        sleep(2)
예제 #9
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
예제 #10
0
def do_distribution(dat):
    """
	Makes the actual transfer of tokens.
	The snapshoting step have to be done before this.
	:return:
	"""

    import config
    try:
        wallet = config.BitShares(node=config.WSS_NODE, wif=dat['form']['key'])
        ga = wallet.wallet.getAccounts()
        print(ga)
    except Exception as err:
        print(err.__repr__())
        Redisdb.rpush("messages", "*|launch_error|key not found")
        print(0)
        return False

    snap_info = pickle.loads(Redisdb.get("snapshot_info"))
    Redisdb.rpush("messages", "--------------")
    Redisdb.rpush("messages",
                  datetime.datetime.now().isoformat() + "Distribution started")

    batch_count = 0
    batch = []
    lst = list(
        Redisdb.hgetall("distribute:" + snap_info['asset_hold_id']).items())
    while True:
        distr = lst.pop(0)
        batch_count += 1
        batch.append(distr)
        if batch_count > 100 or len(lst) == 0:
            op_dat = {
                'operation': 'distribution_batch',
                'job': batch,
                'key': dat['form']['key'],
                'asset': snap_info['asset_distribute']['symbol']
            }
            Redisdb.rpush("operations", pickle.dumps(op_dat))
            Redisdb.incr("batch_jobs", 1)
            if len(lst) == 0:
                break
    Redisdb.rpush("messages",
                  datetime.datetime.now().isoformat() + "Jobs generated")
    Redisdb.rpush("operations",
                  pickle.dumps({'operation': 'distribution_check'}))
예제 #11
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
예제 #12
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'}))